From 957e7cd5f3cd9760bb2f6f0a65d412143b8c8a9a Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 11 Dec 2018 11:20:12 +0300 Subject: [PATCH] Optimize searching constructor delegation calls ^KT-28755 Fixed --- .../kotlin/idea/search/usagesSearch/utils.kt | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt index 50658004f3a..2aee725a841 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt @@ -25,6 +25,7 @@ import com.intellij.psi.search.SearchScope import com.intellij.psi.search.searches.MethodReferencesSearch import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.psi.util.MethodSignatureUtil +import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.toLightMethods @@ -146,7 +147,7 @@ private fun PsiElement.buildProcessDelegationCallKotlinConstructorUsagesTask( } if (klass !is KtClass || element !is KtDeclaration) return { true } - val descriptor = element.constructor ?: return { true } + val descriptor = lazyPub { element.constructor } if (!processClassDelegationCallsToSpecifiedConstructor(klass, descriptor, process)) return { false } @@ -163,7 +164,7 @@ private fun PsiElement.buildProcessDelegationCallJavaConstructorUsagesTask( if (this is KtLightMethod && this.kotlinOrigin == null) return { true } if (!(this is PsiMethod && isConstructor)) return { true } val klass = containingClass ?: return { true } - val descriptor = getJavaMethodDescriptor() as? ConstructorDescriptor ?: return { true } + val descriptor = lazyPub { getJavaMethodDescriptor() as? ConstructorDescriptor } return { processInheritorsDelegatingCallToSpecifiedConstructor(klass, scope, descriptor, process) } } @@ -171,14 +172,14 @@ private fun PsiElement.buildProcessDelegationCallJavaConstructorUsagesTask( private fun processInheritorsDelegatingCallToSpecifiedConstructor( klass: PsiElement, scope: SearchScope, - descriptor: ConstructorDescriptor, + lazyDescriptor: Lazy, process: (KtCallElement) -> Boolean ): Boolean { return HierarchySearchRequest(klass, scope, false).searchInheritors().all { runReadAction { val unwrapped = it.takeIf { it.isValid }?.unwrapped if (unwrapped is KtClass) - processClassDelegationCallsToSpecifiedConstructor(unwrapped, descriptor, process) + processClassDelegationCallsToSpecifiedConstructor(unwrapped, lazyDescriptor, process) else true } @@ -186,19 +187,30 @@ private fun processInheritorsDelegatingCallToSpecifiedConstructor( } private fun processClassDelegationCallsToSpecifiedConstructor( - klass: KtClass, constructor: DeclarationDescriptor, process: (KtCallElement) -> Boolean + klass: KtClass, + lazyDescriptor: Lazy, + process: (KtCallElement) -> Boolean ): Boolean { for (secondaryConstructor in klass.secondaryConstructors) { - val delegationCallDescriptor = secondaryConstructor.getDelegationCall().getConstructorCallDescriptor() - if (constructor == delegationCallDescriptor) { + val delegationCallDescriptor = + secondaryConstructor.getDelegationCall().getConstructorCallDescriptor() + ?: continue + + if (lazyDescriptor.value == delegationCallDescriptor) { if (!process(secondaryConstructor.getDelegationCall())) return false } } if (!klass.isEnum()) return true for (declaration in klass.declarations) { if (declaration is KtEnumEntry) { - val delegationCall = declaration.superTypeListEntries.firstOrNull() - if (delegationCall is KtSuperTypeCallEntry && constructor == delegationCall.calleeExpression.getConstructorCallDescriptor()) { + val delegationCall = + declaration.superTypeListEntries.firstOrNull() as? KtSuperTypeCallEntry + ?: continue + val constructorCallDescriptor = + delegationCall.calleeExpression.getConstructorCallDescriptor() + ?: continue + + if (lazyDescriptor.value == constructorCallDescriptor) { if (!process(delegationCall)) return false } }