Fixed infinite recursion
This commit is contained in:
+36
-24
@@ -66,6 +66,10 @@ enum class DestructuringDeclarationUsageSearch {
|
||||
var destructuringDeclarationUsageSearchMode = if (ApplicationManager.getApplication().isUnitTestMode) ALWAYS_SMART else PLAIN_WHEN_NEEDED
|
||||
var destructuringDeclarationUsageSearchLog: MutableList<String>? = null
|
||||
|
||||
private object DestructuringDeclarationSearchesInProgress : ThreadLocal<HashSet<KtDeclaration>>() {
|
||||
override fun initialValue() = HashSet<KtDeclaration>()
|
||||
}
|
||||
|
||||
//TODO: check if it's too expensive
|
||||
|
||||
fun findDestructuringDeclarationUsages(
|
||||
@@ -85,35 +89,43 @@ fun findDestructuringDeclarationUsages(
|
||||
consumer: Processor<PsiReference>,
|
||||
optimizer: SearchRequestCollector
|
||||
) {
|
||||
val usePlainSearch = when (destructuringDeclarationUsageSearchMode) {
|
||||
ALWAYS_SMART -> false
|
||||
ALWAYS_PLAIN -> true
|
||||
PLAIN_WHEN_NEEDED -> scope is LocalSearchScope // for local scope it's faster to use plain search
|
||||
}
|
||||
if (usePlainSearch) {
|
||||
doPlainSearch(ktDeclaration, scope, optimizer)
|
||||
return
|
||||
}
|
||||
val inProgress = DestructuringDeclarationSearchesInProgress.get()
|
||||
try {
|
||||
if (!inProgress.add(ktDeclaration)) return
|
||||
|
||||
val descriptor = ktDeclaration.resolveToDescriptor() as? CallableDescriptor ?: return
|
||||
val usePlainSearch = when (destructuringDeclarationUsageSearchMode) {
|
||||
ALWAYS_SMART -> false
|
||||
ALWAYS_PLAIN -> true
|
||||
PLAIN_WHEN_NEEDED -> scope is LocalSearchScope // for local scope it's faster to use plain search
|
||||
}
|
||||
if (usePlainSearch) {
|
||||
doPlainSearch(ktDeclaration, scope, optimizer)
|
||||
return
|
||||
}
|
||||
|
||||
if (descriptor is FunctionDescriptor && !descriptor.isValidOperator()) return
|
||||
val descriptor = ktDeclaration.resolveToDescriptor() as? CallableDescriptor ?: return
|
||||
|
||||
val dataType = if (descriptor.isExtension) {
|
||||
descriptor.fuzzyExtensionReceiverType()!!
|
||||
if (descriptor is FunctionDescriptor && !descriptor.isValidOperator()) return
|
||||
|
||||
val dataType = if (descriptor.isExtension) {
|
||||
descriptor.fuzzyExtensionReceiverType()!!
|
||||
}
|
||||
else {
|
||||
val classDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return
|
||||
classDescriptor.defaultType.toFuzzyType(classDescriptor.typeConstructor.parameters)
|
||||
}
|
||||
|
||||
Processor(dataType,
|
||||
ktDeclaration,
|
||||
scope,
|
||||
consumer,
|
||||
plainSearchHandler = { searchScope -> doPlainSearch(ktDeclaration, searchScope, optimizer) },
|
||||
testLog = destructuringDeclarationUsageSearchLog
|
||||
).run()
|
||||
}
|
||||
else {
|
||||
val classDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return
|
||||
classDescriptor.defaultType.toFuzzyType(classDescriptor.typeConstructor.parameters)
|
||||
finally {
|
||||
inProgress.remove(ktDeclaration)
|
||||
}
|
||||
|
||||
Processor(dataType,
|
||||
ktDeclaration,
|
||||
scope,
|
||||
consumer,
|
||||
plainSearchHandler = { searchScope -> doPlainSearch(ktDeclaration, searchScope, optimizer) },
|
||||
testLog = destructuringDeclarationUsageSearchLog
|
||||
).run()
|
||||
}
|
||||
|
||||
private fun doPlainSearch(ktDeclaration: KtDeclaration, scope: SearchScope, optimizer: SearchRequestCollector) {
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtParameter
|
||||
// OPTIONS: usages
|
||||
|
||||
data class A(val <caret>a: A?, val n: Int)
|
||||
|
||||
fun f(a: A) {
|
||||
val (a1, n1) = a
|
||||
val (a2, n2) =
|
||||
a?.a ?: return
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
Checked type of (a1, n1)
|
||||
Checked type of (a2, n2)
|
||||
Checked type of (a2, n2)
|
||||
Searched inheritors of A
|
||||
Searched references to A
|
||||
Searched references to parameter a in A() in Kotlin files
|
||||
Searched references to parameter a in f() in Kotlin files
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:A
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
Value read 7 val (a1, n1) = a
|
||||
Value read 8 val (a2, n2) =
|
||||
Value read 9 a?.a ?: return
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtParameter
|
||||
// OPTIONS: usages
|
||||
|
||||
data class A(val <caret>b: B, val n: Int)
|
||||
data class B(val a: A?, val s: String)
|
||||
|
||||
fun f(a: A) {
|
||||
val (b, n) = a
|
||||
val (a1, s) = b
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
Checked type of (a1, s)
|
||||
Checked type of (b, n)
|
||||
Searched inheritors of A
|
||||
Searched inheritors of B
|
||||
Searched references to A
|
||||
Searched references to B
|
||||
Searched references to a1 in Kotlin files
|
||||
Searched references to b in Kotlin files
|
||||
Searched references to parameter a in B() in Kotlin files
|
||||
Searched references to parameter a in f() in Kotlin files
|
||||
Searched references to parameter b in A() in Kotlin files
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:A
|
||||
Used plain search in LocalSearchScope:
|
||||
CLASS:B
|
||||
+1
@@ -0,0 +1 @@
|
||||
Value read 8 val (b, n) = a
|
||||
@@ -254,6 +254,18 @@ public class FindUsagesTestGenerated extends AbstractFindUsagesTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("recursiveDataClass1.0.kt")
|
||||
public void testRecursiveDataClass1() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/conventions/components/recursiveDataClass1.0.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("recursiveDataClass2.0.kt")
|
||||
public void testRecursiveDataClass2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/conventions/components/recursiveDataClass2.0.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SAM.0.kt")
|
||||
public void testSAM() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/kotlin/conventions/components/SAM.0.kt");
|
||||
|
||||
Reference in New Issue
Block a user