Propagate lazy resolve session to getJetClassesDescriptors()

This commit is contained in:
Nikolay Krasko
2012-08-14 19:30:23 +04:00
parent b722e85c2b
commit 8f5811fce2
7 changed files with 111 additions and 47 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -27,20 +28,20 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.util.QualifiedNamesUtil;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.*;
/**
* @author Nikolay Krasko
*/
public class LazyBindingContextUtils {
private static final Logger LOG = Logger.getInstance("#" + LazyBindingContextUtils.class.getName());
public class ResolveSessionUtils {
private static final Logger LOG = Logger.getInstance("#" + ResolveSessionUtils.class.getName());
private LazyBindingContextUtils() {
private ResolveSessionUtils() {
}
private static class EmptyBodyResolveContext implements BodiesResolveContext {
@@ -198,4 +199,65 @@ public class LazyBindingContextUtils {
return null;
}
public static Collection<ClassDescriptor> getClassDescriptorsByFqName(@NotNull ResolveSession resolveSession, @NotNull FqName fqName) {
if (fqName.isRoot()) {
return Collections.emptyList();
}
Collection<ClassDescriptor> classDescriptors = Lists.newArrayList();
FqName packageFqName = fqName.parent();
while (true) {
NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName(packageFqName);
if (packageDescriptor != null) {
FqName classInPackagePath = new FqName(QualifiedNamesUtil.tail(packageFqName, fqName));
Collection<ClassDescriptor> descriptors = getClassDescriptorsByFqName(packageDescriptor, classInPackagePath);
classDescriptors.addAll(descriptors);
}
if (packageFqName.isRoot()) {
break;
}
else {
packageFqName = packageFqName.parent();
}
}
return classDescriptors;
}
private static Collection<ClassDescriptor> getClassDescriptorsByFqName(NamespaceDescriptor packageDescriptor, FqName path) {
if (path.isRoot()) {
return Collections.emptyList();
}
Collection<JetScope> scopes = Arrays.asList(packageDescriptor.getMemberScope());
List<Name> names = path.pathSegments();
if (names.size() > 1) {
for (Name subName : path.pathSegments().subList(0, names.size() - 1)) {
Collection<JetScope> tempScopes = Lists.newArrayList();
for (JetScope scope : scopes) {
ClassifierDescriptor classifier = scope.getClassifier(subName);
if (classifier instanceof ClassDescriptorBase) {
ClassDescriptorBase classDescriptor = (ClassDescriptorBase) classifier;
tempScopes.add(classDescriptor.getUnsubstitutedInnerClassesScope());
}
}
scopes = tempScopes;
}
}
Name shortName = path.shortName();
Collection<ClassDescriptor> resultClassDescriptors = Lists.newArrayList();
for (JetScope scope : scopes) {
ClassifierDescriptor classifier = scope.getClassifier(shortName);
if (classifier instanceof ClassDescriptor) {
resultClassDescriptors.add((ClassDescriptor) classifier);
}
}
return resultClassDescriptors;
}
}
@@ -37,7 +37,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.ImportPath;
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.resolve.lazy.LazyBindingContextUtils;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -46,7 +46,6 @@ import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.plugin.stubindex.JetExtensionFunctionNameIndex;
import org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex;
import org.jetbrains.jet.plugin.stubindex.JetShortClassNameIndex;
@@ -157,7 +156,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
@NotNull ResolveSession resolveSession,
@NotNull GlobalSearchScope scope
) {
BindingContext context = LazyBindingContextUtils.getExpressionBindingContext(resolveSession, expression);
BindingContext context = ResolveSessionUtils.getExpressionBindingContext(resolveSession, expression);
JetScope jetScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
if (jetScope == null || name.isEmpty()) {
@@ -239,7 +238,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
) {
Collection<DeclarationDescriptor> resultDescriptors = new ArrayList<DeclarationDescriptor>();
BindingContext context = LazyBindingContextUtils.getExpressionBindingContext(resolveSession, expression);
BindingContext context = ResolveSessionUtils.getExpressionBindingContext(resolveSession, expression);
JetExpression receiverExpression = expression.getReceiverExpression();
if (receiverExpression != null) {
@@ -286,18 +285,14 @@ public class JetShortNamesCache extends PsiShortNamesCache {
public Collection<ClassDescriptor> getJetClassesDescriptors(
@NotNull Condition<String> acceptedShortNameCondition,
@NotNull JetFile jetFile
@NotNull ResolveSession resolveSession
) {
BindingContext context = WholeProjectAnalyzerFacade.getLazyResolveContext(jetFile, null);
Collection<ClassDescriptor> classDescriptors = new ArrayList<ClassDescriptor>();
for (String fqName : JetFullClassNameIndex.getInstance().getAllKeys(project)) {
FqName classFQName = new FqName(fqName);
if (acceptedShortNameCondition.value(classFQName.shortName().getName())) {
ClassDescriptor descriptor = context.get(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, classFQName);
if (descriptor != null) {
classDescriptors.add(descriptor);
}
classDescriptors.addAll(ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession, classFQName));
}
}
@@ -21,7 +21,6 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
@@ -32,11 +31,11 @@ import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils;
import org.jetbrains.jet.plugin.caches.JetCacheManager;
import org.jetbrains.jet.plugin.caches.JetShortNamesCache;
import org.jetbrains.jet.plugin.completion.handlers.JetJavaClassInsertHandler;
import org.jetbrains.jet.plugin.project.JsModuleDetector;
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex;
import java.util.Collection;
@@ -54,6 +53,7 @@ public class JetClassCompletionContributor extends CompletionContributor {
@NotNull final CompletionParameters parameters,
@NotNull final CompletionResultSet result,
@NotNull final BindingContext jetContext,
@NotNull final ResolveSession resolveSession,
@NotNull final Consumer<LookupElement> consumer
) {
CompletionResultSet tempResult = result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters));
@@ -75,7 +75,7 @@ public class JetClassCompletionContributor extends CompletionContributor {
JavaPsiClassReferenceElement javaPsiReferenceElement = (JavaPsiClassReferenceElement) lookupElement;
PsiClass psiClass = javaPsiReferenceElement.getObject();
if (addAsJetLookupElement(parameters, psiClass, consumer)) {
if (addAsJetLookupElement(parameters, psiClass, resolveSession, jetContext, consumer)) {
return;
}
@@ -95,8 +95,7 @@ public class JetClassCompletionContributor extends CompletionContributor {
public boolean value(String shortName) {
return result.getPrefixMatcher().prefixMatches(shortName);
}
},
(JetFile) parameters.getOriginalFile());
}, resolveSession);
for (ClassDescriptor descriptor : descriptors) {
consumer.consume(DescriptorLookupConverter.createLookupElement(jetContext, descriptor));
@@ -104,23 +103,27 @@ public class JetClassCompletionContributor extends CompletionContributor {
}
}
private static boolean addAsJetLookupElement(CompletionParameters parameters, PsiClass aClass, Consumer<LookupElement> consumer) {
private static boolean addAsJetLookupElement(
CompletionParameters parameters,
PsiClass aClass,
ResolveSession resolveSession,
BindingContext context,
Consumer<LookupElement> consumer
) {
if (aClass instanceof JetLightClass) {
Project project = parameters.getPosition().getProject();
PsiFile completionFile = parameters.getPosition().getContainingFile();
Collection<JetClassOrObject> classOrObjects =
JetFullClassNameIndex.getInstance().get(aClass.getQualifiedName(), project, GlobalSearchScope.allScope(project));
for (JetClassOrObject classOrObject : classOrObjects) {
if (classOrObject.getContainingFile().getOriginalFile().equals(aClass.getContainingFile())) {
PsiFile fileOfClass = completionFile.getOriginalFile().equals(aClass.getContainingFile()) ? completionFile : aClass.getContainingFile();
Collection<ClassDescriptor> classDescriptors = ResolveSessionUtils.getClassDescriptorsByFqName(
resolveSession,((JetLightClass) aClass).getFqName());
for (ClassDescriptor descriptor : classDescriptors) {
consumer.consume(DescriptorLookupConverter.createLookupElement(context, descriptor));
}
ResolveSession resolveSessionForFile = WholeProjectAnalyzerFacade.getLazyResolveSessionForFile((JetFile) fileOfClass);
ClassDescriptor descriptor = resolveSessionForFile.getClassDescriptor(classOrObject);
LookupElement element = DescriptorLookupConverter.createLookupElement(resolveSessionForFile.getBindingContext(), descriptor);
consumer.consume(element);
return true;
}
}
@@ -35,7 +35,7 @@ import org.jetbrains.jet.cli.jvm.compiler.TipsManager;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.lazy.LazyBindingContextUtils;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lexer.JetTokens;
@@ -84,7 +84,7 @@ public class JetCompletionContributor extends CompletionContributor {
session.resolveSession =
WholeProjectAnalyzerFacade.getLazyResolveSessionForFile((JetFile) position.getContainingFile());
session.expressionBindingContext = LazyBindingContextUtils.getExpressionBindingContext(
session.expressionBindingContext = ResolveSessionUtils.getExpressionBindingContext(
session.resolveSession, jetReference.getExpression());
JetScope scope = session.expressionBindingContext.get(BindingContext.RESOLUTION_SCOPE, jetReference.getExpression());
@@ -96,7 +96,7 @@ public class JetCompletionContributor extends CompletionContributor {
// Rerun completion if nothing was found
session.customInvocationCount = 1;
session.resolveSession = WholeProjectAnalyzerFacade.getLazyResolveSessionForFile((JetFile) position.getContainingFile());
session.expressionBindingContext = LazyBindingContextUtils.getExpressionBindingContext(
session.expressionBindingContext = ResolveSessionUtils.getExpressionBindingContext(
session.resolveSession, jetReference.getExpression());
completeForReference(parameters, result, position, jetReference, session);
@@ -215,7 +215,7 @@ public class JetCompletionContributor extends CompletionContributor {
Collection<String> functionNames = namesCache.getAllTopLevelFunctionNames();
ResolveSession resolveSession = WholeProjectAnalyzerFacade.getLazyResolveSessionForFile((JetFile) position.getContainingFile());
BindingContext resolutionContext = LazyBindingContextUtils.getExpressionBindingContext(resolveSession, expression);
BindingContext resolutionContext = ResolveSessionUtils.getExpressionBindingContext(resolveSession, expression);
for (String name : functionNames) {
if (name.contains(actualPrefix)) {
@@ -233,7 +233,9 @@ public class JetCompletionContributor extends CompletionContributor {
@NotNull CompletionParameters parameters,
@NotNull final CompletionResultSet result,
@NotNull final CompletionSession session) {
JetClassCompletionContributor.addClasses(parameters, result, session.expressionBindingContext, new Consumer<LookupElement>() {
JetClassCompletionContributor.addClasses(
parameters, result,
session.expressionBindingContext, session.resolveSession, new Consumer<LookupElement>() {
@Override
public void consume(@NotNull LookupElement element) {
addCompletionToResult(result, element, session);
@@ -25,7 +25,7 @@ import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
@@ -41,11 +41,13 @@ public class JetExtensionReceiverTypeContributor extends CompletionContributor {
ProcessingContext context,
final @NotNull CompletionResultSet result
) {
BindingContext jetContext = WholeProjectAnalyzerFacade
.getLazyResolveContext((JetFile) parameters.getPosition().getContainingFile(), null);
ResolveSession resolveSession =
WholeProjectAnalyzerFacade.getLazyResolveSessionForFile((JetFile) parameters.getPosition().getContainingFile());
if (parameters.getInvocationCount() > 0 || parameters.getCompletionType() == CompletionType.CLASS_NAME) {
JetClassCompletionContributor.addClasses(parameters, result, jetContext, new Consumer<LookupElement>() {
if (parameters.getInvocationCount() > 0) {
JetClassCompletionContributor.addClasses(
parameters, result,
resolveSession.getBindingContext(), resolveSession, new Consumer<LookupElement>() {
@Override
public void consume(@NotNull LookupElement element) {
result.addElement(element);
@@ -23,7 +23,7 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.JetFilesProvider;
import org.jetbrains.jet.lang.resolve.lazy.LazyBindingContextUtils;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
/**
@@ -48,7 +48,7 @@ public final class WholeProjectAnalyzerFacade {
public static BindingContext getLazyResolveContext(@NotNull JetFile file, @Nullable JetExpression expression) {
ResolveSession resolveSession = getLazyResolveSessionForFile(file);
return expression != null ?
LazyBindingContextUtils.getExpressionBindingContext(resolveSession, expression) :
ResolveSessionUtils.getExpressionBindingContext(resolveSession, expression) :
resolveSession.getBindingContext();
}
}
@@ -96,7 +96,7 @@ public class ImportClassAndFunFix extends JetHintAction<JetSimpleNameExpression>
ResolveSession resolveSession = WholeProjectAnalyzerFacade.getLazyResolveSessionForFile((JetFile) element.getContainingFile());
List<FqName> result = Lists.newArrayList();
result.addAll(getClassNames(referenceName, (JetFile) file));
result.addAll(getClassNames(referenceName, (JetFile) file, resolveSession));
result.addAll(getJetTopLevelFunctions(referenceName, element, resolveSession, file.getProject()));
result.addAll(getJetExtensionFunctions(referenceName, element, resolveSession, file.getProject()));
@@ -159,14 +159,14 @@ public class ImportClassAndFunFix extends JetHintAction<JetSimpleNameExpression>
/*
* Searches for possible class names in kotlin context and java facade.
*/
public static Collection<FqName> getClassNames(@NotNull String referenceName, @NotNull JetFile file) {
public static Collection<FqName> getClassNames(@NotNull String referenceName, @NotNull JetFile file, @NotNull ResolveSession resolveSession) {
Set<FqName> possibleResolveNames = Sets.newHashSet();
if (!JsModuleDetector.isJsModule(file)) {
possibleResolveNames.addAll(getClassesFromCache(referenceName, file));
}
else {
possibleResolveNames.addAll(getJetClasses(referenceName, file));
possibleResolveNames.addAll(getJetClasses(referenceName, file.getProject(), resolveSession));
}
// TODO: Do appropriate sorting
@@ -198,14 +198,14 @@ public class ImportClassAndFunFix extends JetHintAction<JetSimpleNameExpression>
});
}
private static Collection<FqName> getJetClasses(@NotNull final String typeName, @NotNull JetFile file) {
JetShortNamesCache cache = JetCacheManager.getInstance(file.getProject()).getNamesCache();
private static Collection<FqName> getJetClasses(@NotNull final String typeName, @NotNull Project project, @NotNull ResolveSession resolveSession) {
JetShortNamesCache cache = JetCacheManager.getInstance(project).getNamesCache();
Collection<ClassDescriptor> descriptors = cache.getJetClassesDescriptors(new Condition<String>() {
@Override
public boolean value(String s) {
return typeName.equals(s);
}
}, file);
}, resolveSession);
return Collections2.transform(descriptors, new Function<ClassDescriptor, FqName>() {
@Override