Extract AnalyzerFacade interface. Extract AnalyzerFacadeWithCache decorator for AnalyzerFacade.
This commit is contained in:
+22
-104
@@ -18,23 +18,16 @@ package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacade;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacadeWithCache;
|
||||
import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||
@@ -48,106 +41,20 @@ import java.util.Collections;
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class AnalyzerFacadeForJVM {
|
||||
public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM");
|
||||
|
||||
public static final Function<JetFile, Collection<JetFile>> SINGLE_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetFile>>() {
|
||||
@Override
|
||||
public Collection<JetFile> fun(JetFile file) {
|
||||
return Collections.singleton(file);
|
||||
}
|
||||
};
|
||||
|
||||
private final static Key<CachedValue<AnalyzeExhaust>> BINDING_CONTEXT = Key.create("BINDING_CONTEXT");
|
||||
private static final Object lock = new Object();
|
||||
INSTANCE;
|
||||
|
||||
private AnalyzerFacadeForJVM() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze project with string cache for given file. Given file will be fully analyzed.
|
||||
*
|
||||
* @param file
|
||||
* @param declarationProvider
|
||||
* @return
|
||||
*/
|
||||
public static AnalyzeExhaust analyzeFileWithCache(@NotNull final JetFile file,
|
||||
@NotNull final Function<JetFile, Collection<JetFile>> declarationProvider) {
|
||||
// Need lock for getValue(), because parallel threads can start evaluation of compute() simultaneously
|
||||
synchronized (lock) {
|
||||
CachedValue<AnalyzeExhaust> bindingContextCachedValue = file.getUserData(BINDING_CONTEXT);
|
||||
if (bindingContextCachedValue == null) {
|
||||
bindingContextCachedValue =
|
||||
CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<AnalyzeExhaust>() {
|
||||
@Override
|
||||
public Result<AnalyzeExhaust> compute() {
|
||||
try {
|
||||
AnalyzeExhaust bindingContext = analyzeFilesWithJavaIntegration(
|
||||
file.getProject(),
|
||||
declarationProvider.fun(file),
|
||||
Predicates.<PsiFile>equalTo(file),
|
||||
JetControlFlowDataTraceFactory.EMPTY,
|
||||
CompilerSpecialMode.REGULAR);
|
||||
return new Result<AnalyzeExhaust>(bindingContext, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
DiagnosticUtils.throwIfRunningOnServer(e);
|
||||
LOG.error(e);
|
||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||
bindingTraceContext.report(Errors.EXCEPTION_WHILE_ANALYZING.on(file, e));
|
||||
AnalyzeExhaust analyzeExhaust = new AnalyzeExhaust(bindingTraceContext.getBindingContext(), null);
|
||||
return new Result<AnalyzeExhaust>(analyzeExhaust, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
file.putUserData(BINDING_CONTEXT, bindingContextCachedValue);
|
||||
}
|
||||
return bindingContextCachedValue.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze project with string cache for the whole project. All given files will be analyzed only for descriptors.
|
||||
*/
|
||||
public static AnalyzeExhaust analyzeProjectWithCache(@NotNull final Project project,
|
||||
@NotNull final Collection<JetFile> files) {
|
||||
// Need lock for getValue(), because parallel threads can start evaluation of compute() simultaneously
|
||||
synchronized (lock) {
|
||||
CachedValue<AnalyzeExhaust> bindingContextCachedValue = project.getUserData(BINDING_CONTEXT);
|
||||
if (bindingContextCachedValue == null) {
|
||||
bindingContextCachedValue =
|
||||
CachedValuesManager.getManager(project).createCachedValue(new CachedValueProvider<AnalyzeExhaust>() {
|
||||
@Override
|
||||
public Result<AnalyzeExhaust> compute() {
|
||||
try {
|
||||
AnalyzeExhaust analyzeExhaust = analyzeFilesWithJavaIntegration(
|
||||
project,
|
||||
files,
|
||||
Predicates.<PsiFile>alwaysFalse(),
|
||||
JetControlFlowDataTraceFactory.EMPTY,
|
||||
CompilerSpecialMode.REGULAR);
|
||||
return new Result<AnalyzeExhaust>(analyzeExhaust, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
DiagnosticUtils.throwIfRunningOnServer(e);
|
||||
LOG.error(e);
|
||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||
AnalyzeExhaust analyzeExhaust = new AnalyzeExhaust(bindingTraceContext.getBindingContext(), null);
|
||||
return new Result<AnalyzeExhaust>(analyzeExhaust, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
project.putUserData(BINDING_CONTEXT, bindingContextCachedValue);
|
||||
}
|
||||
return bindingContextCachedValue.getValue();
|
||||
}
|
||||
@Override
|
||||
@NotNull
|
||||
public AnalyzeExhaust analyzeFiles(@NotNull Project project,
|
||||
@NotNull Collection<JetFile> files,
|
||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
return analyzeFilesWithJavaIntegration(project, files, filesToAnalyzeCompletely, flowDataTraceFactory, CompilerSpecialMode.REGULAR);
|
||||
}
|
||||
|
||||
public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors(
|
||||
@@ -196,4 +103,15 @@ public class AnalyzerFacadeForJVM {
|
||||
return analyzeFilesWithJavaIntegration(project, files, Predicates.<PsiFile>alwaysFalse(),
|
||||
JetControlFlowDataTraceFactory.EMPTY, CompilerSpecialMode.REGULAR);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static AnalyzeExhaust analyzeFileWithCache(@NotNull final JetFile file,
|
||||
@NotNull final Function<JetFile, Collection<JetFile>> declarationProvider) {
|
||||
return AnalyzerFacadeWithCache.getInstance(INSTANCE).analyzeFileWithCache(file, declarationProvider);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static AnalyzeExhaust analyzeProjectWithCache(@NotNull final Project project, @NotNull final Collection<JetFile> files) {
|
||||
return AnalyzerFacadeWithCache.getInstance(INSTANCE).analyzeProjectWithCache(project, files);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.analyzer;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
public interface AnalyzerFacade {
|
||||
|
||||
@NotNull
|
||||
AnalyzeExhaust analyzeFiles(@NotNull Project project,
|
||||
@NotNull Collection<JetFile> files,
|
||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory);
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.analyzer;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
public class AnalyzerFacadeWithCache implements AnalyzerFacade {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("org.jetbrains.jet.analyzer.AnalyzerFacadeWithCache");
|
||||
|
||||
private final static Key<CachedValue<AnalyzeExhaust>> ANALYZE_EXHAUST = Key.create("ANALYZE_EXHAUST");
|
||||
private static final Object lock = new Object();
|
||||
public static final Function<JetFile, Collection<JetFile>> SINGLE_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetFile>>() {
|
||||
@Override
|
||||
public Collection<JetFile> fun(JetFile file) {
|
||||
return Collections.singleton(file);
|
||||
}
|
||||
};
|
||||
|
||||
public static AnalyzerFacadeWithCache getInstance(@NotNull AnalyzerFacade facade) {
|
||||
return new AnalyzerFacadeWithCache(facade);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private final AnalyzerFacade facade;
|
||||
|
||||
private AnalyzerFacadeWithCache(@NotNull AnalyzerFacade facade) {
|
||||
this.facade = facade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze project with string cache for given file. Given file will be fully analyzed.
|
||||
*
|
||||
* @param file
|
||||
* @param declarationProvider
|
||||
* @return
|
||||
*/
|
||||
@NotNull
|
||||
public AnalyzeExhaust analyzeFileWithCache(@NotNull final JetFile file,
|
||||
@NotNull final Function<JetFile, Collection<JetFile>> declarationProvider) {
|
||||
// Need lock for getValue(), because parallel threads can start evaluation of compute() simultaneously
|
||||
synchronized (lock) {
|
||||
CachedValue<AnalyzeExhaust> bindingContextCachedValue = file.getUserData(ANALYZE_EXHAUST);
|
||||
if (bindingContextCachedValue == null) {
|
||||
bindingContextCachedValue =
|
||||
CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<AnalyzeExhaust>() {
|
||||
@Override
|
||||
public Result<AnalyzeExhaust> compute() {
|
||||
try {
|
||||
AnalyzeExhaust exhaust = facade.analyzeFiles(file.getProject(),
|
||||
declarationProvider.fun(file),
|
||||
Predicates.<PsiFile>equalTo(file),
|
||||
JetControlFlowDataTraceFactory.EMPTY);
|
||||
return new Result<AnalyzeExhaust>(exhaust, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
handleError(e);
|
||||
return emptyExhaustWithDiagnosticOnFile(e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Result<AnalyzeExhaust> emptyExhaustWithDiagnosticOnFile(Throwable e) {
|
||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||
bindingTraceContext.report(Errors.EXCEPTION_WHILE_ANALYZING.on(file, e));
|
||||
AnalyzeExhaust analyzeExhaust = new AnalyzeExhaust(bindingTraceContext.getBindingContext(), null);
|
||||
return new Result<AnalyzeExhaust>(analyzeExhaust, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
}, false);
|
||||
file.putUserData(ANALYZE_EXHAUST, bindingContextCachedValue);
|
||||
}
|
||||
return bindingContextCachedValue.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleError(@NotNull Throwable e) {
|
||||
DiagnosticUtils.throwIfRunningOnServer(e);
|
||||
LOG.error(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze project with string cache for the whole project. All given files will be analyzed only for descriptors.
|
||||
*/
|
||||
@NotNull
|
||||
public AnalyzeExhaust analyzeProjectWithCache(@NotNull final Project project, @NotNull final Collection<JetFile> files) {
|
||||
// Need lock for getValue(), because parallel threads can start evaluation of compute() simultaneously
|
||||
synchronized (lock) {
|
||||
CachedValue<AnalyzeExhaust> bindingContextCachedValue = project.getUserData(ANALYZE_EXHAUST);
|
||||
if (bindingContextCachedValue == null) {
|
||||
bindingContextCachedValue =
|
||||
CachedValuesManager.getManager(project).createCachedValue(new CachedValueProvider<AnalyzeExhaust>() {
|
||||
@Override
|
||||
public Result<AnalyzeExhaust> compute() {
|
||||
try {
|
||||
AnalyzeExhaust analyzeExhaust = facade.analyzeFiles(project,
|
||||
files,
|
||||
Predicates.<PsiFile>alwaysFalse(),
|
||||
JetControlFlowDataTraceFactory.EMPTY);
|
||||
return new Result<AnalyzeExhaust>(analyzeExhaust, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
handleError(e);
|
||||
return emptyExhaust();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Result<AnalyzeExhaust> emptyExhaust() {
|
||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||
AnalyzeExhaust analyzeExhaust = new AnalyzeExhaust(bindingTraceContext.getBindingContext(), null);
|
||||
return new Result<AnalyzeExhaust>(analyzeExhaust, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
}, false);
|
||||
project.putUserData(ANALYZE_EXHAUST, bindingContextCachedValue);
|
||||
}
|
||||
return bindingContextCachedValue.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public AnalyzeExhaust analyzeFiles(@NotNull Project project,
|
||||
@NotNull Collection<JetFile> files,
|
||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
return facade.analyzeFiles(project, files, filesToAnalyzeCompletely, flowDataTraceFactory);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.jet.types;
|
||||
import org.jetbrains.jet.JetLiteFixture;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacadeWithCache;
|
||||
import org.jetbrains.jet.di.InjectorForTests;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -63,7 +64,7 @@ public class JetDefaultModalityModifiersTest extends JetLiteFixture {
|
||||
JetDeclaration aClass = declarations.get(0);
|
||||
assert aClass instanceof JetClass;
|
||||
AnalyzeExhaust bindingContext =
|
||||
AnalyzerFacadeForJVM.analyzeFileWithCache(file, AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER);
|
||||
AnalyzerFacadeForJVM.analyzeFileWithCache(file, AnalyzerFacadeWithCache.SINGLE_DECLARATION_PROVIDER);
|
||||
DeclarationDescriptor classDescriptor =
|
||||
bindingContext.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass);
|
||||
WritableScopeImpl scope = new WritableScopeImpl(libraryScope, root, RedeclarationHandler.DO_NOTHING);
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import jet.Tuple2;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacadeWithCache;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -57,18 +58,18 @@ public class JetSourceNavigationHelper {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static<D extends ClassOrNamespaceDescriptor> Tuple2<BindingContext, D>
|
||||
getBindingContextAndClassOrNamespaceDescriptor(@NotNull WritableSlice<FqName, D> slice,
|
||||
@NotNull JetDeclaration declaration,
|
||||
@Nullable FqName fqName) {
|
||||
private static <D extends ClassOrNamespaceDescriptor> Tuple2<BindingContext, D>
|
||||
getBindingContextAndClassOrNamespaceDescriptor(@NotNull WritableSlice<FqName, D> slice,
|
||||
@NotNull JetDeclaration declaration,
|
||||
@Nullable FqName fqName) {
|
||||
if (fqName == null || DumbService.isDumb(declaration.getProject())) {
|
||||
return null;
|
||||
}
|
||||
final List<JetFile> libraryFiles = findAllSourceFilesWhichContainIdentifier(declaration);
|
||||
for (JetFile libraryFile : libraryFiles) {
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache(libraryFile,
|
||||
AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
AnalyzerFacadeWithCache.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
D descriptor = bindingContext.get(slice, fqName);
|
||||
if (descriptor != null) {
|
||||
return new Tuple2<BindingContext, D>(bindingContext, descriptor);
|
||||
@@ -79,22 +80,25 @@ public class JetSourceNavigationHelper {
|
||||
|
||||
@Nullable
|
||||
private static Tuple2<BindingContext, ClassDescriptor> getBindingContextAndClassDescriptor(@NotNull JetClass decompiledClass) {
|
||||
return getBindingContextAndClassOrNamespaceDescriptor(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, decompiledClass, JetPsiUtil.getFQName(decompiledClass));
|
||||
return getBindingContextAndClassOrNamespaceDescriptor(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, decompiledClass,
|
||||
JetPsiUtil.getFQName(decompiledClass));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Tuple2<BindingContext, NamespaceDescriptor> getBindingContextAndNamespaceDescriptor(@NotNull JetDeclaration declaration) {
|
||||
JetFile file = (JetFile) declaration.getContainingFile();
|
||||
return getBindingContextAndClassOrNamespaceDescriptor(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, declaration, JetPsiUtil.getFQName(file));
|
||||
JetFile file = (JetFile)declaration.getContainingFile();
|
||||
return getBindingContextAndClassOrNamespaceDescriptor(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, declaration,
|
||||
JetPsiUtil.getFQName(file));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetClass getSourceClass(@NotNull JetClass decompiledClass) {
|
||||
Tuple2<BindingContext, ClassDescriptor> bindingContextAndClassDescriptor = getBindingContextAndClassDescriptor(decompiledClass);
|
||||
if (bindingContextAndClassDescriptor == null) return null;
|
||||
PsiElement declaration = bindingContextAndClassDescriptor._1.get(BindingContext.DESCRIPTOR_TO_DECLARATION, bindingContextAndClassDescriptor._2);
|
||||
PsiElement declaration =
|
||||
bindingContextAndClassDescriptor._1.get(BindingContext.DESCRIPTOR_TO_DECLARATION, bindingContextAndClassDescriptor._2);
|
||||
assert declaration instanceof JetClass;
|
||||
return (JetClass) declaration;
|
||||
return (JetClass)declaration;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -119,12 +123,13 @@ public class JetSourceNavigationHelper {
|
||||
Project project = jetDeclaration.getProject();
|
||||
CacheManager cacheManager = CacheManager.SERVICE.getInstance(project);
|
||||
PsiFile[] filesWithWord = cacheManager.getFilesWithWord(name,
|
||||
UsageSearchContext.IN_CODE, createLibrarySourcesScopeForFile(libraryFile, project),
|
||||
UsageSearchContext.IN_CODE,
|
||||
createLibrarySourcesScopeForFile(libraryFile, project),
|
||||
true);
|
||||
List<JetFile> jetFiles = new ArrayList<JetFile>();
|
||||
for (PsiFile psiFile : filesWithWord) {
|
||||
if (psiFile instanceof JetFile) {
|
||||
jetFiles.add((JetFile) psiFile);
|
||||
jetFiles.add((JetFile)psiFile);
|
||||
}
|
||||
}
|
||||
return jetFiles;
|
||||
@@ -132,9 +137,9 @@ public class JetSourceNavigationHelper {
|
||||
|
||||
@Nullable
|
||||
private static <Decl extends JetDeclaration, Descr extends CallableDescriptor> JetDeclaration
|
||||
getSourcePropertyOrFunction(final @NotNull Decl decompiledDeclaration,
|
||||
JetTypeReference receiverType,
|
||||
Matcher<Decl, Descr> matcher) {
|
||||
getSourcePropertyOrFunction(final @NotNull Decl decompiledDeclaration,
|
||||
JetTypeReference receiverType,
|
||||
Matcher<Decl, Descr> matcher) {
|
||||
String entityName = decompiledDeclaration.getName();
|
||||
if (entityName == null) {
|
||||
return null;
|
||||
@@ -142,7 +147,8 @@ public class JetSourceNavigationHelper {
|
||||
|
||||
PsiElement declarationContainer = decompiledDeclaration.getParent();
|
||||
if (declarationContainer instanceof JetFile) {
|
||||
Tuple2<BindingContext, NamespaceDescriptor> bindingContextAndNamespaceDescriptor = getBindingContextAndNamespaceDescriptor(decompiledDeclaration);
|
||||
Tuple2<BindingContext, NamespaceDescriptor> bindingContextAndNamespaceDescriptor =
|
||||
getBindingContextAndNamespaceDescriptor(decompiledDeclaration);
|
||||
if (bindingContextAndNamespaceDescriptor == null) return null;
|
||||
BindingContext bindingContext = bindingContextAndNamespaceDescriptor._1;
|
||||
NamespaceDescriptor namespaceDescriptor = bindingContextAndNamespaceDescriptor._2;
|
||||
@@ -151,11 +157,12 @@ public class JetSourceNavigationHelper {
|
||||
for (Descr candidate : matcher.getCandidatesFromScope(namespaceDescriptor.getMemberScope(), entityName)) {
|
||||
if (candidate.getReceiverParameter() == ReceiverDescriptor.NO_RECEIVER) {
|
||||
if (matcher.areSame(decompiledDeclaration, candidate)) {
|
||||
return (JetDeclaration) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, candidate);
|
||||
return (JetDeclaration)bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// extension property
|
||||
String expectedTypeString = receiverType.getText();
|
||||
for (Descr candidate : matcher.getCandidatesFromScope(namespaceDescriptor.getMemberScope(), entityName)) {
|
||||
@@ -163,7 +170,7 @@ public class JetSourceNavigationHelper {
|
||||
String thisReceiverType = DescriptorRenderer.TEXT.renderType(candidate.getReceiverParameter().getType());
|
||||
if (expectedTypeString.equals(thisReceiverType)) {
|
||||
if (matcher.areSame(decompiledDeclaration, candidate)) {
|
||||
return (JetDeclaration) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, candidate);
|
||||
return (JetDeclaration)bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,7 +201,7 @@ public class JetSourceNavigationHelper {
|
||||
ClassDescriptor expectedContainer = isClassObject ? classDescriptor.getClassObjectDescriptor() : classDescriptor;
|
||||
for (Descr candidate : matcher.getCandidatesFromScope(memberScope, entityName)) {
|
||||
if (candidate.getContainingDeclaration() == expectedContainer) {
|
||||
JetDeclaration property = (JetDeclaration) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, candidate);
|
||||
JetDeclaration property = (JetDeclaration)bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, candidate);
|
||||
if (property != null) {
|
||||
return property;
|
||||
}
|
||||
@@ -207,51 +214,54 @@ public class JetSourceNavigationHelper {
|
||||
|
||||
@Nullable
|
||||
public static JetDeclaration getSourceProperty(final @NotNull JetProperty decompiledProperty) {
|
||||
return getSourcePropertyOrFunction(decompiledProperty, decompiledProperty.getReceiverTypeRef(), new Matcher<JetProperty, VariableDescriptor>() {
|
||||
@Override
|
||||
public boolean areSame(JetProperty declaration, VariableDescriptor descriptor) {
|
||||
return true;
|
||||
}
|
||||
return getSourcePropertyOrFunction(decompiledProperty, decompiledProperty.getReceiverTypeRef(),
|
||||
new Matcher<JetProperty, VariableDescriptor>() {
|
||||
@Override
|
||||
public boolean areSame(JetProperty declaration, VariableDescriptor descriptor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<VariableDescriptor> getCandidatesFromScope(JetScope scope, String name) {
|
||||
return scope.getProperties(name);
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public Set<VariableDescriptor> getCandidatesFromScope(JetScope scope, String name) {
|
||||
return scope.getProperties(name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetDeclaration getSourceFunction(final @NotNull JetFunction decompiledFunction) {
|
||||
return getSourcePropertyOrFunction(decompiledFunction, decompiledFunction.getReceiverTypeRef(), new Matcher<JetFunction, FunctionDescriptor>() {
|
||||
@Override
|
||||
public boolean areSame(JetFunction declaration, FunctionDescriptor descriptor) {
|
||||
List<JetParameter> declarationParameters = declaration.getValueParameters();
|
||||
List<ValueParameterDescriptor> descriptorParameters = descriptor.getValueParameters();
|
||||
if (descriptorParameters.size() != declarationParameters.size()) {
|
||||
return false;
|
||||
}
|
||||
return getSourcePropertyOrFunction(decompiledFunction, decompiledFunction.getReceiverTypeRef(),
|
||||
new Matcher<JetFunction, FunctionDescriptor>() {
|
||||
@Override
|
||||
public boolean areSame(JetFunction declaration, FunctionDescriptor descriptor) {
|
||||
List<JetParameter> declarationParameters = declaration.getValueParameters();
|
||||
List<ValueParameterDescriptor> descriptorParameters = descriptor.getValueParameters();
|
||||
if (descriptorParameters.size() != declarationParameters.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < descriptorParameters.size(); i++) {
|
||||
ValueParameterDescriptor descriptorParameter = descriptorParameters.get(i);
|
||||
JetParameter declarationParameter = declarationParameters.get(i);
|
||||
JetTypeReference typeReference = declarationParameter.getTypeReference();
|
||||
if (typeReference == null) {
|
||||
return false;
|
||||
}
|
||||
String declarationTypeText = typeReference.getText();
|
||||
String descriptorParameterText = DescriptorRenderer.TEXT.renderType(descriptorParameter.getType());
|
||||
if (!declarationTypeText.equals(descriptorParameterText)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < descriptorParameters.size(); i++) {
|
||||
ValueParameterDescriptor descriptorParameter = descriptorParameters.get(i);
|
||||
JetParameter declarationParameter = declarationParameters.get(i);
|
||||
JetTypeReference typeReference = declarationParameter.getTypeReference();
|
||||
if (typeReference == null) {
|
||||
return false;
|
||||
}
|
||||
String declarationTypeText = typeReference.getText();
|
||||
String descriptorParameterText =
|
||||
DescriptorRenderer.TEXT.renderType(descriptorParameter.getType());
|
||||
if (!declarationTypeText.equals(descriptorParameterText)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FunctionDescriptor> getCandidatesFromScope(JetScope scope, String name) {
|
||||
return scope.getFunctions(name);
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public Set<FunctionDescriptor> getCandidatesFromScope(JetScope scope, String name) {
|
||||
return scope.getFunctions(name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private interface Matcher<Decl extends JetDeclaration, Descr extends CallableDescriptor> {
|
||||
|
||||
+88
-56
@@ -26,6 +26,7 @@ import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacadeWithCache;
|
||||
import org.jetbrains.jet.compiler.TipsManager;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -47,7 +48,7 @@ import java.util.List;
|
||||
* Date: 17.01.12
|
||||
*/
|
||||
public class JetFunctionParameterInfoHandler implements
|
||||
ParameterInfoHandlerWithTabActionSupport<JetValueArgumentList, Object, JetValueArgument> {
|
||||
ParameterInfoHandlerWithTabActionSupport<JetValueArgumentList, Object, JetValueArgument> {
|
||||
public final static Color GREEN_BACKGROUND = new Color(231, 254, 234);
|
||||
|
||||
@NotNull
|
||||
@@ -72,7 +73,7 @@ public class JetFunctionParameterInfoHandler implements
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Class> getArgumentListAllowedParentClasses() {
|
||||
return Collections.singleton((Class) JetCallElement.class);
|
||||
return Collections.singleton((Class)JetCallElement.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -139,7 +140,7 @@ public class JetFunctionParameterInfoHandler implements
|
||||
public boolean tracksParameterIndex() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static String renderParameter(ValueParameterDescriptor descriptor, boolean named, BindingContext bindingContext) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (named) builder.append("[");
|
||||
@@ -147,21 +148,27 @@ public class JetFunctionParameterInfoHandler implements
|
||||
builder.append("vararg ");
|
||||
}
|
||||
builder.append(descriptor.getName()).append(": ").
|
||||
append(DescriptorRenderer.TEXT.renderType(getActualParameterType(descriptor)));
|
||||
append(DescriptorRenderer.TEXT.renderType(getActualParameterType(descriptor)));
|
||||
if (descriptor.hasDefaultValue()) {
|
||||
PsiElement element = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor);
|
||||
String defaultExpression = "?";
|
||||
if (element instanceof JetParameter) {
|
||||
JetParameter parameter = (JetParameter) element;
|
||||
JetParameter parameter = (JetParameter)element;
|
||||
JetExpression defaultValue = parameter.getDefaultValue();
|
||||
if (defaultValue != null) {
|
||||
if (defaultValue instanceof JetConstantExpression) {
|
||||
JetConstantExpression constantExpression = (JetConstantExpression) defaultValue;
|
||||
JetConstantExpression constantExpression = (JetConstantExpression)defaultValue;
|
||||
defaultExpression = constantExpression.getText();
|
||||
if (defaultExpression.length() > 10) {
|
||||
if (defaultExpression.startsWith("\"")) defaultExpression = "\"...\"";
|
||||
else if (defaultExpression.startsWith("\'")) defaultExpression = "\'...\'";
|
||||
else defaultExpression = defaultExpression.substring(0, 7) + "...";
|
||||
if (defaultExpression.startsWith("\"")) {
|
||||
defaultExpression = "\"...\"";
|
||||
}
|
||||
else if (defaultExpression.startsWith("\'")) {
|
||||
defaultExpression = "\'...\'";
|
||||
}
|
||||
else {
|
||||
defaultExpression = defaultExpression.substring(0, 7) + "...";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,7 +178,7 @@ public class JetFunctionParameterInfoHandler implements
|
||||
if (named) builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
private static JetType getActualParameterType(ValueParameterDescriptor descriptor) {
|
||||
JetType paramType = descriptor.getType();
|
||||
if (descriptor.getVarargElementType() != null) paramType = descriptor.getVarargElementType();
|
||||
@@ -186,13 +193,13 @@ public class JetFunctionParameterInfoHandler implements
|
||||
}
|
||||
PsiElement parameterOwner = context.getParameterOwner();
|
||||
if (parameterOwner instanceof JetValueArgumentList) {
|
||||
JetValueArgumentList argumentList = (JetValueArgumentList) parameterOwner;
|
||||
JetValueArgumentList argumentList = (JetValueArgumentList)parameterOwner;
|
||||
if (descriptor instanceof FunctionDescriptor) {
|
||||
JetFile file = (JetFile) argumentList.getContainingFile();
|
||||
JetFile file = (JetFile)argumentList.getContainingFile();
|
||||
BindingContext bindingContext =
|
||||
AnalyzerFacadeForJVM.analyzeFileWithCache(file, AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||
AnalyzerFacadeForJVM.analyzeFileWithCache(file, AnalyzerFacadeWithCache.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor)descriptor;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
|
||||
List<JetValueArgument> valueArguments = argumentList.getArguments();
|
||||
@@ -204,27 +211,28 @@ public class JetFunctionParameterInfoHandler implements
|
||||
Color color = context.getDefaultParameterColor();
|
||||
PsiElement parent = argumentList.getParent();
|
||||
if (parent instanceof JetCallElement) {
|
||||
JetCallElement callExpression = (JetCallElement) parent;
|
||||
JetCallElement callExpression = (JetCallElement)parent;
|
||||
JetExpression calleeExpression = callExpression.getCalleeExpression();
|
||||
JetSimpleNameExpression refExpression = null;
|
||||
if (calleeExpression instanceof JetSimpleNameExpression) {
|
||||
refExpression = (JetSimpleNameExpression) calleeExpression;
|
||||
} else if (calleeExpression instanceof JetConstructorCalleeExpression) {
|
||||
JetConstructorCalleeExpression constructorCalleeExpression = (JetConstructorCalleeExpression) calleeExpression;
|
||||
refExpression = (JetSimpleNameExpression)calleeExpression;
|
||||
}
|
||||
else if (calleeExpression instanceof JetConstructorCalleeExpression) {
|
||||
JetConstructorCalleeExpression constructorCalleeExpression = (JetConstructorCalleeExpression)calleeExpression;
|
||||
if (constructorCalleeExpression.getConstructorReferenceExpression() instanceof JetSimpleNameExpression) {
|
||||
refExpression = (JetSimpleNameExpression) constructorCalleeExpression.getConstructorReferenceExpression();
|
||||
refExpression = (JetSimpleNameExpression)constructorCalleeExpression.getConstructorReferenceExpression();
|
||||
}
|
||||
}
|
||||
if (refExpression != null) {
|
||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, refExpression);
|
||||
if (declarationDescriptor != null) {
|
||||
if (declarationDescriptor == functionDescriptor) {
|
||||
color = GREEN_BACKGROUND;
|
||||
color = GREEN_BACKGROUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean[] usedIndexes = new boolean[valueParameters.size()];
|
||||
boolean namedMode = false;
|
||||
Arrays.fill(usedIndexes, false);
|
||||
@@ -236,35 +244,40 @@ public class JetFunctionParameterInfoHandler implements
|
||||
if (valueParameters.size() == 0) builder.append(CodeInsightBundle.message("parameter.info.no.parameters"));
|
||||
for (int i = 0; i < valueParameters.size(); ++i) {
|
||||
if (i != 0) builder.append(", ");
|
||||
boolean highlightParameter =
|
||||
i == currentParameterIndex || (!namedMode && i < currentParameterIndex &&
|
||||
valueParameters.get(valueParameters.size() - 1).
|
||||
getVarargElementType() != null);
|
||||
boolean highlightParameter =
|
||||
i == currentParameterIndex || (!namedMode && i < currentParameterIndex &&
|
||||
valueParameters.get(valueParameters.size() - 1).
|
||||
getVarargElementType() != null);
|
||||
if (highlightParameter) boldStartOffset = builder.length();
|
||||
if (!namedMode) {
|
||||
if (valueArguments.size() > i) {
|
||||
JetValueArgument argument = valueArguments.get(i);
|
||||
if (argument.isNamed()) {
|
||||
namedMode = true;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ValueParameterDescriptor param = valueParameters.get(i);
|
||||
builder.append(renderParameter(param, false, bindingContext));
|
||||
if (i < currentParameterIndex) {
|
||||
if (argument.getArgumentExpression() != null) {
|
||||
//check type
|
||||
JetType paramType = getActualParameterType(param);
|
||||
JetType exprType = bindingContext.get(BindingContext.EXPRESSION_TYPE, argument.getArgumentExpression());
|
||||
JetType exprType =
|
||||
bindingContext.get(BindingContext.EXPRESSION_TYPE, argument.getArgumentExpression());
|
||||
if (exprType != null && !JetTypeChecker.INSTANCE.isSubtypeOf(exprType, paramType)) isGrey = true;
|
||||
}
|
||||
else isGrey = true;
|
||||
else {
|
||||
isGrey = true;
|
||||
}
|
||||
}
|
||||
usedIndexes[i] = true;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ValueParameterDescriptor param = valueParameters.get(i);
|
||||
builder.append(renderParameter(param, false, bindingContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (namedMode) {
|
||||
boolean takeAnyArgument = true;
|
||||
if (valueArguments.size() > i) {
|
||||
@@ -282,20 +295,25 @@ public class JetFunctionParameterInfoHandler implements
|
||||
if (argument.getArgumentExpression() != null) {
|
||||
//check type
|
||||
JetType paramType = getActualParameterType(param);
|
||||
JetType exprType = bindingContext.get(BindingContext.EXPRESSION_TYPE, argument.getArgumentExpression());
|
||||
if (exprType != null && !JetTypeChecker.INSTANCE.isSubtypeOf(exprType, paramType)) isGrey = true;
|
||||
JetType exprType =
|
||||
bindingContext.get(BindingContext.EXPRESSION_TYPE, argument.getArgumentExpression());
|
||||
if (exprType != null && !JetTypeChecker.INSTANCE.isSubtypeOf(exprType, paramType)) {
|
||||
isGrey = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
isGrey = true;
|
||||
}
|
||||
else isGrey = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (takeAnyArgument) {
|
||||
if (i < currentParameterIndex) isGrey = true;
|
||||
|
||||
|
||||
for (int j = 0; j < valueParameters.size(); ++j) {
|
||||
ValueParameterDescriptor param = valueParameters.get(j);
|
||||
if (!usedIndexes[j]) {
|
||||
@@ -308,10 +326,17 @@ public class JetFunctionParameterInfoHandler implements
|
||||
}
|
||||
if (highlightParameter) boldEndOffset = builder.length();
|
||||
}
|
||||
if (builder.toString().isEmpty()) context.setUIComponentEnabled(false);
|
||||
else context.setupUIComponentPresentation(builder.toString(), boldStartOffset, boldEndOffset, isGrey,
|
||||
isDeprecated, false, color);
|
||||
} else context.setUIComponentEnabled(false);
|
||||
if (builder.toString().isEmpty()) {
|
||||
context.setUIComponentEnabled(false);
|
||||
}
|
||||
else {
|
||||
context.setupUIComponentPresentation(builder.toString(), boldStartOffset, boldEndOffset, isGrey,
|
||||
isDeprecated, false, color);
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.setUIComponentEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,24 +349,28 @@ public class JetFunctionParameterInfoHandler implements
|
||||
element = element.getParent();
|
||||
}
|
||||
if (element == null) return null;
|
||||
JetValueArgumentList argumentList = (JetValueArgumentList) element;
|
||||
JetValueArgumentList argumentList = (JetValueArgumentList)element;
|
||||
JetCallElement callExpression;
|
||||
if (element.getParent() instanceof JetCallElement) {
|
||||
callExpression = (JetCallElement) element.getParent();
|
||||
} else return null;
|
||||
callExpression = (JetCallElement)element.getParent();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache(
|
||||
(JetFile) file,
|
||||
AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
(JetFile)file,
|
||||
AnalyzerFacadeWithCache.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
JetExpression calleeExpression = callExpression.getCalleeExpression();
|
||||
if (calleeExpression == null) return null;
|
||||
JetSimpleNameExpression refExpression = null;
|
||||
if (calleeExpression instanceof JetSimpleNameExpression) {
|
||||
refExpression = (JetSimpleNameExpression) calleeExpression;
|
||||
} else if (calleeExpression instanceof JetConstructorCalleeExpression) {
|
||||
JetConstructorCalleeExpression constructorCalleeExpression = (JetConstructorCalleeExpression) calleeExpression;
|
||||
refExpression = (JetSimpleNameExpression)calleeExpression;
|
||||
}
|
||||
else if (calleeExpression instanceof JetConstructorCalleeExpression) {
|
||||
JetConstructorCalleeExpression constructorCalleeExpression = (JetConstructorCalleeExpression)calleeExpression;
|
||||
if (constructorCalleeExpression.getConstructorReferenceExpression() instanceof JetSimpleNameExpression) {
|
||||
refExpression = (JetSimpleNameExpression) constructorCalleeExpression.getConstructorReferenceExpression();
|
||||
refExpression = (JetSimpleNameExpression)constructorCalleeExpression.getConstructorReferenceExpression();
|
||||
}
|
||||
}
|
||||
if (refExpression != null) {
|
||||
@@ -357,18 +386,21 @@ public class JetFunctionParameterInfoHandler implements
|
||||
ArrayList<DeclarationDescriptor> itemsToShow = new ArrayList<DeclarationDescriptor>();
|
||||
for (DeclarationDescriptor variant : variants) {
|
||||
if (variant instanceof FunctionDescriptor) {
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) variant;
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor)variant;
|
||||
if (functionDescriptor.getName().equals(refName)) {
|
||||
//todo: renamed functions?
|
||||
if (placeDescriptor != null && !JetVisibilityChecker.isVisible(placeDescriptor, functionDescriptor)) continue;
|
||||
itemsToShow.add(functionDescriptor);
|
||||
}
|
||||
} else if (variant instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) variant;
|
||||
}
|
||||
else if (variant instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor)variant;
|
||||
if (classDescriptor.getName().equals(refName)) {
|
||||
//todo: renamed classes?
|
||||
for (ConstructorDescriptor constructorDescriptor : classDescriptor.getConstructors()) {
|
||||
if (placeDescriptor != null && !JetVisibilityChecker.isVisible(placeDescriptor, constructorDescriptor)) continue;
|
||||
if (placeDescriptor != null && !JetVisibilityChecker.isVisible(placeDescriptor, constructorDescriptor)) {
|
||||
continue;
|
||||
}
|
||||
itemsToShow.add(constructorDescriptor);
|
||||
}
|
||||
}
|
||||
@@ -390,9 +422,9 @@ public class JetFunctionParameterInfoHandler implements
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent == null) return null;
|
||||
JetValueArgumentList argumentList = (JetValueArgumentList) parent;
|
||||
JetValueArgumentList argumentList = (JetValueArgumentList)parent;
|
||||
if (element instanceof JetValueArgument) {
|
||||
JetValueArgument arg = (JetValueArgument) element;
|
||||
JetValueArgument arg = (JetValueArgument)element;
|
||||
int i = argumentList.getArguments().indexOf(arg);
|
||||
context.setCurrentParameter(i);
|
||||
context.setHighlightedParameter(arg);
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacadeWithCache;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||
@@ -39,7 +40,7 @@ import org.jetbrains.jet.plugin.JetBundle;
|
||||
*/
|
||||
public class ChangeVariableMutabilityFix implements IntentionAction {
|
||||
private boolean isVar;
|
||||
|
||||
|
||||
public ChangeVariableMutabilityFix(boolean isVar) {
|
||||
this.isVar = isVar;
|
||||
}
|
||||
@@ -47,7 +48,7 @@ public class ChangeVariableMutabilityFix implements IntentionAction {
|
||||
public ChangeVariableMutabilityFix() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
@@ -63,7 +64,7 @@ public class ChangeVariableMutabilityFix implements IntentionAction {
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
if (!(file instanceof JetFile)) return false;
|
||||
JetProperty property = getCorrespondingProperty(editor, (JetFile) file);
|
||||
JetProperty property = getCorrespondingProperty(editor, (JetFile)file);
|
||||
return property != null && !property.isVar();
|
||||
}
|
||||
|
||||
@@ -73,13 +74,14 @@ public class ChangeVariableMutabilityFix implements IntentionAction {
|
||||
if (property != null) return property;
|
||||
JetSimpleNameExpression simpleNameExpression = PsiTreeUtil.getParentOfType(elementAtCaret, JetSimpleNameExpression.class);
|
||||
if (simpleNameExpression != null) {
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache(file, AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER)
|
||||
BindingContext bindingContext =
|
||||
AnalyzerFacadeForJVM.analyzeFileWithCache(file, AnalyzerFacadeWithCache.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
VariableDescriptor descriptor = BindingContextUtils.extractVariableDescriptorIfAny(bindingContext, simpleNameExpression, true);
|
||||
if (descriptor != null) {
|
||||
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor);
|
||||
if (declaration instanceof JetProperty) {
|
||||
return (JetProperty) declaration;
|
||||
return (JetProperty)declaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,7 +94,7 @@ public class ChangeVariableMutabilityFix implements IntentionAction {
|
||||
assert property != null && !property.isVar();
|
||||
|
||||
JetProperty newElement = JetPsiFactory.createProperty(project, property.getText().replaceFirst(
|
||||
property.isVar() ? "var" : "val", property.isVar() ? "val" : "var"));
|
||||
property.isVar() ? "var" : "val", property.isVar() ? "val" : "var"));
|
||||
property.replace(newElement);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.jet.plugin.quickfix;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacadeWithCache;
|
||||
import org.jetbrains.jet.lang.DefaultModuleConfiguration;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetImportDirective;
|
||||
@@ -54,8 +55,8 @@ public class ImportInsertHelper {
|
||||
if (JetPluginUtil.checkTypeIsStandard(type, file.getProject()) || ErrorUtils.isErrorType(type)) {
|
||||
return;
|
||||
}
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache(file, AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache(file, AnalyzerFacadeWithCache.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
PsiElement element = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, type.getMemberScope().getContainingDeclaration());
|
||||
if (element != null && element.getContainingFile() == file) { //declaration is in the same file, so no import is needed
|
||||
return;
|
||||
@@ -67,7 +68,7 @@ public class ImportInsertHelper {
|
||||
* Add import directive into the PSI tree for the given namespace.
|
||||
*
|
||||
* @param importFqn full name of the import
|
||||
* @param file File where directive should be added.
|
||||
* @param file File where directive should be added.
|
||||
*/
|
||||
public static void addImportDirective(@NotNull FqName importFqn, @NotNull JetFile file) {
|
||||
addImportDirective(new ImportPath(importFqn, false), null, file);
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
package org.jetbrains.jet.plugin.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.extapi.psi.ASTDelegatePsiElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacadeWithCache;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
@@ -57,13 +57,14 @@ public class QuickFixUtil {
|
||||
public static JetType getDeclarationReturnType(JetNamedDeclaration declaration) {
|
||||
PsiFile file = declaration.getContainingFile();
|
||||
if (!(file instanceof JetFile)) return null;
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache((JetFile) file, AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER)
|
||||
BindingContext bindingContext =
|
||||
AnalyzerFacadeForJVM.analyzeFileWithCache((JetFile)file, AnalyzerFacadeWithCache.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
|
||||
if (!(descriptor instanceof CallableDescriptor)) return null;
|
||||
JetType type = ((CallableDescriptor) descriptor).getReturnType();
|
||||
JetType type = ((CallableDescriptor)descriptor).getReturnType();
|
||||
if (type instanceof DeferredType) {
|
||||
type = ((DeferredType) type).getActualType();
|
||||
type = ((DeferredType)type).getActualType();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -19,15 +19,16 @@ package org.jetbrains.jet.plugin.refactoring;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacadeWithCache;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lexer.JetLexer;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
@@ -59,16 +60,17 @@ public class JetNameSuggester {
|
||||
* 1c. Arrays => arrayOfInnerType
|
||||
* 2. Reference expressions according to reference name camel humps
|
||||
* 3. Method call expression according to method callee expression
|
||||
*
|
||||
* @param expression to suggest name for variable
|
||||
* @param validator to check scope for such names
|
||||
* @param validator to check scope for such names
|
||||
* @return possible names
|
||||
*/
|
||||
public static String[] suggestNames(JetExpression expression, JetNameValidator validator) {
|
||||
ArrayList<String> result = new ArrayList<String>();
|
||||
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache((JetFile) expression.getContainingFile(),
|
||||
AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache((JetFile)expression.getContainingFile(),
|
||||
AnalyzerFacadeWithCache.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
|
||||
if (jetType != null) {
|
||||
addNamesForType(result, jetType, validator);
|
||||
@@ -78,67 +80,85 @@ public class JetNameSuggester {
|
||||
if (result.isEmpty()) addName(result, "value", validator);
|
||||
return ArrayUtil.toStringArray(result);
|
||||
}
|
||||
|
||||
|
||||
private static void addNamesForType(ArrayList<String> result, JetType jetType, JetNameValidator validator) {
|
||||
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
|
||||
JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
|
||||
if (ErrorUtils.containsErrorType(jetType)) return;
|
||||
if (typeChecker.equalTypes(standardLibrary.getBooleanType(), jetType)) {
|
||||
addName(result, "b", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getIntType(), jetType)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getIntType(), jetType)) {
|
||||
addName(result, "i", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getByteType(), jetType)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getByteType(), jetType)) {
|
||||
addName(result, "byte", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getLongType(), jetType)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getLongType(), jetType)) {
|
||||
addName(result, "l", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getFloatType(), jetType)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getFloatType(), jetType)) {
|
||||
addName(result, "fl", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getDoubleType(), jetType)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getDoubleType(), jetType)) {
|
||||
addName(result, "d", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getShortType(), jetType)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getShortType(), jetType)) {
|
||||
addName(result, "sh", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getCharType(), jetType)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getCharType(), jetType)) {
|
||||
addName(result, "c", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getStringType(), jetType)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getStringType(), jetType)) {
|
||||
addName(result, "s", validator);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (jetType.getArguments().size() == 1) {
|
||||
JetType argument = jetType.getArguments().get(0).getType();
|
||||
if (typeChecker.equalTypes(standardLibrary.getArrayType(argument), jetType)) {
|
||||
if (typeChecker.equalTypes(standardLibrary.getBooleanType(), argument)) {
|
||||
addName(result, "booleans", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getIntType(), argument)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getIntType(), argument)) {
|
||||
addName(result, "ints", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getByteType(), argument)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getByteType(), argument)) {
|
||||
addName(result, "bytes", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getLongType(), argument)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getLongType(), argument)) {
|
||||
addName(result, "longs", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getFloatType(), argument)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getFloatType(), argument)) {
|
||||
addName(result, "floats", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getDoubleType(), argument)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getDoubleType(), argument)) {
|
||||
addName(result, "doubles", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getShortType(), argument)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getShortType(), argument)) {
|
||||
addName(result, "shorts", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getCharType(), argument)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getCharType(), argument)) {
|
||||
addName(result, "chars", validator);
|
||||
} else if (typeChecker.equalTypes(standardLibrary.getStringType(), argument)) {
|
||||
}
|
||||
else if (typeChecker.equalTypes(standardLibrary.getStringType(), argument)) {
|
||||
addName(result, "strings", validator);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(argument);
|
||||
if (classDescriptor != null) {
|
||||
String className = classDescriptor.getName();
|
||||
addName(result, "arrayOf" + StringUtil.capitalize(className) + "s", validator);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
addForClassType(result, jetType, validator);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
addForClassType(result, jetType, validator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static void addForClassType(ArrayList<String> result, JetType jetType, JetNameValidator validator) {
|
||||
@@ -152,42 +172,48 @@ public class JetNameSuggester {
|
||||
private static void addCamelNames(ArrayList<String> result, String name, JetNameValidator validator) {
|
||||
if (name == "") return;
|
||||
String s = deleteNonLetterFromString(name);
|
||||
if (s.startsWith("get") || s.startsWith("set")) s = s.substring(0, 3);
|
||||
if (s.startsWith("get") || s.startsWith("set")) {
|
||||
s = s.substring(0, 3);
|
||||
}
|
||||
else if (s.startsWith("is")) s = s.substring(0, 2);
|
||||
for (int i = 0; i < s.length(); ++i) {
|
||||
if (i == 0) {
|
||||
addName(result, StringUtil.decapitalize(s), validator);
|
||||
} else if (s.charAt(i) >= 'A' && s.charAt(i) <= 'Z') {
|
||||
}
|
||||
else if (s.charAt(i) >= 'A' && s.charAt(i) <= 'Z') {
|
||||
addName(result, StringUtil.decapitalize(s.substring(i)), validator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String deleteNonLetterFromString(String s) {
|
||||
Pattern pattern = Pattern.compile("[^a-zA-Z]");
|
||||
Matcher matcher = pattern.matcher(s);
|
||||
return matcher.replaceAll("");
|
||||
}
|
||||
|
||||
|
||||
private static void addNamesForExpression(ArrayList<String> result, JetExpression expression, JetNameValidator validator) {
|
||||
if (expression instanceof JetQualifiedExpression) {
|
||||
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) expression;
|
||||
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression)expression;
|
||||
addNamesForExpression(result, qualifiedExpression.getSelectorExpression(), validator);
|
||||
} else if (expression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression reference = (JetSimpleNameExpression) expression;
|
||||
}
|
||||
else if (expression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression reference = (JetSimpleNameExpression)expression;
|
||||
String referenceName = reference.getReferencedName();
|
||||
if (referenceName == null) return;
|
||||
if (referenceName.equals(referenceName.toUpperCase())) {
|
||||
addName(result, referenceName, validator);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
addCamelNames(result, referenceName, validator);
|
||||
}
|
||||
} else if (expression instanceof JetCallExpression) {
|
||||
JetCallExpression call = (JetCallExpression) expression;
|
||||
}
|
||||
else if (expression instanceof JetCallExpression) {
|
||||
JetCallExpression call = (JetCallExpression)expression;
|
||||
addNamesForExpression(result, call.getCalleeExpression(), validator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean isIdentifier(String name) {
|
||||
ApplicationManager.getApplication().assertReadAccessAllowed();
|
||||
if (name == null || name.isEmpty()) return false;
|
||||
|
||||
@@ -28,13 +28,14 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacadeWithCache;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.NamespaceType;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
@@ -66,15 +67,16 @@ public class JetRefactoringUtil {
|
||||
while (selectionStart < selectionEnd && Character.isSpaceChar(text.charAt(selectionStart))) ++selectionStart;
|
||||
while (selectionStart < selectionEnd && Character.isSpaceChar(text.charAt(selectionEnd - 1))) --selectionEnd;
|
||||
callback.run(findExpression(editor, file, selectionStart, selectionEnd));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
smartSelectExpression(editor, file, offset, callback);
|
||||
}
|
||||
}
|
||||
|
||||
private static void smartSelectExpression(@NotNull Editor editor, @NotNull PsiFile file, int offset,
|
||||
@NotNull final SelectExpressionCallback callback)
|
||||
throws IntroduceRefactoringException {
|
||||
@NotNull final SelectExpressionCallback callback)
|
||||
throws IntroduceRefactoringException {
|
||||
if (offset < 0) throw new IntroduceRefactoringException(JetRefactoringBundle.message("cannot.refactor.not.expression"));
|
||||
PsiElement element = file.findElementAt(offset);
|
||||
if (element == null) throw new IntroduceRefactoringException(JetRefactoringBundle.message("cannot.refactor.not.expression"));
|
||||
@@ -88,34 +90,38 @@ public class JetRefactoringUtil {
|
||||
if (element instanceof JetExpression && !(element instanceof JetStatementExpression)) {
|
||||
boolean addExpression = true;
|
||||
if (element.getParent() instanceof JetQualifiedExpression) {
|
||||
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) element.getParent();
|
||||
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression)element.getParent();
|
||||
if (qualifiedExpression.getReceiverExpression() != element) {
|
||||
addExpression = false;
|
||||
}
|
||||
} else if (element.getParent() instanceof JetCallElement) {
|
||||
}
|
||||
else if (element.getParent() instanceof JetCallElement) {
|
||||
addExpression = false;
|
||||
} else if (element.getParent() instanceof JetOperationExpression) {
|
||||
JetOperationExpression operationExpression = (JetOperationExpression) element.getParent();
|
||||
}
|
||||
else if (element.getParent() instanceof JetOperationExpression) {
|
||||
JetOperationExpression operationExpression = (JetOperationExpression)element.getParent();
|
||||
if (operationExpression.getOperationReference() == element) {
|
||||
addExpression = false;
|
||||
}
|
||||
}
|
||||
if (addExpression) {
|
||||
JetExpression expression = (JetExpression) element;
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache((JetFile) expression.getContainingFile(),
|
||||
AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
JetExpression expression = (JetExpression)element;
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache((JetFile)expression.getContainingFile(),
|
||||
AnalyzerFacadeWithCache.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
|
||||
if (expressionType == null || !(expressionType instanceof NamespaceType) &&
|
||||
!JetTypeChecker.INSTANCE.equalTypes(JetStandardLibrary.
|
||||
getInstance().getTuple0Type(), expressionType)) {
|
||||
getInstance().getTuple0Type(), expressionType)) {
|
||||
expressions.add(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
element = element.getParent();
|
||||
}
|
||||
if (expressions.size() == 0) throw new IntroduceRefactoringException(JetRefactoringBundle.message("cannot.refactor.not.expression"));
|
||||
if (expressions.size() == 0) {
|
||||
throw new IntroduceRefactoringException(JetRefactoringBundle.message("cannot.refactor.not.expression"));
|
||||
}
|
||||
|
||||
final DefaultListModel model = new DefaultListModel();
|
||||
for (JetExpression expression : expressions) {
|
||||
@@ -125,13 +131,13 @@ public class JetRefactoringUtil {
|
||||
final ScopeHighlighter highlighter = new ScopeHighlighter(editor);
|
||||
|
||||
final JList list = new JBList(model);
|
||||
|
||||
|
||||
list.setCellRenderer(new DefaultListCellRenderer() {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
Component rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
JetExpression element = (JetExpression) value;
|
||||
JetExpression element = (JetExpression)value;
|
||||
if (element.isValid()) {
|
||||
setText(getExpressionShortText(element));
|
||||
}
|
||||
@@ -145,7 +151,7 @@ public class JetRefactoringUtil {
|
||||
highlighter.dropHighlight();
|
||||
int selectedIndex = list.getSelectedIndex();
|
||||
if (selectedIndex < 0) return;
|
||||
JetExpression expression = (JetExpression) model.get(selectedIndex);
|
||||
JetExpression expression = (JetExpression)model.get(selectedIndex);
|
||||
ArrayList<PsiElement> toExtract = new ArrayList<PsiElement>();
|
||||
toExtract.add(expression);
|
||||
highlighter.highlight(expression, toExtract);
|
||||
@@ -153,11 +159,11 @@ public class JetRefactoringUtil {
|
||||
});
|
||||
|
||||
JBPopupFactory.getInstance().createListPopupBuilder(list).
|
||||
setTitle(JetRefactoringBundle.message("expressions.title")).setMovable(false).setResizable(false).
|
||||
setRequestFocus(true).setItemChoosenCallback(new Runnable() {
|
||||
setTitle(JetRefactoringBundle.message("expressions.title")).setMovable(false).setResizable(false).
|
||||
setRequestFocus(true).setItemChoosenCallback(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.run((JetExpression) list.getSelectedValue());
|
||||
callback.run((JetExpression)list.getSelectedValue());
|
||||
}
|
||||
}).addListener(new JBPopupAdapter() {
|
||||
@Override
|
||||
@@ -165,7 +171,6 @@ public class JetRefactoringUtil {
|
||||
highlighter.dropHighlight();
|
||||
}
|
||||
}).createPopup().showInBestPositionFor(editor);
|
||||
|
||||
}
|
||||
|
||||
public static String getExpressionShortText(@NotNull JetExpression expression) { //todo: write appropriate implementation
|
||||
@@ -178,24 +183,26 @@ public class JetRefactoringUtil {
|
||||
|
||||
@Nullable
|
||||
private static JetExpression findExpression(@NotNull Editor editor, @NotNull PsiFile file,
|
||||
int startOffset, int endOffset) throws IntroduceRefactoringException{
|
||||
int startOffset, int endOffset) throws IntroduceRefactoringException {
|
||||
PsiElement element = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, endOffset, JetExpression.class);
|
||||
if (element == null || element.getTextRange().getStartOffset() != startOffset ||
|
||||
element.getTextRange().getEndOffset() != endOffset) {
|
||||
//todo: if it's infix expression => add (), then commit document then return new created expression
|
||||
throw new IntroduceRefactoringException(JetRefactoringBundle.message("cannot.refactor.not.expression"));
|
||||
} else if (!(element instanceof JetExpression)) {
|
||||
}
|
||||
else if (!(element instanceof JetExpression)) {
|
||||
throw new IntroduceRefactoringException(JetRefactoringBundle.message("cannot.refactor.not.expression"));
|
||||
} else if (element instanceof JetBlockExpression) {
|
||||
List<JetElement> statements = ((JetBlockExpression) element).getStatements();
|
||||
}
|
||||
else if (element instanceof JetBlockExpression) {
|
||||
List<JetElement> statements = ((JetBlockExpression)element).getStatements();
|
||||
if (statements.size() == 1) {
|
||||
JetElement elem = statements.get(0);
|
||||
if (elem.getText().equals(element.getText()) && elem instanceof JetExpression) {
|
||||
return (JetExpression) elem;
|
||||
return (JetExpression)elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (JetExpression) element;
|
||||
return (JetExpression)element;
|
||||
}
|
||||
|
||||
public static class IntroduceRefactoringException extends Exception {
|
||||
@@ -209,5 +216,4 @@ public class JetRefactoringUtil {
|
||||
return myMessage;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+239
-193
@@ -34,14 +34,15 @@ import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacadeWithCache;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.NamespaceType;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.refactoring.*;
|
||||
|
||||
@@ -65,7 +66,8 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
};
|
||||
try {
|
||||
JetRefactoringUtil.selectExpression(editor, file, callback);
|
||||
} catch (JetRefactoringUtil.IntroduceRefactoringException e) {
|
||||
}
|
||||
catch (JetRefactoringUtil.IntroduceRefactoringException e) {
|
||||
showErrorHint(project, editor, e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -76,34 +78,37 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
return;
|
||||
}
|
||||
if (_expression.getParent() instanceof JetParenthesizedExpression) {
|
||||
_expression = (JetExpression) _expression.getParent();
|
||||
_expression = (JetExpression)_expression.getParent();
|
||||
}
|
||||
final JetExpression expression = _expression;
|
||||
if (expression.getParent() instanceof JetQualifiedExpression) {
|
||||
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) expression.getParent();
|
||||
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression)expression.getParent();
|
||||
if (qualifiedExpression.getReceiverExpression() != expression) {
|
||||
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.no.expression"));
|
||||
return;
|
||||
}
|
||||
} else if (expression.getParent() instanceof JetCallElement || expression instanceof JetStatementExpression) {
|
||||
}
|
||||
else if (expression.getParent() instanceof JetCallElement || expression instanceof JetStatementExpression) {
|
||||
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.no.expression"));
|
||||
return;
|
||||
} else if (expression.getParent() instanceof JetOperationExpression) {
|
||||
JetOperationExpression operationExpression = (JetOperationExpression) expression.getParent();
|
||||
}
|
||||
else if (expression.getParent() instanceof JetOperationExpression) {
|
||||
JetOperationExpression operationExpression = (JetOperationExpression)expression.getParent();
|
||||
if (operationExpression.getOperationReference() == expression) {
|
||||
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.no.expression"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache((JetFile) expression.getContainingFile(),
|
||||
AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache((JetFile)expression.getContainingFile(),
|
||||
AnalyzerFacadeWithCache.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
final JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); //can be null or error type
|
||||
if (expressionType instanceof NamespaceType) {
|
||||
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.namespace.expression"));
|
||||
return;
|
||||
} if (expressionType != null &&
|
||||
JetTypeChecker.INSTANCE.equalTypes(JetStandardLibrary.getInstance().getTuple0Type(), expressionType)) {
|
||||
}
|
||||
if (expressionType != null &&
|
||||
JetTypeChecker.INSTANCE.equalTypes(JetStandardLibrary.getInstance().getTuple0Type(), expressionType)) {
|
||||
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.expression.has.unit.type"));
|
||||
return;
|
||||
}
|
||||
@@ -114,8 +119,8 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
return;
|
||||
}
|
||||
final boolean isInplaceAvailableOnDataContext =
|
||||
editor.getSettings().isVariableInplaceRenameEnabled() &&
|
||||
!ApplicationManager.getApplication().isUnitTestMode();
|
||||
editor.getSettings().isVariableInplaceRenameEnabled() &&
|
||||
!ApplicationManager.getApplication().isUnitTestMode();
|
||||
final ArrayList<JetExpression> allOccurrences = findOccurrences(occurrenceContainer, expression);
|
||||
Pass<OccurrencesChooser.ReplaceChoice> callback = new Pass<OccurrencesChooser.ReplaceChoice>() {
|
||||
@Override
|
||||
@@ -125,10 +130,11 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
if (OccurrencesChooser.ReplaceChoice.ALL == replaceChoice) {
|
||||
if (allOccurrences.size() > 1) replaceOccurrence = true;
|
||||
allReplaces = allOccurrences;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
allReplaces = Collections.singletonList(expression);
|
||||
}
|
||||
|
||||
|
||||
PsiElement commonParent = PsiTreeUtil.findCommonParent(allReplaces);
|
||||
PsiElement commonContainer = getContainer(commonParent);
|
||||
JetNameValidatorImpl validator = new JetNameValidatorImpl(commonContainer,
|
||||
@@ -142,8 +148,8 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
final ArrayList<JetExpression> references = new ArrayList<JetExpression>();
|
||||
final Ref<JetExpression> reference = new Ref<JetExpression>();
|
||||
final Runnable introduceRunnable = introduceVariable(project, expression, suggestedNames, allReplaces, commonContainer,
|
||||
commonParent, replaceOccurrence, propertyRef, references,
|
||||
reference);
|
||||
commonParent, replaceOccurrence, propertyRef, references,
|
||||
reference);
|
||||
final boolean finalReplaceOccurrence = replaceOccurrence;
|
||||
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
||||
@Override
|
||||
@@ -156,13 +162,13 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
if (isInplaceAvailableOnDataContext) {
|
||||
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
|
||||
PsiDocumentManager.getInstance(project).
|
||||
doPostponedOperationsAndUnblockDocument(editor.getDocument());
|
||||
doPostponedOperationsAndUnblockDocument(editor.getDocument());
|
||||
JetInplaceVariableIntroducer variableIntroducer =
|
||||
new JetInplaceVariableIntroducer(property, editor, project, INTRODUCE_VARIABLE,
|
||||
references.toArray(new JetExpression[references.size()]),
|
||||
reference.get(), finalReplaceOccurrence,
|
||||
property, /*todo*/false, /*todo*/false,
|
||||
expressionType);
|
||||
new JetInplaceVariableIntroducer(property, editor, project, INTRODUCE_VARIABLE,
|
||||
references.toArray(new JetExpression[references.size()]),
|
||||
reference.get(), finalReplaceOccurrence,
|
||||
property, /*todo*/false, /*todo*/false,
|
||||
expressionType);
|
||||
variableIntroducer.performInplaceRefactoring(suggestedNamesSet);
|
||||
}
|
||||
}
|
||||
@@ -172,147 +178,163 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
};
|
||||
if (isInplaceAvailableOnDataContext) {
|
||||
OccurrencesChooser.<JetExpression>simpleChooser(editor).
|
||||
showChooser(expression, allOccurrences, callback);
|
||||
} else {
|
||||
showChooser(expression, allOccurrences, callback);
|
||||
}
|
||||
else {
|
||||
callback.pass(OccurrencesChooser.ReplaceChoice.ALL);
|
||||
}
|
||||
}
|
||||
|
||||
private static Runnable introduceVariable(final @NotNull Project project, final JetExpression expression,
|
||||
|
||||
private static Runnable introduceVariable(final @NotNull Project project, final JetExpression expression,
|
||||
final String[] suggestedNames,
|
||||
final List<JetExpression> allReplaces, final PsiElement commonContainer,
|
||||
final PsiElement commonParent, final boolean replaceOccurrence,
|
||||
final Ref<JetProperty> propertyRef,
|
||||
final ArrayList<JetExpression> references,
|
||||
final ArrayList<JetExpression> references,
|
||||
final Ref<JetExpression> reference) {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String variableText = "val " + suggestedNames[0] + " = ";
|
||||
if (expression instanceof JetParenthesizedExpression) {
|
||||
JetParenthesizedExpression parenthesizedExpression = (JetParenthesizedExpression) expression;
|
||||
JetExpression innerExpression = parenthesizedExpression.getExpression();
|
||||
if (innerExpression != null) variableText += innerExpression.getText();
|
||||
else variableText += expression.getText();
|
||||
} else variableText += expression.getText();
|
||||
JetProperty property = JetPsiFactory.createProperty(project, variableText);
|
||||
if (property == null) return;
|
||||
PsiElement anchor = calculateAnchor(commonParent, commonContainer, allReplaces);
|
||||
if (anchor == null) return;
|
||||
boolean needBraces = !(commonContainer instanceof JetBlockExpression ||
|
||||
commonContainer instanceof JetClassBody ||
|
||||
commonContainer instanceof JetClassInitializer);
|
||||
if (!needBraces) {
|
||||
property = (JetProperty) commonContainer.addBefore(property, anchor);
|
||||
commonContainer.addBefore(JetPsiFactory.createWhiteSpace(project, "\n"), anchor);
|
||||
} else {
|
||||
JetExpression emptyBody = JetPsiFactory.createEmptyBody(project);
|
||||
PsiElement firstChild = emptyBody.getFirstChild();
|
||||
emptyBody.addAfter(JetPsiFactory.createWhiteSpace(project, "\n"), firstChild);
|
||||
if (replaceOccurrence && commonContainer != null) {
|
||||
for (JetExpression replace : allReplaces) {
|
||||
boolean isActualExpression = expression == replace;
|
||||
JetExpression element = (JetExpression) replace.replace(JetPsiFactory.createExpression(project, suggestedNames[0]));
|
||||
if (isActualExpression) reference.set(element);
|
||||
}
|
||||
PsiElement oldElement = commonContainer;
|
||||
if (commonContainer instanceof JetWhenEntry) {
|
||||
JetExpression body = ((JetWhenEntry) commonContainer).getExpression();
|
||||
if (body != null) {
|
||||
oldElement = body;
|
||||
}
|
||||
} else if (commonContainer instanceof JetNamedFunction) {
|
||||
JetExpression body = ((JetNamedFunction) commonContainer).getBodyExpression();
|
||||
if (body != null) {
|
||||
oldElement = body;
|
||||
}
|
||||
} else if (commonContainer instanceof JetSecondaryConstructor) {
|
||||
JetExpression body = ((JetSecondaryConstructor) commonContainer).getBodyExpression();
|
||||
if (body != null) {
|
||||
oldElement = body;
|
||||
}
|
||||
} else if (commonContainer instanceof JetContainerNode) {
|
||||
JetContainerNode container = (JetContainerNode) commonContainer;
|
||||
PsiElement[] children = container.getChildren();
|
||||
for (PsiElement child : children) {
|
||||
if (child instanceof JetExpression) {
|
||||
oldElement = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
//ugly logic to make sure we are working with right actual expression
|
||||
JetExpression actualExpression = reference.get();
|
||||
int diff = actualExpression.getTextRange().getStartOffset() - oldElement.getTextRange().getStartOffset();
|
||||
String actualExpressionText = actualExpression.getText();
|
||||
PsiElement newElement = emptyBody.addAfter(oldElement, firstChild);
|
||||
PsiElement elem = newElement.findElementAt(diff);
|
||||
while (elem != null && !(elem instanceof JetExpression &&
|
||||
actualExpressionText.equals(elem.getText()))) {
|
||||
elem = elem.getParent();
|
||||
}
|
||||
if (elem != null) {
|
||||
reference.set((JetExpression) elem);
|
||||
}
|
||||
emptyBody.addAfter(JetPsiFactory.createWhiteSpace(project, "\n"), firstChild);
|
||||
property = (JetProperty) emptyBody.addAfter(property, firstChild);
|
||||
emptyBody.addAfter(JetPsiFactory.createWhiteSpace(project, "\n"), firstChild);
|
||||
actualExpression = reference.get();
|
||||
diff = actualExpression.getTextRange().getStartOffset() - emptyBody.getTextRange().getStartOffset();
|
||||
actualExpressionText = actualExpression.getText();
|
||||
emptyBody = (JetExpression) anchor.replace(emptyBody);
|
||||
elem = emptyBody.findElementAt(diff);
|
||||
while (elem != null && !(elem instanceof JetExpression &&
|
||||
actualExpressionText.equals(elem.getText()))) {
|
||||
elem = elem.getParent();
|
||||
}
|
||||
if (elem != null) {
|
||||
reference.set((JetExpression) elem);
|
||||
}
|
||||
} else {
|
||||
property = (JetProperty) emptyBody.addAfter(property, firstChild);
|
||||
emptyBody.addAfter(JetPsiFactory.createWhiteSpace(project, "\n"), firstChild);
|
||||
emptyBody = (JetExpression) anchor.replace(emptyBody);
|
||||
}
|
||||
for (PsiElement child : emptyBody.getChildren()) {
|
||||
if (child instanceof JetProperty) {
|
||||
property = (JetProperty) child;
|
||||
}
|
||||
}
|
||||
if (commonContainer instanceof JetNamedFunction) {
|
||||
//we should remove equals sign
|
||||
JetNamedFunction function = (JetNamedFunction) commonContainer;
|
||||
if (!function.hasDeclaredReturnType()) {
|
||||
//todo: add return type
|
||||
}
|
||||
function.getEqualsToken().delete();
|
||||
} else if (commonContainer instanceof JetContainerNode) {
|
||||
JetContainerNode node = (JetContainerNode) commonContainer;
|
||||
if (node.getParent() instanceof JetIfExpression) {
|
||||
PsiElement next = node.getNextSibling();
|
||||
if (next != null) {
|
||||
PsiElement nextnext = next.getNextSibling();
|
||||
if (nextnext != null && nextnext.getNode().getElementType() == JetTokens.ELSE_KEYWORD) {
|
||||
if (next instanceof PsiWhiteSpace) {
|
||||
next.replace(JetPsiFactory.createWhiteSpace(project, " ")) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (JetExpression replace : allReplaces) {
|
||||
if (replaceOccurrence && !needBraces) {
|
||||
boolean isActualExpression = expression == replace;
|
||||
JetExpression element = (JetExpression) replace.replace(JetPsiFactory.createExpression(project, suggestedNames[0]));
|
||||
references.add(element);
|
||||
if (isActualExpression) reference.set(element);
|
||||
} else if (!needBraces) {
|
||||
replace.delete();
|
||||
}
|
||||
}
|
||||
propertyRef.set(property);
|
||||
}
|
||||
};
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String variableText = "val " + suggestedNames[0] + " = ";
|
||||
if (expression instanceof JetParenthesizedExpression) {
|
||||
JetParenthesizedExpression parenthesizedExpression = (JetParenthesizedExpression)expression;
|
||||
JetExpression innerExpression = parenthesizedExpression.getExpression();
|
||||
if (innerExpression != null) {
|
||||
variableText += innerExpression.getText();
|
||||
}
|
||||
else {
|
||||
variableText += expression.getText();
|
||||
}
|
||||
}
|
||||
else {
|
||||
variableText += expression.getText();
|
||||
}
|
||||
JetProperty property = JetPsiFactory.createProperty(project, variableText);
|
||||
if (property == null) return;
|
||||
PsiElement anchor = calculateAnchor(commonParent, commonContainer, allReplaces);
|
||||
if (anchor == null) return;
|
||||
boolean needBraces = !(commonContainer instanceof JetBlockExpression ||
|
||||
commonContainer instanceof JetClassBody ||
|
||||
commonContainer instanceof JetClassInitializer);
|
||||
if (!needBraces) {
|
||||
property = (JetProperty)commonContainer.addBefore(property, anchor);
|
||||
commonContainer.addBefore(JetPsiFactory.createWhiteSpace(project, "\n"), anchor);
|
||||
}
|
||||
else {
|
||||
JetExpression emptyBody = JetPsiFactory.createEmptyBody(project);
|
||||
PsiElement firstChild = emptyBody.getFirstChild();
|
||||
emptyBody.addAfter(JetPsiFactory.createWhiteSpace(project, "\n"), firstChild);
|
||||
if (replaceOccurrence && commonContainer != null) {
|
||||
for (JetExpression replace : allReplaces) {
|
||||
boolean isActualExpression = expression == replace;
|
||||
JetExpression element =
|
||||
(JetExpression)replace.replace(JetPsiFactory.createExpression(project, suggestedNames[0]));
|
||||
if (isActualExpression) reference.set(element);
|
||||
}
|
||||
PsiElement oldElement = commonContainer;
|
||||
if (commonContainer instanceof JetWhenEntry) {
|
||||
JetExpression body = ((JetWhenEntry)commonContainer).getExpression();
|
||||
if (body != null) {
|
||||
oldElement = body;
|
||||
}
|
||||
}
|
||||
else if (commonContainer instanceof JetNamedFunction) {
|
||||
JetExpression body = ((JetNamedFunction)commonContainer).getBodyExpression();
|
||||
if (body != null) {
|
||||
oldElement = body;
|
||||
}
|
||||
}
|
||||
else if (commonContainer instanceof JetSecondaryConstructor) {
|
||||
JetExpression body = ((JetSecondaryConstructor)commonContainer).getBodyExpression();
|
||||
if (body != null) {
|
||||
oldElement = body;
|
||||
}
|
||||
}
|
||||
else if (commonContainer instanceof JetContainerNode) {
|
||||
JetContainerNode container = (JetContainerNode)commonContainer;
|
||||
PsiElement[] children = container.getChildren();
|
||||
for (PsiElement child : children) {
|
||||
if (child instanceof JetExpression) {
|
||||
oldElement = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
//ugly logic to make sure we are working with right actual expression
|
||||
JetExpression actualExpression = reference.get();
|
||||
int diff = actualExpression.getTextRange().getStartOffset() - oldElement.getTextRange().getStartOffset();
|
||||
String actualExpressionText = actualExpression.getText();
|
||||
PsiElement newElement = emptyBody.addAfter(oldElement, firstChild);
|
||||
PsiElement elem = newElement.findElementAt(diff);
|
||||
while (elem != null && !(elem instanceof JetExpression &&
|
||||
actualExpressionText.equals(elem.getText()))) {
|
||||
elem = elem.getParent();
|
||||
}
|
||||
if (elem != null) {
|
||||
reference.set((JetExpression)elem);
|
||||
}
|
||||
emptyBody.addAfter(JetPsiFactory.createWhiteSpace(project, "\n"), firstChild);
|
||||
property = (JetProperty)emptyBody.addAfter(property, firstChild);
|
||||
emptyBody.addAfter(JetPsiFactory.createWhiteSpace(project, "\n"), firstChild);
|
||||
actualExpression = reference.get();
|
||||
diff = actualExpression.getTextRange().getStartOffset() - emptyBody.getTextRange().getStartOffset();
|
||||
actualExpressionText = actualExpression.getText();
|
||||
emptyBody = (JetExpression)anchor.replace(emptyBody);
|
||||
elem = emptyBody.findElementAt(diff);
|
||||
while (elem != null && !(elem instanceof JetExpression &&
|
||||
actualExpressionText.equals(elem.getText()))) {
|
||||
elem = elem.getParent();
|
||||
}
|
||||
if (elem != null) {
|
||||
reference.set((JetExpression)elem);
|
||||
}
|
||||
}
|
||||
else {
|
||||
property = (JetProperty)emptyBody.addAfter(property, firstChild);
|
||||
emptyBody.addAfter(JetPsiFactory.createWhiteSpace(project, "\n"), firstChild);
|
||||
emptyBody = (JetExpression)anchor.replace(emptyBody);
|
||||
}
|
||||
for (PsiElement child : emptyBody.getChildren()) {
|
||||
if (child instanceof JetProperty) {
|
||||
property = (JetProperty)child;
|
||||
}
|
||||
}
|
||||
if (commonContainer instanceof JetNamedFunction) {
|
||||
//we should remove equals sign
|
||||
JetNamedFunction function = (JetNamedFunction)commonContainer;
|
||||
if (!function.hasDeclaredReturnType()) {
|
||||
//todo: add return type
|
||||
}
|
||||
function.getEqualsToken().delete();
|
||||
}
|
||||
else if (commonContainer instanceof JetContainerNode) {
|
||||
JetContainerNode node = (JetContainerNode)commonContainer;
|
||||
if (node.getParent() instanceof JetIfExpression) {
|
||||
PsiElement next = node.getNextSibling();
|
||||
if (next != null) {
|
||||
PsiElement nextnext = next.getNextSibling();
|
||||
if (nextnext != null && nextnext.getNode().getElementType() == JetTokens.ELSE_KEYWORD) {
|
||||
if (next instanceof PsiWhiteSpace) {
|
||||
next.replace(JetPsiFactory.createWhiteSpace(project, " "));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (JetExpression replace : allReplaces) {
|
||||
if (replaceOccurrence && !needBraces) {
|
||||
boolean isActualExpression = expression == replace;
|
||||
JetExpression element = (JetExpression)replace.replace(JetPsiFactory.createExpression(project, suggestedNames[0]));
|
||||
references.add(element);
|
||||
if (isActualExpression) reference.set(element);
|
||||
}
|
||||
else if (!needBraces) {
|
||||
replace.delete();
|
||||
}
|
||||
}
|
||||
propertyRef.set(property);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static PsiElement calculateAnchor(PsiElement commonParent, PsiElement commonContainer,
|
||||
@@ -322,7 +344,8 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
while (anchor.getParent() != commonContainer) {
|
||||
anchor = anchor.getParent();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
anchor = commonContainer.getFirstChild();
|
||||
int startOffset = commonContainer.getTextRange().getEndOffset();
|
||||
for (JetExpression expr : allReplaces) {
|
||||
@@ -339,7 +362,7 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
|
||||
private static ArrayList<JetExpression> findOccurrences(PsiElement occurrenceContainer, @NotNull JetExpression expression) {
|
||||
if (expression instanceof JetParenthesizedExpression) {
|
||||
JetParenthesizedExpression parenthesizedExpression = (JetParenthesizedExpression) expression;
|
||||
JetParenthesizedExpression parenthesizedExpression = (JetParenthesizedExpression)expression;
|
||||
JetExpression innerExpression = parenthesizedExpression.getExpression();
|
||||
if (innerExpression != null) {
|
||||
expression = innerExpression;
|
||||
@@ -349,9 +372,9 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
|
||||
final ArrayList<JetExpression> result = new ArrayList<JetExpression>();
|
||||
|
||||
final BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache((JetFile) expression.getContainingFile(),
|
||||
AnalyzerFacadeForJVM.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
final BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFileWithCache((JetFile)expression.getContainingFile(),
|
||||
AnalyzerFacadeWithCache.SINGLE_DECLARATION_PROVIDER)
|
||||
.getBindingContext();
|
||||
|
||||
JetVisitorVoid visitor = new JetVisitorVoid() {
|
||||
@Override
|
||||
@@ -368,26 +391,36 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
if (element1.getNode().getElementType() == JetTokens.IDENTIFIER &&
|
||||
element2.getNode().getElementType() == JetTokens.IDENTIFIER) {
|
||||
if (element1.getParent() instanceof JetSimpleNameExpression &&
|
||||
element2.getParent() instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression expr1 = (JetSimpleNameExpression) element1.getParent();
|
||||
JetSimpleNameExpression expr2 = (JetSimpleNameExpression) element2.getParent();
|
||||
element2.getParent() instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression expr1 = (JetSimpleNameExpression)element1.getParent();
|
||||
JetSimpleNameExpression expr2 = (JetSimpleNameExpression)element2.getParent();
|
||||
DeclarationDescriptor descr1 = bindingContext.get(BindingContext.REFERENCE_TARGET, expr1);
|
||||
DeclarationDescriptor descr2 = bindingContext.get(BindingContext.REFERENCE_TARGET, expr2);
|
||||
if (descr1 != descr2) return 1;
|
||||
else return 0;
|
||||
if (descr1 != descr2) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!element1.textMatches(element2)) return 1;
|
||||
else return 0;
|
||||
if (!element1.textMatches(element2)) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}, null, false)) {
|
||||
PsiElement parent = expression.getParent();
|
||||
if (parent instanceof JetParenthesizedExpression) {
|
||||
result.add((JetParenthesizedExpression) parent);
|
||||
} else {
|
||||
result.add((JetParenthesizedExpression)parent);
|
||||
}
|
||||
else {
|
||||
result.add(expression);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
super.visitExpression(expression);
|
||||
}
|
||||
}
|
||||
@@ -399,25 +432,28 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
@Nullable
|
||||
private static PsiElement getContainer(PsiElement place) {
|
||||
if (place instanceof JetBlockExpression || place instanceof JetClassBody ||
|
||||
place instanceof JetClassInitializer) {
|
||||
place instanceof JetClassInitializer) {
|
||||
return place;
|
||||
}
|
||||
while (place != null) {
|
||||
PsiElement parent = place.getParent();
|
||||
if (parent instanceof JetContainerNode) {
|
||||
if (!isBadContainerNode((JetContainerNode) parent, place)) {
|
||||
if (!isBadContainerNode((JetContainerNode)parent, place)) {
|
||||
return parent;
|
||||
}
|
||||
} if (parent instanceof JetBlockExpression || parent instanceof JetWhenEntry ||
|
||||
}
|
||||
if (parent instanceof JetBlockExpression || parent instanceof JetWhenEntry ||
|
||||
parent instanceof JetClassBody || parent instanceof JetClassInitializer) {
|
||||
return parent;
|
||||
} else if (parent instanceof JetNamedFunction) {
|
||||
JetNamedFunction function = (JetNamedFunction) parent;
|
||||
}
|
||||
else if (parent instanceof JetNamedFunction) {
|
||||
JetNamedFunction function = (JetNamedFunction)parent;
|
||||
if (function.getBodyExpression() == place) {
|
||||
return parent;
|
||||
}
|
||||
} else if (parent instanceof JetSecondaryConstructor) {
|
||||
JetSecondaryConstructor secondaryConstructor = (JetSecondaryConstructor) parent;
|
||||
}
|
||||
else if (parent instanceof JetSecondaryConstructor) {
|
||||
JetSecondaryConstructor secondaryConstructor = (JetSecondaryConstructor)parent;
|
||||
if (secondaryConstructor.getBodyExpression() == place) {
|
||||
return parent;
|
||||
}
|
||||
@@ -426,13 +462,14 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static boolean isBadContainerNode(JetContainerNode parent, PsiElement place) {
|
||||
if (parent.getParent() instanceof JetIfExpression &&
|
||||
((JetIfExpression) parent.getParent()).getCondition() == place) {
|
||||
((JetIfExpression)parent.getParent()).getCondition() == place) {
|
||||
return true;
|
||||
} else if (parent.getParent() instanceof JetLoopExpression &&
|
||||
((JetLoopExpression) parent.getParent()).getBody() != place) {
|
||||
}
|
||||
else if (parent.getParent() instanceof JetLoopExpression &&
|
||||
((JetLoopExpression)parent.getParent()).getBody() != place) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -444,27 +481,36 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
while (place != null) {
|
||||
PsiElement parent = place.getParent();
|
||||
if (parent instanceof JetContainerNode) {
|
||||
if (!(place instanceof JetBlockExpression) && !isBadContainerNode((JetContainerNode) parent, place)) {
|
||||
if (!(place instanceof JetBlockExpression) && !isBadContainerNode((JetContainerNode)parent, place)) {
|
||||
result = parent;
|
||||
}
|
||||
} else if (parent instanceof JetClassBody || parent instanceof JetFile || parent instanceof JetClassInitializer) {
|
||||
if (result == null) return parent;
|
||||
else return result;
|
||||
} else if (parent instanceof JetBlockExpression) {
|
||||
}
|
||||
else if (parent instanceof JetClassBody || parent instanceof JetFile || parent instanceof JetClassInitializer) {
|
||||
if (result == null) {
|
||||
return parent;
|
||||
}
|
||||
else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else if (parent instanceof JetBlockExpression) {
|
||||
result = parent;
|
||||
} else if (parent instanceof JetWhenEntry ) {
|
||||
}
|
||||
else if (parent instanceof JetWhenEntry) {
|
||||
if (!(place instanceof JetBlockExpression)) {
|
||||
result = parent;
|
||||
}
|
||||
} else if (parent instanceof JetNamedFunction) {
|
||||
JetNamedFunction function = (JetNamedFunction) parent;
|
||||
}
|
||||
else if (parent instanceof JetNamedFunction) {
|
||||
JetNamedFunction function = (JetNamedFunction)parent;
|
||||
if (function.getBodyExpression() == place) {
|
||||
if (!(place instanceof JetBlockExpression)) {
|
||||
result = parent;
|
||||
}
|
||||
}
|
||||
} else if (parent instanceof JetSecondaryConstructor) {
|
||||
JetSecondaryConstructor secondaryConstructor = (JetSecondaryConstructor) parent;
|
||||
}
|
||||
else if (parent instanceof JetSecondaryConstructor) {
|
||||
JetSecondaryConstructor secondaryConstructor = (JetSecondaryConstructor)parent;
|
||||
if (secondaryConstructor.getBodyExpression() == place) {
|
||||
if (!(place instanceof JetBlockExpression)) {
|
||||
result = parent;
|
||||
|
||||
Reference in New Issue
Block a user