From d257285c860e0188b05cd98bd744395c76162546 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 5 Apr 2019 22:11:37 +0200 Subject: [PATCH] Load Java enums as final classes In case Java enum has an abstract member, it has the ACC_ABSTRACT flag set in the bytecode. However, we should still load it with final modality to be consistent with Kotlin enums which are always considered final #KT-23426 Fixed --- .../fir/FirDiagnosticsSmokeTestGenerated.java | 5 ++ .../compileKotlinAgainstJava/AbstractEnum.txt | 2 +- .../tests/enum/javaEnumWithAbstractFun.txt | 2 +- .../tests/multiplatform/enum/javaEnum.kt | 32 ++++++++++ .../tests/multiplatform/enum/javaEnum.txt | 59 +++++++++++++++++++ .../EnumArgumentWithCustomToString.txt | 2 +- .../enum/EnumWithSpecializedEntry.txt | 2 +- .../checkers/DiagnosticsTestGenerated.java | 5 ++ .../DiagnosticsUsingJavacTestGenerated.java | 5 ++ .../descriptors/LazyJavaClassDescriptor.kt | 2 +- 10 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.txt diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java index 723a08f88d4..0005fffd962 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -13439,6 +13439,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/multiplatform/enum/enumEntryWithBody.kt"); } + @TestMetadata("javaEnum.kt") + public void testJavaEnum() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.kt"); + } + @TestMetadata("simpleEnum.kt") public void testSimpleEnum() throws Exception { runTest("compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.kt"); diff --git a/compiler/testData/compileKotlinAgainstJava/AbstractEnum.txt b/compiler/testData/compileKotlinAgainstJava/AbstractEnum.txt index cfecaae18a2..371715e4477 100644 --- a/compiler/testData/compileKotlinAgainstJava/AbstractEnum.txt +++ b/compiler/testData/compileKotlinAgainstJava/AbstractEnum.txt @@ -2,7 +2,7 @@ package test public fun useEnum(): kotlin.String! -public abstract enum class AbstractEnum : kotlin.Enum { +public final enum class AbstractEnum : kotlin.Enum { enum entry ONE private constructor AbstractEnum() diff --git a/compiler/testData/diagnostics/tests/enum/javaEnumWithAbstractFun.txt b/compiler/testData/diagnostics/tests/enum/javaEnumWithAbstractFun.txt index 6aa080a3e4a..956f568278d 100644 --- a/compiler/testData/diagnostics/tests/enum/javaEnumWithAbstractFun.txt +++ b/compiler/testData/diagnostics/tests/enum/javaEnumWithAbstractFun.txt @@ -2,7 +2,7 @@ package public fun main(): kotlin.Unit -public abstract enum class A : kotlin.Enum { +public final enum class A : kotlin.Enum { enum entry ENTRY public constructor A() diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.kt b/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.kt new file mode 100644 index 00000000000..5072b4f2cd8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.kt @@ -0,0 +1,32 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt +expect enum class Foo { + ENTRY +} + +expect enum class _TimeUnit + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt +actual typealias Foo = FooImpl + +actual typealias _TimeUnit = java.util.concurrent.TimeUnit + +// FILE: FooImpl.java +public enum FooImpl { + ENTRY("OK") { + @Override + public String getResult() { + return value; + } + }; + + protected final String value; + + public FooImpl(String value) { + this.value = value; + } + + public abstract String getResult(); +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.txt b/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.txt new file mode 100644 index 00000000000..a2cb80a759b --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.txt @@ -0,0 +1,59 @@ +// -- Module: -- +package + +public final expect enum class Foo : kotlin.Enum { + expect enum entry ENTRY + + 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 +} + +public final expect enum class _TimeUnit : kotlin.Enum<_TimeUnit> { + 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: _TimeUnit): 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): _TimeUnit + public final /*synthesized*/ fun values(): kotlin.Array<_TimeUnit> +} + + +// -- Module: -- +package + +public final enum class FooImpl : kotlin.Enum { + enum entry ENTRY + + public constructor FooImpl(/*0*/ value: kotlin.String!) + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected/*protected and package*/ final val value: kotlin.String! + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: FooImpl!): 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 abstract fun getResult(): kotlin.String! + 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): FooImpl + public final /*synthesized*/ fun values(): kotlin.Array +} +public actual typealias Foo = FooImpl +public actual typealias _TimeUnit = java.util.concurrent.TimeUnit diff --git a/compiler/testData/loadJava/compiledJava/annotations/EnumArgumentWithCustomToString.txt b/compiler/testData/loadJava/compiledJava/annotations/EnumArgumentWithCustomToString.txt index f26751bdb70..744f8f93de7 100644 --- a/compiler/testData/loadJava/compiledJava/annotations/EnumArgumentWithCustomToString.txt +++ b/compiler/testData/loadJava/compiledJava/annotations/EnumArgumentWithCustomToString.txt @@ -4,7 +4,7 @@ public open class EnumArgumentWithCustomToString { public constructor EnumArgumentWithCustomToString() @test.EnumArgumentWithCustomToString.EnumAnno(value = E.CAKE) @test.EnumArgumentWithCustomToString.EnumArrayAnno(value = {E.CAKE, E.CAKE}) public/*package*/ open fun annotated(): kotlin.Unit - public open enum class E : kotlin.Enum { + public final enum class E : kotlin.Enum { enum entry CAKE private constructor E() diff --git a/compiler/testData/loadJava/compiledJava/enum/EnumWithSpecializedEntry.txt b/compiler/testData/loadJava/compiledJava/enum/EnumWithSpecializedEntry.txt index 4032c3f43f0..e90cdfec6ab 100644 --- a/compiler/testData/loadJava/compiledJava/enum/EnumWithSpecializedEntry.txt +++ b/compiler/testData/loadJava/compiledJava/enum/EnumWithSpecializedEntry.txt @@ -1,6 +1,6 @@ package test -public open enum class EnumWithSpecializedEntry : kotlin.Enum { +public final enum class EnumWithSpecializedEntry : kotlin.Enum { enum entry E1 enum entry E2 diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 381f3d98c19..fee2db0232a 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -13446,6 +13446,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/multiplatform/enum/enumEntryWithBody.kt"); } + @TestMetadata("javaEnum.kt") + public void testJavaEnum() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.kt"); + } + @TestMetadata("simpleEnum.kt") public void testSimpleEnum() throws Exception { runTest("compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 070497c3312..ec94134201c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -13441,6 +13441,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/multiplatform/enum/enumEntryWithBody.kt"); } + @TestMetadata("javaEnum.kt") + public void testJavaEnum() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/enum/javaEnum.kt"); + } + @TestMetadata("simpleEnum.kt") public void testSimpleEnum() throws Exception { runTest("compiler/testData/diagnostics/tests/multiplatform/enum/simpleEnum.kt"); diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt index f24cb7b64d6..70e84901be0 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt @@ -72,7 +72,7 @@ class LazyJavaClassDescriptor( } private val modality = - if (jClass.isAnnotationType) Modality.FINAL + if (jClass.isAnnotationType || jClass.isEnum) Modality.FINAL else Modality.convertFromFlags(jClass.isAbstract || jClass.isInterface, !jClass.isFinal) private val visibility = jClass.visibility