Kapt3: Put static modifiers on nested non-inner classes.

Do not initialize synthetic and static fields in constructor.
This commit is contained in:
Yan Zhulanow
2016-10-26 03:41:13 +03:00
committed by Yan Zhulanow
parent 68c2e8d71d
commit e131763cb0
7 changed files with 119 additions and 30 deletions
@@ -46,7 +46,7 @@ class JCTreeConverter(
private val MODALITY_MODIFIERS = Opcodes.ACC_FINAL or Opcodes.ACC_ABSTRACT private val MODALITY_MODIFIERS = Opcodes.ACC_FINAL or Opcodes.ACC_ABSTRACT
private val CLASS_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or private val CLASS_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or
Opcodes.ACC_DEPRECATED or Opcodes.ACC_INTERFACE or Opcodes.ACC_ANNOTATION or Opcodes.ACC_ENUM Opcodes.ACC_DEPRECATED or Opcodes.ACC_INTERFACE or Opcodes.ACC_ANNOTATION or Opcodes.ACC_ENUM or Opcodes.ACC_STATIC
private val METHOD_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or private val METHOD_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or
Opcodes.ACC_SYNCHRONIZED or Opcodes.ACC_STATIC or Opcodes.ACC_NATIVE or Opcodes.ACC_DEPRECATED Opcodes.ACC_SYNCHRONIZED or Opcodes.ACC_STATIC or Opcodes.ACC_NATIVE or Opcodes.ACC_DEPRECATED
@@ -80,7 +80,7 @@ class JCTreeConverter(
val descriptor = origin.descriptor as? ClassDescriptor ?: return null val descriptor = origin.descriptor as? ClassDescriptor ?: return null
// Nested classes will be processed during the outer classes conversion // Nested classes will be processed during the outer classes conversion
if (descriptor.containingDeclaration is ClassDescriptor) return null if (descriptor.isNested) return null
val classDeclaration = convertClass(clazz) val classDeclaration = convertClass(clazz)
@@ -101,10 +101,13 @@ class JCTreeConverter(
if (isSynthetic(clazz.access)) return null if (isSynthetic(clazz.access)) return null
val descriptor = origins[clazz]?.descriptor as? ClassDescriptor ?: return null val descriptor = origins[clazz]?.descriptor as? ClassDescriptor ?: return null
val modifiers = convertModifiers(clazz.access, ElementKind.CLASS, clazz.visibleAnnotations, clazz.invisibleAnnotations) val modifiers = convertModifiers(
if (!descriptor.isInner && descriptor.isNested) (clazz.access or Opcodes.ACC_STATIC) else clazz.access,
ElementKind.CLASS, clazz.visibleAnnotations, clazz.invisibleAnnotations)
val simpleName = name(descriptor.name.asString()) val simpleName = name(descriptor.name.asString())
val typeParams = JavacList.nil<JCTypeParameter>() val typeParams = JavacList.nil<JCTypeParameter>()
val extending = if (clazz.superName == "java/lang/Object") null else convertFqName(clazz.superName) val extending = if (clazz.superName == "java/lang/Object" || clazz.isEnum()) null else convertFqName(clazz.superName)
val implementing = mapValues(clazz.interfaces) { convertFqName(it) } val implementing = mapValues(clazz.interfaces) { convertFqName(it) }
val fields = mapValues<FieldNode, JCTree>(clazz.fields) { convertField(it) } val fields = mapValues<FieldNode, JCTree>(clazz.fields) { convertField(it) }
@@ -123,13 +126,14 @@ class JCTreeConverter(
val modifiers = convertModifiers(field.access, ElementKind.FIELD, field.visibleAnnotations, field.invisibleAnnotations) val modifiers = convertModifiers(field.access, ElementKind.FIELD, field.visibleAnnotations, field.invisibleAnnotations)
val name = name(field.name) val name = name(field.name)
val type = convertFqName(Type.getType(field.desc).className) val type = Type.getType(field.desc)
val typeExpression = convertFqName(type.className)
val value = field.value val value = field.value
val initializer = when (value) { val initializer = when (value) {
is Byte, is Boolean, is Char, is Short, is Int, is Long, is Float, is Double, is String -> treeMaker.Literal(value) is Byte, is Boolean, is Char, is Short, is Int, is Long, is Float, is Double, is String -> treeMaker.Literal(value)
else -> null else -> if (isFinal(field.access)) convertLiteralExpression(getDefaultValue(type)) else null
} }
return treeMaker.VarDef(modifiers, name, type, initializer) return treeMaker.VarDef(modifiers, name, typeExpression, initializer)
} }
private fun convertMethod(method: MethodNode, containingClass: ClassNode, containingClassSimpleName: Name): JCMethodDecl? { private fun convertMethod(method: MethodNode, containingClass: ClassNode, containingClassSimpleName: Name): JCMethodDecl? {
@@ -176,7 +180,7 @@ class JCTreeConverter(
val superClass = declaration.getSuperClassOrAny() val superClass = declaration.getSuperClassOrAny()
val superClassConstructor = superClass.constructors.firstOrNull { it.visibility.isVisible(null, it, declaration) } val superClassConstructor = superClass.constructors.firstOrNull { it.visibility.isVisible(null, it, declaration) }
var statements = if (superClassConstructor != null) { val superClassConstructorCall = if (superClassConstructor != null) {
val args = mapValues(superClassConstructor.valueParameters) { param -> val args = mapValues(superClassConstructor.valueParameters) { param ->
convertLiteralExpression(getDefaultValue(typeMapper.mapType(param.type))) convertLiteralExpression(getDefaultValue(typeMapper.mapType(param.type)))
} }
@@ -186,16 +190,7 @@ class JCTreeConverter(
JavacList.nil<JCStatement>() JavacList.nil<JCStatement>()
} }
for (field in containingClass.fields) { treeMaker.Block(0, superClassConstructorCall)
if ((field.access and Opcodes.ACC_FINAL) == 0) continue
val type = Type.getType(field.desc)
val assignment = treeMaker.Assign(
convertFqName("this.${field.name}"),
convertLiteralExpression(getDefaultValue(type)))
statements = statements.append(treeMaker.Exec(assignment))
}
treeMaker.Block(0, statements)
} else if (returnType == Type.VOID_TYPE) { } else if (returnType == Type.VOID_TYPE) {
treeMaker.Block(0, JavacList.nil()) treeMaker.Block(0, JavacList.nil())
} else { } else {
@@ -342,4 +337,10 @@ private operator fun <T : Any> JavacList<T>.plus(other: JavacList<T>): JavacList
return this.appendList(other) return this.appendList(other)
} }
private fun isSynthetic(access: Int) = (access and Opcodes.ACC_SYNTHETIC) > 0 private val ClassDescriptor.isNested: Boolean
get() = containingDeclaration is ClassDescriptor
private fun isSynthetic(access: Int) = (access and Opcodes.ACC_SYNTHETIC) > 0
private fun isFinal(access: Int) = (access and Opcodes.ACC_FINAL) > 0
private fun isStatic(access: Int) = (access and Opcodes.ACC_STATIC) > 0
private fun ClassNode.isEnum() = (access and Opcodes.ACC_ENUM) > 0
@@ -46,4 +46,10 @@ public class JCTreeConverterTestGenerated extends AbstractJCTreeConverterTest {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/inheritanceSimple.kt"); String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/inheritanceSimple.kt");
doTest(fileName); doTest(fileName);
} }
@TestMetadata("nestedClasses.kt")
public void testNestedClasses() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/nestedClasses.kt");
doTest(fileName);
}
} }
+3 -6
View File
@@ -1,8 +1,8 @@
public final class User { public final class User {
private final java.lang.String firstName; private final java.lang.String firstName = null;
private final java.lang.String secondName; private final java.lang.String secondName = null;
private final int age; private final int age = 0;
public final void procedure() { public final void procedure() {
} }
@@ -21,9 +21,6 @@ public final class User {
public /*missing*/ User(java.lang.String firstName, java.lang.String secondName, int age) { public /*missing*/ User(java.lang.String firstName, java.lang.String secondName, int age) {
super(); super();
this.firstName = null;
this.secondName = null;
this.age = 0;
} }
public final java.lang.String component1() { public final java.lang.String component1() {
+3 -5
View File
@@ -11,15 +11,13 @@ public final class Context {
//////////////////// ////////////////////
public enum Result extends java.lang.Enum { public enum Result {
; ;
public static final Result SUCCESS; public static final Result SUCCESS = null;
public static final Result ERROR; public static final Result ERROR = null;
protected /*missing*/ Result(java.lang.String $enum_name_or_ordinal$0, int $enum_name_or_ordinal$1) { protected /*missing*/ Result(java.lang.String $enum_name_or_ordinal$0, int $enum_name_or_ordinal$1) {
super(null, 0); super(null, 0);
this.SUCCESS = null;
this.ERROR = null;
} }
public static Result[] values() { public static Result[] values() {
+15
View File
@@ -0,0 +1,15 @@
class Test {
class Nested {
class NestedNested
}
inner class Inner
object NestedObject
interface NestedInterface
enum class NestedEnum {
BLACK, WHITE
}
}
+57
View File
@@ -0,0 +1,57 @@
public final class Test {
public /*missing*/ Test() {
super();
}
public static final class Nested {
public /*missing*/ Nested() {
super();
}
public static final class NestedNested {
public /*missing*/ NestedNested() {
super();
}
}
}
public final class Inner {
public /*missing*/ Inner(Test $outer) {
super();
}
}
public static final class NestedObject {
public static final Test.NestedObject INSTANCE = null;
private /*missing*/ NestedObject() {
super();
}
}
public static abstract interface NestedInterface {
}
public static enum NestedEnum {
;
public static final Test.NestedEnum BLACK = null;
public static final Test.NestedEnum WHITE = null;
protected /*missing*/ NestedEnum(java.lang.String $enum_name_or_ordinal$0, int $enum_name_or_ordinal$1) {
super(null, 0);
}
public static Test.NestedEnum[] values() {
return null;
}
public static Test.NestedEnum valueOf(java.lang.String p0) {
return null;
}
}
}
+15
View File
@@ -9,4 +9,19 @@ class Simple {
@interface MyAnnotation { @interface MyAnnotation {
}
enum EnumClass {
BLACK, WHITE
}
enum EnumClass2 {
WHITE("A"), RED("B");
private final String blah;
EnumClass2(String blah) {
this.blah = blah;
}
} }