diff options
Diffstat (limited to 'src/core/lombok/javac')
-rw-r--r-- | src/core/lombok/javac/handlers/HandleBuilder.java | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 1e8b8a22..0bd43ba4 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -45,6 +45,7 @@ import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.JCTree.JCIf; import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCModifiers; import com.sun.tools.javac.tree.JCTree.JCNewClass; import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree; @@ -553,7 +554,9 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.<JCExpression>nil(), null); JCExpression invoke = call; + ListBuffer<JCStatement> preStatements = null; ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); + for (BuilderFieldData bfd : builderFields) { String setterPrefix = !prefix.isEmpty() ? prefix : fluent ? "" : "set"; String prefixedSetterName = bfd.name.toString(); @@ -566,17 +569,22 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { tgt[i] = maker.Select(maker.Ident(type.toName("this")), bfd.obtainVia == null ? bfd.rawName : type.toName(bfd.obtainVia.field())); } } else { + String name = bfd.obtainVia.method(); + JCMethodInvocation inv; if (bfd.obtainVia.isStatic()) { - for (int i = 0; i < tgt.length; i++) { - JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(bfd.obtainVia.method())); - tgt[i] = maker.Apply(typeParameterNames(maker, typeParams), c, List.<JCExpression>of(maker.Ident(type.toName("this")))); - } + JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(name)); + inv = maker.Apply(typeParameterNames(maker, typeParams), c, List.<JCExpression>of(maker.Ident(type.toName("this")))); } else { - for (int i = 0; i < tgt.length; i++) { - JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(bfd.obtainVia.method())); - tgt[i] = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>nil()); - } + JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(name)); + inv = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>nil()); } + for (int i = 0; i < tgt.length; i++) tgt[i] = maker.Ident(bfd.name); + + // javac appears to cache the type of JCMethodInvocation expressions based on position, meaning, if you have 2 ObtainVia-based method invokes on different types, you get bizarre type mismatch errors. + // going via a local variable declaration solves the problem. + JCExpression varType = JavacHandlerUtil.cloneType(maker, bfd.type, ast, type.getContext()); + if (preStatements == null) preStatements = new ListBuffer<JCStatement>(); + preStatements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), bfd.name, varType, inv)); } JCExpression arg; @@ -589,6 +597,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { statements.append(maker.If(isNotNull, maker.Exec(invokeBuilder), null)); } } + if (!statements.isEmpty()) { JCExpression tempVarType = namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams); statements.prepend(maker.VarDef(maker.Modifiers(Flags.FINAL), type.toName(BUILDER_TEMP_VAR), tempVarType, invoke)); @@ -596,6 +605,11 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } else { statements.append(maker.Return(invoke)); } + + if (preStatements != null) { + preStatements.appendList(statements); + statements = preStatements; + } JCBlock body = maker.Block(0, statements.toList()); List<JCAnnotation> annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__UNIQUE), List.<JCExpression>nil())) : List.<JCAnnotation>nil(); return maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); |