diff --git a/idea/src/org/jetbrains/jet/plugin/caches/KotlinIndicesHelper.kt b/idea/src/org/jetbrains/jet/plugin/caches/KotlinIndicesHelper.kt index 9401c5e27d9..1bc9d29bd82 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/KotlinIndicesHelper.kt +++ b/idea/src/org/jetbrains/jet/plugin/caches/KotlinIndicesHelper.kt @@ -42,6 +42,8 @@ public class KotlinIndicesHelper(private val project: Project, private val resolveSession: ResolveSessionForBodies, private val scope: GlobalSearchScope, private val visibilityFilter: (DeclarationDescriptor) -> Boolean) { + private val moduleDescriptor = resolveSession.getModuleDescriptor() + public fun getTopLevelObjects(nameFilter: (String) -> Boolean): Collection { val allObjectNames = JetTopLevelObjectShortNameIndex.getInstance().getAllKeys(project).stream() + JetFromJavaDescriptorHelper.getPossiblePackageDeclarationsNames(project, scope).stream() @@ -57,13 +59,13 @@ public class KotlinIndicesHelper(private val project: Project, val topObjects = JetTopLevelObjectShortNameIndex.getInstance().get(name, project, scope) for (objectDeclaration in topObjects) { val fqName = objectDeclaration.getFqName() ?: error("Local object declaration in JetTopLevelShortObjectNameIndex:${objectDeclaration.getText()}") - result.addAll(ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(resolveSession.getModuleDescriptor(), fqName, ResolveSessionUtils.SINGLETON_FILTER)) + result.addAll(ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(moduleDescriptor, fqName, ResolveSessionUtils.SINGLETON_FILTER)) } for (psiClass in JetFromJavaDescriptorHelper.getCompiledClassesForTopLevelObjects(project, scope)) { val qualifiedName = psiClass.getQualifiedName() if (qualifiedName != null) { - result.addAll(ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(resolveSession.getModuleDescriptor(), FqName(qualifiedName), ResolveSessionUtils.SINGLETON_FILTER)) + result.addAll(ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(moduleDescriptor, FqName(qualifiedName), ResolveSessionUtils.SINGLETON_FILTER)) } } @@ -99,7 +101,7 @@ public class KotlinIndicesHelper(private val project: Project, .toSet() for (affectedPackage in affectedPackages) { - val packageDescriptor = resolveSession.getModuleDescriptor().getPackage(affectedPackage) + val packageDescriptor = moduleDescriptor.getPackage(affectedPackage) ?: error("There's a function in stub index with invalid package: $affectedPackage") addAll(packageDescriptor.getMemberScope().getFunctions(identifier)) } @@ -115,7 +117,7 @@ public class KotlinIndicesHelper(private val project: Project, .toSet() for (affectedPackage in affectedPackages) { - val packageDescriptor = resolveSession.getModuleDescriptor().getPackage(affectedPackage) + val packageDescriptor = moduleDescriptor.getPackage(affectedPackage) ?: error("There's a property in stub index with invalid package: $affectedPackage") addAll(packageDescriptor.getMemberScope().getProperties(identifier)) } @@ -153,7 +155,7 @@ public class KotlinIndicesHelper(private val project: Project, val receiverValue = ExpressionReceiver(receiverExpression, expressionType) return matchingFqNames.flatMap { - findSuitableExtensions(it, receiverValue, dataFlowInfo, isInfixCall, resolutionScope, resolveSession.getModuleDescriptor(), bindingContext) + findSuitableExtensions(it, receiverValue, dataFlowInfo, isInfixCall, resolutionScope, moduleDescriptor, bindingContext) } } else { @@ -162,7 +164,7 @@ public class KotlinIndicesHelper(private val project: Project, val result = HashSet() for (receiver in resolutionScope.getImplicitReceiversHierarchy()) { matchingFqNames.flatMapTo(result) { - findSuitableExtensions(it, receiver.getValue(), dataFlowInfo, false, resolutionScope, resolveSession.getModuleDescriptor(), bindingContext) + findSuitableExtensions(it, receiver.getValue(), dataFlowInfo, false, resolutionScope, moduleDescriptor, bindingContext) } } return result @@ -190,29 +192,30 @@ public class KotlinIndicesHelper(private val project: Project, ExpressionTypingUtils.checkIsExtensionCallable(receiverValue, it, isInfixCall, bindingContext, dataFlowInfo) } } - public fun getClassDescriptors(nameFilter: (String) -> Boolean): Collection { + public fun getClassDescriptors(nameFilter: (String) -> Boolean, kindFilter: (ClassKind) -> Boolean): Collection { return JetFullClassNameIndex.getInstance().getAllKeys(project).stream() .map { FqName(it) } .filter { nameFilter(it.shortName().asString()) } .toList() - .flatMap { getClassDescriptorsByFQName(it) } + .flatMap { getClassDescriptorsByFQName(it, kindFilter) } } - private fun getClassDescriptorsByFQName(classFQName: FqName): Collection { - val jetClassOrObjects = JetFullClassNameIndex.getInstance().get(classFQName.asString(), project, scope) + private fun getClassDescriptorsByFQName(classFQName: FqName, kindFilter: (ClassKind) -> Boolean): Collection { + val declarations = JetFullClassNameIndex.getInstance()[classFQName.asString(), project, scope] - if (jetClassOrObjects.isEmpty()) { + if (declarations.isEmpty()) { // This fqn is absent in caches, dead or not in scope return listOf() } // Note: Can't search with psi element as analyzer could be built over temp files - return ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession.getModuleDescriptor(), classFQName).filter(visibilityFilter) + return ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(moduleDescriptor, classFQName) { kindFilter(it.getKind()) } + .filter(visibilityFilter) } private fun findTopLevelCallables(fqName: FqName, context: JetExpression, jetScope: JetScope): Collection { val importDirective = JetPsiFactory(context.getProject()).createImportDirective(ImportPath(fqName, false)) - val allDescriptors = analyzeImportReference(importDirective, jetScope, BindingTraceContext(), resolveSession.getModuleDescriptor()) + val allDescriptors = analyzeImportReference(importDirective, jetScope, BindingTraceContext(), moduleDescriptor) return allDescriptors.filterIsInstance(javaClass()).filter { it.getExtensionReceiverParameter() == null } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/TypesCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt similarity index 66% rename from idea/src/org/jetbrains/jet/plugin/completion/TypesCompletion.kt rename to idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt index 034e0d8e799..e4dff9bff6f 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/TypesCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt @@ -31,18 +31,20 @@ import org.jetbrains.jet.plugin.project.ResolveSessionForBodies import org.jetbrains.jet.plugin.caches.KotlinIndicesHelper import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor -class TypesCompletion(val parameters: CompletionParameters, - val resolveSession: ResolveSessionForBodies, - val prefixMatcher: PrefixMatcher, - val visibilityFilter: (DeclarationDescriptor) -> Boolean) { - fun addAllTypes(result: LookupElementsCollector) { - result.addDescriptorElements(KotlinBuiltIns.getInstance().getNonPhysicalClasses().filter { prefixMatcher.prefixMatches(it.getName().asString()) }, - suppressAutoInsertion = true) +class AllClassesCompletion(val parameters: CompletionParameters, + val resolveSession: ResolveSessionForBodies, + val prefixMatcher: PrefixMatcher, + val kindFilter: (ClassKind) -> Boolean, + val visibilityFilter: (DeclarationDescriptor) -> Boolean) { + fun collect(result: LookupElementsCollector) { + val builtIns = KotlinBuiltIns.getInstance().getNonPhysicalClasses().filter { kindFilter(it.getKind()) && prefixMatcher.prefixMatches(it.getName().asString()) } + result.addDescriptorElements(builtIns, suppressAutoInsertion = true) val file = parameters.getOriginalFile() val project = file.getProject() val searchScope = file.getResolveScope() - result.addDescriptorElements(KotlinIndicesHelper(project, resolveSession, searchScope, visibilityFilter).getClassDescriptors { prefixMatcher.prefixMatches(it) }, + val helper = KotlinIndicesHelper(project, resolveSession, searchScope, visibilityFilter) + result.addDescriptorElements(helper.getClassDescriptors({ prefixMatcher.prefixMatches(it) }, kindFilter), suppressAutoInsertion = true) if (!ProjectStructureUtil.isJsKotlinModule(file as JetFile)) { @@ -60,14 +62,22 @@ class TypesCompletion(val parameters: CompletionParameters, addLookupElementForCompiledKotlinClass(psiClass, collector) } else if (!JavaResolverUtils.isCompiledKotlinPackageClass(psiClass)) { - collector.addElementWithAutoInsertionSuppressed(KotlinLookupElementFactory.createLookupElementForJavaClass(psiClass)) + val kind = when { + psiClass.isAnnotationType() -> ClassKind.ANNOTATION_CLASS + psiClass.isInterface() -> ClassKind.TRAIT + psiClass.isEnum() -> ClassKind.ENUM_CLASS + else -> ClassKind.CLASS + } + if (kindFilter(kind)) { + collector.addElementWithAutoInsertionSuppressed(KotlinLookupElementFactory.createLookupElementForJavaClass(psiClass)) + } } } }) } private fun addLookupElementForCompiledKotlinClass(aClass: PsiClass, collector: LookupElementsCollector) { - if (JetFromJavaDescriptorHelper.getCompiledClassKind(aClass) != ClassKind.CLASS_OBJECT) { + if (kindFilter(JetFromJavaDescriptorHelper.getCompiledClassKind(aClass))) { val qualifiedName = aClass.getQualifiedName() if (qualifiedName != null) { val descriptors = ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession.getModuleDescriptor(), FqName(qualifiedName)).filter(visibilityFilter) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt index 10121cc00ff..524b2a3d093 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt @@ -110,17 +110,20 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess return configuration.completeNonImportedDeclarations || prefixMatcher.getPrefix().length >= 3 } - protected fun getKotlinTopLevelDeclarations(): Collection { - val filter = { (name: String) -> prefixMatcher.prefixMatches(name) } - return indicesHelper.getTopLevelCallables(filter, jetReference!!.expression) + indicesHelper.getTopLevelObjects(filter) + protected fun getKotlinTopLevelCallables(): Collection { + return indicesHelper.getTopLevelCallables({ prefixMatcher.prefixMatches(it) }, jetReference!!.expression) + } + + protected fun getKotlinTopLevelObjects(): Collection { + return indicesHelper.getTopLevelObjects({ prefixMatcher.prefixMatches(it) }) } protected fun getKotlinExtensions(): Collection { return indicesHelper.getCallableExtensions({ prefixMatcher.prefixMatches(it) }, jetReference!!.expression) } - protected fun addAllTypes() { - TypesCompletion(parameters, resolveSession, prefixMatcher, { isVisibleDescriptor(it) }).addAllTypes(collector) + protected fun addAllClasses(kindFilter: (ClassKind) -> Boolean) { + AllClassesCompletion(parameters, resolveSession, prefixMatcher, kindFilter, { isVisibleDescriptor(it) }).collect(collector) } } @@ -138,7 +141,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, if (completeReference) { if (shouldRunOnlyTypeCompletion()) { if (configuration.completeNonImportedDeclarations) { - addAllTypes() + addAllClasses { !it.isSingleton() } } else { addReferenceVariants(JetScope.TYPE or JetScope.PACKAGE) @@ -164,8 +167,8 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, private fun addNonImported() { if (shouldRunTopLevelCompletion()) { - addAllTypes() - collector.addDescriptorElements(getKotlinTopLevelDeclarations(), suppressAutoInsertion = true) + addAllClasses { it != ClassKind.ENUM_ENTRY } + collector.addDescriptorElements(getKotlinTopLevelCallables(), suppressAutoInsertion = true) } if (shouldRunExtensionsCompletion()) { @@ -223,7 +226,8 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para private fun processNonImported(processor: (DeclarationDescriptor) -> Unit) { if (shouldRunTopLevelCompletion()) { - getKotlinTopLevelDeclarations().forEach(processor) + getKotlinTopLevelCallables().forEach(processor) + getKotlinTopLevelObjects().forEach(processor) //TODO: shouldn't it work via inheritors search? } if (shouldRunExtensionsCompletion()) {