Down-shifting to plain search when operator usage search required
This commit is contained in:
+29
-2
@@ -48,6 +48,7 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
|||||||
import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
|
import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
|
||||||
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
||||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
|
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
|
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
@@ -59,7 +60,9 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
enum class DestructuringDeclarationUsageSearch {
|
enum class DestructuringDeclarationUsageSearch {
|
||||||
ALWAYS_SMART, ALWAYS_PLAIN, PLAIN_WHEN_NEEDED
|
ALWAYS_SMART,
|
||||||
|
ALWAYS_PLAIN,
|
||||||
|
PLAIN_WHEN_NEEDED // use plain search for LocalSearchScope and when unknown type of reference encountered
|
||||||
}
|
}
|
||||||
|
|
||||||
// for tests
|
// for tests
|
||||||
@@ -223,12 +226,18 @@ private class Processor(
|
|||||||
PROCESS_LAMBDAS
|
PROCESS_LAMBDAS
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: check if it's operator (too expensive)
|
|
||||||
/**
|
/**
|
||||||
* Adds declaration whose type is our data class (or data class used anywhere inside that type)
|
* Adds declaration whose type is our data class (or data class used anywhere inside that type)
|
||||||
* or which has parameter of functional type with our data class used inside
|
* or which has parameter of functional type with our data class used inside
|
||||||
*/
|
*/
|
||||||
private fun addCallableDeclarationToProcess(declaration: PsiElement, kind: CallableToProcessKind) {
|
private fun addCallableDeclarationToProcess(declaration: PsiElement, kind: CallableToProcessKind) {
|
||||||
|
if (declaration.isOperatorExpensiveToSearch()) { // cancel all tasks and use plain search
|
||||||
|
tasks.clear()
|
||||||
|
scopesToUsePlainSearch.clear()
|
||||||
|
plainSearchHandler(searchScope)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
data class ProcessCallableUsagesTask(val declaration: PsiElement, val kind: CallableToProcessKind) : Task {
|
data class ProcessCallableUsagesTask(val declaration: PsiElement, val kind: CallableToProcessKind) : Task {
|
||||||
override fun perform() {
|
override fun perform() {
|
||||||
// we don't need to search usages of declarations in Java because Java doesn't have implicitly typed declarations so such usages cannot affect Kotlin code
|
// we don't need to search usages of declarations in Java because Java doesn't have implicitly typed declarations so such usages cannot affect Kotlin code
|
||||||
@@ -621,6 +630,24 @@ private class Processor(
|
|||||||
return hasModifierProperty(PsiModifier.PRIVATE) || parents.any { it is PsiCodeBlock }
|
return hasModifierProperty(PsiModifier.PRIVATE) || parents.any { it is PsiCodeBlock }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun PsiElement.isOperatorExpensiveToSearch(): Boolean {
|
||||||
|
when (this) {
|
||||||
|
is KtFunction -> {
|
||||||
|
if (name?.startsWith("component") == true) return false // component functions are not so expensive to search
|
||||||
|
return hasModifier(KtTokens.OPERATOR_KEYWORD)
|
||||||
|
|| hasModifier(KtTokens.OVERRIDE_KEYWORD) && (resolveToDescriptorIfAny() as? FunctionDescriptor)?.isOperator == true
|
||||||
|
}
|
||||||
|
|
||||||
|
is KtLightMethod -> {
|
||||||
|
return kotlinOrigin?.isOperatorExpensiveToSearch() == true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun KotlinType.containsTypeOrDerivedInside(type: FuzzyType): Boolean {
|
private fun KotlinType.containsTypeOrDerivedInside(type: FuzzyType): Boolean {
|
||||||
return type.checkIsSuperTypeOf(this) != null || arguments.any { it.type.containsTypeOrDerivedInside(type) }
|
return type.checkIsSuperTypeOf(this) != null || arguments.any { it.type.containsTypeOrDerivedInside(type) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtParameter
|
||||||
|
// OPTIONS: usages
|
||||||
|
|
||||||
|
data class A(val <caret>x: Int, val y: Int) {
|
||||||
|
fun f() {
|
||||||
|
val (x, y) = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B
|
||||||
|
|
||||||
|
operator fun B.plus(other: B): A = TODO()
|
||||||
|
|
||||||
|
fun f(b1: B, b2: B) {
|
||||||
|
val (x, y) = b1 + b2
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
Searched inheritors of A
|
||||||
|
Searched references to A
|
||||||
|
Used plain search in LocalSearchScope:
|
||||||
|
CLASS:A
|
||||||
|
Used plain search in whole search scope
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Value read 15 val (x, y) = b1 + b2
|
||||||
|
Value read 6 val (x, y) = this
|
||||||
@@ -254,6 +254,12 @@ public class FindUsagesTestGenerated extends AbstractFindUsagesTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("operators.0.kt")
|
||||||
|
public void testOperators() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/conventions/components/operators.0.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("recursiveDataClass1.0.kt")
|
@TestMetadata("recursiveDataClass1.0.kt")
|
||||||
public void testRecursiveDataClass1() throws Exception {
|
public void testRecursiveDataClass1() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/conventions/components/recursiveDataClass1.0.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/conventions/components/recursiveDataClass1.0.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user