diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt index 66fbb919009..ee7a58fb77f 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt @@ -158,7 +158,7 @@ abstract class CompletionSession( protected fun indicesHelper(mayIncludeInaccessible: Boolean): KotlinIndicesHelper { val filter = if (mayIncludeInaccessible) isVisibleFilter else isVisibleFilterCheckAlways - return KotlinIndicesHelper(resolutionFacade, searchScope, filter, visibilityFilterMayIncludeAccessible = mayIncludeInaccessible) + return KotlinIndicesHelper(resolutionFacade, searchScope, filter, filterOutPrivate = !mayIncludeInaccessible) } protected val toFromOriginalFileMapper: ToFromOriginalFileMapper @@ -394,9 +394,10 @@ abstract class CompletionSession( return callTypeAndReceiver.receiver == null } - protected fun getTopLevelCallables(): Collection { - return indicesHelper(true).getTopLevelCallables({ prefixMatcher.prefixMatches(it) }) - .filterShadowedNonImported() + protected fun getTopLevelCallables(): Collection { + val result = LinkedHashSet() + indicesHelper(true).processTopLevelCallables({ prefixMatcher.prefixMatches(it) }) { result.add(it) } + return result.filterShadowedNonImported() } protected fun CallTypeAndReceiver<*, *>.shouldCompleteCallableExtensions(): Boolean { diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt index 4a0f114881e..2c6381254d7 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt @@ -62,7 +62,7 @@ public class KotlinIndicesHelper( private val scope: GlobalSearchScope, visibilityFilter: (DeclarationDescriptor) -> Boolean, applyExcludeSettings: Boolean = true, - private val visibilityFilterMayIncludeAccessible: Boolean = false + private val filterOutPrivate: Boolean = true ) { private val moduleDescriptor = resolutionFacade.moduleDescriptor @@ -91,16 +91,26 @@ public class KotlinIndicesHelper( index.get(name, project, scope).filterTo(this) { it.getParent() is KtFile && it.getReceiverTypeReference() == null } } - public fun getTopLevelCallables(nameFilter: (String) -> Boolean): Collection { - return (KotlinTopLevelFunctionFqnNameIndex.getInstance().getAllKeys(project).asSequence() + - KotlinTopLevelPropertyFqnNameIndex.getInstance().getAllKeys(project).asSequence()) - .map { FqName(it) } - .filter { - ProgressManager.checkCanceled() - nameFilter(it.shortName().asString()) + public fun processTopLevelCallables(nameFilter: (String) -> Boolean, processor: (CallableDescriptor) -> Unit) { + fun processIndex(index: StringStubIndexExtension) { + for (key in index.getAllKeys(project)) { + ProgressManager.checkCanceled() + if (!nameFilter(key.substringAfterLast('.', key))) continue + + for (declaration in index.get(key, project, scope)) { + if (declaration.receiverTypeReference != null) continue + if (filterOutPrivate && declaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) continue + + for (descriptor in declaration.resolveToDescriptorsWithHack()) { + if (descriptorFilter(descriptor)) { + processor(descriptor) + } + } } - .toSet() - .flatMap { findTopLevelCallables(it).filter(descriptorFilter) } + } + } + processIndex(KotlinTopLevelFunctionFqnNameIndex.getInstance()) + processIndex(KotlinTopLevelPropertyFqnNameIndex.getInstance()) } public fun getCallableTopLevelExtensions( @@ -211,7 +221,7 @@ public class KotlinIndicesHelper( for (declaration in index.get(name, project, scope)) { val objectDeclaration = declaration.parent.parent as? KtObjectDeclaration ?: continue if (objectDeclaration.isObjectLiteral()) continue - if (!visibilityFilterMayIncludeAccessible && declaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) continue + if (filterOutPrivate && declaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) continue if (!filter(declaration, objectDeclaration)) continue for (descriptor in declaration.resolveToDescriptorsWithHack()) { if (descriptorKindFilter.accepts(descriptor) && descriptorFilter(descriptor)) { @@ -244,7 +254,7 @@ public class KotlinIndicesHelper( for (method in shortNamesCache.getMethodsByName(name, scope)) { if (!method.hasModifierProperty(PsiModifier.STATIC)) continue - if (!visibilityFilterMayIncludeAccessible && method.hasModifierProperty(PsiModifier.PRIVATE)) continue + if (filterOutPrivate && method.hasModifierProperty(PsiModifier.PRIVATE)) continue if (method.containingClass?.parent !is PsiFile) continue // only top-level classes val descriptor = method.getJavaMethodDescriptor(resolutionFacade) ?: continue val container = descriptor.containingDeclaration as? ClassDescriptor ?: continue @@ -268,7 +278,7 @@ public class KotlinIndicesHelper( for (field in shortNamesCache.getFieldsByName(name, scope)) { if (!field.hasModifierProperty(PsiModifier.STATIC)) continue - if (!visibilityFilterMayIncludeAccessible && field.hasModifierProperty(PsiModifier.PRIVATE)) continue + if (filterOutPrivate && field.hasModifierProperty(PsiModifier.PRIVATE)) continue val descriptor = field.getJavaFieldDescriptor() ?: continue if (descriptorKindFilter.accepts(descriptor) && descriptorFilter(descriptor)) { processor(descriptor) @@ -279,12 +289,6 @@ public class KotlinIndicesHelper( shortNamesCache.processAllFieldNames(fieldNamesProcessor, scope, idFilter) } - private fun findTopLevelCallables(fqName: FqName): Collection { - return resolutionFacade.resolveImportReference(moduleDescriptor, fqName) - .filterIsInstance() - .filter { it.getExtensionReceiverParameter() == null } - } - private fun isExcludedFromAutoImport(descriptor: DeclarationDescriptor): Boolean { val fqName = descriptor.importableFqName?.asString() ?: return false