diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java index 2f2ffe87162..44b0049fb23 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java @@ -20,12 +20,12 @@ import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import kotlin.jvm.KotlinSignature; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.psi.codeFragmentUtil.CodeFragmentUtilPackage; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -51,6 +51,7 @@ public class QualifiedExpressionResolver { EVERYTHING } + @KotlinSignature( "fun analyseImportReference(importDirective: JetImportDirective, scope: JetScope, trace: BindingTrace, module: ModuleDescriptor): Collection") @NotNull public Collection analyseImportReference( @NotNull JetImportDirective importDirective, diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/stubindex/KotlinIndexUtil.java b/idea/idea-analysis/src/org/jetbrains/jet/plugin/stubindex/KotlinIndexUtil.java index 52a3cfabf7e..caec696c85a 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/stubindex/KotlinIndexUtil.java +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/stubindex/KotlinIndexUtil.java @@ -19,11 +19,10 @@ package org.jetbrains.jet.plugin.stubindex; import com.intellij.psi.PsiElement; import com.intellij.psi.stubs.StubIndexExtension; import com.intellij.psi.stubs.StubIndexKey; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; public class KotlinIndexUtil { - @NonNls + @NotNull public static StubIndexKey createIndexKey(@NotNull Class> indexClass) { return StubIndexKey.createIndexKey(indexClass.getCanonicalName()); } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.kt b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.kt index b76c2789e2c..7d1c44f635c 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.kt +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.kt @@ -18,7 +18,6 @@ package org.jetbrains.jet.plugin.caches import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Condition import com.intellij.psi.* import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.PsiShortNamesCache @@ -158,7 +157,7 @@ public class JetShortNamesCache(private val project: Project) : PsiShortNamesCac public fun getTopLevelFunctionDescriptorsByName(name: String, context: JetExpression /*TODO: to be dropped*/, resolveSession: ResolveSessionForBodies, scope: GlobalSearchScope): Collection { - val jetScope = resolveSession.resolveToElement(context).get(BindingContext.RESOLUTION_SCOPE, context) ?: return listOf() + val jetScope = resolveSession.resolveToElement(context).get(BindingContext.RESOLUTION_SCOPE, context) ?: return listOf() val result = hashSetOf() @@ -167,16 +166,22 @@ public class JetShortNamesCache(private val project: Project) : PsiShortNamesCac val topLevelFunctionFqNames = JetFromJavaDescriptorHelper.getTopLevelFunctionFqNames(project, scope, false) for (fqName in topLevelFunctionFqNames) { if (fqName.lastSegmentIs(identifier)) { - val importDirective = JetPsiFactory(context.getProject()).createImportDirective(ImportPath(fqName, false)) - val declarationDescriptors = QualifiedExpressionResolver().analyseImportReference(importDirective, jetScope, BindingTraceContext(), resolveSession.getModuleDescriptor()) - for (declarationDescriptor in declarationDescriptors) { - if (declarationDescriptor is FunctionDescriptor) { - result.add(declarationDescriptor as FunctionDescriptor) - } - } + findCompiledTopLevelEntities(fqName, context, jetScope, resolveSession).filterIsInstanceTo(result, javaClass()) } } + result.addJetSourceTopLevelFunctions(name, resolveSession, scope) + + return result + } + + private fun findCompiledTopLevelEntities(fqName: FqName, context: JetExpression, jetScope: JetScope, resolveSession: ResolveSessionForBodies): Collection { + val importDirective = JetPsiFactory(context.getProject()).createImportDirective(ImportPath(fqName, false)) + return QualifiedExpressionResolver().analyseImportReference(importDirective, jetScope, BindingTraceContext(), resolveSession.getModuleDescriptor()) + } + + private fun MutableCollection.addJetSourceTopLevelFunctions(name: String, resolveSession: ResolveSessionForBodies, scope: GlobalSearchScope) { + val identifier = Name.identifier(name) val affectedPackages = JetTopLevelNonExtensionFunctionShortNameIndex.getInstance().get(name, project, scope) .map { it.getContainingFile() } .filterIsInstance(javaClass()) @@ -186,36 +191,54 @@ public class JetShortNamesCache(private val project: Project) : PsiShortNamesCac for (affectedPackage in affectedPackages) { val packageDescriptor = resolveSession.getModuleDescriptor().getPackage(affectedPackage) ?: error("There's a function in stub index with invalid package: $affectedPackage") - result.addAll(packageDescriptor.getMemberScope().getFunctions(identifier)) + addAll(packageDescriptor.getMemberScope().getFunctions(identifier)) } - - return result } private fun getJetExtensionFunctionsByName(name: String, scope: GlobalSearchScope): Collection = JetTopLevelExtensionFunctionShortNameIndex.getInstance().get(name, project, scope) // TODO: Make it work for properties - public fun getJetCallableExtensions(nameFilter: (String) -> Boolean, expression: JetSimpleNameExpression, resolveSession: ResolveSessionForBodies, searchScope: GlobalSearchScope): Collection { + public fun getJetTopLevelCallables(nameFilter: (String) -> Boolean, context: JetExpression /*TODO: to be dropped*/, resolveSession: ResolveSessionForBodies, scope: GlobalSearchScope): Collection { + val result = ArrayList() + + JetTopLevelNonExtensionFunctionShortNameIndex.getInstance().getAllKeys(project) + .stream() + .filter(nameFilter) + .forEach { result.addJetSourceTopLevelFunctions(it, resolveSession, scope) } + + val jetScope = resolveSession.resolveToElement(context).get(BindingContext.RESOLUTION_SCOPE, context) ?: return listOf() + JetFromJavaDescriptorHelper.getTopLevelFunctionFqNames(project, scope, false) + .filter { nameFilter(it.shortName().asString()) } + .flatMapTo(result) { findCompiledTopLevelEntities(it, context, jetScope, resolveSession) } + + return result + } + + // TODO: Make it work for properties + public fun getJetCallableExtensions(nameFilter: (String) -> Boolean, + expression: JetSimpleNameExpression, + resolveSession: ResolveSessionForBodies, + scope: GlobalSearchScope): Collection { val context = resolveSession.resolveToElement(expression) val receiverExpression = expression.getReceiverExpression() ?: return listOf() val expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression) - val scope = context.get(BindingContext.RESOLUTION_SCOPE, receiverExpression) + val jetScope = context.get(BindingContext.RESOLUTION_SCOPE, receiverExpression) - if (expressionType == null || scope == null || expressionType.isError()) { + if (expressionType == null || jetScope == null || expressionType.isError()) { return listOf() } - val functionFQNs = extensionFunctionsFromSourceFqNames(nameFilter, searchScope) + val functionFQNs = extensionFunctionsFromSourceFqNames(nameFilter, scope) - JetFromJavaDescriptorHelper.getTopLevelFunctionFqNames(project, searchScope, true) + JetFromJavaDescriptorHelper.getTopLevelFunctionFqNames(project, scope, true) .filterTo(functionFQNs) { nameFilter(it.shortName().asString()) } // Iterate through the function with attempt to resolve found functions - return functionFQNs.flatMap { ExpressionTypingUtils.canFindSuitableCall(it, receiverExpression, expressionType, scope, resolveSession.getModuleDescriptor()) } + return functionFQNs.flatMap { ExpressionTypingUtils.canFindSuitableCall(it, receiverExpression, expressionType, jetScope, resolveSession.getModuleDescriptor()) } } - private fun extensionFunctionsFromSourceFqNames(nameFilter: (String) -> Boolean, searchScope: GlobalSearchScope): HashSet { + private fun extensionFunctionsFromSourceFqNames(nameFilter: (String) -> Boolean, scope: GlobalSearchScope): HashSet { val extensionFunctionNames = HashSet(JetTopLevelExtensionFunctionShortNameIndex.getInstance().getAllKeys(project)) val functionFQNs = HashSet() @@ -223,7 +246,7 @@ public class JetShortNamesCache(private val project: Project) : PsiShortNamesCac // Collect all possible extension function qualified names for (name in extensionFunctionNames) { if (nameFilter(name)) { - val extensionFunctions = getJetExtensionFunctionsByName(name, searchScope) + val extensionFunctions = getJetExtensionFunctionsByName(name, scope) for (extensionFunction in extensionFunctions) { if (extensionFunction is JetNamedFunction) { @@ -241,21 +264,21 @@ public class JetShortNamesCache(private val project: Project) : PsiShortNamesCac return functionFQNs } - public fun getJetClassesDescriptors(acceptedShortNameCondition: (String) -> Boolean, analyzer: KotlinCodeAnalyzer, searchScope: GlobalSearchScope): Collection { + public fun getJetClassesDescriptors(acceptedShortNameCondition: (String) -> Boolean, analyzer: KotlinCodeAnalyzer, scope: GlobalSearchScope): Collection { val classDescriptors = ArrayList() for (fqName in JetFullClassNameIndex.getInstance().getAllKeys(project)) { val classFQName = FqName(fqName) if (acceptedShortNameCondition(classFQName.shortName().asString())) { - classDescriptors.addAll(getJetClassesDescriptorsByFQName(analyzer, classFQName, searchScope)) + classDescriptors.addAll(getJetClassesDescriptorsByFQName(analyzer, classFQName, scope)) } } return classDescriptors } - private fun getJetClassesDescriptorsByFQName(analyzer: KotlinCodeAnalyzer, classFQName: FqName, searchScope: GlobalSearchScope): Collection { - val jetClassOrObjects = JetFullClassNameIndex.getInstance().get(classFQName.asString(), project, searchScope) + private fun getJetClassesDescriptorsByFQName(analyzer: KotlinCodeAnalyzer, classFQName: FqName, scope: GlobalSearchScope): Collection { + val jetClassOrObjects = JetFullClassNameIndex.getInstance().get(classFQName.asString(), project, scope) if (jetClassOrObjects.isEmpty()) { // This fqn is absent in caches, dead or not in scope diff --git a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt index 65e0abb0dcb..2e609f97ea4 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt @@ -129,8 +129,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, if (shouldRunTopLevelCompletion()) { TypesCompletion(parameters, resolveSession, prefixMatcher).addAllTypes(collector) - addKotlinTopLevelFunctions() - addKotlinTopLevelObjects() + addKotlinTopLevelDeclarations() } if (shouldRunExtensionsCompletion()) { @@ -155,15 +154,9 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, } } - private fun addKotlinTopLevelFunctions() { - for (name in shortNamesCache.getAllTopLevelFunctionNames()) { - if (prefixMatcher.prefixMatches(name)) { - collector.addDescriptorElements(shortNamesCache.getTopLevelFunctionDescriptorsByName(name, jetReference!!.expression, resolveSession, searchScope)) - } - } - } + private fun addKotlinTopLevelDeclarations() { + collector.addDescriptorElements(shortNamesCache.getJetTopLevelCallables({ prefixMatcher.prefixMatches(it) }, jetReference!!.expression, resolveSession, searchScope)) - private fun addKotlinTopLevelObjects() { for (name in shortNamesCache.getAllTopLevelObjectNames()) { if (prefixMatcher.prefixMatches(name)) { collector.addDescriptorElements(shortNamesCache.getTopLevelObjectsByName(name, resolveSession, searchScope))