From c2ba4e3ab98fb6e550edca43c4da6b5648938ac7 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 27 Jan 2017 23:21:16 +0300 Subject: [PATCH] KT-14252 Completion could suggest constructors available via typealiases #KT-14252 fixed --- .../SamTypeAliasConstructorDescriptor.kt | 2 +- .../jetbrains/kotlin/util/descriptorUtils.kt | 17 +++- .../idea/completion/smart/SmartCompletion.kt | 2 +- .../smart/TypeInstantiationItems.kt | 77 ++++++++++++------- .../smart/ConstructorForGenericType.kt | 1 + .../smart/ConstructorForGenericType.kt.after | 4 +- .../smart/SAMConstructorForTypeAlias.kt | 13 ++++ .../constructor/ConstructorViaTypeAlias.kt | 13 ++++ ...eParamsPartialSubstitution1ViaTypeAlias.kt | 13 ++++ ...eParamsPartialSubstitution2ViaTypeAlias.kt | 13 ++++ ...rWithTypeParamsSubstitutionViaTypeAlias.kt | 13 ++++ .../ConstructorWithTypeParamsViaTypeAlias.kt | 13 ++++ .../test/JvmSmartCompletionTestGenerated.java | 36 +++++++++ .../kotlin/idea/core/KotlinIndicesHelper.kt | 17 ++-- 14 files changed, 197 insertions(+), 37 deletions(-) create mode 100644 idea/idea-completion/testData/smart/SAMConstructorForTypeAlias.kt create mode 100644 idea/idea-completion/testData/smart/constructor/ConstructorViaTypeAlias.kt create mode 100644 idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsPartialSubstitution1ViaTypeAlias.kt create mode 100644 idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsPartialSubstitution2ViaTypeAlias.kt create mode 100644 idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsSubstitutionViaTypeAlias.kt create mode 100644 idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsViaTypeAlias.kt diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/SamTypeAliasConstructorDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/SamTypeAliasConstructorDescriptor.kt index 1d009f2f9f2..71f687e38ce 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/SamTypeAliasConstructorDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/SamTypeAliasConstructorDescriptor.kt @@ -31,7 +31,7 @@ class SamTypeAliasConstructorDescriptorImpl( typeAliasDescriptor.containingDeclaration, null, samInterfaceConstructorDescriptor.baseDescriptorForSynthetic.annotations, - samInterfaceConstructorDescriptor.baseDescriptorForSynthetic.name, + typeAliasDescriptor.name, CallableMemberDescriptor.Kind.SYNTHESIZED, typeAliasDescriptor.source ), SamTypeAliasConstructorDescriptor { diff --git a/idea/ide-common/src/org/jetbrains/kotlin/util/descriptorUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/util/descriptorUtils.kt index 6bfe3d22295..728e82f93ed 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/util/descriptorUtils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/util/descriptorUtils.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.util import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE +import org.jetbrains.kotlin.resolve.calls.tower.getTypeAliasConstructors import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeConstructor @@ -76,4 +77,18 @@ fun TypeConstructor.supertypesWithAny(): Collection { .map { it.constructor.declarationDescriptor as? ClassDescriptor } .all { it == null || it.kind == ClassKind.INTERFACE } return if (noSuperClass) supertypes + builtIns.anyType else supertypes -} \ No newline at end of file +} + +val ClassifierDescriptorWithTypeParameters.constructors: Collection + get() = when (this) { + is TypeAliasDescriptor -> getTypeAliasConstructors() + is ClassDescriptor -> this.constructors + else -> emptyList() + } + +val ClassifierDescriptorWithTypeParameters.kind: ClassKind? + get() = when (this) { + is TypeAliasDescriptor -> classDescriptor?.kind + is ClassDescriptor -> kind + else -> null + } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt index b2ee7f72541..2f3f4bc62d4 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/SmartCompletion.kt @@ -210,7 +210,7 @@ class SmartCompletion( } if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) { - TypeInstantiationItems(resolutionFacade, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory, forBasicCompletion) + TypeInstantiationItems(resolutionFacade, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory, forBasicCompletion, indicesHelper) .addTo(items, inheritanceSearchers, expectedInfos) if (expression is KtSimpleNameExpression) { diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt index 99bd216f91b..3e191b9f85f 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/TypeInstantiationItems.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.completion.* import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler import org.jetbrains.kotlin.idea.core.ExpectedInfo +import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper import org.jetbrains.kotlin.idea.core.Tail import org.jetbrains.kotlin.idea.core.multipleFuzzyTypes import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler @@ -41,14 +42,17 @@ import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor +import org.jetbrains.kotlin.load.java.descriptors.SamTypeAliasConstructorDescriptor import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass +import org.jetbrains.kotlin.synthetic.JavaSyntheticConstructorsProvider import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.util.constructors +import org.jetbrains.kotlin.util.kind import org.jetbrains.kotlin.utils.addIfNotNull import java.util.* @@ -59,7 +63,8 @@ class TypeInstantiationItems( val toFromOriginalFileMapper: ToFromOriginalFileMapper, val inheritorSearchScope: GlobalSearchScope, val lookupElementFactory: LookupElementFactory, - val forOrdinaryCompletion: Boolean + val forOrdinaryCompletion: Boolean, + val indicesHelper: KotlinIndicesHelper ) { fun addTo( items: MutableCollection, @@ -87,22 +92,31 @@ class TypeInstantiationItems( ) { if (fuzzyType.type.isFunctionType) return // do not show "object: ..." for function types - val classifier = fuzzyType.type.constructor.declarationDescriptor - if (classifier !is ClassDescriptor) return + val classifier = fuzzyType.type.constructor.declarationDescriptor as? ClassifierDescriptorWithTypeParameters ?: return + val classDescriptor = when (classifier) { + is ClassDescriptor -> classifier + is TypeAliasDescriptor -> classifier.classDescriptor + else -> null + } - addSamConstructorItem(items, classifier, tail) + addSamConstructorItem(items, classifier, classDescriptor, tail) + items.addIfNotNull(createTypeInstantiationItem(fuzzyType, classDescriptor, tail)) - items.addIfNotNull(createTypeInstantiationItem(fuzzyType, tail)) + indicesHelper.resolveTypeAliasesUsingIndex(fuzzyType.type, classifier.name.asString()).forEach { + addSamConstructorItem(items, it, classDescriptor, tail) + val typeAliasFuzzyType = it.defaultType.toFuzzyType(fuzzyType.freeParameters) + items.addIfNotNull(createTypeInstantiationItem(typeAliasFuzzyType, classDescriptor, tail)) + } - if (!forOrdinaryCompletion && !KotlinBuiltIns.isAny(classifier)) { // do not search inheritors of Any + if (classDescriptor != null && !forOrdinaryCompletion && !KotlinBuiltIns.isAny(classDescriptor)) { // do not search inheritors of Any val typeArgs = fuzzyType.type.arguments - inheritanceSearchers.addInheritorSearcher(classifier, classifier, typeArgs, fuzzyType.freeParameters, tail) + inheritanceSearchers.addInheritorSearcher(classDescriptor, classDescriptor, typeArgs, fuzzyType.freeParameters, tail) val javaClassId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(DescriptorUtils.getFqName(classifier)) if (javaClassId != null) { val javaAnalog = resolutionFacade.moduleDescriptor.resolveTopLevelClass(javaClassId.asSingleFqName(), NoLookupLocation.FROM_IDE) if (javaAnalog != null) { - inheritanceSearchers.addInheritorSearcher(javaAnalog, classifier, typeArgs, fuzzyType.freeParameters, tail) + inheritanceSearchers.addInheritorSearcher(javaAnalog, classDescriptor, typeArgs, fuzzyType.freeParameters, tail) } } } @@ -125,8 +139,8 @@ class TypeInstantiationItems( add(InheritanceSearcher(psiClass, kotlinClassDescriptor, typeArgs, freeParameters, tail)) } - private fun createTypeInstantiationItem(fuzzyType: FuzzyType, tail: Tail?): LookupElement? { - val classifier = fuzzyType.type.constructor.declarationDescriptor as? ClassDescriptor ?: return null + private fun createTypeInstantiationItem(fuzzyType: FuzzyType, classDescriptor: ClassDescriptor?, tail: Tail?): LookupElement? { + val classifier = fuzzyType.type.constructor.declarationDescriptor as? ClassifierDescriptorWithTypeParameters ?: return null var lookupElement = lookupElementFactory.createLookupElement(classifier, useReceiverTypes = false) @@ -137,7 +151,7 @@ class TypeInstantiationItems( // not all inner classes can be instantiated and we handle them via constructors returned by ReferenceVariantsHelper if (classifier.isInner) return null - val isAbstract = classifier.modality == Modality.ABSTRACT + val isAbstract = classDescriptor?.modality == Modality.ABSTRACT if (forOrdinaryCompletion && isAbstract) return null val allConstructors = classifier.constructors @@ -286,21 +300,30 @@ class TypeInstantiationItems( return FuzzyType(this, freeParameters).freeParameters.isNotEmpty() } - private fun addSamConstructorItem(collection: MutableCollection, `class`: ClassDescriptor, tail: Tail?) { - if (`class`.kind == ClassKind.INTERFACE) { - val container = `class`.containingDeclaration - val scope = when (container) { - is PackageFragmentDescriptor -> container.getMemberScope() - is ClassDescriptor -> container.staticScope - else -> return + private fun addSamConstructorItem(collection: MutableCollection, + classifier: ClassifierDescriptorWithTypeParameters, + classDescriptor: ClassDescriptor?, + tail: Tail?) { + if (classDescriptor?.kind == ClassKind.INTERFACE) { + val samConstructor = if (classifier is TypeAliasDescriptor) { + JavaSyntheticConstructorsProvider.getSyntheticConstructors(classifier, NoLookupLocation.FROM_IDE) + .filterIsInstance() + .singleOrNull() ?: return } - val samConstructor = scope.getContributedFunctions(`class`.name, NoLookupLocation.FROM_IDE) - .filterIsInstance() - .singleOrNull() ?: return - lookupElementFactory.createStandardLookupElementsForDescriptor(samConstructor, useReceiverTypes = false) - .mapTo(collection) { - it.assignSmartCompletionPriority(SmartCompletionItemPriority.INSTANTIATION).addTail(tail) - } + else { + val container = classifier.containingDeclaration + val scope = when (container) { + is PackageFragmentDescriptor -> container.getMemberScope() + is ClassDescriptor -> container.staticScope + else -> return + } + scope.getContributedFunctions(classifier.name, NoLookupLocation.FROM_IDE) + .filterIsInstance() + .singleOrNull() ?: return + } + lookupElementFactory + .createStandardLookupElementsForDescriptor(samConstructor, useReceiverTypes = false) + .mapTo(collection) { it.assignSmartCompletionPriority(SmartCompletionItemPriority.INSTANTIATION).addTail(tail) } } } @@ -334,7 +357,7 @@ class TypeInstantiationItems( } } - val lookupElement = createTypeInstantiationItem(inheritorFuzzyType, tail) ?: continue + val lookupElement = createTypeInstantiationItem(inheritorFuzzyType, descriptor, tail) ?: continue consumer(lookupElement.assignSmartCompletionPriority(SmartCompletionItemPriority.INHERITOR_INSTANTIATION)) } } diff --git a/idea/idea-completion/testData/handlers/smart/ConstructorForGenericType.kt b/idea/idea-completion/testData/handlers/smart/ConstructorForGenericType.kt index 75e7138603e..9e021cd87aa 100644 --- a/idea/idea-completion/testData/handlers/smart/ConstructorForGenericType.kt +++ b/idea/idea-completion/testData/handlers/smart/ConstructorForGenericType.kt @@ -8,3 +8,4 @@ fun f(){ } // ELEMENT: HashMap +// TAIL_TEXT: (...) (kotlin.collections) diff --git a/idea/idea-completion/testData/handlers/smart/ConstructorForGenericType.kt.after b/idea/idea-completion/testData/handlers/smart/ConstructorForGenericType.kt.after index 7a85152b714..c69d7a63ae1 100644 --- a/idea/idea-completion/testData/handlers/smart/ConstructorForGenericType.kt.after +++ b/idea/idea-completion/testData/handlers/smart/ConstructorForGenericType.kt.after @@ -1,10 +1,12 @@ import java.util.HashMap import java.util.List +import kotlin.collections.HashMap fun foo(p: HashMap>){} fun f(){ - foo(HashMap()) + foo(HashMap()) } // ELEMENT: HashMap +// TAIL_TEXT: (...) (kotlin.collections) diff --git a/idea/idea-completion/testData/smart/SAMConstructorForTypeAlias.kt b/idea/idea-completion/testData/smart/SAMConstructorForTypeAlias.kt new file mode 100644 index 00000000000..b682279923e --- /dev/null +++ b/idea/idea-completion/testData/smart/SAMConstructorForTypeAlias.kt @@ -0,0 +1,13 @@ + +typealias TaRunnable = Runnable + + +fun usesRunnable(runnable: Runnable) { + +} + +fun usage() { + usesRunnable() +} + +// EXIST: {"lookupString":"TaRunnable","tailText":" {...} (function: () -> Unit) ()","typeText":"Runnable"} \ No newline at end of file diff --git a/idea/idea-completion/testData/smart/constructor/ConstructorViaTypeAlias.kt b/idea/idea-completion/testData/smart/constructor/ConstructorViaTypeAlias.kt new file mode 100644 index 00000000000..8d239e695af --- /dev/null +++ b/idea/idea-completion/testData/smart/constructor/ConstructorViaTypeAlias.kt @@ -0,0 +1,13 @@ +class SomeClass +typealias TaSomeClass = SomeClass + +fun usesSomeClass(p: SomeClass) { + +} + + +fun usage() { + usesSomeClass() +} + +// EXIST: {"lookupString":"TaSomeClass","tailText":"() ()"} \ No newline at end of file diff --git a/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsPartialSubstitution1ViaTypeAlias.kt b/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsPartialSubstitution1ViaTypeAlias.kt new file mode 100644 index 00000000000..502d5fc03d1 --- /dev/null +++ b/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsPartialSubstitution1ViaTypeAlias.kt @@ -0,0 +1,13 @@ +class SomeClass +typealias TaSomeClass = SomeClass + +fun usesSomeClass(p: SomeClass) { + +} + + +fun usage() { + usesSomeClass() +} + +// EXIST: {"lookupString":"TaSomeClass","tailText":"() ()","typeText":"SomeClass"} \ No newline at end of file diff --git a/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsPartialSubstitution2ViaTypeAlias.kt b/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsPartialSubstitution2ViaTypeAlias.kt new file mode 100644 index 00000000000..b47317a0c0a --- /dev/null +++ b/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsPartialSubstitution2ViaTypeAlias.kt @@ -0,0 +1,13 @@ +class SomeClass +typealias TaSomeClass = SomeClass + +fun usesSomeClass(p: SomeClass<*, *>) { + +} + + +fun usage() { + usesSomeClass() +} + +// EXIST: {"lookupString":"TaSomeClass","tailText":"() ()","typeText":"SomeClass"} \ No newline at end of file diff --git a/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsSubstitutionViaTypeAlias.kt b/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsSubstitutionViaTypeAlias.kt new file mode 100644 index 00000000000..8d7531a95eb --- /dev/null +++ b/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsSubstitutionViaTypeAlias.kt @@ -0,0 +1,13 @@ +class SomeClass +typealias TaSomeClass = SomeClass + +fun usesSomeClass(p: SomeClass<*, *>) { + +} + + +fun usage() { + usesSomeClass() +} + +// EXIST: {"lookupString":"TaSomeClass","tailText":"() ()","typeText":"SomeClass"} \ No newline at end of file diff --git a/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsViaTypeAlias.kt b/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsViaTypeAlias.kt new file mode 100644 index 00000000000..722560399f9 --- /dev/null +++ b/idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsViaTypeAlias.kt @@ -0,0 +1,13 @@ +class SomeClass +typealias TaSomeClass = SomeClass + +fun usesSomeClass(p: SomeClass<*, *>) { + +} + + +fun usage() { + usesSomeClass() +} + +// EXIST: {"lookupString":"TaSomeClass","tailText":"() ()","typeText":"SomeClass"} \ No newline at end of file diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java index 4f67fcdec53..b6a6cb1bdd4 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java @@ -498,6 +498,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT doTest(fileName); } + @TestMetadata("SAMConstructorForTypeAlias.kt") + public void testSAMConstructorForTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/SAMConstructorForTypeAlias.kt"); + doTest(fileName); + } + @TestMetadata("SAMExpected1.kt") public void testSAMExpected1() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/SAMExpected1.kt"); @@ -827,6 +833,36 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/smart/constructor"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("ConstructorViaTypeAlias.kt") + public void testConstructorViaTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/constructor/ConstructorViaTypeAlias.kt"); + doTest(fileName); + } + + @TestMetadata("ConstructorWithTypeParamsPartialSubstitution1ViaTypeAlias.kt") + public void testConstructorWithTypeParamsPartialSubstitution1ViaTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsPartialSubstitution1ViaTypeAlias.kt"); + doTest(fileName); + } + + @TestMetadata("ConstructorWithTypeParamsPartialSubstitution2ViaTypeAlias.kt") + public void testConstructorWithTypeParamsPartialSubstitution2ViaTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsPartialSubstitution2ViaTypeAlias.kt"); + doTest(fileName); + } + + @TestMetadata("ConstructorWithTypeParamsSubstitutionViaTypeAlias.kt") + public void testConstructorWithTypeParamsSubstitutionViaTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsSubstitutionViaTypeAlias.kt"); + doTest(fileName); + } + + @TestMetadata("ConstructorWithTypeParamsViaTypeAlias.kt") + public void testConstructorWithTypeParamsViaTypeAlias() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/constructor/ConstructorWithTypeParamsViaTypeAlias.kt"); + doTest(fileName); + } + @TestMetadata("GenericJavaClass.kt") public void testGenericJavaClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/constructor/GenericJavaClass.kt"); diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt index 6b22c10939b..e5414184096 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt @@ -49,6 +49,7 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.isHiddenInResolution import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.asSimpleType import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList import java.lang.reflect.Field import java.lang.reflect.Modifier @@ -175,29 +176,33 @@ class KotlinIndicesHelper( } - private fun resolveTypeAliasesUsingIndex(type: KotlinType, originalTypeName: String, out: MutableCollection) { + fun resolveTypeAliasesUsingIndex(type: KotlinType, originalTypeName: String): Set { + val typeConstructor = type.constructor + val index = KotlinTypeAliasByExpansionShortNameIndex.INSTANCE + val out = mutableSetOf() fun searchRecursively(typeName: String) { ProgressManager.checkCanceled() index[typeName, project, scope].asSequence() .map { it.resolveToDescriptorIfAny() as? TypeAliasDescriptor } .filterNotNull() - .filter { it.expandedType == type } - .map { it.name.asString() } + .filter { it.expandedType.constructor == typeConstructor } .filter { it !in out } - .onEach(::searchRecursively) - .toCollection(out) + .onEach { out.add(it) } + .map { it.name.asString() } + .forEach(::searchRecursively) } searchRecursively(originalTypeName) + return out } private fun MutableCollection.addTypeNames(type: KotlinType) { val constructor = type.constructor constructor.declarationDescriptor?.name?.asString()?.let { typeName -> add(typeName) - resolveTypeAliasesUsingIndex(type, typeName, this) + resolveTypeAliasesUsingIndex(type, typeName).mapTo(this, { it.name.asString() }) } constructor.supertypes.forEach { addTypeNames(it) } }