Fix infinite recursion during indexing types (EA-86494)
This commit is contained in:
@@ -19,7 +19,10 @@ package org.jetbrains.kotlin.idea.stubindex
|
||||
import com.intellij.psi.stubs.IndexSink
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.stubs.*
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinCallableStubBase
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinModifierListStub
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinStubWithFqName
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinTypeAliasStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
import org.jetbrains.kotlin.util.aliasImportMap
|
||||
|
||||
@@ -27,10 +30,12 @@ fun <TDeclaration : KtCallableDeclaration> indexTopLevelExtension(stub: KotlinCa
|
||||
if (stub.isExtension()) {
|
||||
val declaration = stub.psi
|
||||
val containingTypeReference = declaration.receiverTypeReference!!
|
||||
containingTypeReference.typeElement?.index(declaration, containingTypeReference) { typeName ->
|
||||
index(containingTypeReference.typeElement, declaration, containingTypeReference) { typeName ->
|
||||
val name = declaration.name ?: return@index
|
||||
sink.occurrence(KotlinTopLevelExtensionsByReceiverTypeIndex.INSTANCE.key,
|
||||
KotlinTopLevelExtensionsByReceiverTypeIndex.buildKey(typeName, name))
|
||||
sink.occurrence(
|
||||
KotlinTopLevelExtensionsByReceiverTypeIndex.INSTANCE.key,
|
||||
KotlinTopLevelExtensionsByReceiverTypeIndex.buildKey(typeName, name)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,53 +44,68 @@ fun indexTypeAliasExpansion(stub: KotlinTypeAliasStub, sink: IndexSink) {
|
||||
val declaration = stub.psi
|
||||
val typeReference = declaration.getTypeReference() ?: return
|
||||
val typeElement = typeReference.typeElement ?: return
|
||||
typeElement.index(declaration, typeReference) { typeName ->
|
||||
index(typeElement, declaration, typeReference) { typeName ->
|
||||
sink.occurrence(KotlinTypeAliasByExpansionShortNameIndex.KEY, typeName)
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtTypeElement.index(
|
||||
private fun index(
|
||||
typeElement: KtTypeElement?,
|
||||
declaration: KtTypeParameterListOwner,
|
||||
containingTypeReference: KtTypeReference,
|
||||
occurrence: (String) -> Unit
|
||||
) {
|
||||
fun internalIndex(
|
||||
typeElement: KtTypeElement?,
|
||||
declaration: KtTypeParameterListOwner,
|
||||
containingTypeReference: KtTypeReference,
|
||||
visited: MutableSet<KtTypeElement>,
|
||||
occurrence: (String) -> Unit
|
||||
) {
|
||||
when (this) {
|
||||
is KtUserType -> {
|
||||
val referenceName = referencedName ?: return
|
||||
) {
|
||||
if (typeElement == null) return
|
||||
if (typeElement in visited) return
|
||||
|
||||
val typeParameter = declaration.typeParameters.firstOrNull { it.name == referenceName }
|
||||
if (typeParameter != null) {
|
||||
val bound = typeParameter.extendsBound
|
||||
if (bound != null) {
|
||||
bound.typeElement?.index(declaration, containingTypeReference, occurrence)
|
||||
visited.add(typeElement)
|
||||
|
||||
when (typeElement) {
|
||||
is KtUserType -> {
|
||||
val referenceName = typeElement.referencedName ?: return
|
||||
|
||||
val typeParameter = declaration.typeParameters.firstOrNull { it.name == referenceName }
|
||||
if (typeParameter != null) {
|
||||
val bound = typeParameter.extendsBound
|
||||
if (bound != null) {
|
||||
internalIndex(bound.typeElement, declaration, containingTypeReference, visited, occurrence)
|
||||
} else {
|
||||
occurrence("Any")
|
||||
}
|
||||
return
|
||||
}
|
||||
else {
|
||||
occurrence("Any")
|
||||
}
|
||||
return
|
||||
|
||||
occurrence(referenceName)
|
||||
|
||||
typeElement.aliasImportMap()[referenceName].forEach { occurrence(it) }
|
||||
}
|
||||
|
||||
occurrence(referenceName)
|
||||
is KtNullableType -> internalIndex(typeElement.innerType, declaration, containingTypeReference, visited, occurrence)
|
||||
|
||||
aliasImportMap()[referenceName].forEach { occurrence(it) }
|
||||
}
|
||||
|
||||
is KtNullableType -> innerType?.index(declaration, containingTypeReference, occurrence)
|
||||
|
||||
is KtFunctionType -> {
|
||||
val arity = parameters.size + (if (receiverTypeReference != null) 1 else 0)
|
||||
val suspendPrefix =
|
||||
is KtFunctionType -> {
|
||||
val arity = typeElement.parameters.size + (if (typeElement.receiverTypeReference != null) 1 else 0)
|
||||
val suspendPrefix =
|
||||
if (containingTypeReference.modifierList?.hasModifier(KtTokens.SUSPEND_KEYWORD) == true)
|
||||
"Suspend"
|
||||
else
|
||||
""
|
||||
occurrence("${suspendPrefix}Function$arity")
|
||||
occurrence("${suspendPrefix}Function$arity")
|
||||
}
|
||||
|
||||
is KtDynamicType -> occurrence("Any")
|
||||
|
||||
else -> error("Unsupported type: $typeElement")
|
||||
}
|
||||
|
||||
is KtDynamicType -> occurrence("Any")
|
||||
|
||||
else -> error("Unsupported type: $this")
|
||||
}
|
||||
|
||||
internalIndex(typeElement, declaration, containingTypeReference, mutableSetOf(), occurrence)
|
||||
}
|
||||
|
||||
fun indexInternals(stub: KotlinCallableStubBase<*>, sink: IndexSink) {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
//fun <T: T> T.some() {}
|
||||
Generated
+5
@@ -39,6 +39,11 @@ public class KotlinTypeAliasByExpansionShortNameIndexTestGenerated extends Abstr
|
||||
runTest("idea/testData/typealiasExpansionIndex/generics.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("recursion.kt")
|
||||
public void testRecursion() throws Exception {
|
||||
runTest("idea/testData/typealiasExpansionIndex/recursion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleType.kt")
|
||||
public void testSimpleType() throws Exception {
|
||||
runTest("idea/testData/typealiasExpansionIndex/simpleType.kt");
|
||||
|
||||
Reference in New Issue
Block a user