KT-17689: Fix TypeAliasQualifier to provide enum entries descriptors
- this adds enum entries to the completion on the typealiases - we cannot use `unsubstitutedInnerClassesScope` instead of `EnumEntriesScope` because it allows to complete things that are not allowed to be resolved by the Kotlin compiler; see `EnumEntriesScope` doc for details - ^KT-17689 Fixed
This commit is contained in:
committed by
Roman Golyshev
parent
f419d2eb30
commit
9a938b07ba
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getTopmostParentQualifiedExpressionForSe
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
||||||
import org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope
|
import org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
|
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -107,7 +108,23 @@ class TypeAliasQualifier(
|
|||||||
classDescriptor.staticScope
|
classDescriptor.staticScope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We cannot use [org.jetbrains.kotlin.descriptors.ClassDescriptor.getUnsubstitutedMemberScope] directly,
|
||||||
|
* because we do not allow complete resolve through type aliases yet (see KT-15298).
|
||||||
|
*
|
||||||
|
* However, we want to allow to resolve and autocomplete enum constants even through type aliases;
|
||||||
|
* that's why we use [org.jetbrains.kotlin.descriptors.ClassDescriptor.getUnsubstitutedMemberScope],
|
||||||
|
* but filter only enum entries.
|
||||||
|
*/
|
||||||
private inner class EnumEntriesScope : MemberScopeImpl() {
|
private inner class EnumEntriesScope : MemberScopeImpl() {
|
||||||
|
override fun getContributedDescriptors(
|
||||||
|
kindFilter: DescriptorKindFilter,
|
||||||
|
nameFilter: (Name) -> Boolean
|
||||||
|
): Collection<DeclarationDescriptor> =
|
||||||
|
classDescriptor.unsubstitutedInnerClassesScope
|
||||||
|
.getContributedDescriptors(kindFilter, nameFilter)
|
||||||
|
.filter { DescriptorUtils.isEnumEntry(it) }
|
||||||
|
|
||||||
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? =
|
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? =
|
||||||
classDescriptor.unsubstitutedInnerClassesScope
|
classDescriptor.unsubstitutedInnerClassesScope
|
||||||
.getContributedClassifier(name, location)
|
.getContributedClassifier(name, location)
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
enum class A {
|
||||||
|
ONE;
|
||||||
|
class B // Not allowed to resolve through typealiases
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias AA = A
|
||||||
|
typealias AAA = AA
|
||||||
|
|
||||||
|
fun usage() {
|
||||||
|
AAA.<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: ONE
|
||||||
|
// ABSENT: B
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
enum class A {
|
||||||
|
ONE;
|
||||||
|
class B // Not allowed to resolve through typealiases
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias AA = A
|
||||||
|
|
||||||
|
fun usage() {
|
||||||
|
AA.<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: ONE, values, valueOf
|
||||||
|
// ABSENT: B
|
||||||
+10
@@ -101,6 +101,16 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
runTest("idea/idea-completion/testData/basic/common/DataClassMembers2.kt");
|
runTest("idea/idea-completion/testData/basic/common/DataClassMembers2.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EnumItemsThroughChainedTypeAlias.kt")
|
||||||
|
public void testEnumItemsThroughChainedTypeAlias() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/EnumItemsThroughChainedTypeAlias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EnumItemsThroughSingleTypeAlias.kt")
|
||||||
|
public void testEnumItemsThroughSingleTypeAlias() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/EnumItemsThroughSingleTypeAlias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ExtendClassName.kt")
|
@TestMetadata("ExtendClassName.kt")
|
||||||
public void testExtendClassName() throws Exception {
|
public void testExtendClassName() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/basic/common/ExtendClassName.kt");
|
runTest("idea/idea-completion/testData/basic/common/ExtendClassName.kt");
|
||||||
|
|||||||
+10
@@ -101,6 +101,16 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
runTest("idea/idea-completion/testData/basic/common/DataClassMembers2.kt");
|
runTest("idea/idea-completion/testData/basic/common/DataClassMembers2.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EnumItemsThroughChainedTypeAlias.kt")
|
||||||
|
public void testEnumItemsThroughChainedTypeAlias() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/EnumItemsThroughChainedTypeAlias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EnumItemsThroughSingleTypeAlias.kt")
|
||||||
|
public void testEnumItemsThroughSingleTypeAlias() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/basic/common/EnumItemsThroughSingleTypeAlias.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ExtendClassName.kt")
|
@TestMetadata("ExtendClassName.kt")
|
||||||
public void testExtendClassName() throws Exception {
|
public void testExtendClassName() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/basic/common/ExtendClassName.kt");
|
runTest("idea/idea-completion/testData/basic/common/ExtendClassName.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user