From ba2c3136bbe37e9cc7024848510d57ce0ac54837 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 8 Sep 2017 10:51:22 +0300 Subject: [PATCH] Prohibit non-inner classes in enum entries since 1.3 --- .../kotlin/resolve/ModifiersChecker.java | 12 +++++++++++ .../InnerClassAccessThroughEnum.kt | 4 ++-- .../enum/dontCreatePackageTypeForEnumEntry.kt | 2 +- .../tests/enum/inner/insideEnumEntry.kt | 2 +- .../inner/innerClassInEnumEntryClass_lv11.kt | 10 +++++----- .../inner/innerClassInEnumEntryClass_lv12.kt | 10 +++++----- .../inner/innerClassInEnumEntryClass_lv13.kt | 19 ++++++++++++++++++ .../inner/innerClassInEnumEntryClass_lv13.txt | 20 +++++++++++++++++++ .../tests/inner/nestedClassNotAllowed.kt | 2 +- .../checkers/DiagnosticsTestGenerated.java | 6 ++++++ .../DiagnosticsUsingJavacTestGenerated.java | 6 ++++++ .../kotlin/config/LanguageVersionSettings.kt | 1 + 12 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv13.kt create mode 100644 compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv13.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java index 86e92330fbf..e1d3c85b596 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java @@ -20,6 +20,7 @@ import com.google.common.collect.Maps; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1; @@ -202,6 +203,17 @@ public class ModifiersChecker { return; } + // Since 1.3, enum entries can contain inner classes only. + // Companion objects are reported in ModifierCheckerCore. + if (DescriptorUtils.isEnumEntry(containingClass) && !classDescriptor.isInner() && kind != DetailedClassKind.COMPANION_OBJECT) { + DiagnosticFactory1 diagnostic = + languageVersionSettings.supportsFeature(LanguageFeature.NestedClassesInEnumEntryShouldBeInner) + ? NESTED_CLASS_NOT_ALLOWED + : NESTED_CLASS_NOT_ALLOWED_SINCE_1_3; + trace.report(diagnostic.on(ktClassOrObject, kind.withCapitalFirstLetter)); + return; + } + if (!classDescriptor.isInner() && (containingClass.isInner() || DescriptorUtils.isLocal(containingClass))) { trace.report(NESTED_CLASS_NOT_ALLOWED.on(ktClassOrObject, kind.withCapitalFirstLetter)); } diff --git a/compiler/testData/diagnostics/tests/classObjects/InnerClassAccessThroughEnum.kt b/compiler/testData/diagnostics/tests/classObjects/InnerClassAccessThroughEnum.kt index 9716e5b09cc..47cffaa0584 100644 --- a/compiler/testData/diagnostics/tests/classObjects/InnerClassAccessThroughEnum.kt +++ b/compiler/testData/diagnostics/tests/classObjects/InnerClassAccessThroughEnum.kt @@ -3,13 +3,13 @@ package a enum class C { E1, E2, E3 { - object O_O + object O_O fun b() { O_O } - class G + class G }, E4 { diff --git a/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry.kt b/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry.kt index 390fddb281c..c85104c5806 100644 --- a/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry.kt +++ b/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry.kt @@ -1,7 +1,7 @@ enum class E { FIRST, SECOND { - class A + class A }; } diff --git a/compiler/testData/diagnostics/tests/enum/inner/insideEnumEntry.kt b/compiler/testData/diagnostics/tests/enum/inner/insideEnumEntry.kt index 7f302c53f19..4e397f71047 100644 --- a/compiler/testData/diagnostics/tests/enum/inner/insideEnumEntry.kt +++ b/compiler/testData/diagnostics/tests/enum/inner/insideEnumEntry.kt @@ -1,6 +1,6 @@ enum class E { ABC { - enum class F { + enum class F { DEF } } diff --git a/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv11.kt b/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv11.kt index a2570f57c71..eec67b9562e 100644 --- a/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv11.kt +++ b/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv11.kt @@ -1,16 +1,16 @@ -// !LANGUAGE: -InnerClassInEnumEntryClass +// !LANGUAGE: -InnerClassInEnumEntryClass -NestedClassesInEnumEntryShouldBeInner enum class Enum { ENTRY_WITH_CLASS { inner class TestInner - class TestNested + class TestNested - interface TestInterface + interface TestInterface - object TestObject + object TestObject - enum class TestEnumClass { + enum class TestEnumClass { OTHER_ENTRY } diff --git a/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv12.kt b/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv12.kt index e9210739943..8bf43ee756c 100644 --- a/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv12.kt +++ b/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv12.kt @@ -1,16 +1,16 @@ -// !LANGUAGE: +InnerClassInEnumEntryClass +// !LANGUAGE: +InnerClassInEnumEntryClass -NestedClassesInEnumEntryShouldBeInner enum class Enum { ENTRY_WITH_CLASS { inner class TestInner - class TestNested + class TestNested - interface TestInterface + interface TestInterface - object TestObject + object TestObject - enum class TestEnumClass { + enum class TestEnumClass { OTHER_ENTRY } diff --git a/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv13.kt b/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv13.kt new file mode 100644 index 00000000000..6128b4c68ac --- /dev/null +++ b/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv13.kt @@ -0,0 +1,19 @@ +// !LANGUAGE: +InnerClassInEnumEntryClass +NestedClassesInEnumEntryShouldBeInner + +enum class Enum { + ENTRY_WITH_CLASS { + inner class TestInner + + class TestNested + + interface TestInterface + + object TestObject + + enum class TestEnumClass { + OTHER_ENTRY + } + + companion object {} + } +} diff --git a/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv13.txt b/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv13.txt new file mode 100644 index 00000000000..e357e6ce0df --- /dev/null +++ b/compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv13.txt @@ -0,0 +1,20 @@ +package + +public final enum class Enum : kotlin.Enum { + enum entry ENTRY_WITH_CLASS + + private constructor Enum() + 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: Enum): 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): Enum + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed.kt b/compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed.kt index a5865d6383f..02a84676a0b 100644 --- a/compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed.kt +++ b/compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed.kt @@ -20,6 +20,6 @@ fun foo() { enum class E { E1 { // Not allowed in Java, but no reason to disallow in Kotlin - class D + class D } } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 66af3c619c9..bdefbe53fea 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -11872,6 +11872,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("innerClassInEnumEntryClass_lv13.kt") + public void testInnerClassInEnumEntryClass_lv13() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv13.kt"); + doTest(fileName); + } + @TestMetadata("InnerClassNameClash.kt") public void testInnerClassNameClash() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/InnerClassNameClash.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 4bb59bb5761..b804df496e6 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -11872,6 +11872,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing doTest(fileName); } + @TestMetadata("innerClassInEnumEntryClass_lv13.kt") + public void testInnerClassInEnumEntryClass_lv13() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/innerClassInEnumEntryClass_lv13.kt"); + doTest(fileName); + } + @TestMetadata("InnerClassNameClash.kt") public void testInnerClassNameClash() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inner/InnerClassNameClash.kt"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index fc2e69e55b5..6cbde0485ce 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -63,6 +63,7 @@ enum class LanguageFeature( CallableReferencesToClassMembersWithEmptyLHS(KOTLIN_1_2), RestrictionOfValReassignmentViaBackingField(KOTLIN_1_3), + NestedClassesInEnumEntryShouldBeInner(KOTLIN_1_3), // Experimental features