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);