From fa292ec0e0ae7f4f63ab2a00a5b2932b05c1a071 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 2 Sep 2015 15:48:24 +0300 Subject: [PATCH] Enum entries now can have no initializer if default secondary constructor is available. #KT-8484 Fixed --- .../kotlin/resolve/DeclarationsChecker.java | 3 +-- .../codegen/box/enum/emptyConstructor.kt | 8 ++++++ .../tests/enum/emptyConstructor.kt | 4 +++ .../tests/enum/emptyConstructor.txt | 18 +++++++++++++ .../tests/enum/multipleConstructors.kt | 8 ++++++ .../tests/enum/multipleConstructors.txt | 26 +++++++++++++++++++ .../checkers/JetDiagnosticsTestGenerated.java | 12 +++++++++ .../BlackBoxCodegenTestGenerated.java | 6 +++++ .../kotlin/resolve/DescriptorUtils.java | 7 +++++ 9 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/box/enum/emptyConstructor.kt create mode 100644 compiler/testData/diagnostics/tests/enum/emptyConstructor.kt create mode 100644 compiler/testData/diagnostics/tests/enum/emptyConstructor.txt create mode 100644 compiler/testData/diagnostics/tests/enum/multipleConstructors.kt create mode 100644 compiler/testData/diagnostics/tests/enum/multipleConstructors.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java index 2f3f161b4c1..0c39d7b9f37 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.java @@ -507,8 +507,7 @@ public class DeclarationsChecker { if (DescriptorUtils.isEnumClass(declaration)) { ClassDescriptor enumClass = (ClassDescriptor) declaration; - ConstructorDescriptor constructor = enumClass.getUnsubstitutedPrimaryConstructor(); - if ((constructor == null || !constructor.getValueParameters().isEmpty()) && !enumEntry.hasInitializer()) { + if (!enumEntry.hasInitializer() && !DescriptorUtils.hasDefaultConstructor(enumClass)) { trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(enumEntry)); } } diff --git a/compiler/testData/codegen/box/enum/emptyConstructor.kt b/compiler/testData/codegen/box/enum/emptyConstructor.kt new file mode 100644 index 00000000000..c82a4ac41c3 --- /dev/null +++ b/compiler/testData/codegen/box/enum/emptyConstructor.kt @@ -0,0 +1,8 @@ +package test + +enum class My(val s: String) { + ENTRY; + constructor(): this("OK") +} + +fun box() = My.ENTRY.s diff --git a/compiler/testData/diagnostics/tests/enum/emptyConstructor.kt b/compiler/testData/diagnostics/tests/enum/emptyConstructor.kt new file mode 100644 index 00000000000..97493b36a35 --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/emptyConstructor.kt @@ -0,0 +1,4 @@ +enum class E { + A; // no constructor call needed + constructor() +} diff --git a/compiler/testData/diagnostics/tests/enum/emptyConstructor.txt b/compiler/testData/diagnostics/tests/enum/emptyConstructor.txt new file mode 100644 index 00000000000..382b2729bc5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/emptyConstructor.txt @@ -0,0 +1,18 @@ +package + +internal final enum class E : kotlin.Enum { + enum entry A + + private constructor E() + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/enum/multipleConstructors.kt b/compiler/testData/diagnostics/tests/enum/multipleConstructors.kt new file mode 100644 index 00000000000..70a2c379ca7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/multipleConstructors.kt @@ -0,0 +1,8 @@ +enum class E(val x: Int, val y: Int) { + A(1, 2), + B(1), + C; // no constructor call needed even here + + constructor(): this(0, 0) + constructor(x: Int): this(x, 0) +} diff --git a/compiler/testData/diagnostics/tests/enum/multipleConstructors.txt b/compiler/testData/diagnostics/tests/enum/multipleConstructors.txt new file mode 100644 index 00000000000..e6fe93fec9e --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/multipleConstructors.txt @@ -0,0 +1,26 @@ +package + +internal final enum class E : kotlin.Enum { + enum entry A + + enum entry B + + enum entry C + + private constructor E() + private constructor E(/*0*/ x: kotlin.Int) + private constructor E(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int) + internal final val x: kotlin.Int + internal final val y: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 1331bb77b62..19d41ed2e79 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -5199,6 +5199,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("emptyConstructor.kt") + public void testEmptyConstructor() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/emptyConstructor.kt"); + doTest(fileName); + } + @TestMetadata("entryShouldBeOfEnumType.kt") public void testEntryShouldBeOfEnumType() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/entryShouldBeOfEnumType.kt"); @@ -5385,6 +5391,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("multipleConstructors.kt") + public void testMultipleConstructors() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/multipleConstructors.kt"); + doTest(fileName); + } + @TestMetadata("openMemberInEnum.kt") public void testOpenMemberInEnum() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/openMemberInEnum.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java index 6f45a9dfe9b..63fb37bbb5f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -3415,6 +3415,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("emptyConstructor.kt") + public void testEmptyConstructor() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/emptyConstructor.kt"); + doTest(fileName); + } + @TestMetadata("emptyEnumValuesValueOf.kt") public void testEmptyEnumValuesValueOf() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/emptyEnumValuesValueOf.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java index 93ad277b355..a5abe752b8d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java @@ -540,6 +540,13 @@ public class DescriptorUtils { return !isSingletonOrAnonymousObject(classDescriptor) && !isTrait(classDescriptor); } + public static boolean hasDefaultConstructor(@NotNull ClassDescriptor classDescriptor) { + for (ConstructorDescriptor constructor : classDescriptor.getConstructors()) { + if (constructor.getValueParameters().isEmpty()) return true; + } + return false; + } + public static Set getPackagesFqNames(ModuleDescriptor module) { Set result = getSubPackagesFqNames(module.getPackage(FqName.ROOT)); result.add(FqName.ROOT);