Performance fix for Import Member

This commit is contained in:
Valentin Kipyatkov
2016-10-25 19:37:57 +03:00
parent d9ef8aa96f
commit 8c99b0e64c
2 changed files with 48 additions and 25 deletions
@@ -206,28 +206,41 @@ class KotlinIndicesHelper(
.toSet() .toSet()
} }
fun getJvmCallablesByName(name: String): Collection<CallableDescriptor> { fun processJvmCallablesByName(
name: String,
filter: (PsiMember) -> Boolean,
processor: (CallableDescriptor) -> Unit
) {
val javaDeclarations = PsiShortNamesCache.getInstance(project).getFieldsByName(name, scopeWithoutKotlin).asSequence() + val javaDeclarations = PsiShortNamesCache.getInstance(project).getFieldsByName(name, scopeWithoutKotlin).asSequence() +
PsiShortNamesCache.getInstance(project).getMethodsByName(name, scopeWithoutKotlin).asSequence() PsiShortNamesCache.getInstance(project).getMethodsByName(name, scopeWithoutKotlin).asSequence()
return javaDeclarations val processed = HashSet<CallableDescriptor>()
.filterNot { it is KtLightElement<*,*> } for (javaDeclaration in javaDeclarations) {
.mapNotNull { (it as PsiMember).getJavaMemberDescriptor(resolutionFacade) as? CallableDescriptor } ProgressManager.checkCanceled()
.filter(descriptorFilter) if (javaDeclaration is KtLightElement<*, *>) continue
.toSet() if (!filter(javaDeclaration as PsiMember)) continue
val descriptor = javaDeclaration.getJavaMemberDescriptor(resolutionFacade) as? CallableDescriptor ?: continue
if (!processed.add(descriptor)) continue
if (!descriptorFilter(descriptor)) continue
processor(descriptor)
}
} }
fun getKotlinCallablesByName(name: String): Collection<CallableDescriptor> { fun processKotlinCallablesByName(
val functions = KotlinFunctionShortNameIndex.getInstance().get(name, project, scope) name: String,
.asSequence() filter: (KtCallableDeclaration) -> Boolean,
.map { it.descriptor as? CallableDescriptor } processor: (CallableDescriptor) -> Unit
val properties = KotlinPropertyShortNameIndex.getInstance().get(name, project, scope) ) {
.asSequence() val functions: Sequence<KtCallableDeclaration> = KotlinFunctionShortNameIndex.getInstance().get(name, project, scope).asSequence()
.map { it.descriptor as? CallableDescriptor } val properties: Sequence<KtCallableDeclaration> = KotlinPropertyShortNameIndex.getInstance().get(name, project, scope).asSequence()
val processed = HashSet<CallableDescriptor>()
return (functions + properties) for (declaration in functions + properties) {
.filterNotNull() ProgressManager.checkCanceled()
.filter(descriptorFilter) if (!filter(declaration)) continue
.toSet() val descriptor = declaration.descriptor as? CallableDescriptor ?: continue
if (!processed.add(descriptor)) continue
if (!descriptorFilter(descriptor)) continue
processor(descriptor)
}
} }
fun getKotlinClasses(nameFilter: (String) -> Boolean, kindFilter: (ClassKind) -> Boolean): Collection<ClassDescriptor> { fun getKotlinClasses(nameFilter: (String) -> Boolean, kindFilter: (ClassKind) -> Boolean): Collection<ClassDescriptor> {
@@ -28,6 +28,7 @@ import com.intellij.packageDependencies.DependencyValidationManager
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiErrorElement import com.intellij.psi.PsiErrorElement
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.psi.PsiModifier
import com.intellij.psi.util.PsiModificationTracker import com.intellij.psi.util.PsiModificationTracker
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -62,7 +63,6 @@ import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils.isTopLevelDeclaration
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
@@ -393,14 +393,24 @@ internal class ImportMemberFix(expression: KtSimpleNameExpression) : ImportFixBa
if (!element.isImportDirectiveExpression() && !isSelectorInQualified(element)) { if (!element.isImportDirectiveExpression() && !isSelectorInQualified(element)) {
val filterByCallType = { descriptor: DeclarationDescriptor -> callTypeAndReceiver.callType.descriptorKindFilter.accepts(descriptor) } val filterByCallType = { descriptor: DeclarationDescriptor -> callTypeAndReceiver.callType.descriptorKindFilter.accepts(descriptor) }
indicesHelper.getKotlinCallablesByName(name) val processor = { descriptor: CallableDescriptor ->
.filter { it.canBeReferencedViaImport() && !isTopLevelDeclaration(it) } if (descriptor.canBeReferencedViaImport() && filterByCallType(descriptor)) {
.filterTo(result, filterByCallType) result.add(descriptor)
}
}
indicesHelper.processKotlinCallablesByName(
name,
filter = { declaration -> (declaration.parent as? KtClassBody)?.parent is KtObjectDeclaration },
processor = processor
)
if (!ProjectStructureUtil.isJsKotlinModule(element.getContainingKtFile())) { if (!ProjectStructureUtil.isJsKotlinModule(element.getContainingKtFile())) {
indicesHelper.getJvmCallablesByName(name) indicesHelper.processJvmCallablesByName(
.filter { it.canBeReferencedViaImport() } name,
.filterTo(result, filterByCallType) filter = { it.hasModifierProperty(PsiModifier.STATIC) },
processor = processor
)
} }
} }
return result return result