From 8f5811fce2d7b6fb0bc3ba75e627fbec338bc3d1 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Tue, 14 Aug 2012 19:30:23 +0400 Subject: [PATCH] Propagate lazy resolve session to getJetClassesDescriptors() --- ...extUtils.java => ResolveSessionUtils.java} | 74 +++++++++++++++++-- .../jet/plugin/caches/JetShortNamesCache.java | 15 ++-- .../JetClassCompletionContributor.java | 29 ++++---- .../completion/JetCompletionContributor.java | 12 +-- .../JetExtensionReceiverTypeContributor.java | 12 +-- .../project/WholeProjectAnalyzerFacade.java | 4 +- .../plugin/quickfix/ImportClassAndFunFix.java | 12 +-- 7 files changed, 111 insertions(+), 47 deletions(-) rename compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/{LazyBindingContextUtils.java => ResolveSessionUtils.java} (75%) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyBindingContextUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSessionUtils.java similarity index 75% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyBindingContextUtils.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSessionUtils.java index 654b936eb06..9e46b39a7b3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyBindingContextUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSessionUtils.java @@ -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 getClassDescriptorsByFqName(@NotNull ResolveSession resolveSession, @NotNull FqName fqName) { + if (fqName.isRoot()) { + return Collections.emptyList(); + } + + Collection 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 descriptors = getClassDescriptorsByFqName(packageDescriptor, classInPackagePath); + classDescriptors.addAll(descriptors); + } + + if (packageFqName.isRoot()) { + break; + } + else { + packageFqName = packageFqName.parent(); + } + } + + return classDescriptors; + } + + private static Collection getClassDescriptorsByFqName(NamespaceDescriptor packageDescriptor, FqName path) { + if (path.isRoot()) { + return Collections.emptyList(); + } + + Collection scopes = Arrays.asList(packageDescriptor.getMemberScope()); + + List names = path.pathSegments(); + if (names.size() > 1) { + for (Name subName : path.pathSegments().subList(0, names.size() - 1)) { + Collection 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 resultClassDescriptors = Lists.newArrayList(); + for (JetScope scope : scopes) { + ClassifierDescriptor classifier = scope.getClassifier(shortName); + if (classifier instanceof ClassDescriptor) { + resultClassDescriptors.add((ClassDescriptor) classifier); + } + } + + return resultClassDescriptors; + } } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java index d27db8e10ad..a4b4d972529 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java @@ -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 resultDescriptors = new ArrayList(); - 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 getJetClassesDescriptors( @NotNull Condition acceptedShortNameCondition, - @NotNull JetFile jetFile + @NotNull ResolveSession resolveSession ) { - BindingContext context = WholeProjectAnalyzerFacade.getLazyResolveContext(jetFile, null); Collection classDescriptors = new ArrayList(); 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)); } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetClassCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetClassCompletionContributor.java index 561aad3ebf3..29fe370a5fc 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetClassCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetClassCompletionContributor.java @@ -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 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 consumer) { + private static boolean addAsJetLookupElement( + CompletionParameters parameters, + PsiClass aClass, + ResolveSession resolveSession, + BindingContext context, + Consumer consumer + ) { if (aClass instanceof JetLightClass) { Project project = parameters.getPosition().getProject(); - PsiFile completionFile = parameters.getPosition().getContainingFile(); Collection 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 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; } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java index a193571eee3..6a5c014aa03 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java @@ -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 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() { + JetClassCompletionContributor.addClasses( + parameters, result, + session.expressionBindingContext, session.resolveSession, new Consumer() { @Override public void consume(@NotNull LookupElement element) { addCompletionToResult(result, element, session); diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.java index 7d7b92482b5..f1e818ecb78 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetExtensionReceiverTypeContributor.java @@ -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() { + if (parameters.getInvocationCount() > 0) { + JetClassCompletionContributor.addClasses( + parameters, result, + resolveSession.getBindingContext(), resolveSession, new Consumer() { @Override public void consume(@NotNull LookupElement element) { result.addElement(element); diff --git a/idea/src/org/jetbrains/jet/plugin/project/WholeProjectAnalyzerFacade.java b/idea/src/org/jetbrains/jet/plugin/project/WholeProjectAnalyzerFacade.java index c6365a15818..aa28a0aa878 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/WholeProjectAnalyzerFacade.java +++ b/idea/src/org/jetbrains/jet/plugin/project/WholeProjectAnalyzerFacade.java @@ -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(); } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java index d2d12e4fb97..28cab114b38 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java @@ -96,7 +96,7 @@ public class ImportClassAndFunFix extends JetHintAction ResolveSession resolveSession = WholeProjectAnalyzerFacade.getLazyResolveSessionForFile((JetFile) element.getContainingFile()); List 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 /* * Searches for possible class names in kotlin context and java facade. */ - public static Collection getClassNames(@NotNull String referenceName, @NotNull JetFile file) { + public static Collection getClassNames(@NotNull String referenceName, @NotNull JetFile file, @NotNull ResolveSession resolveSession) { Set 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 }); } - private static Collection getJetClasses(@NotNull final String typeName, @NotNull JetFile file) { - JetShortNamesCache cache = JetCacheManager.getInstance(file.getProject()).getNamesCache(); + private static Collection getJetClasses(@NotNull final String typeName, @NotNull Project project, @NotNull ResolveSession resolveSession) { + JetShortNamesCache cache = JetCacheManager.getInstance(project).getNamesCache(); Collection descriptors = cache.getJetClassesDescriptors(new Condition() { @Override public boolean value(String s) { return typeName.equals(s); } - }, file); + }, resolveSession); return Collections2.transform(descriptors, new Function() { @Override