KT-15898 Cannot use type alias to qualify enum entry

Type alias static scope includes enum entries for underlying enum class.
This commit is contained in:
Dmitry Petrov
2017-01-25 12:25:19 +03:00
parent a974ed1049
commit 1613ad0505
11 changed files with 120 additions and 2 deletions
@@ -17,13 +17,18 @@
package org.jetbrains.kotlin.resolve.scopes.receivers
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.psiUtil.getTopmostParentQualifiedExpressionForSelector
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
import org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.Printer
import java.util.*
interface Qualifier : QualifierReceiver {
@@ -91,7 +96,28 @@ class TypeAliasQualifier(
}
override val staticScope: MemberScope
get() = classDescriptor.staticScope
get() = when {
DescriptorUtils.isEnumClass(classDescriptor) ->
ChainedMemberScope("Static scope for typealias ${descriptor.name}",
listOf(classDescriptor.staticScope, EnumEntriesScope()))
else ->
classDescriptor.staticScope
}
private inner class EnumEntriesScope : MemberScopeImpl() {
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? =
classDescriptor.unsubstitutedInnerClassesScope
.getContributedClassifier(name, location)
?.takeIf { DescriptorUtils.isEnumEntry(it) }
override fun printScopeStructure(p: Printer) {
p.println(javaClass.simpleName, " {")
p.pushIndent()
p.println("descriptor = ", descriptor)
p.popIndent()
p.println("}")
}
}
}
class ClassValueReceiver(val classQualifier: ClassifierQualifier, private val type: KotlinType) : ExpressionReceiver {
@@ -0,0 +1,10 @@
enum class MyEnum {
O;
companion object {
val K = "K"
}
}
typealias MyAlias = MyEnum
fun box() = MyAlias.O.name + MyAlias.K
@@ -0,0 +1,22 @@
@kotlin.Metadata
public final class EnumEntryQualifierKt {
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@kotlin.Metadata
public enum class MyEnum {
public final static field Companion: MyEnum.Companion
private final static @org.jetbrains.annotations.NotNull field K: java.lang.String
public final static field O: MyEnum
inner class MyEnum/Companion
protected method <init>(p0: java.lang.String, p1: int): void
public static method valueOf(p0: java.lang.String): MyEnum
public static method values(): MyEnum[]
}
@kotlin.Metadata
public final static class MyEnum/Companion {
inner class MyEnum/Companion
private method <init>(): void
public final @org.jetbrains.annotations.NotNull method getK(): java.lang.String
}
@@ -0,0 +1,6 @@
enum class MyEnum { A }
typealias TestAlias = MyEnum
val test1 = MyEnum.A
val test2 = TestAlias.A
@@ -0,0 +1,24 @@
package
public val test1: MyEnum
public val test2: MyEnum
public final enum class MyEnum : kotlin.Enum<MyEnum> {
enum entry A
private constructor MyEnum()
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: MyEnum): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<MyEnum!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): MyEnum
public final /*synthesized*/ fun values(): kotlin.Array<MyEnum>
}
public typealias TestAlias = MyEnum
@@ -17261,6 +17261,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/typealias"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("enumEntryQualifier.kt")
public void testEnumEntryQualifier() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt");
doTest(fileName);
}
@TestMetadata("genericTypeAliasConstructor.kt")
public void testGenericTypeAliasConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/genericTypeAliasConstructor.kt");
@@ -22168,6 +22168,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("enumEntryQualifier.kt")
public void testEnumEntryQualifier() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/enumEntryQualifier.kt");
doTest(fileName);
}
@TestMetadata("exposedExpandedType.kt")
public void testExposedExpandedType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/exposedExpandedType.kt");
@@ -17261,6 +17261,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/typealias"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("enumEntryQualifier.kt")
public void testEnumEntryQualifier() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt");
doTest(fileName);
}
@TestMetadata("genericTypeAliasConstructor.kt")
public void testGenericTypeAliasConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/genericTypeAliasConstructor.kt");
@@ -17261,6 +17261,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/typealias"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("enumEntryQualifier.kt")
public void testEnumEntryQualifier() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt");
doTest(fileName);
}
@TestMetadata("genericTypeAliasConstructor.kt")
public void testGenericTypeAliasConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/genericTypeAliasConstructor.kt");
@@ -21729,6 +21729,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/typealias"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("enumEntryQualifier.kt")
public void testEnumEntryQualifier() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/enumEntryQualifier.kt");
doTest(fileName);
}
@TestMetadata("genericTypeAliasConstructor.kt")
public void testGenericTypeAliasConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/genericTypeAliasConstructor.kt");
@@ -123,7 +123,7 @@ public final class BindingUtils {
if (descriptor instanceof TypeAliasDescriptor) {
ClassDescriptor classDescriptor = ((TypeAliasDescriptor) descriptor).getClassDescriptor();
assert classDescriptor != null : "Class descriptor must be non-null in resolved typealias: " + descriptor;
if (classDescriptor.getKind() != ClassKind.OBJECT) {
if (classDescriptor.getKind() != ClassKind.OBJECT && classDescriptor.getKind() != ClassKind.ENUM_CLASS) {
classDescriptor = classDescriptor.getCompanionObjectDescriptor();
assert classDescriptor != null : "Resolved typealias must have non-null class descriptor: " + descriptor;
}