diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IndexUtils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IndexUtils.kt index c5c45aaae50..af5230353d9 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IndexUtils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/IndexUtils.kt @@ -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 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, 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) { diff --git a/idea/testData/typealiasExpansionIndex/recursion.kt b/idea/testData/typealiasExpansionIndex/recursion.kt new file mode 100644 index 00000000000..30a6d5685d5 --- /dev/null +++ b/idea/testData/typealiasExpansionIndex/recursion.kt @@ -0,0 +1 @@ +//fun T.some() {} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/KotlinTypeAliasByExpansionShortNameIndexTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/KotlinTypeAliasByExpansionShortNameIndexTestGenerated.java index ff3417e392b..1e91afb01f7 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/KotlinTypeAliasByExpansionShortNameIndexTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/KotlinTypeAliasByExpansionShortNameIndexTestGenerated.java @@ -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");