More efficient getting of top-level callables

This commit is contained in:
Valentin Kipyatkov
2015-11-06 13:33:32 +03:00
parent ae9482a36c
commit 5d56339aba
2 changed files with 28 additions and 23 deletions
@@ -158,7 +158,7 @@ abstract class CompletionSession(
protected fun indicesHelper(mayIncludeInaccessible: Boolean): KotlinIndicesHelper { protected fun indicesHelper(mayIncludeInaccessible: Boolean): KotlinIndicesHelper {
val filter = if (mayIncludeInaccessible) isVisibleFilter else isVisibleFilterCheckAlways 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 protected val toFromOriginalFileMapper: ToFromOriginalFileMapper
@@ -394,9 +394,10 @@ abstract class CompletionSession(
return callTypeAndReceiver.receiver == null return callTypeAndReceiver.receiver == null
} }
protected fun getTopLevelCallables(): Collection<DeclarationDescriptor> { protected fun getTopLevelCallables(): Collection<CallableDescriptor> {
return indicesHelper(true).getTopLevelCallables({ prefixMatcher.prefixMatches(it) }) val result = LinkedHashSet<CallableDescriptor>()
.filterShadowedNonImported() indicesHelper(true).processTopLevelCallables({ prefixMatcher.prefixMatches(it) }) { result.add(it) }
return result.filterShadowedNonImported()
} }
protected fun CallTypeAndReceiver<*, *>.shouldCompleteCallableExtensions(): Boolean { protected fun CallTypeAndReceiver<*, *>.shouldCompleteCallableExtensions(): Boolean {
@@ -62,7 +62,7 @@ public class KotlinIndicesHelper(
private val scope: GlobalSearchScope, private val scope: GlobalSearchScope,
visibilityFilter: (DeclarationDescriptor) -> Boolean, visibilityFilter: (DeclarationDescriptor) -> Boolean,
applyExcludeSettings: Boolean = true, applyExcludeSettings: Boolean = true,
private val visibilityFilterMayIncludeAccessible: Boolean = false private val filterOutPrivate: Boolean = true
) { ) {
private val moduleDescriptor = resolutionFacade.moduleDescriptor 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 } index.get(name, project, scope).filterTo(this) { it.getParent() is KtFile && it.getReceiverTypeReference() == null }
} }
public fun getTopLevelCallables(nameFilter: (String) -> Boolean): Collection<CallableDescriptor> { public fun processTopLevelCallables(nameFilter: (String) -> Boolean, processor: (CallableDescriptor) -> Unit) {
return (KotlinTopLevelFunctionFqnNameIndex.getInstance().getAllKeys(project).asSequence() + fun processIndex(index: StringStubIndexExtension<out KtCallableDeclaration>) {
KotlinTopLevelPropertyFqnNameIndex.getInstance().getAllKeys(project).asSequence()) for (key in index.getAllKeys(project)) {
.map { FqName(it) } ProgressManager.checkCanceled()
.filter { if (!nameFilter(key.substringAfterLast('.', key))) continue
ProgressManager.checkCanceled()
nameFilter(it.shortName().asString()) 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( public fun getCallableTopLevelExtensions(
@@ -211,7 +221,7 @@ public class KotlinIndicesHelper(
for (declaration in index.get(name, project, scope)) { for (declaration in index.get(name, project, scope)) {
val objectDeclaration = declaration.parent.parent as? KtObjectDeclaration ?: continue val objectDeclaration = declaration.parent.parent as? KtObjectDeclaration ?: continue
if (objectDeclaration.isObjectLiteral()) 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 if (!filter(declaration, objectDeclaration)) continue
for (descriptor in declaration.resolveToDescriptorsWithHack()) { for (descriptor in declaration.resolveToDescriptorsWithHack()) {
if (descriptorKindFilter.accepts(descriptor) && descriptorFilter(descriptor)) { if (descriptorKindFilter.accepts(descriptor) && descriptorFilter(descriptor)) {
@@ -244,7 +254,7 @@ public class KotlinIndicesHelper(
for (method in shortNamesCache.getMethodsByName(name, scope)) { for (method in shortNamesCache.getMethodsByName(name, scope)) {
if (!method.hasModifierProperty(PsiModifier.STATIC)) continue 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 if (method.containingClass?.parent !is PsiFile) continue // only top-level classes
val descriptor = method.getJavaMethodDescriptor(resolutionFacade) ?: continue val descriptor = method.getJavaMethodDescriptor(resolutionFacade) ?: continue
val container = descriptor.containingDeclaration as? ClassDescriptor ?: continue val container = descriptor.containingDeclaration as? ClassDescriptor ?: continue
@@ -268,7 +278,7 @@ public class KotlinIndicesHelper(
for (field in shortNamesCache.getFieldsByName(name, scope)) { for (field in shortNamesCache.getFieldsByName(name, scope)) {
if (!field.hasModifierProperty(PsiModifier.STATIC)) continue 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 val descriptor = field.getJavaFieldDescriptor() ?: continue
if (descriptorKindFilter.accepts(descriptor) && descriptorFilter(descriptor)) { if (descriptorKindFilter.accepts(descriptor) && descriptorFilter(descriptor)) {
processor(descriptor) processor(descriptor)
@@ -279,12 +289,6 @@ public class KotlinIndicesHelper(
shortNamesCache.processAllFieldNames(fieldNamesProcessor, scope, idFilter) shortNamesCache.processAllFieldNames(fieldNamesProcessor, scope, idFilter)
} }
private fun findTopLevelCallables(fqName: FqName): Collection<CallableDescriptor> {
return resolutionFacade.resolveImportReference(moduleDescriptor, fqName)
.filterIsInstance<CallableDescriptor>()
.filter { it.getExtensionReceiverParameter() == null }
}
private fun isExcludedFromAutoImport(descriptor: DeclarationDescriptor): Boolean { private fun isExcludedFromAutoImport(descriptor: DeclarationDescriptor): Boolean {
val fqName = descriptor.importableFqName?.asString() ?: return false val fqName = descriptor.importableFqName?.asString() ?: return false