diff options
author | Jan Rieke <rieke@subshell.com> | 2018-06-01 13:48:38 +0200 |
---|---|---|
committer | Jan Rieke <rieke@subshell.com> | 2018-06-01 15:57:59 +0200 |
commit | d11263a6c60008894213a1b465f2b16be3a03468 (patch) | |
tree | cec107359645cae08db71535846839cb86376949 /src/core/lombok/javac/handlers/HandleSuperBuilder.java | |
parent | 51c0c40ac422ddd2828bb0ec79e252e85f1511c9 (diff) | |
download | lombok-d11263a6c60008894213a1b465f2b16be3a03468.tar.gz lombok-d11263a6c60008894213a1b465f2b16be3a03468.tar.bz2 lombok-d11263a6c60008894213a1b465f2b16be3a03468.zip |
support @Builder.Default
Diffstat (limited to 'src/core/lombok/javac/handlers/HandleSuperBuilder.java')
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSuperBuilder.java | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index c48e4761..beee47a9 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -39,6 +39,7 @@ import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCIdent; +import com.sun.tools.javac.tree.JCTree.JCIf; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCModifiers; @@ -82,7 +83,6 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JCExpression type; Name rawName; Name name; - Name nameOfDefaultProvider; Name nameOfSetFlag; SingularData singularData; ObtainVia obtainVia; @@ -164,13 +164,16 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } if (isDefault != null) { - bfd.nameOfDefaultProvider = tdParent.toName("$default$" + bfd.name); bfd.nameOfSetFlag = tdParent.toName(bfd.name + "$set"); - JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams); - recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); - if (md != null) { - injectMethod(tdParent, md); - } + // The @Builder annotation removes the initializing expression on the field and moves + // it to a method called "$default$FIELDNAME". This method is then called upon building. + // We do NOT do this, because this is unexpected and may lead to bugs when using other + // constructors (see, e.g., issue #1347). + // Instead, we keep the init expression and only set a new value in the builder-based + // constructor if it was set in the builder. Drawback is that the init expression is + // always executed, even if it was unnecessary because its value is overwritten by the + // builder. + // TODO: Once the issue is resolved in @Builder, we can adapt the solution here. } addObtainVia(bfd, fieldNode); builderFields.add(bfd); @@ -435,9 +438,16 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { } JCFieldAccess thisX = maker.Select(maker.Ident(typeNode.toName("this")), bfd.rawName); - JCExpression assign = maker.Assign(thisX, rhs); - - statements.append(maker.Exec(assign)); + JCStatement assign = maker.Exec(maker.Assign(thisX, rhs)); + + // In case of @Builder.Default, only set the value if it really was set in the builder. + if (bfd.nameOfSetFlag != null) { + JCFieldAccess setField = maker.Select(maker.Ident(builderVariableName), bfd.nameOfSetFlag); + JCIf ifSet = maker.If(setField, assign, null); + statements.append(ifSet); + } else { + statements.append(assign); + } } JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.<JCAnnotation>nil()); @@ -575,18 +585,6 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); } - private JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode, List<JCTypeParameter> params) { - JavacTreeMaker maker = fieldNode.getTreeMaker(); - JCVariableDecl field = (JCVariableDecl) fieldNode.get(); - - JCStatement statement = maker.Return(field.init); - field.init = null; - - JCBlock body = maker.Block(0, List.<JCStatement>of(statement)); - int modifiers = Flags.PRIVATE | Flags.STATIC; - return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, field, fieldNode.getContext()), copyTypeParams(fieldNode, params), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null); - } - private void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JCTree source) { int len = builderFields.size(); java.util.List<JavacNode> existing = new ArrayList<JavacNode>(); |