Kapt3: Initialize final fields in class constructors

This commit is contained in:
Yan Zhulanow
2016-10-26 00:41:24 +03:00
committed by Yan Zhulanow
parent 666a522fed
commit edaadb0d48
2 changed files with 23 additions and 5 deletions
@@ -98,7 +98,7 @@ class JCTreeConverter(context: Context, val classes: List<ClassNode>, val origin
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) }
val methods = mapValues<MethodNode, JCTree>(clazz.methods) { convertMethod(it, simpleName) } val methods = mapValues<MethodNode, JCTree>(clazz.methods) { convertMethod(it, clazz, simpleName) }
val nestedClasses = mapValues<InnerClassNode, JCTree>(clazz.innerClasses) { innerClass -> val nestedClasses = mapValues<InnerClassNode, JCTree>(clazz.innerClasses) { innerClass ->
if (innerClass.outerName != clazz.name) return@mapValues null if (innerClass.outerName != clazz.name) return@mapValues null
val innerClassNode = classes.firstOrNull { it.name == innerClass.name } ?: return@mapValues null val innerClassNode = classes.firstOrNull { it.name == innerClass.name } ?: return@mapValues null
@@ -122,7 +122,7 @@ class JCTreeConverter(context: Context, val classes: List<ClassNode>, val origin
return treeMaker.VarDef(modifiers, name, type, initializer) return treeMaker.VarDef(modifiers, name, type, initializer)
} }
private fun convertMethod(method: MethodNode, containingClassSimpleName: Name): JCMethodDecl? { private fun convertMethod(method: MethodNode, containingClass: ClassNode, containingClassSimpleName: Name): JCMethodDecl? {
if (isSynthetic(method.access)) return null if (isSynthetic(method.access)) return null
val modifiers = convertModifiers(method.access, ElementKind.METHOD, method.visibleAnnotations, method.invisibleAnnotations) val modifiers = convertModifiers(method.access, ElementKind.METHOD, method.visibleAnnotations, method.invisibleAnnotations)
@@ -132,9 +132,10 @@ class JCTreeConverter(context: Context, val classes: List<ClassNode>, val origin
val receiverParameter = null val receiverParameter = null
val returnType = Type.getReturnType(method.desc) val returnType = Type.getReturnType(method.desc)
val returnTypeExpr = convertFqName(returnType.className) val returnTypeExpr = if (isConstructor) null else convertFqName(returnType.className)
val parametersInfo = method.getParametersInfo() val parametersInfo = method.getParametersInfo()
@Suppress("NAME_SHADOWING")
val parameters = mapValues(parametersInfo) { info -> val parameters = mapValues(parametersInfo) { info ->
val modifiers = convertModifiers(info.access, ElementKind.PARAMETER, info.visibleAnnotations, info.invisibleAnnotations) val modifiers = convertModifiers(info.access, ElementKind.PARAMETER, info.visibleAnnotations, info.invisibleAnnotations)
val name = name(info.name) val name = name(info.name)
@@ -148,7 +149,20 @@ class JCTreeConverter(context: Context, val classes: List<ClassNode>, val origin
val body = if (defaultValue != null) { val body = if (defaultValue != null) {
null null
} else if (isConstructor || returnType == Type.VOID_TYPE) { } else if (isConstructor) {
var statements = JavacList.nil<JCStatement>()
for (field in containingClass.fields) {
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) {
treeMaker.Block(0, JavacList.nil()) treeMaker.Block(0, JavacList.nil())
} else { } else {
val returnStatement = treeMaker.Return(convertLiteralExpression(getDefaultValue(returnType))) val returnStatement = treeMaker.Return(convertLiteralExpression(getDefaultValue(returnType)))
+5 -1
View File
@@ -1,3 +1,4 @@
public final class User { public final class User {
private final java.lang.String firstName; private final java.lang.String firstName;
private final java.lang.String secondName; private final java.lang.String secondName;
@@ -18,7 +19,10 @@ public final class User {
return 0; return 0;
} }
public void User(java.lang.String firstName, java.lang.String secondName, int age) { public /*missing*/ User(java.lang.String firstName, java.lang.String secondName, int age) {
this.firstName = null;
this.secondName = null;
this.age = 0;
} }
public final java.lang.String component1() { public final java.lang.String component1() {