Fix infinite recursion during indexing types (EA-86494)

This commit is contained in:
Nikolay Krasko
2019-01-30 17:47:01 +03:00
parent d95189281d
commit 726e18333d
3 changed files with 59 additions and 33 deletions
@@ -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) {
+1
View File
@@ -0,0 +1 @@
//fun <T: T> T.some() {}
@@ -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");