提交 1ad12b29 编写于 作者: P Pavel V. Talanov

Extract AnalyzerFacade interface. Extract AnalyzerFacadeWithCache decorator for AnalyzerFacade.

上级 766b4dc9
......@@ -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);
}
}
/*
* 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);
}
/*
* 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> {
......
......@@ -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;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册