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 com.intellij.psi.stubs.IndexSink
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.* 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.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.util.aliasImportMap import org.jetbrains.kotlin.util.aliasImportMap
@@ -27,10 +30,12 @@ fun <TDeclaration : KtCallableDeclaration> indexTopLevelExtension(stub: KotlinCa
if (stub.isExtension()) { if (stub.isExtension()) {
val declaration = stub.psi val declaration = stub.psi
val containingTypeReference = declaration.receiverTypeReference!! val containingTypeReference = declaration.receiverTypeReference!!
containingTypeReference.typeElement?.index(declaration, containingTypeReference) { typeName -> index(containingTypeReference.typeElement, declaration, containingTypeReference) { typeName ->
val name = declaration.name ?: return@index val name = declaration.name ?: return@index
sink.occurrence(KotlinTopLevelExtensionsByReceiverTypeIndex.INSTANCE.key, sink.occurrence(
KotlinTopLevelExtensionsByReceiverTypeIndex.buildKey(typeName, name)) KotlinTopLevelExtensionsByReceiverTypeIndex.INSTANCE.key,
KotlinTopLevelExtensionsByReceiverTypeIndex.buildKey(typeName, name)
)
} }
} }
} }
@@ -39,53 +44,68 @@ fun indexTypeAliasExpansion(stub: KotlinTypeAliasStub, sink: IndexSink) {
val declaration = stub.psi val declaration = stub.psi
val typeReference = declaration.getTypeReference() ?: return val typeReference = declaration.getTypeReference() ?: return
val typeElement = typeReference.typeElement ?: return val typeElement = typeReference.typeElement ?: return
typeElement.index(declaration, typeReference) { typeName -> index(typeElement, declaration, typeReference) { typeName ->
sink.occurrence(KotlinTypeAliasByExpansionShortNameIndex.KEY, 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, declaration: KtTypeParameterListOwner,
containingTypeReference: KtTypeReference, containingTypeReference: KtTypeReference,
visited: MutableSet<KtTypeElement>,
occurrence: (String) -> Unit occurrence: (String) -> Unit
) { ) {
when (this) { if (typeElement == null) return
is KtUserType -> { if (typeElement in visited) return
val referenceName = referencedName ?: return
val typeParameter = declaration.typeParameters.firstOrNull { it.name == referenceName } visited.add(typeElement)
if (typeParameter != null) {
val bound = typeParameter.extendsBound when (typeElement) {
if (bound != null) { is KtUserType -> {
bound.typeElement?.index(declaration, containingTypeReference, occurrence) 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") occurrence(referenceName)
}
return typeElement.aliasImportMap()[referenceName].forEach { occurrence(it) }
} }
occurrence(referenceName) is KtNullableType -> internalIndex(typeElement.innerType, declaration, containingTypeReference, visited, occurrence)
aliasImportMap()[referenceName].forEach { occurrence(it) } is KtFunctionType -> {
} val arity = typeElement.parameters.size + (if (typeElement.receiverTypeReference != null) 1 else 0)
val suspendPrefix =
is KtNullableType -> innerType?.index(declaration, containingTypeReference, occurrence)
is KtFunctionType -> {
val arity = parameters.size + (if (receiverTypeReference != null) 1 else 0)
val suspendPrefix =
if (containingTypeReference.modifierList?.hasModifier(KtTokens.SUSPEND_KEYWORD) == true) if (containingTypeReference.modifierList?.hasModifier(KtTokens.SUSPEND_KEYWORD) == true)
"Suspend" "Suspend"
else 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) { 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"); runTest("idea/testData/typealiasExpansionIndex/generics.kt");
} }
@TestMetadata("recursion.kt")
public void testRecursion() throws Exception {
runTest("idea/testData/typealiasExpansionIndex/recursion.kt");
}
@TestMetadata("simpleType.kt") @TestMetadata("simpleType.kt")
public void testSimpleType() throws Exception { public void testSimpleType() throws Exception {
runTest("idea/testData/typealiasExpansionIndex/simpleType.kt"); runTest("idea/testData/typealiasExpansionIndex/simpleType.kt");