diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java b/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java index c33e1cacaf9..54d1d4becce 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java @@ -54,9 +54,6 @@ import org.jetbrains.jet.plugin.stubindex.*; import java.util.*; -import static org.jetbrains.jet.lang.psi.PsiPackage.JetPsiFactory; -import static org.jetbrains.jet.plugin.caches.JetFromJavaDescriptorHelper.getTopLevelFunctionFqNames; - /** * Will provide both java elements from kotlin context and some declarations special to kotlin. * All those declaration are planned to be used in completion. @@ -151,8 +148,6 @@ public class JetShortNamesCache extends PsiShortNamesCache { /** * Get kotlin non-extension top-level function names. Method is allowed to give invalid names - all result should be * checked with getTopLevelFunctionDescriptorsByName(). - * - * @return */ @NotNull public Collection getAllTopLevelFunctionNames() { @@ -218,34 +213,28 @@ public class JetShortNamesCache extends PsiShortNamesCache { @NotNull public Collection getTopLevelFunctionDescriptorsByName( @NotNull String name, - @NotNull JetSimpleNameExpression expression, + @NotNull JetExpression context /*TODO: to be dropped*/, @NotNull ResolveSessionForBodies resolveSession, - @NotNull GlobalSearchScope scope - ) { - // name parameter can differ from expression.getReferenceName() when expression contains completion suffix - final Name referenceName = expression.getIdentifier() == null ? JetPsiUtil.getConventionName(expression) : Name.identifier(name); - if (referenceName == null || referenceName.toString().isEmpty()) { - return Collections.emptyList(); - } - - BindingContext context = resolveSession.resolveToElement(expression); - JetScope jetScope = context.get(BindingContext.RESOLUTION_SCOPE, expression); + @NotNull GlobalSearchScope scope) { + JetScope jetScope = resolveSession.resolveToElement(context).get(BindingContext.RESOLUTION_SCOPE, context); if (jetScope == null) { return Collections.emptyList(); } Set result = Sets.newHashSet(); + //TODO: this code is temporary and is to be dropped when compiled top level functions are indexed + final Name identifier = Name.identifier(name); Collection topLevelFunctionFqNames = - ContainerUtil.filter(getTopLevelFunctionFqNames(project, scope, false), new Condition() { + ContainerUtil.filter(JetFromJavaDescriptorHelper.getTopLevelFunctionFqNames(project, scope, false), new Condition() { @Override public boolean value(FqName fqName) { - return fqName.lastSegmentIs(referenceName); + return fqName.lastSegmentIs(identifier); } }); for (FqName fqName : topLevelFunctionFqNames) { - JetImportDirective importDirective = JetPsiFactory(expression).createImportDirective(new ImportPath(fqName, false)); + JetImportDirective importDirective = new JetPsiFactory(context.getProject()).createImportDirective(new ImportPath(fqName, false)); Collection declarationDescriptors = new QualifiedExpressionResolver().analyseImportReference( importDirective, jetScope, new BindingTraceContext(), resolveSession.getModuleDescriptor()); for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { @@ -256,8 +245,7 @@ public class JetShortNamesCache extends PsiShortNamesCache { } Set affectedPackages = Sets.newHashSet(); - Collection jetNamedFunctions = - JetTopLevelNonExtensionFunctionShortNameIndex.getInstance().get(referenceName.asString(), project, scope); + Collection jetNamedFunctions = JetTopLevelNonExtensionFunctionShortNameIndex.getInstance().get(name, project, scope); for (JetNamedFunction jetNamedFunction : jetNamedFunctions) { PsiFile containingFile = jetNamedFunction.getContainingFile(); if (containingFile instanceof JetFile) { @@ -270,7 +258,7 @@ public class JetShortNamesCache extends PsiShortNamesCache { PackageViewDescriptor packageDescriptor = resolveSession.getModuleDescriptor().getPackage(affectedPackage); assert packageDescriptor != null : "There's a function in stub index with invalid package: " + affectedPackage; JetScope memberScope = packageDescriptor.getMemberScope(); - result.addAll(memberScope.getFunctions(referenceName)); + result.addAll(memberScope.getFunctions(identifier)); } return result; @@ -304,7 +292,7 @@ public class JetShortNamesCache extends PsiShortNamesCache { } Set functionFQNs = extensionFunctionsFromSourceFqNames(acceptedNameCondition, searchScope); - functionFQNs.addAll(ContainerUtil.filter(getTopLevelFunctionFqNames(project, searchScope, true), new Condition() { + functionFQNs.addAll(ContainerUtil.filter(JetFromJavaDescriptorHelper.getTopLevelFunctionFqNames(project, searchScope, true), new Condition() { @Override public boolean value(FqName fqName) { return acceptedNameCondition.value(fqName.shortName().asString()); diff --git a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt index 569167d2e16..ae7ff7c962b 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt @@ -31,6 +31,7 @@ import org.jetbrains.jet.plugin.codeInsight.TipsManager import org.jetbrains.jet.plugin.completion.smart.SmartCompletion import org.jetbrains.jet.plugin.references.JetSimpleNameReference import org.jetbrains.jet.plugin.project.ResolveSessionForBodies +import com.intellij.openapi.module.ModuleUtilCore class CompletionSessionConfiguration( val completeNonImportedDeclarations: Boolean, @@ -76,6 +77,11 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, private val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, resolveSession, { isVisibleDescriptor(it) }) + private val project = position.getProject() + private val shortNamesCache = JetShortNamesCache.getKotlinInstance(project) + private val module = ModuleUtilCore.findModuleForPsiElement(parameters.getOriginalFile()) + private val searchScope = if (module != null) GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module) else GlobalSearchScope.EMPTY_SCOPE + public fun complete(): Boolean { assert(parameters.getCompletionType() == CompletionType.BASIC) @@ -95,7 +101,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, } else { addReferenceVariants { isPartOfTypeDeclaration(it) } - JavaCompletionContributor.advertiseSecondCompletion(position.getProject(), resultSet) + JavaCompletionContributor.advertiseSecondCompletion(project, resultSet) } } else { @@ -123,24 +129,18 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, if (shouldRunTopLevelCompletion()) { TypesCompletion(parameters, resolveSession, prefixMatcher).addAllTypes(collector) - addJetTopLevelFunctions() - addJetTopLevelObjects() + addKotlinTopLevelFunctions() + addKotlinTopLevelObjects() } if (shouldRunExtensionsCompletion()) { - addJetExtensions() + addKotlinExtensions() } } private fun isOnlyKeywordCompletion() = PsiTreeUtil.getParentOfType(position, javaClass()) != null - private fun addJetExtensions() { - val project = position.getProject() - val namesCache = JetShortNamesCache.getKotlinInstance(project) - collector.addDescriptorElements(namesCache.getJetCallableExtensions({ prefixMatcher.prefixMatches(it!!) }, jetReference!!.expression, resolveSession, GlobalSearchScope.allScope(project))) - } - private fun isPartOfTypeDeclaration(descriptor: DeclarationDescriptor): Boolean { return when (descriptor) { is PackageViewDescriptor, is TypeParameterDescriptor -> true @@ -155,34 +155,26 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, } } - private fun addJetTopLevelFunctions() { - val actualPrefix = prefixMatcher.getPrefix() - val project = position.getProject() - val namesCache = JetShortNamesCache.getKotlinInstance(project) - val scope = GlobalSearchScope.allScope(project) - val functionNames = namesCache.getAllTopLevelFunctionNames() - - // TODO: Fix complete extension not only on contains - for (name in functionNames) { - if (name.contains(actualPrefix)) { - collector.addDescriptorElements(namesCache.getTopLevelFunctionDescriptorsByName(name, jetReference!!.expression, resolveSession, scope)) + private fun addKotlinTopLevelFunctions() { + for (name in shortNamesCache.getAllTopLevelFunctionNames()) { + if (prefixMatcher.prefixMatches(name)) { + collector.addDescriptorElements(shortNamesCache.getTopLevelFunctionDescriptorsByName(name, jetReference!!.expression, resolveSession, searchScope)) } } } - private fun addJetTopLevelObjects() { - val project = position.getProject() - val namesCache = JetShortNamesCache.getKotlinInstance(project) - val scope = GlobalSearchScope.allScope(project) - val objectNames = namesCache.getAllTopLevelObjectNames() - - for (name in objectNames) { + private fun addKotlinTopLevelObjects() { + for (name in shortNamesCache.getAllTopLevelObjectNames()) { if (prefixMatcher.prefixMatches(name)) { - collector.addDescriptorElements(namesCache.getTopLevelObjectsByName(name, jetReference!!.expression, resolveSession, scope)) + collector.addDescriptorElements(shortNamesCache.getTopLevelObjectsByName(name, jetReference!!.expression, resolveSession, searchScope)) } } } + private fun addKotlinExtensions() { + collector.addDescriptorElements(shortNamesCache.getJetCallableExtensions({ prefixMatcher.prefixMatches(it!!) }, jetReference!!.expression, resolveSession, searchScope)) + } + private fun shouldRunOnlyTypeCompletion(): Boolean { // Check that completion in the type annotation context and if there's a qualified // expression we are at first of it @@ -196,9 +188,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, } private fun shouldRunTopLevelCompletion(): Boolean { - if (!configuration.completeNonImportedDeclarations) { - return false - } + if (!configuration.completeNonImportedDeclarations) return false if (position.getNode()!!.getElementType() == JetTokens.IDENTIFIER) { val parent = position.getParent() diff --git a/idea/src/org/jetbrains/jet/plugin/completion/TypesCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/TypesCompletion.kt index d446deccb66..8fce96c34ad 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/TypesCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/TypesCompletion.kt @@ -34,6 +34,7 @@ import org.jetbrains.jet.plugin.caches.JetShortNamesCache import org.jetbrains.jet.plugin.completion.handlers.JetJavaClassInsertHandler import org.jetbrains.jet.plugin.project.ProjectStructureUtil import org.jetbrains.jet.plugin.project.ResolveSessionForBodies +import com.intellij.openapi.module.ModuleUtilCore class TypesCompletion(val parameters: CompletionParameters, val resolveSession: ResolveSessionForBodies, val prefixMatcher: PrefixMatcher) { fun addAllTypes(result: LookupElementsCollector) { @@ -41,7 +42,9 @@ class TypesCompletion(val parameters: CompletionParameters, val resolveSession: val project = parameters.getOriginalFile().getProject() val namesCache = JetShortNamesCache.getKotlinInstance(project) - result.addDescriptorElements(namesCache.getJetClassesDescriptors({ prefixMatcher.prefixMatches(it!!) }, resolveSession, GlobalSearchScope.allScope(project))) + val module = ModuleUtilCore.findModuleForPsiElement(parameters.getOriginalFile()) ?: return + val searchScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module) + result.addDescriptorElements(namesCache.getJetClassesDescriptors({ prefixMatcher.prefixMatches(it!!) }, resolveSession, searchScope)) if (!ProjectStructureUtil.isJsKotlinModule(parameters.getOriginalFile() as JetFile)) { addAdaptedJavaCompletion(result) diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.java index c1b10a47f93..2194f08a774 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.java @@ -27,6 +27,8 @@ import com.intellij.codeInsight.intention.HighPriorityAction; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiClass; @@ -40,6 +42,7 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; @@ -53,8 +56,8 @@ import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.actions.JetAddImportAction; import org.jetbrains.jet.plugin.caches.JetShortNamesCache; import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; -import org.jetbrains.jet.plugin.project.ResolveSessionForBodies; import org.jetbrains.jet.plugin.project.ProjectStructureUtil; +import org.jetbrains.jet.plugin.project.ResolveSessionForBodies; import org.jetbrains.jet.plugin.util.JetPsiHeuristicsUtil; import java.util.Collection; @@ -93,16 +96,19 @@ public class AutoImportFix extends JetHintAction implem return Collections.emptyList(); } - ResolveSessionForBodies resolveSessionForBodies = - ResolvePackage.getLazyResolveSession(element); + ResolveSessionForBodies resolveSessionForBodies = ResolvePackage.getLazyResolveSession(element); + + Module module = ModuleUtilCore.findModuleForPsiElement(file); + if (module == null) return Collections.emptyList(); + GlobalSearchScope searchScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module); List result = Lists.newArrayList(); if (!isSuppressedTopLevelImportInPosition(element)) { - result.addAll(getClassNames(referenceName, (JetFile) file, resolveSessionForBodies)); - result.addAll(getJetTopLevelFunctions(referenceName, element, resolveSessionForBodies, file.getProject())); + result.addAll(getClassNames(referenceName, (JetFile) file, searchScope, resolveSessionForBodies)); + result.addAll(getJetTopLevelFunctions(referenceName, element, searchScope, resolveSessionForBodies, file.getProject())); } - result.addAll(getJetExtensionFunctions(referenceName, element, resolveSessionForBodies, file.getProject())); + result.addAll(getJetExtensionFunctions(referenceName, element, searchScope, resolveSessionForBodies, file.getProject())); return Collections2.filter(result, new Predicate() { @Override @@ -119,14 +125,15 @@ public class AutoImportFix extends JetHintAction implem private static Collection getJetTopLevelFunctions( @NotNull String referenceName, - @NotNull JetSimpleNameExpression expression, + @NotNull JetExpression context, + @NotNull GlobalSearchScope searchScope, @NotNull ResolveSessionForBodies resolveSession, @NotNull Project project ) { JetShortNamesCache namesCache = JetShortNamesCache.getKotlinInstance(project); Collection topLevelFunctions = namesCache.getTopLevelFunctionDescriptorsByName( - referenceName, expression, resolveSession, GlobalSearchScope.allScope(project)); + referenceName, context, resolveSession, searchScope); return Sets.newHashSet(Collections2.transform(topLevelFunctions, new Function() { @Override @@ -140,6 +147,7 @@ public class AutoImportFix extends JetHintAction implem private static Collection getJetExtensionFunctions( @NotNull final String referenceName, @NotNull JetSimpleNameExpression expression, + @NotNull GlobalSearchScope searchScope, @NotNull ResolveSessionForBodies resolveSession, @NotNull Project project ) { @@ -153,7 +161,7 @@ public class AutoImportFix extends JetHintAction implem }, expression, resolveSession, - GlobalSearchScope.allScope(project)); + searchScope); return Sets.newHashSet(Collections2.transform(jetCallableExtensions, new Function() { @Override @@ -167,24 +175,24 @@ public class AutoImportFix extends JetHintAction implem /* * Searches for possible class names in kotlin context and java facade. */ - public static Collection getClassNames(@NotNull String referenceName, @NotNull JetFile file, @NotNull KotlinCodeAnalyzer analyzer) { + public static Collection getClassNames(@NotNull String referenceName, @NotNull JetFile file, @NotNull GlobalSearchScope searchScope, @NotNull KotlinCodeAnalyzer analyzer) { Set possibleResolveNames = Sets.newHashSet(); if (!ProjectStructureUtil.isJsKotlinModule(file)) { - possibleResolveNames.addAll(getClassesFromCache(referenceName, file)); + possibleResolveNames.addAll(getClassesFromCache(referenceName, searchScope, file)); } else { - possibleResolveNames.addAll(getJetClasses(referenceName, file.getProject(), analyzer)); + possibleResolveNames.addAll(getJetClasses(referenceName, searchScope, file.getProject(), analyzer)); } // TODO: Do appropriate sorting return Lists.newArrayList(possibleResolveNames); } - private static Collection getClassesFromCache(@NotNull String typeName, @NotNull final JetFile file) { + private static Collection getClassesFromCache(@NotNull String typeName, @NotNull GlobalSearchScope searchScope, @NotNull final JetFile file) { PsiShortNamesCache cache = getShortNamesCache(file); - PsiClass[] classes = cache.getClassesByName(typeName, GlobalSearchScope.allScope(file.getProject())); + PsiClass[] classes = cache.getClassesByName(typeName, searchScope); Collection accessibleClasses = Collections2.filter(Lists.newArrayList(classes), new Predicate() { @Override @@ -214,14 +222,14 @@ public class AutoImportFix extends JetHintAction implem return PsiShortNamesCache.getInstance(jetFile.getProject()); } - private static Collection getJetClasses(@NotNull final String typeName, @NotNull Project project, @NotNull KotlinCodeAnalyzer resolveSession) { + private static Collection getJetClasses(@NotNull final String typeName, @NotNull GlobalSearchScope searchScope, @NotNull Project project, @NotNull KotlinCodeAnalyzer resolveSession) { JetShortNamesCache cache = JetShortNamesCache.getKotlinInstance(project); Collection descriptors = cache.getJetClassesDescriptors(new Condition() { @Override public boolean value(String s) { return typeName.equals(s); } - }, resolveSession, GlobalSearchScope.allScope(project)); + }, resolveSession, searchScope); return Collections2.transform(descriptors, new Function() { @Override