Generate enum values with bodies properly (KT-15803)
This commit is contained in:
+78
-24
@@ -155,22 +155,15 @@ class ClassFileToSourceStubConverter(
|
|||||||
val isNested = (descriptor as? ClassDescriptor)?.isNested ?: false
|
val isNested = (descriptor as? ClassDescriptor)?.isNested ?: false
|
||||||
val isInner = isNested && (descriptor as? ClassDescriptor)?.isInner ?: false
|
val isInner = isNested && (descriptor as? ClassDescriptor)?.isInner ?: false
|
||||||
|
|
||||||
val flags = when {
|
val flags = getClassAccessFlags(clazz, descriptor, isInner, isNested)
|
||||||
(descriptor.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.INTERFACE -> {
|
|
||||||
// Classes inside interfaces should always be public and static.
|
|
||||||
// See com.sun.tools.javac.comp.Enter.visitClassDef for more information.
|
|
||||||
(clazz.access or Opcodes.ACC_PUBLIC or Opcodes.ACC_STATIC) and
|
|
||||||
Opcodes.ACC_PRIVATE.inv() and Opcodes.ACC_PROTECTED.inv() // Remove private and protected modifiers
|
|
||||||
}
|
|
||||||
!isInner && isNested -> clazz.access or Opcodes.ACC_STATIC
|
|
||||||
else -> clazz.access
|
|
||||||
}
|
|
||||||
|
|
||||||
val modifiers = convertModifiers(flags, ElementKind.CLASS, packageFqName, clazz.visibleAnnotations, clazz.invisibleAnnotations)
|
|
||||||
|
|
||||||
val isEnum = clazz.isEnum()
|
val isEnum = clazz.isEnum()
|
||||||
val isAnnotation = clazz.isAnnotation()
|
val isAnnotation = clazz.isAnnotation()
|
||||||
|
|
||||||
|
val modifiers = convertModifiers(flags,
|
||||||
|
if (isEnum) ElementKind.ENUM else ElementKind.CLASS,
|
||||||
|
packageFqName, clazz.visibleAnnotations, clazz.invisibleAnnotations)
|
||||||
|
|
||||||
val isDefaultImpls = clazz.name.endsWith("${descriptor.name.asString()}/DefaultImpls")
|
val isDefaultImpls = clazz.name.endsWith("${descriptor.name.asString()}/DefaultImpls")
|
||||||
&& isPublic(clazz.access) && isFinal(clazz.access)
|
&& isPublic(clazz.access) && isFinal(clazz.access)
|
||||||
&& descriptor is ClassDescriptor
|
&& descriptor is ClassDescriptor
|
||||||
@@ -181,14 +174,7 @@ class ClassFileToSourceStubConverter(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val simpleName = when (descriptor) {
|
val simpleName = getClassName(clazz, descriptor, isDefaultImpls, packageFqName)
|
||||||
is PackageFragmentDescriptor -> {
|
|
||||||
val className = if (packageFqName.isEmpty()) clazz.name else clazz.name.drop(packageFqName.length + 1)
|
|
||||||
if (className.isEmpty()) throw IllegalStateException("Invalid package facade class name: ${clazz.name}")
|
|
||||||
className
|
|
||||||
}
|
|
||||||
else -> if (isDefaultImpls) "DefaultImpls" else descriptor.name.asString()
|
|
||||||
}
|
|
||||||
|
|
||||||
val interfaces = mapJList(clazz.interfaces) {
|
val interfaces = mapJList(clazz.interfaces) {
|
||||||
if (isAnnotation && it == "java/lang/annotation/Annotation") return@mapJList null
|
if (isAnnotation && it == "java/lang/annotation/Annotation") return@mapJList null
|
||||||
@@ -200,7 +186,49 @@ class ClassFileToSourceStubConverter(
|
|||||||
val hasSuperClass = clazz.superName != "java/lang/Object" && !isEnum
|
val hasSuperClass = clazz.superName != "java/lang/Object" && !isEnum
|
||||||
val genericType = signatureParser.parseClassSignature(clazz.signature, superClass, interfaces)
|
val genericType = signatureParser.parseClassSignature(clazz.signature, superClass, interfaces)
|
||||||
|
|
||||||
val fields = mapJList<FieldNode, JCTree>(clazz.fields) { convertField(it, packageFqName) }
|
class EnumValueData(val field: FieldNode, val innerClass: InnerClassNode?, val correspondingClass: ClassNode?)
|
||||||
|
|
||||||
|
val enumValuesData = clazz.fields.filter { it.isEnumValue() }.map { field ->
|
||||||
|
var foundInnerClass: InnerClassNode? = null
|
||||||
|
var correspondingClass: ClassNode? = null
|
||||||
|
|
||||||
|
for (innerClass in clazz.innerClasses) {
|
||||||
|
// Class should have the same name as enum value
|
||||||
|
if (innerClass.innerName != field.name) continue
|
||||||
|
val classNode = kaptContext.compiledClasses.firstOrNull { it.name == innerClass.name } ?: continue
|
||||||
|
|
||||||
|
// Super class name of the class should be our enum class
|
||||||
|
if (classNode.superName != clazz.name) continue
|
||||||
|
|
||||||
|
correspondingClass = classNode
|
||||||
|
foundInnerClass = innerClass
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumValueData(field, foundInnerClass, correspondingClass)
|
||||||
|
}
|
||||||
|
|
||||||
|
val enumValues: JavacList<JCTree> = mapJList(enumValuesData) { data ->
|
||||||
|
val constructorArguments = Type.getArgumentTypes(clazz.methods.firstOrNull {
|
||||||
|
it.name == "<init>" && Type.getArgumentsAndReturnSizes(it.desc).shr(2) >= 2
|
||||||
|
}?.desc ?: "()Z")
|
||||||
|
|
||||||
|
val args = mapJList(constructorArguments.drop(2)) { convertLiteralExpression(getDefaultValue(it)) }
|
||||||
|
|
||||||
|
val def = data.correspondingClass?.let { convertClass(it, packageFqName, false) }
|
||||||
|
|
||||||
|
convertField(data.field, packageFqName, treeMaker.NewClass(
|
||||||
|
/* enclosing = */ null,
|
||||||
|
/* typeArgs = */ JavacList.nil(),
|
||||||
|
/* clazz = */ treeMaker.Ident(treeMaker.name(data.field.name)),
|
||||||
|
/* args = */ args,
|
||||||
|
/* def = */ def))
|
||||||
|
}
|
||||||
|
|
||||||
|
val fields = mapJList<FieldNode, JCTree>(clazz.fields) {
|
||||||
|
if (it.isEnumValue()) null else convertField(it, packageFqName)
|
||||||
|
}
|
||||||
|
|
||||||
val methods = mapJList<MethodNode, JCTree>(clazz.methods) {
|
val methods = mapJList<MethodNode, JCTree>(clazz.methods) {
|
||||||
if (isEnum) {
|
if (isEnum) {
|
||||||
if (it.name == "values" && it.desc == "()[L${clazz.name};") return@mapJList null
|
if (it.name == "values" && it.desc == "()[L${clazz.name};") return@mapJList null
|
||||||
@@ -209,7 +237,9 @@ class ClassFileToSourceStubConverter(
|
|||||||
|
|
||||||
convertMethod(it, clazz, packageFqName)
|
convertMethod(it, clazz, packageFqName)
|
||||||
}
|
}
|
||||||
|
|
||||||
val nestedClasses = mapJList<InnerClassNode, JCTree>(clazz.innerClasses) { innerClass ->
|
val nestedClasses = mapJList<InnerClassNode, JCTree>(clazz.innerClasses) { innerClass ->
|
||||||
|
if (enumValuesData.any { it.innerClass == innerClass }) return@mapJList null
|
||||||
if (innerClass.outerName != clazz.name) return@mapJList null
|
if (innerClass.outerName != clazz.name) return@mapJList null
|
||||||
val innerClassNode = kaptContext.compiledClasses.firstOrNull { it.name == innerClass.name } ?: return@mapJList null
|
val innerClassNode = kaptContext.compiledClasses.firstOrNull { it.name == innerClass.name } ?: return@mapJList null
|
||||||
convertClass(innerClassNode, packageFqName, false)
|
convertClass(innerClassNode, packageFqName, false)
|
||||||
@@ -221,10 +251,32 @@ class ClassFileToSourceStubConverter(
|
|||||||
genericType.typeParameters,
|
genericType.typeParameters,
|
||||||
if (hasSuperClass) genericType.superClass else null,
|
if (hasSuperClass) genericType.superClass else null,
|
||||||
genericType.interfaces,
|
genericType.interfaces,
|
||||||
fields + methods + nestedClasses)
|
enumValues + fields + methods + nestedClasses)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertField(field: FieldNode, packageFqName: String): JCVariableDecl? {
|
private fun getClassAccessFlags(clazz: ClassNode, descriptor: DeclarationDescriptor, isInner: Boolean, isNested: Boolean) = when {
|
||||||
|
(descriptor.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.INTERFACE -> {
|
||||||
|
// Classes inside interfaces should always be public and static.
|
||||||
|
// See com.sun.tools.javac.comp.Enter.visitClassDef for more information.
|
||||||
|
(clazz.access or Opcodes.ACC_PUBLIC or Opcodes.ACC_STATIC) and
|
||||||
|
Opcodes.ACC_PRIVATE.inv() and Opcodes.ACC_PROTECTED.inv() // Remove private and protected modifiers
|
||||||
|
}
|
||||||
|
!isInner && isNested -> clazz.access or Opcodes.ACC_STATIC
|
||||||
|
else -> clazz.access
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getClassName(clazz: ClassNode, descriptor: DeclarationDescriptor, isDefaultImpls: Boolean, packageFqName: String): String {
|
||||||
|
return when (descriptor) {
|
||||||
|
is PackageFragmentDescriptor -> {
|
||||||
|
val className = if (packageFqName.isEmpty()) clazz.name else clazz.name.drop(packageFqName.length + 1)
|
||||||
|
if (className.isEmpty()) throw IllegalStateException("Invalid package facade class name: ${clazz.name}")
|
||||||
|
className
|
||||||
|
}
|
||||||
|
else -> if (isDefaultImpls) "DefaultImpls" else descriptor.name.asString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun convertField(field: FieldNode, packageFqName: String, explicitInitializer: JCExpression? = null): JCVariableDecl? {
|
||||||
if (isSynthetic(field.access)) return null
|
if (isSynthetic(field.access)) return null
|
||||||
val descriptor = kaptContext.origins[field]?.descriptor
|
val descriptor = kaptContext.origins[field]?.descriptor
|
||||||
|
|
||||||
@@ -244,7 +296,8 @@ class ClassFileToSourceStubConverter(
|
|||||||
|
|
||||||
val value = field.value
|
val value = field.value
|
||||||
|
|
||||||
val initializer = convertValueOfPrimitiveTypeOrString(value)
|
val initializer = explicitInitializer
|
||||||
|
?: convertValueOfPrimitiveTypeOrString(value)
|
||||||
?: if (isFinal(field.access)) convertLiteralExpression(getDefaultValue(type)) else null
|
?: if (isFinal(field.access)) convertLiteralExpression(getDefaultValue(type)) else null
|
||||||
|
|
||||||
return treeMaker.VarDef(modifiers, name, typeExpression, initializer)
|
return treeMaker.VarDef(modifiers, name, typeExpression, initializer)
|
||||||
@@ -460,6 +513,7 @@ class ClassFileToSourceStubConverter(
|
|||||||
} ?: annotations
|
} ?: annotations
|
||||||
|
|
||||||
val flags = when (kind) {
|
val flags = when (kind) {
|
||||||
|
ElementKind.ENUM -> access and CLASS_MODIFIERS and Opcodes.ACC_ABSTRACT.inv().toLong()
|
||||||
ElementKind.CLASS -> access and CLASS_MODIFIERS
|
ElementKind.CLASS -> access and CLASS_MODIFIERS
|
||||||
ElementKind.METHOD -> access and METHOD_MODIFIERS
|
ElementKind.METHOD -> access and METHOD_MODIFIERS
|
||||||
ElementKind.FIELD -> access and FIELD_MODIFIERS
|
ElementKind.FIELD -> access and FIELD_MODIFIERS
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.tree.AnnotationNode
|
import org.jetbrains.org.objectweb.asm.tree.AnnotationNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.ClassNode
|
import org.jetbrains.org.objectweb.asm.tree.ClassNode
|
||||||
|
import org.jetbrains.org.objectweb.asm.tree.FieldNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
internal fun isEnum(access: Int) = (access and Opcodes.ACC_ENUM) != 0
|
internal fun isEnum(access: Int) = (access and Opcodes.ACC_ENUM) != 0
|
||||||
@@ -33,6 +34,8 @@ internal fun ClassNode.isEnum() = (access and Opcodes.ACC_ENUM) != 0
|
|||||||
internal fun ClassNode.isAnnotation() = (access and Opcodes.ACC_ANNOTATION) != 0
|
internal fun ClassNode.isAnnotation() = (access and Opcodes.ACC_ANNOTATION) != 0
|
||||||
internal fun MethodNode.isVarargs() = (access and Opcodes.ACC_VARARGS) != 0
|
internal fun MethodNode.isVarargs() = (access and Opcodes.ACC_VARARGS) != 0
|
||||||
|
|
||||||
|
internal fun FieldNode.isEnumValue() = (access and Opcodes.ACC_ENUM) != 0
|
||||||
|
|
||||||
internal fun <T> List<T>?.isNullOrEmpty() = this == null || this.isEmpty()
|
internal fun <T> List<T>?.isNullOrEmpty() = this == null || this.isEmpty()
|
||||||
|
|
||||||
internal fun MethodNode.isJvmOverloadsGenerated(): Boolean {
|
internal fun MethodNode.isJvmOverloadsGenerated(): Boolean {
|
||||||
|
|||||||
+6
@@ -32,6 +32,12 @@ import java.util.regex.Pattern;
|
|||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFileToSourceStubConverterTest {
|
public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFileToSourceStubConverterTest {
|
||||||
|
@TestMetadata("abstractEnum.kt")
|
||||||
|
public void testAbstractEnum() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/abstractEnum.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("abstractMethods.kt")
|
@TestMetadata("abstractMethods.kt")
|
||||||
public void testAbstractMethods() throws Exception {
|
public void testAbstractMethods() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/abstractMethods.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/abstractMethods.kt");
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
enum class E {
|
||||||
|
X {
|
||||||
|
override fun a() {}
|
||||||
|
},
|
||||||
|
Y {
|
||||||
|
override fun a() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract fun a()
|
||||||
|
|
||||||
|
fun b() {}
|
||||||
|
|
||||||
|
object Obj
|
||||||
|
class NestedClass
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class E2 {
|
||||||
|
X("") {
|
||||||
|
override fun a() {}
|
||||||
|
},
|
||||||
|
Y(5) {
|
||||||
|
override fun a() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(n: Int) {}
|
||||||
|
constructor(s: String) {}
|
||||||
|
|
||||||
|
abstract fun a()
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class E3(val a: String) {
|
||||||
|
X(""), Y("")
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class E4(val a: String, val b: Int, val c: Long, val d: Boolean) {
|
||||||
|
X("", 4, 2L, true)
|
||||||
|
}
|
||||||
+125
@@ -0,0 +1,125 @@
|
|||||||
|
public enum E {
|
||||||
|
/*public static final*/ X /* = new X(){
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public void a() {
|
||||||
|
}
|
||||||
|
|
||||||
|
X() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
} */,
|
||||||
|
/*public static final*/ Y /* = new Y(){
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public void a() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Y() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
} */;
|
||||||
|
|
||||||
|
public abstract void a();
|
||||||
|
|
||||||
|
public final void b() {
|
||||||
|
}
|
||||||
|
|
||||||
|
E() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Obj {
|
||||||
|
public static final E.Obj INSTANCE = null;
|
||||||
|
|
||||||
|
private Obj() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class NestedClass {
|
||||||
|
|
||||||
|
public NestedClass() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
public enum E2 {
|
||||||
|
/*public static final*/ X /* = new X(0){
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public void a() {
|
||||||
|
}
|
||||||
|
|
||||||
|
X() {
|
||||||
|
super(0);
|
||||||
|
}
|
||||||
|
} */,
|
||||||
|
/*public static final*/ Y /* = new Y(0){
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public void a() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Y() {
|
||||||
|
super(0);
|
||||||
|
}
|
||||||
|
} */;
|
||||||
|
|
||||||
|
public abstract void a();
|
||||||
|
|
||||||
|
E2(int n) {
|
||||||
|
}
|
||||||
|
|
||||||
|
E2(java.lang.String s) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
public enum E3 {
|
||||||
|
/*public static final*/ X /* = new X(null) */,
|
||||||
|
/*public static final*/ Y /* = new Y(null) */;
|
||||||
|
private final java.lang.String a = null;
|
||||||
|
|
||||||
|
public final java.lang.String getA() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
E3(java.lang.String a) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
public enum E4 {
|
||||||
|
/*public static final*/ X /* = new X(null, 0, 0L, false) */;
|
||||||
|
private final java.lang.String a = null;
|
||||||
|
private final int b = 0;
|
||||||
|
private final long c = 0L;
|
||||||
|
private final boolean d = false;
|
||||||
|
|
||||||
|
public final java.lang.String getA() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getB() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final long getC() {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean getD() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
E4(java.lang.String a, int b, long c, boolean d) {
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -37,8 +37,8 @@ public abstract @interface Anno3 {
|
|||||||
|
|
||||||
|
|
||||||
public enum Colors {
|
public enum Colors {
|
||||||
/*public static final*/ WHITE /* = null */,
|
/*public static final*/ WHITE /* = new WHITE() */,
|
||||||
/*public static final*/ BLACK /* = null */;
|
/*public static final*/ BLACK /* = new BLACK() */;
|
||||||
|
|
||||||
Colors() {
|
Colors() {
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -37,8 +37,8 @@ package test;
|
|||||||
|
|
||||||
@Anno(value = "enum")
|
@Anno(value = "enum")
|
||||||
public enum Enum {
|
public enum Enum {
|
||||||
/*public static final*/ WHITE /* = null */,
|
/*public static final*/ WHITE /* = new WHITE(0) */,
|
||||||
/*public static final*/ BLACK /* = null */;
|
/*public static final*/ BLACK /* = new BLACK(0) */;
|
||||||
private final int x = 0;
|
private final int x = 0;
|
||||||
|
|
||||||
public final int getX() {
|
public final int getX() {
|
||||||
|
|||||||
+4
-4
@@ -7,8 +7,8 @@ public abstract @interface Anno1 {
|
|||||||
|
|
||||||
|
|
||||||
public enum Enum1 {
|
public enum Enum1 {
|
||||||
/*public static final*/ BLACK /* = null */,
|
/*public static final*/ BLACK /* = new BLACK() */,
|
||||||
/*public static final*/ WHITE /* = null */;
|
/*public static final*/ WHITE /* = new WHITE() */;
|
||||||
|
|
||||||
Enum1() {
|
Enum1() {
|
||||||
}
|
}
|
||||||
@@ -18,8 +18,8 @@ public enum Enum1 {
|
|||||||
|
|
||||||
|
|
||||||
public enum Enum2 {
|
public enum Enum2 {
|
||||||
/*public static final*/ RED /* = null */,
|
/*public static final*/ RED /* = new RED(null, 0) */,
|
||||||
/*public static final*/ WHITE /* = null */;
|
/*public static final*/ WHITE /* = new WHITE(null, 0) */;
|
||||||
private final java.lang.String col = null;
|
private final java.lang.String col = null;
|
||||||
private final int col2 = 0;
|
private final int col2 = 0;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -32,8 +32,8 @@ public final class Inheritor extends BaseClass {
|
|||||||
|
|
||||||
|
|
||||||
public enum Result {
|
public enum Result {
|
||||||
/*public static final*/ SUCCESS /* = null */,
|
/*public static final*/ SUCCESS /* = new SUCCESS() */,
|
||||||
/*public static final*/ ERROR /* = null */;
|
/*public static final*/ ERROR /* = new ERROR() */;
|
||||||
|
|
||||||
Result() {
|
Result() {
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -37,8 +37,8 @@ public final class Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static enum NestedEnum {
|
public static enum NestedEnum {
|
||||||
/*public static final*/ BLACK /* = null */,
|
/*public static final*/ BLACK /* = new BLACK() */,
|
||||||
/*public static final*/ WHITE /* = null */;
|
/*public static final*/ WHITE /* = new WHITE() */;
|
||||||
|
|
||||||
NestedEnum() {
|
NestedEnum() {
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-14
@@ -1,8 +1,20 @@
|
|||||||
package test;
|
package test;
|
||||||
|
|
||||||
|
public enum EnumClass {
|
||||||
|
/*public static final*/ BLACK /* = new BLACK() */,
|
||||||
|
/*public static final*/ WHITE /* = new WHITE() */;
|
||||||
|
|
||||||
|
EnumClass() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
package test;
|
||||||
|
|
||||||
public enum EnumClass2 {
|
public enum EnumClass2 {
|
||||||
/*public static final*/ WHITE /* = null */,
|
/*public static final*/ WHITE /* = new WHITE(null) */,
|
||||||
/*public static final*/ RED /* = null */;
|
/*public static final*/ RED /* = new RED(null) */;
|
||||||
private final java.lang.String blah = null;
|
private final java.lang.String blah = null;
|
||||||
|
|
||||||
EnumClass2(java.lang.String blah) {
|
EnumClass2(java.lang.String blah) {
|
||||||
@@ -18,18 +30,6 @@ public abstract @interface MyAnnotation {
|
|||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
|
|
||||||
package test;
|
|
||||||
|
|
||||||
public enum EnumClass {
|
|
||||||
/*public static final*/ BLACK /* = null */,
|
|
||||||
/*public static final*/ WHITE /* = null */;
|
|
||||||
|
|
||||||
EnumClass() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////
|
|
||||||
|
|
||||||
package error;
|
package error;
|
||||||
|
|
||||||
public final class NonExistentClass {
|
public final class NonExistentClass {
|
||||||
|
|||||||
+9
@@ -24,4 +24,13 @@ enum EnumClass2 {
|
|||||||
EnumClass2(String blah) {
|
EnumClass2(String blah) {
|
||||||
this.blah = blah;
|
this.blah = blah;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EnumClass3 {
|
||||||
|
A {
|
||||||
|
@Override
|
||||||
|
void a() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract void a();
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user