Prohibit non-inner classes in enum entries since 1.3
This commit is contained in:
@@ -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<KtClassOrObject, String> 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));
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,13 +3,13 @@ package a
|
||||
|
||||
enum class C {
|
||||
E1, E2, E3 {
|
||||
object O_O
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>object O_O<!>
|
||||
|
||||
fun b() {
|
||||
O_O
|
||||
}
|
||||
|
||||
class G
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>class G<!>
|
||||
},
|
||||
|
||||
E4 {
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
enum class E {
|
||||
FIRST,
|
||||
SECOND {
|
||||
class A
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>class A<!>
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
enum class E {
|
||||
ABC {
|
||||
enum class F {
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>enum class F<!> {
|
||||
DEF
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,16 +1,16 @@
|
||||
// !LANGUAGE: -InnerClassInEnumEntryClass
|
||||
// !LANGUAGE: -InnerClassInEnumEntryClass -NestedClassesInEnumEntryShouldBeInner
|
||||
|
||||
enum class Enum {
|
||||
ENTRY_WITH_CLASS {
|
||||
<!WRONG_MODIFIER_CONTAINING_DECLARATION!>inner<!> class TestInner
|
||||
|
||||
class TestNested
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>class TestNested<!>
|
||||
|
||||
interface TestInterface
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>interface TestInterface<!>
|
||||
|
||||
object TestObject
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>object TestObject<!>
|
||||
|
||||
enum class TestEnumClass {
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>enum class TestEnumClass<!> {
|
||||
OTHER_ENTRY
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -1,16 +1,16 @@
|
||||
// !LANGUAGE: +InnerClassInEnumEntryClass
|
||||
// !LANGUAGE: +InnerClassInEnumEntryClass -NestedClassesInEnumEntryShouldBeInner
|
||||
|
||||
enum class Enum {
|
||||
ENTRY_WITH_CLASS {
|
||||
inner class TestInner
|
||||
|
||||
class TestNested
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>class TestNested<!>
|
||||
|
||||
interface TestInterface
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>interface TestInterface<!>
|
||||
|
||||
object TestObject
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>object TestObject<!>
|
||||
|
||||
enum class TestEnumClass {
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>enum class TestEnumClass<!> {
|
||||
OTHER_ENTRY
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// !LANGUAGE: +InnerClassInEnumEntryClass +NestedClassesInEnumEntryShouldBeInner
|
||||
|
||||
enum class Enum {
|
||||
ENTRY_WITH_CLASS {
|
||||
inner class TestInner
|
||||
|
||||
<!NESTED_CLASS_NOT_ALLOWED!>class TestNested<!>
|
||||
|
||||
<!NESTED_CLASS_NOT_ALLOWED!>interface TestInterface<!>
|
||||
|
||||
<!NESTED_CLASS_NOT_ALLOWED!>object TestObject<!>
|
||||
|
||||
<!NESTED_CLASS_NOT_ALLOWED!>enum class TestEnumClass<!> {
|
||||
OTHER_ENTRY
|
||||
}
|
||||
|
||||
<!WRONG_MODIFIER_CONTAINING_DECLARATION!>companion<!> object {}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package
|
||||
|
||||
public final enum class Enum : kotlin.Enum<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<Enum!>!
|
||||
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<Enum>
|
||||
}
|
||||
@@ -20,6 +20,6 @@ fun foo() {
|
||||
enum class E {
|
||||
E1 {
|
||||
// Not allowed in Java, but no reason to disallow in Kotlin
|
||||
class D
|
||||
<!NESTED_CLASS_NOT_ALLOWED_SINCE_1_3!>class D<!>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
+6
@@ -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");
|
||||
|
||||
@@ -63,6 +63,7 @@ enum class LanguageFeature(
|
||||
CallableReferencesToClassMembersWithEmptyLHS(KOTLIN_1_2),
|
||||
|
||||
RestrictionOfValReassignmentViaBackingField(KOTLIN_1_3),
|
||||
NestedClassesInEnumEntryShouldBeInner(KOTLIN_1_3),
|
||||
|
||||
// Experimental features
|
||||
|
||||
|
||||
Reference in New Issue
Block a user