From 3910f31de9e23ca1c02f6c16563d09ad60dac13b Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Thu, 25 Aug 2016 20:11:42 +0300 Subject: [PATCH] Correct processing of "is" check --- .../destructuringDeclarationUsages.kt | 35 +++++++++++++++---- .../conventions/components/dataClass.2.kt | 1 + .../components/dataClass.results.txt | 3 +- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/destructuringDeclarationUsages.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/destructuringDeclarationUsages.kt index 07ff9a73543..883cc778268 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/destructuringDeclarationUsages.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/destructuringDeclarationUsages.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinRequestResultProcessor import org.jetbrains.kotlin.idea.search.restrictToKotlinSources +import org.jetbrains.kotlin.idea.search.unionSafe import org.jetbrains.kotlin.idea.util.FuzzyType import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType import org.jetbrains.kotlin.idea.util.toFuzzyType @@ -70,10 +71,7 @@ fun findDestructuringDeclarationUsages( ) { // for local scope it's faster to use plain search if (scope is LocalSearchScope) { - val unwrappedElement = ktDeclaration.namedUnwrappedElement ?: return - val resultProcessor = KotlinRequestResultProcessor(unwrappedElement, - filter = { ref -> ref is KtDestructuringDeclarationReference }) - optimizer.searchWord("(", scope.restrictToKotlinSources(), UsageSearchContext.IN_CODE, true, unwrappedElement, resultProcessor) + doPlainSearch(ktDeclaration, scope, optimizer) return } @@ -89,18 +87,32 @@ fun findDestructuringDeclarationUsages( classDescriptor.defaultType.toFuzzyType(classDescriptor.typeConstructor.parameters) } - Processor(dataType, ktDeclaration, scope, consumer).run() + Processor(dataType, + ktDeclaration, + scope, + consumer, + plainSearchHandler = { searchScope -> doPlainSearch(ktDeclaration, searchScope, optimizer) } + ).run() +} + +private fun doPlainSearch(ktDeclaration: KtDeclaration, scope: SearchScope, optimizer: SearchRequestCollector) { + val unwrappedElement = ktDeclaration.namedUnwrappedElement ?: return + val resultProcessor = KotlinRequestResultProcessor(unwrappedElement, + filter = { ref -> ref is KtDestructuringDeclarationReference }) + optimizer.searchWord("(", scope.restrictToKotlinSources(), UsageSearchContext.IN_CODE, true, unwrappedElement, resultProcessor) } private class Processor( private val dataType: FuzzyType, private val target: KtDeclaration, private val searchScope: SearchScope, - private val consumer: Processor + private val consumer: Processor, + private val plainSearchHandler: (SearchScope) -> Unit ) { private val project = target.project private val declarationsToSearch = ArrayList() private val declarationsToSearchSet = HashSet() + private var scopeToUsePlainSearch: SearchScope = LocalSearchScope.EMPTY fun run() { val dataClassDescriptor = dataType.type.constructor.declarationDescriptor ?: return @@ -135,6 +147,8 @@ private class Processor( val declaration = declarationsToSearch[index++] processDeclarationOfTypeWithDataClass(declaration) } + + plainSearchHandler(scopeToUsePlainSearch) } //TODO: check if it's operator (too expensive) @@ -200,7 +214,9 @@ private class Processor( } is KtIsExpression -> { - return true //TODO! + val scopeOfPossibleSmartCast = typeRefParent.getParentOfType(true) + scopeOfPossibleSmartCast?.let { usePlainSearch(it) } + return true } is KtBinaryExpressionWithTypeRHS -> { @@ -321,6 +337,11 @@ private class Processor( } } + private fun usePlainSearch(scopeElement: KtElement) { + scopeToUsePlainSearch = LocalSearchScope(scopeElement) + .intersectWith(searchScope) + .unionSafe(scopeToUsePlainSearch) + } private fun PsiModifierListOwner.isPrivateOrLocal(): Boolean { return hasModifierProperty(PsiModifier.PRIVATE) || parents.any { it is PsiCodeBlock } diff --git a/idea/testData/findUsages/kotlin/conventions/components/dataClass.2.kt b/idea/testData/findUsages/kotlin/conventions/components/dataClass.2.kt index b5f949e2922..7cd92d6ccfe 100644 --- a/idea/testData/findUsages/kotlin/conventions/components/dataClass.2.kt +++ b/idea/testData/findUsages/kotlin/conventions/components/dataClass.2.kt @@ -24,6 +24,7 @@ fun listOfA() = listOf(A(1, "", "")) fun x(o: Any) { if (o is A) { val (x, y) = o + val (x1, y1) = A(1, "", "") } } diff --git a/idea/testData/findUsages/kotlin/conventions/components/dataClass.results.txt b/idea/testData/findUsages/kotlin/conventions/components/dataClass.results.txt index 526015837be..fe2e13a98e7 100644 --- a/idea/testData/findUsages/kotlin/conventions/components/dataClass.results.txt +++ b/idea/testData/findUsages/kotlin/conventions/components/dataClass.results.txt @@ -6,7 +6,8 @@ [dataClass.2.kt] Value read 13 val (x4, y4, z4) = listOfA()[0] [dataClass.2.kt] Value read 15 val (x5, y5, z5) = javaClass.getA()[0] [dataClass.2.kt] Value read 26 val (x, y) = o -[dataClass.2.kt] Value read 32 val (x, y) = list[0] +[dataClass.2.kt] Value read 27 val (x1, y1) = A(1, "", "") +[dataClass.2.kt] Value read 33 val (x, y) = list[0] [dataClass.2.kt] Value read 5 a.n [dataClass.2.kt] Value read 8 val (x, y, z) = a [dataClass.2.kt] Value read 9 val (x1, y1, z1) = f() \ No newline at end of file