diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 1a40a2536c8..5261a4f7552 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -512,6 +512,8 @@ public interface Errors { DiagnosticFactory0 HEADER_DECLARATION_WITH_DEFAULT_PARAMETER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 HEADER_CLASS_CONSTRUCTOR_DELEGATION_CALL = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 HEADER_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0> HEADER_ENUM_CONSTRUCTOR = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 HEADER_ENUM_ENTRY_WITH_BODY = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 HEADER_PROPERTY_INITIALIZER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 IMPL_TYPE_ALIAS_NOT_TO_CLASS = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 835cbc5577b..6fef4e8e2fd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -265,6 +265,8 @@ public class DefaultErrorMessages { MAP.put(HEADER_DECLARATION_WITH_DEFAULT_PARAMETER, "Header declaration cannot have parameters with default values"); MAP.put(HEADER_CLASS_CONSTRUCTOR_DELEGATION_CALL, "Explicit delegation call for constructor of a header class is not allowed"); MAP.put(HEADER_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "Header class constructor cannot have a property parameter"); + MAP.put(HEADER_ENUM_CONSTRUCTOR, "Header enum class cannot have a constructor"); + MAP.put(HEADER_ENUM_ENTRY_WITH_BODY, "Header enum entry cannot have a body"); MAP.put(HEADER_PROPERTY_INITIALIZER, "Header property cannot have an initializer"); MAP.put(IMPL_TYPE_ALIAS_NOT_TO_CLASS, "Right-hand side of 'impl' type alias should be a class, not another type alias"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index 5db50e6dacb..e1e135b0d45 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -28,7 +28,6 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier import org.jetbrains.kotlin.resolve.BindingContext.* import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers @@ -274,6 +273,10 @@ class DeclarationsChecker( trace.report(HEADER_DECLARATION_WITH_BODY.on(declaration)) } + if (constructorDescriptor.containingDeclaration.kind == ClassKind.ENUM_CLASS) { + trace.report(HEADER_ENUM_CONSTRUCTOR.on(declaration)) + } + if (declaration is KtPrimaryConstructor && !DescriptorUtils.isAnnotationClass(constructorDescriptor.constructedClass)) { for (parameter in declaration.valueParameters) { if (parameter.hasValOrVar()) { @@ -895,15 +898,20 @@ class DeclarationsChecker( } } - private fun checkEnumEntry(enumEntry: KtEnumEntry, classDescriptor: ClassDescriptor) { - val declaration = classDescriptor.containingDeclaration - if (DescriptorUtils.isEnumClass(declaration)) { - if (!enumEntry.hasInitializer() && !hasDefaultConstructor(declaration as ClassDescriptor)) { + private fun checkEnumEntry(enumEntry: KtEnumEntry, enumEntryClass: ClassDescriptor) { + val enumClass = enumEntryClass.containingDeclaration as ClassDescriptor + if (DescriptorUtils.isEnumClass(enumClass)) { + if (enumClass.isHeader) { + if (enumEntry.getBody() != null) { + trace.report(HEADER_ENUM_ENTRY_WITH_BODY.on(enumEntry)) + } + } + else if (!enumEntry.hasInitializer() && !hasDefaultConstructor(enumClass)) { trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(enumEntry)) } } else { - assert(DescriptorUtils.isInterface(declaration)) { "Enum entry should be declared in enum class: " + classDescriptor } + assert(DescriptorUtils.isInterface(enumClass)) { "Enum entry should be declared in enum class: " + enumEntryClass } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt index ae332f874f0..bfda6dc8b59 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Compatible import org.jetbrains.kotlin.resolve.checkers.HeaderImplDeclarationChecker.Compatibility.Incompatible import org.jetbrains.kotlin.resolve.descriptorUtil.classId @@ -212,6 +213,8 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null) unimplemented: List>>> ) : Incompatible("some members are not implemented", unimplemented) + object EnumEntries : Incompatible("some entries from header enum are missing in the impl enum") + // Common object Modality : Incompatible("modality is different") @@ -390,7 +393,16 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null) unimplemented.add(aMember to incompatibilityMap) } - // TODO: check static scope, enum entries + if (a.kind == ClassKind.ENUM_CLASS) { + fun ClassDescriptor.enumEntries() = + unsubstitutedMemberScope.getDescriptorsFiltered().filter(DescriptorUtils::isEnumEntry).map { it.name } + val aEntries = a.enumEntries() + val bEntries = b.enumEntries() + + if (!bEntries.containsAll(aEntries)) return Incompatible.EnumEntries + } + + // TODO: check static scope? if (unimplemented.isEmpty()) return Compatible diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt index 5f7cbf5fd00..8e2bf421805 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassMemberScope.kt @@ -334,9 +334,13 @@ open class LazyClassMemberScope( val classOrObject = declarationProvider.correspondingClassOrObject ?: return null val hasPrimaryConstructor = classOrObject.hasExplicitPrimaryConstructor() - if (DescriptorUtils.isInterface(thisDescriptor) && !hasPrimaryConstructor) return null - - if (thisDescriptor.isHeader && thisDescriptor.kind == ClassKind.OBJECT) return null + if (!hasPrimaryConstructor) { + when (thisDescriptor.kind) { + ClassKind.INTERFACE -> return null + ClassKind.OBJECT, ClassKind.ENUM_CLASS -> if (thisDescriptor.isHeader) return null + else -> {} + } + } if (DescriptorUtils.canHaveDeclaredConstructors(thisDescriptor) || hasPrimaryConstructor) { val constructor = c.functionDescriptorResolver.resolvePrimaryConstructorDescriptor( diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/additionalEntriesInImpl.kt b/compiler/testData/diagnostics/tests/multiplatform/enum/additionalEntriesInImpl.kt new file mode 100644 index 00000000000..bcea2b2ac02 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/additionalEntriesInImpl.kt @@ -0,0 +1,10 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt +header enum class Foo { A, B } +header enum class Bar { X, Y, Z } + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt +impl enum class Foo { A, B, C, D, E } +impl enum class Bar { V, X, W, Y, Z } diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/additionalEntriesInImpl.txt b/compiler/testData/diagnostics/tests/multiplatform/enum/additionalEntriesInImpl.txt new file mode 100644 index 00000000000..314fa0790c5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/additionalEntriesInImpl.txt @@ -0,0 +1,98 @@ +// -- Module: -- +package + +public final header enum class Bar : kotlin.Enum { + enum entry X + + enum entry Y + + enum entry Z + + 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: Bar): 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Bar + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final header enum class Foo : kotlin.Enum { + enum entry A + + enum entry B + + 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: Foo): 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Foo + public final /*synthesized*/ fun values(): kotlin.Array +} + + +// -- Module: -- +package + +public final impl enum class Bar : kotlin.Enum { + enum entry V + + enum entry X + + enum entry W + + enum entry Y + + enum entry Z + + private constructor Bar() + 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: Bar): 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! + 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): Bar + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final impl enum class Foo : kotlin.Enum { + enum entry A + + enum entry B + + enum entry C + + enum entry D + + enum entry E + + private constructor Foo() + 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: Foo): 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! + 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): Foo + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/constructorInHeaderEnum.kt b/compiler/testData/diagnostics/tests/multiplatform/enum/constructorInHeaderEnum.kt new file mode 100644 index 00000000000..f43bf7e8953 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/constructorInHeaderEnum.kt @@ -0,0 +1,15 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +header enum class En(x: Int) { + E1, + E2(42), + ; + + constructor(s: String) +} + +header enum class En2 { + E1() +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/constructorInHeaderEnum.txt b/compiler/testData/diagnostics/tests/multiplatform/enum/constructorInHeaderEnum.txt new file mode 100644 index 00000000000..d6082920ceb --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/constructorInHeaderEnum.txt @@ -0,0 +1,21 @@ +package + +public final header enum class En : kotlin.Enum { + enum entry E1 + + enum entry E2 + + private constructor En(/*0*/ x: kotlin.Int) + private constructor En(/*0*/ s: kotlin.String) + 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: En): 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): En + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/differentEntryOrder.kt b/compiler/testData/diagnostics/tests/multiplatform/enum/differentEntryOrder.kt new file mode 100644 index 00000000000..6bdc6f5ff9f --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/differentEntryOrder.kt @@ -0,0 +1,10 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt +header enum class Foo { A, B } +header enum class Bar { X, Y, Z } + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt +impl enum class Foo { B, A } +impl enum class Bar { X, Z, Y } diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/differentEntryOrder.txt b/compiler/testData/diagnostics/tests/multiplatform/enum/differentEntryOrder.txt new file mode 100644 index 00000000000..7793ae89178 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/differentEntryOrder.txt @@ -0,0 +1,88 @@ +// -- Module: -- +package + +public final header enum class Bar : kotlin.Enum { + enum entry X + + enum entry Y + + enum entry Z + + 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: Bar): 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Bar + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final header enum class Foo : kotlin.Enum { + enum entry A + + enum entry B + + 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: Foo): 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Foo + public final /*synthesized*/ fun values(): kotlin.Array +} + + +// -- Module: -- +package + +public final impl enum class Bar : kotlin.Enum { + enum entry X + + enum entry Z + + enum entry Y + + private constructor Bar() + 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: Bar): 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! + 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): Bar + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final impl enum class Foo : kotlin.Enum { + enum entry B + + enum entry A + + private constructor Foo() + 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: Foo): 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! + 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): Foo + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/enumEntryWithBody.kt b/compiler/testData/diagnostics/tests/multiplatform/enum/enumEntryWithBody.kt new file mode 100644 index 00000000000..646c15f6daa --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/enumEntryWithBody.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +header enum class En { + E1, + E2 { + fun foo() = "" + }, + E3 { }; +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/enumEntryWithBody.txt b/compiler/testData/diagnostics/tests/multiplatform/enum/enumEntryWithBody.txt new file mode 100644 index 00000000000..347f516f7e4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/enumEntryWithBody.txt @@ -0,0 +1,21 @@ +package + +public final header enum class En : kotlin.Enum { + enum entry E1 + + enum entry E2 + + enum entry E3 + + 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: En): 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): En + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.kt b/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.kt new file mode 100644 index 00000000000..1ffdff8cb93 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.kt @@ -0,0 +1,16 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt +header enum class Foo { + ENTRY1, + ENTRY2, + ENTRY3; +} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt +impl enum class Foo(val x: String) { + ENTRY1("1"), + ENTRY2("2"), + ENTRY3("3"); +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.txt b/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.txt new file mode 100644 index 00000000000..bbe83822682 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.txt @@ -0,0 +1,50 @@ +// -- Module: -- +package + +public final header enum class Foo : kotlin.Enum { + enum entry ENTRY1 + + enum entry ENTRY2 + + enum entry ENTRY3 + + 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: Foo): 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Foo + public final /*synthesized*/ fun values(): kotlin.Array +} + + +// -- Module: -- +package + +public final impl enum class Foo : kotlin.Enum { + enum entry ENTRY1 + + enum entry ENTRY2 + + enum entry ENTRY3 + + private constructor Foo(/*0*/ x: kotlin.String) + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + public final val x: kotlin.String + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Foo): 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! + 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): Foo + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/classKinds.txt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/classKinds.txt index eff3813dda0..cbd776d1e3c 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/classKinds.txt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/classKinds.txt @@ -19,7 +19,6 @@ public final header class Class { public final header enum class En : kotlin.Enum { enum entry ENTRY - private constructor En() 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 diff --git a/compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/common.kt b/compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/common.kt new file mode 100644 index 00000000000..85698d0891d --- /dev/null +++ b/compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/common.kt @@ -0,0 +1,3 @@ +header enum class AB { A, B } + +header enum class CD { C, D } diff --git a/compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/jvm.kt b/compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/jvm.kt new file mode 100644 index 00000000000..79f76b6f3a8 --- /dev/null +++ b/compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/jvm.kt @@ -0,0 +1,3 @@ +impl enum class AB { A, C } + +impl enum class CD { C } diff --git a/compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/output.txt b/compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/output.txt new file mode 100644 index 00000000000..43cd9393851 --- /dev/null +++ b/compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/output.txt @@ -0,0 +1,26 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: COMPILATION_ERROR +Output: +compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/common.kt:1:19: error: header declaration 'AB' has no implementation in module +The following declaration is incompatible because some entries from header enum are missing in the impl enum: + public final impl enum class AB : Enum + +header enum class AB { A, B } + ^ +compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/common.kt:3:19: error: header declaration 'CD' has no implementation in module +The following declaration is incompatible because some entries from header enum are missing in the impl enum: + public final impl enum class CD : Enum + +header enum class CD { C, D } + ^ +compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/jvm.kt:1:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl enum class AB { A, C } +^ +compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/jvm.kt:3:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code +impl enum class CD { C } +^ + diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 4f4ef4195a5..6e25e1467b2 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -13054,6 +13054,45 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/enum") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Enum extends AbstractDiagnosticsTest { + @TestMetadata("additionalEntriesInImpl.kt") + public void testAdditionalEntriesInImpl() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/enum/additionalEntriesInImpl.kt"); + doTest(fileName); + } + + public void testAllFilesPresentInEnum() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/enum"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("constructorInHeaderEnum.kt") + public void testConstructorInHeaderEnum() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/enum/constructorInHeaderEnum.kt"); + doTest(fileName); + } + + @TestMetadata("differentEntryOrder.kt") + public void testDifferentEntryOrder() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/enum/differentEntryOrder.kt"); + doTest(fileName); + } + + @TestMetadata("enumEntryWithBody.kt") + public void testEnumEntryWithBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/enum/enumEntryWithBody.kt"); + doTest(fileName); + } + + @TestMetadata("simpleEnum.kt") + public void testSimpleEnum() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java index 63194701dcb..90a1aa1aece 100644 --- a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java @@ -98,6 +98,12 @@ public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatform doTest(fileName); } + @TestMetadata("enumsWithDifferentEntries") + public void testEnumsWithDifferentEntries() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/classScopes/enumsWithDifferentEntries/"); + doTest(fileName); + } + @TestMetadata("fakeOverrides") public void testFakeOverrides() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/multiplatform/classScopes/fakeOverrides/");