From f46aa53e8c592f562ef5dc21e65e9c74c98a8ecc Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Fri, 10 Feb 2017 17:02:29 +0100 Subject: builder-based constructors for type @Builders [Eclipse] --- .../lombok/eclipse/handlers/HandleBuilder.java | 56 ++++++++++++++++++---- 1 file changed, 47 insertions(+), 9 deletions(-) (limited to 'src/core/lombok/eclipse/handlers/HandleBuilder.java') diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index afa03538..4f152fe3 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -139,6 +139,10 @@ public class HandleBuilder extends EclipseAnnotationHandler { String builderMethodName = builderInstance.builderMethodName(); String buildMethodName = builderInstance.buildMethodName(); String builderClassName = builderInstance.builderClassName(); + + boolean inherit = builderInstance.inherit(); + String superclassBuilderClassName = builderInstance.superclassBuilderClassName(); + String toBuilderMethodName = "toBuilder"; boolean toBuilder = builderInstance.toBuilder(); List typeArgsForToBuilder = null; @@ -146,6 +150,9 @@ public class HandleBuilder extends EclipseAnnotationHandler { if (builderMethodName == null) builderMethodName = "builder"; if (buildMethodName == null) builderMethodName = "build"; if (builderClassName == null) builderClassName = ""; + if (superclassBuilderClassName == null) { + superclassBuilderClassName = ""; + } if (!checkName("builderMethodName", builderMethodName, annotationNode)) return; if (!checkName("buildMethodName", buildMethodName, annotationNode)) return; @@ -189,15 +196,26 @@ public class HandleBuilder extends EclipseAnnotationHandler { allFields.add(fieldNode); } - new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, null, - Collections.emptyList(), annotationNode); + if (builderClassName.isEmpty()) { + builderClassName = new String(td.name) + "Builder"; + } + if (superclassBuilderClassName.isEmpty() && td.superclass != null) { + superclassBuilderClassName = new String(td.superclass.getLastToken()) + "Builder"; + } + + boolean callSuperConstructor = inherit && td.superclass != null; + new HandleConstructor().generateConstructor(tdParent, AccessLevel.PROTECTED, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, true, + Collections.emptyList(), annotationNode, builderClassName, callSuperConstructor); returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p); typeParams = td.typeParameters; thrownExceptions = null; nameOfStaticBuilderMethod = null; - if (builderClassName.isEmpty()) builderClassName = new String(td.name) + "Builder"; } else if (parent.get() instanceof ConstructorDeclaration) { + if (inherit) { + annotationNode.addError("@Builder(inherit=true) is only supported for type builders."); + return; + } ConstructorDeclaration cd = (ConstructorDeclaration) parent.get(); if (cd.typeParameters != null && cd.typeParameters.length > 0) { annotationNode.addError("@Builder is not supported on constructors with constructor type parameters."); @@ -212,6 +230,10 @@ public class HandleBuilder extends EclipseAnnotationHandler { nameOfStaticBuilderMethod = null; if (builderClassName.isEmpty()) builderClassName = new String(cd.selector) + "Builder"; } else if (parent.get() instanceof MethodDeclaration) { + if (inherit) { + annotationNode.addError("@Builder(inherit=true) is only supported for type builders."); + return; + } MethodDeclaration md = (MethodDeclaration) parent.get(); tdParent = parent.up(); isStatic = md.isStatic(); @@ -341,7 +363,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { EclipseNode builderType = findInnerClass(tdParent, builderClassName); if (builderType == null) { - builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast); + builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast, inherit ? superclassBuilderClassName : null); } else { TypeDeclaration builderTypeDeclaration = (TypeDeclaration) builderType.get(); if (isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) { @@ -396,7 +418,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) { ConstructorDeclaration cd = HandleConstructor.createConstructor( AccessLevel.PACKAGE, builderType, Collections.emptyList(), false, null, - annotationNode, Collections.emptyList()); + annotationNode, Collections.emptyList(), null, false); if (cd != null) injectMethod(builderType, cd); } @@ -405,7 +427,8 @@ public class HandleBuilder extends EclipseAnnotationHandler { } if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) { - MethodDeclaration md = generateBuildMethod(isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast); + boolean useBuilderBasedConstructor = parent.get() instanceof TypeDeclaration; + MethodDeclaration md = generateBuildMethod(isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast, useBuilderBasedConstructor); if (md != null) injectMethod(builderType, md); } @@ -514,7 +537,13 @@ public class HandleBuilder extends EclipseAnnotationHandler { return decl; } - public MethodDeclaration generateBuildMethod(boolean isStatic, String name, char[] staticName, TypeReference returnType, List builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source) { + /** + * @param useBuilderBasedConstructor + * if true, the {@code build()} method will use a constructor + * that takes the builder instance as parameter (instead of a + * constructor with all relevant fields as parameters) + */ + public MethodDeclaration generateBuildMethod(boolean isStatic, String name, char[] staticName, TypeReference returnType, List builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source, boolean useBuilderBasedConstructor) { MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; List statements = new ArrayList(); @@ -554,7 +583,13 @@ public class HandleBuilder extends EclipseAnnotationHandler { if (staticName == null) { AllocationExpression allocationStatement = new AllocationExpression(); allocationStatement.type = copyType(out.returnType); - allocationStatement.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]); + if (useBuilderBasedConstructor) { + // Use a constructor that only has this builder as parameter. + allocationStatement.arguments = new Expression[] {new ThisReference(0, 0)}; + } else { + // Use a constructor with all the fields. + allocationStatement.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]); + } statements.add(new ReturnStatement(allocationStatement, 0, 0)); } else { MessageSend invoke = new MessageSend(); @@ -672,7 +707,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { return null; } - public EclipseNode makeBuilderClass(boolean isStatic, EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, ASTNode source) { + public EclipseNode makeBuilderClass(boolean isStatic, EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, ASTNode source, String parentBuilderClassName) { TypeDeclaration parent = (TypeDeclaration) tdParent.get(); TypeDeclaration builder = new TypeDeclaration(parent.compilationResult); builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; @@ -680,6 +715,9 @@ public class HandleBuilder extends EclipseAnnotationHandler { if (isStatic) builder.modifiers |= ClassFileConstants.AccStatic; builder.typeParameters = copyTypeParams(typeParams, source); builder.name = builderClassName.toCharArray(); + if (parentBuilderClassName != null) { + builder.superclass = new SingleTypeReference(parentBuilderClassName.toCharArray(), 0); + } builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return injectType(tdParent, builder); } -- cgit From bd51fa8484fde587eef10fc58e4527f26ec16430 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Mon, 13 Mar 2017 14:32:57 +0100 Subject: activate extendable builders explicitly (ensure backwards compatibility) --- src/core/lombok/Builder.java | 23 ++++++++++++++++++---- .../lombok/eclipse/handlers/HandleBuilder.java | 15 +++++++++++--- src/core/lombok/javac/handlers/HandleBuilder.java | 18 +++++++++++++---- 3 files changed, 45 insertions(+), 11 deletions(-) (limited to 'src/core/lombok/eclipse/handlers/HandleBuilder.java') diff --git a/src/core/lombok/Builder.java b/src/core/lombok/Builder.java index 855e96e8..9cf82191 100644 --- a/src/core/lombok/Builder.java +++ b/src/core/lombok/Builder.java @@ -123,14 +123,29 @@ public @interface Builder { String builderClassName() default ""; /** - * If true, the generated builder class will extend the builder of the + * If true, the generated builder class will extend the {@code @Builder} of the * superclass. In this way, the builder will also contain methods for fields - * from the superclass. Note that both this builder and the superclass' - * builder must be a type {@code @Builder}; this feature does neither work - * for constructor nor method {@code @Builder}s. + * from the superclass.
+ * Note that both this builder and the superclass' builder must be a type + * {@code @Builder}; this feature does neither work for constructor nor + * method {@code @Builder}s. The parent {@code @Builder} must be + * {@link #extendable()}.
+ * Implies {@link #extendable()}. */ boolean inherit() default false; + /** + * If true, the generated builder pattern will be extendable by + * {@code @Builder}s of subclasses, using the {@link #inherit()} feature. + * This is achieved by generating a special constructor that takes a builder + * instance as parameter (instead of an {@link AllArgsConstructor}).
+ * Note that this builder must be a type {@code @Builder}; this feature does + * neither work for constructor nor method {@code @Builder}s.
+ * If {@link #inherit()} {@code == true}, {@link #extendable()} will + * automatically be {@code true}. + */ + boolean extendable() default false; + /** * Name of the builder class in the superclass. Only relevant if * {@code inherit = true} (see {@link #inherit()}). diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 4f152fe3..4bfc89f4 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -141,6 +141,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { String builderClassName = builderInstance.builderClassName(); boolean inherit = builderInstance.inherit(); + boolean extendable = inherit || builderInstance.extendable(); // inherit implies extendable String superclassBuilderClassName = builderInstance.superclassBuilderClassName(); String toBuilderMethodName = "toBuilder"; @@ -203,9 +204,9 @@ public class HandleBuilder extends EclipseAnnotationHandler { superclassBuilderClassName = new String(td.superclass.getLastToken()) + "Builder"; } - boolean callSuperConstructor = inherit && td.superclass != null; + boolean callBuilderBasedSuperConstructor = inherit && td.superclass != null; new HandleConstructor().generateConstructor(tdParent, AccessLevel.PROTECTED, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, true, - Collections.emptyList(), annotationNode, builderClassName, callSuperConstructor); + Collections.emptyList(), annotationNode, extendable ? builderClassName : null, callBuilderBasedSuperConstructor); returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p); typeParams = td.typeParameters; @@ -216,6 +217,10 @@ public class HandleBuilder extends EclipseAnnotationHandler { annotationNode.addError("@Builder(inherit=true) is only supported for type builders."); return; } + if (extendable) { + annotationNode.addError("@Builder(extendable=true) is only supported for type builders."); + return; + } ConstructorDeclaration cd = (ConstructorDeclaration) parent.get(); if (cd.typeParameters != null && cd.typeParameters.length > 0) { annotationNode.addError("@Builder is not supported on constructors with constructor type parameters."); @@ -234,6 +239,10 @@ public class HandleBuilder extends EclipseAnnotationHandler { annotationNode.addError("@Builder(inherit=true) is only supported for type builders."); return; } + if (extendable) { + annotationNode.addError("@Builder(extendable=true) is only supported for type builders."); + return; + } MethodDeclaration md = (MethodDeclaration) parent.get(); tdParent = parent.up(); isStatic = md.isStatic(); @@ -427,7 +436,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { } if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) { - boolean useBuilderBasedConstructor = parent.get() instanceof TypeDeclaration; + boolean useBuilderBasedConstructor = parent.get() instanceof TypeDeclaration && extendable; MethodDeclaration md = generateBuildMethod(isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast, useBuilderBasedConstructor); if (md != null) injectMethod(builderType, md); } diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 32bf7949..7701d85c 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -110,6 +110,7 @@ public class HandleBuilder extends JavacAnnotationHandler { String toBuilderMethodName = "toBuilder"; boolean inherit = builderInstance.inherit(); + boolean extendable = inherit || builderInstance.extendable(); // inherit implies extendable String superclassBuilderClassName = builderInstance.superclassBuilderClassName(); boolean toBuilder = builderInstance.toBuilder(); @@ -176,8 +177,8 @@ public class HandleBuilder extends JavacAnnotationHandler { superclassBuilderClassName = extendsClause + "Builder"; } - boolean callSuperConstructor = inherit && extendsClause != null; - new HandleConstructor().generateConstructor(tdParent, AccessLevel.PROTECTED, List.nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, null, annotationNode, builderClassName, callSuperConstructor); + boolean callBuilderBasedSuperConstructor = inherit && extendsClause != null; + new HandleConstructor().generateConstructor(tdParent, AccessLevel.PROTECTED, List.nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, null, annotationNode, extendable ? builderClassName : null, callBuilderBasedSuperConstructor); returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), td.name, td.typarams); typeParams = td.typarams; @@ -187,7 +188,12 @@ public class HandleBuilder extends JavacAnnotationHandler { if (inherit) { annotationNode.addError("@Builder(inherit=true) is only supported for type builders."); return; - } JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get(); + } + if (extendable) { + annotationNode.addError("@Builder(extendable=true) is only supported for type builders."); + return; + } + JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get(); if (!jmd.typarams.isEmpty()) { annotationNode.addError("@Builder is not supported on constructors with constructor type parameters."); return; @@ -205,6 +211,10 @@ public class HandleBuilder extends JavacAnnotationHandler { annotationNode.addError("@Builder(inherit=true) is only supported for type builders."); return; } + if (extendable) { + annotationNode.addError("@Builder(extendable=true) is only supported for type builders."); + return; + } tdParent = parent.up(); JCClassDecl td = (JCClassDecl) tdParent.get(); JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get(); @@ -387,7 +397,7 @@ public class HandleBuilder extends JavacAnnotationHandler { } if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) { - boolean useBuilderBasedConstructor = parent.get() instanceof JCClassDecl; + boolean useBuilderBasedConstructor = parent.get() instanceof JCClassDecl && extendable; JCMethodDecl md = generateBuildMethod(isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning, useBuilderBasedConstructor); if (md != null) injectMethod(builderType, md); } -- cgit From f51bbce3e396a0151bc0242d00e250f2bc720316 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Mon, 13 Mar 2017 15:59:46 +0100 Subject: do not assign values in build() method for extendable builders (WIP) --- .../lombok/eclipse/handlers/HandleBuilder.java | 43 ++++++++++++---------- src/core/lombok/javac/handlers/HandleBuilder.java | 41 +++++++++++---------- 2 files changed, 45 insertions(+), 39 deletions(-) (limited to 'src/core/lombok/eclipse/handlers/HandleBuilder.java') diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 4bfc89f4..74ef57a7 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -556,31 +556,34 @@ public class HandleBuilder extends EclipseAnnotationHandler { MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; List statements = new ArrayList(); + List args = new ArrayList(); - if (addCleaning) { - FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0); - thisUnclean.receiver = new ThisReference(0, 0); - Expression notClean = new UnaryExpression(thisUnclean, OperatorIds.NOT); - MessageSend invokeClean = new MessageSend(); - invokeClean.selector = CLEAN_METHOD_NAME; - statements.add(new IfStatement(notClean, invokeClean, 0, 0)); - } + // Extendable builders assign their values in the constructor, not in this build() method. + if (!useBuilderBasedConstructor) { + if (addCleaning) { + FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0); + thisUnclean.receiver = new ThisReference(0, 0); + Expression notClean = new UnaryExpression(thisUnclean, OperatorIds.NOT); + MessageSend invokeClean = new MessageSend(); + invokeClean.selector = CLEAN_METHOD_NAME; + statements.add(new IfStatement(notClean, invokeClean, 0, 0)); + } - for (BuilderFieldData bfd : builderFields) { - if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { - bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name); + for (BuilderFieldData bfd : builderFields) { + if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { + bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name); + } } - } - List args = new ArrayList(); - for (BuilderFieldData bfd : builderFields) { - args.add(new SingleNameReference(bfd.name, 0L)); - } + for (BuilderFieldData bfd : builderFields) { + args.add(new SingleNameReference(bfd.name, 0L)); + } - if (addCleaning) { - FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0); - thisUnclean.receiver = new ThisReference(0, 0); - statements.add(new Assignment(thisUnclean, new TrueLiteral(0, 0), 0)); + if (addCleaning) { + FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0); + thisUnclean.receiver = new ThisReference(0, 0); + statements.add(new Assignment(thisUnclean, new TrueLiteral(0, 0), 0)); + } } out.modifiers = ClassFileConstants.AccPublic; diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 7701d85c..41ff64e0 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -546,27 +546,30 @@ public class HandleBuilder extends JavacAnnotationHandler { JCExpression call; ListBuffer statements = new ListBuffer(); - - if (addCleaning) { - JCExpression notClean = maker.Unary(CTC_NOT, maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean"))); - JCStatement invokeClean = maker.Exec(maker.Apply(List.nil(), maker.Ident(type.toName("$lombokClean")), List.nil())); - JCIf ifUnclean = maker.If(notClean, invokeClean, null); - statements.append(ifUnclean); - } - - for (BuilderFieldData bfd : builderFields) { - if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { - bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, source, statements, bfd.name); - } - } - ListBuffer args = new ListBuffer(); - for (BuilderFieldData bfd : builderFields) { - args.append(maker.Ident(bfd.name)); - } + + // Extendable builders assign their values in the constructor, not in this build() method. + if (!useBuilderBasedConstructor) { + if (addCleaning) { + JCExpression notClean = maker.Unary(CTC_NOT, maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean"))); + JCStatement invokeClean = maker.Exec(maker.Apply(List.nil(), maker.Ident(type.toName("$lombokClean")), List.nil())); + JCIf ifUnclean = maker.If(notClean, invokeClean, null); + statements.append(ifUnclean); + } + + for (BuilderFieldData bfd : builderFields) { + if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { + bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, source, statements, bfd.name); + } + } - if (addCleaning) { - statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, true)))); + for (BuilderFieldData bfd : builderFields) { + args.append(maker.Ident(bfd.name)); + } + + if (addCleaning) { + statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, true)))); + } } if (builderName == null) { -- cgit From cd2e2f25690c46f01b876074682e87af369d15d3 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Tue, 14 Mar 2017 16:22:26 +0100 Subject: moved code only relevant to builders to HandleBuilder (Eclipse) reverted HandleConstructor to original state moved generation of builder-based constructor to HandleBuilder --- .../lombok/eclipse/handlers/HandleBuilder.java | 116 ++++++++++++++++++++- .../lombok/eclipse/handlers/HandleConstructor.java | 72 ++----------- 2 files changed, 124 insertions(+), 64 deletions(-) (limited to 'src/core/lombok/eclipse/handlers/HandleBuilder.java') diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 58e08b0d..ebeb82ea 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -25,6 +25,7 @@ import static lombok.eclipse.Eclipse.*; import static lombok.core.handlers.HandlerUtil.*; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -39,6 +40,7 @@ import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FalseLiteral; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; @@ -49,6 +51,7 @@ import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; +import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; @@ -80,6 +83,7 @@ import lombok.core.HandlerPriority; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; +import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult; import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer; import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists; @@ -99,6 +103,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { } private static class BuilderFieldData { + EclipseNode fieldNode; TypeReference type; char[] rawName; char[] name; @@ -188,6 +193,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { // Value will only skip making a field final if it has an explicit @NonFinal annotation, so we check for that. if (fd.initialization != null && valuePresent && !hasAnnotation(NonFinal.class, fieldNode)) continue; BuilderFieldData bfd = new BuilderFieldData(); + bfd.fieldNode = fieldNode; bfd.rawName = fieldNode.getName().toCharArray(); bfd.name = removePrefixFromField(fieldNode); bfd.type = fd.type; @@ -205,8 +211,13 @@ public class HandleBuilder extends EclipseAnnotationHandler { } boolean callBuilderBasedSuperConstructor = inherit && td.superclass != null; - new HandleConstructor().generateConstructor(tdParent, extendable ? AccessLevel.PROTECTED : AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, - Collections.emptyList(), annotationNode, extendable ? builderClassName : null, callBuilderBasedSuperConstructor); + if (extendable) { + generateConstructor(tdParent, builderFields, annotationNode, + builderClassName, callBuilderBasedSuperConstructor); + } else { + new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, + Collections.emptyList(), annotationNode); + } returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p); typeParams = td.typeParameters; @@ -427,7 +438,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) { ConstructorDeclaration cd = HandleConstructor.createConstructor( AccessLevel.PACKAGE, builderType, Collections.emptyList(), false, - annotationNode, Collections.emptyList(), null, false); + annotationNode, Collections.emptyList()); if (cd != null) injectMethod(builderType, cd); } @@ -524,6 +535,105 @@ public class HandleBuilder extends EclipseAnnotationHandler { } + /** + * @param builderClassnameAsParameter + * if {@code != null}, the only parameter of the constructor will + * be a builder with this classname; the constructor will then + * use the values within this builder to assign the fields of new + * instances. + * @param callBuilderBasedSuperConstructor + * if {@code true}, the constructor will explicitly call a super + * constructor with the builder as argument. Requires + * {@code builderClassAsParameter != null}. + */ + private void generateConstructor(EclipseNode typeNode, List builderFields, EclipseNode sourceNode, + String builderClassnameAsParameter, boolean callBuilderBasedSuperConstructor) { + + if (builderClassnameAsParameter == null || builderClassnameAsParameter.isEmpty()) { + typeNode.addError("A builder-based constructor requires a non-empty 'builderClassnameAsParameter' value."); + } + + AccessLevel level = AccessLevel.PROTECTED; + ASTNode source = sourceNode.get(); + + TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get()); + long p = (long) source.sourceStart << 32 | source.sourceEnd; + + boolean isEnum = (((TypeDeclaration) typeNode.get()).modifiers & ClassFileConstants.AccEnum) != 0; + if (isEnum) { + level = AccessLevel.PRIVATE; + } + +// boolean suppressConstructorProperties = Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES)); + + ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult); + + constructor.modifiers = toEclipseModifier(level); + constructor.selector = typeDeclaration.name; + if (callBuilderBasedSuperConstructor) { + constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.Super); + constructor.constructorCall.arguments = new Expression[] {new SingleNameReference("b".toCharArray(), p)}; + } else { + constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper); + } + constructor.constructorCall.sourceStart = source.sourceStart; + constructor.constructorCall.sourceEnd = source.sourceEnd; + constructor.thrownExceptions = null; + constructor.typeParameters = null; + constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; + constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart; + constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd; + constructor.arguments = null; + + List assigns = new ArrayList(); + List nullChecks = new ArrayList(); + + for (BuilderFieldData fieldNode : builderFields) { + char[] fieldName = removePrefixFromField(fieldNode.fieldNode); + FieldReference thisX = new FieldReference(fieldNode.rawName, p); + int s = (int) (p >> 32); + int e = (int) p; + thisX.receiver = new ThisReference(s, e); + + if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) { + fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode, assigns, fieldNode.name); + } + + Expression assignmentExpr; + if (builderClassnameAsParameter != null) { + char[][] variableInBuilder = new char[][] {"b".toCharArray(), fieldName}; + long[] positions = new long[] {p, p}; + assignmentExpr = new QualifiedNameReference(variableInBuilder, positions, s, e); + } else { + assignmentExpr = new SingleNameReference(fieldName, p); + } + + Assignment assignment = new Assignment(thisX, assignmentExpr, (int) p); + assigns.add(assignment); + Annotation[] nonNulls = findAnnotations((FieldDeclaration)fieldNode.fieldNode.get(), NON_NULL_PATTERN); + if (nonNulls.length != 0) { + Statement nullCheck = generateNullCheck((FieldDeclaration)fieldNode.fieldNode.get(), sourceNode); + if (nullCheck != null) { + nullChecks.add(nullCheck); + } + } + } + + nullChecks.addAll(assigns); + constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]); + constructor.arguments = new Argument[] {new Argument("b".toCharArray(), p, new SingleTypeReference(builderClassnameAsParameter.toCharArray(), p), Modifier.FINAL)}; + + // Generate annotations that must be put on the generated method, and attach them. +// Annotation[] constructorProperties = null; +// if (!suppressConstructorProperties && level != AccessLevel.PRIVATE && level != AccessLevel.PACKAGE && !HandleConstructor.isLocalType(typeNode)) { +// constructorProperties = HandleConstructor.createConstructorProperties(source, builderFields); +// } + + constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope); + + injectMethod(typeNode, constructor); + } + private MethodDeclaration generateCleanMethod(List builderFields, EclipseNode builderType, ASTNode source) { List statements = new ArrayList(); diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java index a8b823b2..49b09231 100644 --- a/src/core/lombok/eclipse/handlers/HandleConstructor.java +++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java @@ -64,12 +64,10 @@ import org.eclipse.jdt.internal.compiler.ast.IntLiteral; import org.eclipse.jdt.internal.compiler.ast.LongLiteral; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.NullLiteral; -import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; -import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.eclipse.jdt.internal.compiler.ast.ThisReference; @@ -97,7 +95,7 @@ public class HandleConstructor { List fields = force ? findFinalFields(typeNode) : Collections.emptyList(); List onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor", annotationNode); - new HandleConstructor().generateConstructor(typeNode, level, fields, force, staticName, SkipIfConstructorExists.NO, onConstructor, annotationNode, null, false); + new HandleConstructor().generateConstructor(typeNode, level, fields, force, staticName, SkipIfConstructorExists.NO, onConstructor, annotationNode); } } @@ -120,7 +118,7 @@ public class HandleConstructor { new HandleConstructor().generateConstructor( typeNode, level, findRequiredFields(typeNode), false, staticName, SkipIfConstructorExists.NO, - onConstructor, annotationNode, null, false); + onConstructor, annotationNode); } } @@ -179,7 +177,7 @@ public class HandleConstructor { new HandleConstructor().generateConstructor( typeNode, level, findAllFields(typeNode), false, staticName, SkipIfConstructorExists.NO, - onConstructor, annotationNode, null, false); + onConstructor, annotationNode); } } @@ -201,34 +199,23 @@ public class HandleConstructor { EclipseNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists, List onConstructor, EclipseNode sourceNode) { - generateConstructor(typeNode, level, findRequiredFields(typeNode), false, staticName, skipIfConstructorExists, onConstructor, sourceNode, null, false); + generateConstructor(typeNode, level, findRequiredFields(typeNode), false, staticName, skipIfConstructorExists, onConstructor, sourceNode); } public void generateAllArgsConstructor( EclipseNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists, List onConstructor, EclipseNode sourceNode) { - generateConstructor(typeNode, level, findAllFields(typeNode), false, staticName, skipIfConstructorExists, onConstructor, sourceNode, null, false); + generateConstructor(typeNode, level, findAllFields(typeNode), false, staticName, skipIfConstructorExists, onConstructor, sourceNode); } public enum SkipIfConstructorExists { YES, NO, I_AM_BUILDER; } - /** - * @param builderClassnameAsParameter - * if {@code != null}, the only parameter of the constructor will - * be a builder with this classname; the constructor will then - * use the values within this builder to assign the fields of new - * instances. - * @param callBuilderBasedSuperConstructor - * if {@code true}, the constructor will explicitly call a super - * constructor with the builder as argument. Requires - * {@code builderClassAsParameter != null}. - */ public void generateConstructor( EclipseNode typeNode, AccessLevel level, List fields, boolean allToDefault, String staticName, SkipIfConstructorExists skipIfConstructorExists, - List onConstructor, EclipseNode sourceNode, String builderClassnameAsParameter, boolean callBuilderBasedSuperConstructor) { + List onConstructor, EclipseNode sourceNode) { ASTNode source = sourceNode.get(); boolean staticConstrRequired = staticName != null && !staticName.equals(""); @@ -263,7 +250,7 @@ public class HandleConstructor { ConstructorDeclaration constr = createConstructor( staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields, allToDefault, - sourceNode, onConstructor, builderClassnameAsParameter, callBuilderBasedSuperConstructor); + sourceNode, onConstructor); injectMethod(typeNode, constr); if (staticConstrRequired) { MethodDeclaration staticConstr = createStaticConstructor(level, staticName, typeNode, allToDefault ? Collections.emptyList() : fields, source); @@ -303,28 +290,9 @@ public class HandleConstructor { return new Annotation[] { ann }; } - /** - * @param builderClassnameAsParameter - * if {@code != null}, the only parameter of the constructor will - * be a builder with this classname; the constructor will then - * use the values within this builder to assign the fields of new - * instances. - * @param callBuilderBasedSuperConstructor - * if {@code true}, the constructor will explicitly call a super - * constructor with the builder as argument. Requires - * {@code builderClassnameAsParameter != null}. - */ public static ConstructorDeclaration createConstructor( AccessLevel level, EclipseNode type, Collection fields, boolean allToDefault, - EclipseNode sourceNode, List onConstructor, - String builderClassnameAsParameter, boolean callBuilderBasedSuperConstructor) { - - if (builderClassnameAsParameter != null && builderClassnameAsParameter.isEmpty()) { - builderClassnameAsParameter = null; - } - if (callBuilderBasedSuperConstructor && builderClassnameAsParameter == null) { - type.addError("Calling a builder-based superclass constructor ('callBuilderBasedSuperConstructor') requires a non-empty 'builderClassnameAsParameter' value."); - } + EclipseNode sourceNode, List onConstructor) { ASTNode source = sourceNode.get(); TypeDeclaration typeDeclaration = ((TypeDeclaration) type.get()); @@ -345,12 +313,7 @@ public class HandleConstructor { constructor.modifiers = toEclipseModifier(level); constructor.selector = typeDeclaration.name; - if (callBuilderBasedSuperConstructor) { - constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.Super); - constructor.constructorCall.arguments = new Expression[] {new SingleNameReference("b".toCharArray(), p)}; - } else { - constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper); - } + constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper); constructor.constructorCall.sourceStart = source.sourceStart; constructor.constructorCall.sourceEnd = source.sourceEnd; constructor.thrownExceptions = null; @@ -373,16 +336,7 @@ public class HandleConstructor { int e = (int) p; thisX.receiver = new ThisReference(s, e); - Expression assignmentExpr; - if (allToDefault) { - assignmentExpr = getDefaultExpr(field.type, s, e); - } else if (builderClassnameAsParameter != null) { - char[][] variableInBuilder = new char[][] {"b".toCharArray(), fieldName}; - long[] positions = new long[] {p, p}; - assignmentExpr = new QualifiedNameReference(variableInBuilder, positions, s, e); - } else { - assignmentExpr = new SingleNameReference(fieldName, p); - } + Expression assignmentExpr = allToDefault ? getDefaultExpr(field.type, s, e) : new SingleNameReference(fieldName, p); Assignment assignment = new Assignment(thisX, assignmentExpr, (int) p); assignment.sourceStart = (int) (p >> 32); assignment.sourceEnd = assignment.statementEnd = (int) (p >> 32); @@ -403,11 +357,7 @@ public class HandleConstructor { nullChecks.addAll(assigns); constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]); - if (builderClassnameAsParameter != null) { - constructor.arguments = new Argument[] {new Argument("b".toCharArray(), p, new SingleTypeReference(builderClassnameAsParameter.toCharArray(), p), Modifier.FINAL)}; - } else { - constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[params.size()]); - } + constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[params.size()]); /* Generate annotations that must be put on the generated method, and attach them. */ { Annotation[] constructorProperties = null; -- cgit From e61561b5a587f9cc770902c3ad9532f0daa5b85f Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Tue, 14 Mar 2017 18:47:29 +0100 Subject: singularizer's build code for any variable name (not only "this") --- .../eclipse/handlers/EclipseSingularsRecipes.java | 24 +++++++-- .../lombok/eclipse/handlers/HandleBuilder.java | 58 ++++++++++++++-------- .../lombok/eclipse/handlers/HandleConstructor.java | 2 +- .../singulars/EclipseGuavaSingularizer.java | 6 +-- .../singulars/EclipseJavaUtilListSingularizer.java | 11 ++-- .../singulars/EclipseJavaUtilMapSingularizer.java | 8 +-- .../singulars/EclipseJavaUtilSetSingularizer.java | 8 +-- .../singulars/EclipseJavaUtilSingularizer.java | 28 +++++------ src/core/lombok/javac/handlers/HandleBuilder.java | 17 ++++--- 9 files changed, 98 insertions(+), 64 deletions(-) (limited to 'src/core/lombok/eclipse/handlers/HandleBuilder.java') diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java index 4cb41d4f..10ed7fbb 100644 --- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java +++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java @@ -45,6 +45,8 @@ import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; +import org.eclipse.jdt.internal.compiler.ast.Reference; +import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.ThisReference; @@ -212,7 +214,7 @@ public class EclipseSingularsRecipes { public abstract List generateFields(SingularData data, EclipseNode builderType); public abstract void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain); - public abstract void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName); + public abstract void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName, String builderVariable); public boolean requiresCleaning() { try { @@ -302,17 +304,18 @@ public class EclipseSingularsRecipes { private static final char[] SIZE_TEXT = new char[] {'s', 'i', 'z', 'e'}; - /** Generates 'this.name.size()' as an expression; if nullGuard is true, it's this.name == null ? 0 : this.name.size(). */ - protected Expression getSize(EclipseNode builderType, char[] name, boolean nullGuard) { + /** Generates 'this.name.size()' as an expression; if nullGuard is true, it's this.name == null ? 0 : this.name.size(). + * @param builderVariable */ + protected Expression getSize(EclipseNode builderType, char[] name, boolean nullGuard, String builderVariable) { MessageSend invoke = new MessageSend(); - ThisReference thisRef = new ThisReference(0, 0); + Reference thisRef = getBuilderReference(builderVariable); FieldReference thisDotName = new FieldReference(name, 0L); thisDotName.receiver = thisRef; invoke.receiver = thisDotName; invoke.selector = SIZE_TEXT; if (!nullGuard) return invoke; - ThisReference cdnThisRef = new ThisReference(0, 0); + Reference cdnThisRef = getBuilderReference(builderVariable); FieldReference cdnThisDotName = new FieldReference(name, 0L); cdnThisDotName.receiver = cdnThisRef; NullLiteral nullLiteral = new NullLiteral(0, 0); @@ -341,5 +344,16 @@ public class EclipseSingularsRecipes { return new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS); } + + /** + * @return a {@link SingleNameReference} to the builder in the variable builderVariable. If builderVariable == "this", a {@link ThisReference} is returned. + */ + protected static Reference getBuilderReference(String builderVariable) { + if ("this".equals(builderVariable)) { + return new ThisReference(0, 0); + } else { + return new SingleNameReference(builderVariable.toCharArray(), 0); + } + } } } diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index ebeb82ea..3d4a7a66 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -37,6 +37,7 @@ import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; +import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; @@ -55,9 +56,11 @@ import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; +import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.Statement; +import org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.TrueLiteral; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; @@ -212,7 +215,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { boolean callBuilderBasedSuperConstructor = inherit && td.superclass != null; if (extendable) { - generateConstructor(tdParent, builderFields, annotationNode, + generateBuilderBasedConstructor(tdParent, builderFields, annotationNode, builderClassName, callBuilderBasedSuperConstructor); } else { new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, @@ -546,11 +549,12 @@ public class HandleBuilder extends EclipseAnnotationHandler { * constructor with the builder as argument. Requires * {@code builderClassAsParameter != null}. */ - private void generateConstructor(EclipseNode typeNode, List builderFields, EclipseNode sourceNode, + private void generateBuilderBasedConstructor(EclipseNode typeNode, List builderFields, EclipseNode sourceNode, String builderClassnameAsParameter, boolean callBuilderBasedSuperConstructor) { if (builderClassnameAsParameter == null || builderClassnameAsParameter.isEmpty()) { typeNode.addError("A builder-based constructor requires a non-empty 'builderClassnameAsParameter' value."); + return; } AccessLevel level = AccessLevel.PROTECTED; @@ -564,8 +568,6 @@ public class HandleBuilder extends EclipseAnnotationHandler { level = AccessLevel.PRIVATE; } -// boolean suppressConstructorProperties = Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES)); - ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult); constructor.modifiers = toEclipseModifier(level); @@ -585,7 +587,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd; constructor.arguments = null; - List assigns = new ArrayList(); + List statements = new ArrayList(); List nullChecks = new ArrayList(); for (BuilderFieldData fieldNode : builderFields) { @@ -595,21 +597,18 @@ public class HandleBuilder extends EclipseAnnotationHandler { int e = (int) p; thisX.receiver = new ThisReference(s, e); - if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) { - fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode, assigns, fieldNode.name); - } - Expression assignmentExpr; - if (builderClassnameAsParameter != null) { + if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) { + fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode, statements, fieldNode.name, "b"); + assignmentExpr = new SingleNameReference(fieldNode.name, p); + } else { char[][] variableInBuilder = new char[][] {"b".toCharArray(), fieldName}; long[] positions = new long[] {p, p}; assignmentExpr = new QualifiedNameReference(variableInBuilder, positions, s, e); - } else { - assignmentExpr = new SingleNameReference(fieldName, p); } Assignment assignment = new Assignment(thisX, assignmentExpr, (int) p); - assigns.add(assignment); + statements.add(assignment); Annotation[] nonNulls = findAnnotations((FieldDeclaration)fieldNode.fieldNode.get(), NON_NULL_PATTERN); if (nonNulls.length != 0) { Statement nullCheck = generateNullCheck((FieldDeclaration)fieldNode.fieldNode.get(), sourceNode); @@ -619,15 +618,34 @@ public class HandleBuilder extends EclipseAnnotationHandler { } } - nullChecks.addAll(assigns); + nullChecks.addAll(statements); constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]); constructor.arguments = new Argument[] {new Argument("b".toCharArray(), p, new SingleTypeReference(builderClassnameAsParameter.toCharArray(), p), Modifier.FINAL)}; - // Generate annotations that must be put on the generated method, and attach them. -// Annotation[] constructorProperties = null; -// if (!suppressConstructorProperties && level != AccessLevel.PRIVATE && level != AccessLevel.PACKAGE && !HandleConstructor.isLocalType(typeNode)) { -// constructorProperties = HandleConstructor.createConstructorProperties(source, builderFields); -// } + boolean suppressConstructorProperties = Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES)); + if (!suppressConstructorProperties) { + // Add ConstructorProperties + long[] poss = new long[3]; + Arrays.fill(poss, p); + QualifiedTypeReference constructorPropertiesType = new QualifiedTypeReference(HandleConstructor.JAVA_BEANS_CONSTRUCTORPROPERTIES, poss); + setGeneratedBy(constructorPropertiesType, source); + SingleMemberAnnotation ann = new SingleMemberAnnotation(constructorPropertiesType, source.sourceStart); + ann.declarationSourceEnd = source.sourceEnd; + + ArrayInitializer fieldNames = new ArrayInitializer(); + fieldNames.sourceStart = source.sourceStart; + fieldNames.sourceEnd = source.sourceEnd; + fieldNames.expressions = new Expression[1]; + + fieldNames.expressions[0] = new StringLiteral("b".toCharArray(), source.sourceStart, source.sourceEnd, 0); + setGeneratedBy(fieldNames.expressions[0], source); + + ann.memberValue = fieldNames; + setGeneratedBy(ann, source); + setGeneratedBy(ann.memberValue, source); + Annotation[] constructorProperties = new Annotation[] { ann }; + constructor.annotations = copyAnnotations(source, constructorProperties); + } constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope); @@ -681,7 +699,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { for (BuilderFieldData bfd : builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { - bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name); + bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name, "this"); } } diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java index 49b09231..b504495d 100644 --- a/src/core/lombok/eclipse/handlers/HandleConstructor.java +++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java @@ -258,7 +258,7 @@ public class HandleConstructor { } } - private static final char[][] JAVA_BEANS_CONSTRUCTORPROPERTIES = new char[][] { "java".toCharArray(), "beans".toCharArray(), "ConstructorProperties".toCharArray() }; + public static final char[][] JAVA_BEANS_CONSTRUCTORPROPERTIES = new char[][] { "java".toCharArray(), "beans".toCharArray(), "ConstructorProperties".toCharArray() }; public static Annotation[] createConstructorProperties(ASTNode source, Collection fields) { if (fields.isEmpty()) return null; diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index 242bde1f..d9f4cb73 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -195,7 +195,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { injectMethod(builderType, md); } - @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName) { + @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName, String builderVariable) { TypeReference varType = new QualifiedTypeReference(fromQualifiedName(data.getTargetFqn()), NULL_POSS); String simpleTypeName = getSimpleTargetTypeName(data); int agrumentsCount = getTypeArgumentsCount(); @@ -214,14 +214,14 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { invokeBuild = new MessageSend(); invokeBuild.selector = new char[] {'b', 'u', 'i', 'l', 'd'}; FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L); - thisDotField.receiver = new ThisReference(0, 0); + thisDotField.receiver = getBuilderReference(builderVariable); invokeBuild.receiver = thisDotField; } Expression isNull; { //this.pluralName == null FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L); - thisDotField.receiver = new ThisReference(0, 0); + thisDotField.receiver = getBuilderReference(builderVariable); isNull = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL); } diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java index 576115b0..f512bacf 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java @@ -45,7 +45,6 @@ import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.SwitchStatement; -import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.mangosdk.spi.ProviderFor; @@ -56,9 +55,9 @@ public class EclipseJavaUtilListSingularizer extends EclipseJavaUtilListSetSingu return LombokImmutableList.of("java.util.List", "java.util.Collection", "java.lang.Iterable"); } - @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName) { + @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName, String builderVariable) { if (useGuavaInstead(builderType)) { - guavaListSetSingularizer.appendBuildCode(data, builderType, statements, targetVariableName); + guavaListSetSingularizer.appendBuildCode(data, builderType, statements, targetVariableName, builderVariable); return; } @@ -76,7 +75,7 @@ public class EclipseJavaUtilListSingularizer extends EclipseJavaUtilListSetSingu /* case 1: (singleton) break; */ { switchContents.add(new CaseStatement(makeIntLiteral(new char[] {'1'}, null), 0, 0)); FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L); - thisDotField.receiver = new ThisReference(0, 0); + thisDotField.receiver = getBuilderReference(builderVariable); MessageSend thisDotFieldGet0 = new MessageSend(); thisDotFieldGet0.receiver = thisDotField; thisDotFieldGet0.selector = new char[] {'g', 'e', 't'}; @@ -97,7 +96,7 @@ public class EclipseJavaUtilListSingularizer extends EclipseJavaUtilListSetSingu Expression argToUnmodifiable; /* new j.u.ArrayList(this.pluralName); */ { FieldReference thisDotPluralName = new FieldReference(data.getPluralName(), 0L); - thisDotPluralName.receiver = new ThisReference(0, 0); + thisDotPluralName.receiver = getBuilderReference(builderVariable); TypeReference targetTypeExpr = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS); targetTypeExpr = addTypeArgs(1, false, builderType, targetTypeExpr, data.getTypeArgs()); AllocationExpression constructorCall = new AllocationExpression(); @@ -117,7 +116,7 @@ public class EclipseJavaUtilListSingularizer extends EclipseJavaUtilListSetSingu SwitchStatement switchStat = new SwitchStatement(); switchStat.statements = switchContents.toArray(new Statement[switchContents.size()]); - switchStat.expression = getSize(builderType, data.getPluralName(), true); + switchStat.expression = getSize(builderType, data.getPluralName(), true, builderVariable); TypeReference localShadowerType = new QualifiedTypeReference(Eclipse.fromQualifiedName(data.getTargetFqn()), NULL_POSS); localShadowerType = addTypeArgs(1, false, builderType, localShadowerType, data.getTypeArgs()); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java index ef9e2a76..3d7b05ed 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java @@ -293,16 +293,16 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer injectMethod(builderType, md); } - @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName) { + @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName, String builderVariable) { if (useGuavaInstead(builderType)) { - guavaMapSingularizer.appendBuildCode(data, builderType, statements, targetVariableName); + guavaMapSingularizer.appendBuildCode(data, builderType, statements, targetVariableName, builderVariable); return; } if (data.getTargetFqn().equals("java.util.Map")) { - statements.addAll(createJavaUtilSetMapInitialCapacitySwitchStatements(data, builderType, true, "emptyMap", "singletonMap", "LinkedHashMap")); + statements.addAll(createJavaUtilSetMapInitialCapacitySwitchStatements(data, builderType, true, "emptyMap", "singletonMap", "LinkedHashMap", builderVariable)); } else { - statements.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, true, true, false, true, "TreeMap")); + statements.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, true, true, false, true, "TreeMap", builderVariable)); } } } diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java index 2d16eae0..200e615e 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java @@ -37,16 +37,16 @@ public class EclipseJavaUtilSetSingularizer extends EclipseJavaUtilListSetSingul return LombokImmutableList.of("java.util.Set", "java.util.SortedSet", "java.util.NavigableSet"); } - @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName) { + @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName, String builderVariable) { if (useGuavaInstead(builderType)) { - guavaListSetSingularizer.appendBuildCode(data, builderType, statements, targetVariableName); + guavaListSetSingularizer.appendBuildCode(data, builderType, statements, targetVariableName, builderVariable); return; } if (data.getTargetFqn().equals("java.util.Set")) { - statements.addAll(createJavaUtilSetMapInitialCapacitySwitchStatements(data, builderType, false, "emptySet", "singleton", "LinkedHashSet")); + statements.addAll(createJavaUtilSetMapInitialCapacitySwitchStatements(data, builderType, false, "emptySet", "singleton", "LinkedHashSet", builderVariable)); } else { - statements.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, false, true, false, true, "TreeSet")); + statements.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, false, true, false, true, "TreeSet", builderVariable)); } } } diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java index 6661f4af..8bcfa65d 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java @@ -90,7 +90,7 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { return Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.SINGULAR_USE_GUAVA)); } - protected List createJavaUtilSetMapInitialCapacitySwitchStatements(SingularData data, EclipseNode builderType, boolean mapMode, String emptyCollectionMethod, String singletonCollectionMethod, String targetType) { + protected List createJavaUtilSetMapInitialCapacitySwitchStatements(SingularData data, EclipseNode builderType, boolean mapMode, String emptyCollectionMethod, String singletonCollectionMethod, String targetType, String builderVariable) { List switchContents = new ArrayList(); char[] keyName = mapMode ? (new String(data.getPluralName()) + "$key").toCharArray() : data.getPluralName(); @@ -112,7 +112,7 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { /* !mapMode: pluralName = java.util.Collections.singletonCollectionMethod(this.pluralName.get(0)); mapMode: pluralName = java.util.Collections.singletonCollectionMethod(this.pluralName$key.get(0), this.pluralName$value.get(0)); */ { FieldReference thisDotKey = new FieldReference(keyName, 0L); - thisDotKey.receiver = new ThisReference(0, 0); + thisDotKey.receiver = getBuilderReference(builderVariable); MessageSend thisDotKeyGet0 = new MessageSend(); thisDotKeyGet0.receiver = thisDotKey; thisDotKeyGet0.selector = new char[] {'g', 'e', 't'}; @@ -122,7 +122,7 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { if (mapMode) { char[] valueName = (new String(data.getPluralName()) + "$value").toCharArray(); FieldReference thisDotValue = new FieldReference(valueName, 0L); - thisDotValue.receiver = new ThisReference(0, 0); + thisDotValue.receiver = getBuilderReference(builderVariable); MessageSend thisDotValueGet0 = new MessageSend(); thisDotValueGet0.receiver = thisDotValue; thisDotValueGet0.selector = new char[] {'g', 'e', 't'}; @@ -143,12 +143,12 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { { // default: switchContents.add(new CaseStatement(null, 0, 0)); - switchContents.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, mapMode, false, true, emptyCollectionMethod == null, targetType)); + switchContents.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, mapMode, false, true, emptyCollectionMethod == null, targetType, builderVariable)); } SwitchStatement switchStat = new SwitchStatement(); switchStat.statements = switchContents.toArray(new Statement[switchContents.size()]); - switchStat.expression = getSize(builderType, keyName, true); + switchStat.expression = getSize(builderType, keyName, true, builderVariable); TypeReference localShadowerType = new QualifiedTypeReference(fromQualifiedName(data.getTargetFqn()), NULL_POSS); localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs()); @@ -157,7 +157,7 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { return Arrays.asList(varDefStat, switchStat); } - protected List createJavaUtilSimpleCreationAndFillStatements(SingularData data, EclipseNode builderType, boolean mapMode, boolean defineVar, boolean addInitialCapacityArg, boolean nullGuard, String targetType) { + protected List createJavaUtilSimpleCreationAndFillStatements(SingularData data, EclipseNode builderType, boolean mapMode, boolean defineVar, boolean addInitialCapacityArg, boolean nullGuard, String targetType, String builderVariable) { char[] varName = mapMode ? (new String(data.getPluralName()) + "$key").toCharArray() : data.getPluralName(); Statement createStat; { @@ -166,11 +166,11 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { if (addInitialCapacityArg) { // this.varName.size() < MAX_POWER_OF_2 ? 1 + this.varName.size() + (this.varName.size() - 3) / 3 : Integer.MAX_VALUE; // lessThanCutOff = this.varName.size() < MAX_POWER_OF_2 - Expression lessThanCutoff = new BinaryExpression(getSize(builderType, varName, nullGuard), makeIntLiteral("0x40000000".toCharArray(), null), OperatorIds.LESS); + Expression lessThanCutoff = new BinaryExpression(getSize(builderType, varName, nullGuard, builderVariable), makeIntLiteral("0x40000000".toCharArray(), null), OperatorIds.LESS); FieldReference integerMaxValue = new FieldReference("MAX_VALUE".toCharArray(), 0L); integerMaxValue.receiver = new QualifiedNameReference(TypeConstants.JAVA_LANG_INTEGER, NULL_POSS, 0, 0); - Expression sizeFormulaLeft = new BinaryExpression(makeIntLiteral(new char[] {'1'}, null), getSize(builderType, varName, nullGuard), OperatorIds.PLUS); - Expression sizeFormulaRightLeft = new BinaryExpression(getSize(builderType, varName, nullGuard), makeIntLiteral(new char[] {'3'}, null), OperatorIds.MINUS); + Expression sizeFormulaLeft = new BinaryExpression(makeIntLiteral(new char[] {'1'}, null), getSize(builderType, varName, nullGuard, builderVariable), OperatorIds.PLUS); + Expression sizeFormulaRightLeft = new BinaryExpression(getSize(builderType, varName, nullGuard, builderVariable), makeIntLiteral(new char[] {'3'}, null), OperatorIds.MINUS); Expression sizeFormulaRight = new BinaryExpression(sizeFormulaRightLeft, makeIntLiteral(new char[] {'3'}, null), OperatorIds.DIVIDE); Expression sizeFormula = new BinaryExpression(sizeFormulaLeft, sizeFormulaRight, OperatorIds.PLUS); Expression cond = new ConditionalExpression(lessThanCutoff, sizeFormula, integerMaxValue); @@ -203,9 +203,9 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { pluralnameDotPut.selector = new char[] {'p', 'u', 't'}; pluralnameDotPut.receiver = new SingleNameReference(data.getPluralName(), 0L); FieldReference thisDotKey = new FieldReference(varName, 0L); - thisDotKey.receiver = new ThisReference(0, 0); + thisDotKey.receiver = getBuilderReference(builderVariable); FieldReference thisDotValue = new FieldReference((new String(data.getPluralName()) + "$value").toCharArray(), 0L); - thisDotValue.receiver = new ThisReference(0, 0); + thisDotValue.receiver = getBuilderReference(builderVariable); MessageSend keyArg = new MessageSend(); keyArg.receiver = thisDotKey; keyArg.arguments = new Expression[] {new SingleNameReference(iVar, 0L)}; @@ -219,7 +219,7 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { LocalDeclaration forInit = new LocalDeclaration(iVar, 0, 0); forInit.type = TypeReference.baseTypeReference(TypeIds.T_int, 0); forInit.initialization = makeIntLiteral(new char[] {'0'}, null); - Expression checkExpr = new BinaryExpression(new SingleNameReference(iVar, 0L), getSize(builderType, varName, nullGuard), OperatorIds.LESS); + Expression checkExpr = new BinaryExpression(new SingleNameReference(iVar, 0L), getSize(builderType, varName, nullGuard, builderVariable), OperatorIds.LESS); Expression incrementExpr = new PostfixExpression(new SingleNameReference(iVar, 0L), IntLiteral.One, OperatorIds.PLUS, 0); fillStat = new ForStatement(new Statement[] {forInit}, checkExpr, new Statement[] {incrementExpr}, pluralnameDotPut, true, 0, 0); } else { @@ -228,14 +228,14 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { pluralnameDotAddAll.selector = new char[] {'a', 'd', 'd', 'A', 'l', 'l'}; pluralnameDotAddAll.receiver = new SingleNameReference(data.getPluralName(), 0L); FieldReference thisDotPluralname = new FieldReference(varName, 0L); - thisDotPluralname.receiver = new ThisReference(0, 0); + thisDotPluralname.receiver = getBuilderReference(builderVariable); pluralnameDotAddAll.arguments = new Expression[] {thisDotPluralname}; fillStat = pluralnameDotAddAll; } if (nullGuard) { FieldReference thisDotField = new FieldReference(varName, 0L); - thisDotField.receiver = new ThisReference(0, 0); + thisDotField.receiver = getBuilderReference(builderVariable); Expression cond = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL); fillStat = new IfStatement(cond, fillStat, 0, 0); } diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index f46a95fd..42e76cf1 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -562,13 +562,16 @@ public class HandleBuilder extends JavacAnnotationHandler { JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.nil()); - // Add ConstructorProperties - JCExpression constructorPropertiesType = chainDots(typeNode, "java", "beans", "ConstructorProperties"); - ListBuffer fieldNames = new ListBuffer(); - fieldNames.append(maker.Literal(builderVariableName.toString())); - JCExpression fieldNamesArray = maker.NewArray(null, List.nil(), fieldNames.toList()); - JCAnnotation annotation = maker.Annotation(constructorPropertiesType, List.of(fieldNamesArray)); - mods.annotations = mods.annotations.append(annotation); + boolean suppressConstructorProperties = Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES)); + if (!suppressConstructorProperties) { + // Add ConstructorProperties + JCExpression constructorPropertiesType = chainDots(typeNode, "java", "beans", "ConstructorProperties"); + ListBuffer fieldNames = new ListBuffer(); + fieldNames.append(maker.Literal(builderVariableName.toString())); + JCExpression fieldNamesArray = maker.NewArray(null, List.nil(), fieldNames.toList()); + JCAnnotation annotation = maker.Annotation(constructorPropertiesType, List.of(fieldNamesArray)); + mods.annotations = mods.annotations.append(annotation); + } // Create a constructor that has just the builder as parameter. ListBuffer params = new ListBuffer(); -- cgit From 14550d408415b9f7f7090db9770ef0b58ccd4212 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Wed, 15 Mar 2017 10:32:06 +0100 Subject: ConstructorProperties not necessary; javadoc --- .../lombok/eclipse/handlers/HandleBuilder.java | 42 ++++++---------------- src/core/lombok/javac/handlers/HandleBuilder.java | 30 +++++++--------- 2 files changed, 24 insertions(+), 48 deletions(-) (limited to 'src/core/lombok/eclipse/handlers/HandleBuilder.java') diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 3d4a7a66..3795c3de 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -37,7 +37,6 @@ import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; -import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; @@ -56,11 +55,9 @@ import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; -import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.Statement; -import org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.TrueLiteral; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; @@ -213,8 +210,8 @@ public class HandleBuilder extends EclipseAnnotationHandler { superclassBuilderClassName = new String(td.superclass.getLastToken()) + "Builder"; } - boolean callBuilderBasedSuperConstructor = inherit && td.superclass != null; if (extendable) { + boolean callBuilderBasedSuperConstructor = td.superclass != null; generateBuilderBasedConstructor(tdParent, builderFields, annotationNode, builderClassName, callBuilderBasedSuperConstructor); } else { @@ -539,13 +536,21 @@ public class HandleBuilder extends EclipseAnnotationHandler { } /** + * Generates a constructor that has a builder as the only parameter. + * The values from the builder are used to initialize the fields of new instances. + * + * @param typeNode + * the type (with the {@code @Builder} annotation) for which a + * constructor should be generated. + * @param builderFields a list of fields in the builder which should be assigned to new instances. + * @param sourceNode the annotation (used for setting source code locations for the generated code). * @param builderClassnameAsParameter - * if {@code != null}, the only parameter of the constructor will + * If {@code != null}, the only parameter of the constructor will * be a builder with this classname; the constructor will then * use the values within this builder to assign the fields of new * instances. * @param callBuilderBasedSuperConstructor - * if {@code true}, the constructor will explicitly call a super + * If {@code true}, the constructor will explicitly call a super * constructor with the builder as argument. Requires * {@code builderClassAsParameter != null}. */ @@ -622,31 +627,6 @@ public class HandleBuilder extends EclipseAnnotationHandler { constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]); constructor.arguments = new Argument[] {new Argument("b".toCharArray(), p, new SingleTypeReference(builderClassnameAsParameter.toCharArray(), p), Modifier.FINAL)}; - boolean suppressConstructorProperties = Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES)); - if (!suppressConstructorProperties) { - // Add ConstructorProperties - long[] poss = new long[3]; - Arrays.fill(poss, p); - QualifiedTypeReference constructorPropertiesType = new QualifiedTypeReference(HandleConstructor.JAVA_BEANS_CONSTRUCTORPROPERTIES, poss); - setGeneratedBy(constructorPropertiesType, source); - SingleMemberAnnotation ann = new SingleMemberAnnotation(constructorPropertiesType, source.sourceStart); - ann.declarationSourceEnd = source.sourceEnd; - - ArrayInitializer fieldNames = new ArrayInitializer(); - fieldNames.sourceStart = source.sourceStart; - fieldNames.sourceEnd = source.sourceEnd; - fieldNames.expressions = new Expression[1]; - - fieldNames.expressions[0] = new StringLiteral("b".toCharArray(), source.sourceStart, source.sourceEnd, 0); - setGeneratedBy(fieldNames.expressions[0], source); - - ann.memberValue = fieldNames; - setGeneratedBy(ann, source); - setGeneratedBy(ann.memberValue, source); - Annotation[] constructorProperties = new Annotation[] { ann }; - constructor.annotations = copyAnnotations(source, constructorProperties); - } - constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope); injectMethod(typeNode, constructor); diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 42e76cf1..9860fb07 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -175,8 +175,8 @@ public class HandleBuilder extends JavacAnnotationHandler { superclassBuilderClassName = extendsClause + "Builder"; } - boolean callBuilderBasedSuperConstructor = inherit && extendsClause != null; if (extendable) { + boolean callBuilderBasedSuperConstructor = extendsClause != null; generateBuilderBasedConstructor(tdParent, builderFields, annotationNode, builderClassName, callBuilderBasedSuperConstructor); } else { new HandleConstructor().generateConstructor(tdParent, AccessLevel.PROTECTED, List.nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); @@ -510,13 +510,20 @@ public class HandleBuilder extends JavacAnnotationHandler { /** * Generates a constructor that has a builder as the only parameter. - * + * The values from the builder are used to initialize the fields of new instances. + * + * @param typeNode + * the type (with the {@code @Builder} annotation) for which a + * constructor should be generated. + * @param builderFields a list of fields in the builder which should be assigned to new instances. + * @param source the annotation (used for setting source code locations for the generated code). * @param builderClassnameAsParameter - * the only parameter of the constructor will be a builder with - * this classname; the constructor will use the values within - * this builder to assign the fields of new instances. + * If {@code != null}, the only parameter of the constructor will + * be a builder with this classname; the constructor will then + * use the values within this builder to assign the fields of new + * instances. * @param callBuilderBasedSuperConstructor - * if {@code true}, the constructor will explicitly call a super + * If {@code true}, the constructor will explicitly call a super * constructor with the builder as argument. Requires * {@code builderClassAsParameter != null}. */ @@ -562,17 +569,6 @@ public class HandleBuilder extends JavacAnnotationHandler { JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.nil()); - boolean suppressConstructorProperties = Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES)); - if (!suppressConstructorProperties) { - // Add ConstructorProperties - JCExpression constructorPropertiesType = chainDots(typeNode, "java", "beans", "ConstructorProperties"); - ListBuffer fieldNames = new ListBuffer(); - fieldNames.append(maker.Literal(builderVariableName.toString())); - JCExpression fieldNamesArray = maker.NewArray(null, List.nil(), fieldNames.toList()); - JCAnnotation annotation = maker.Annotation(constructorPropertiesType, List.of(fieldNamesArray)); - mods.annotations = mods.annotations.append(annotation); - } - // Create a constructor that has just the builder as parameter. ListBuffer params = new ListBuffer(); long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext()); -- cgit From 2a6c0c16b303b6af0b96e296858c2c54140f6dfe Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 28 Mar 2018 00:38:07 +0200 Subject: [builderParentClass] Code to handle builder on enums removed; that doesn’t make a heck of a lot of sense and enums aren’t extensible in the first place. Also fixed up a wrong access level; now all existing builder tests pass. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/lombok/eclipse/handlers/HandleBuilder.java | 5 +---- src/core/lombok/javac/handlers/HandleBuilder.java | 7 ++----- 2 files changed, 3 insertions(+), 9 deletions(-) (limited to 'src/core/lombok/eclipse/handlers/HandleBuilder.java') diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index b5c6e793..08ef91b5 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -604,12 +604,9 @@ public class HandleBuilder extends EclipseAnnotationHandler { TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get()); long p = (long) source.sourceStart << 32 | source.sourceEnd; - boolean isEnum = (((TypeDeclaration) typeNode.get()).modifiers & ClassFileConstants.AccEnum) != 0; - AccessLevel level = isEnum ? AccessLevel.PRIVATE : AccessLevel.PROTECTED; - ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult); - constructor.modifiers = toEclipseModifier(level); + constructor.modifiers = toEclipseModifier(AccessLevel.PROTECTED); constructor.selector = typeDeclaration.name; if (callBuilderBasedSuperConstructor) { constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.Super); diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 4c575d91..a74ebfda 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -195,7 +195,7 @@ public class HandleBuilder extends JavacAnnotationHandler { boolean callBuilderBasedSuperConstructor = extendsClause != null; generateBuilderBasedConstructor(tdParent, builderFields, annotationNode, builderClassName, callBuilderBasedSuperConstructor); } else { - handleConstructor.generateConstructor(tdParent, AccessLevel.PROTECTED, List.nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); + handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, List.nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); } returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), td.name, td.typarams); @@ -569,9 +569,6 @@ public class HandleBuilder extends JavacAnnotationHandler { private void generateBuilderBasedConstructor(JavacNode typeNode, java.util.List builderFields, JavacNode source, String builderClassnameAsParameter, boolean callBuilderBasedSuperConstructor) { JavacTreeMaker maker = typeNode.getTreeMaker(); - boolean isEnum = (((JCClassDecl) typeNode.get()).mods.flags & Flags.ENUM) != 0; - AccessLevel level = isEnum ? AccessLevel.PRIVATE : AccessLevel.PROTECTED; - ListBuffer nullChecks = new ListBuffer(); ListBuffer statements = new ListBuffer(); @@ -599,7 +596,7 @@ public class HandleBuilder extends JavacAnnotationHandler { statements.append(maker.Exec(assign)); } - JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.nil()); + JCModifiers mods = maker.Modifiers(toJavacModifier(AccessLevel.PROTECTED), List.nil()); // Create a constructor that has just the builder as parameter. ListBuffer params = new ListBuffer(); -- cgit From 9470ca650ef6eb977047464041bff26fcafdeae3 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Wed, 30 May 2018 13:30:54 +0200 Subject: ecj: revert changes to HandleBuilder (everything in HandleSuperBuilder) --- .../lombok/eclipse/handlers/HandleBuilder.java | 244 ++++----------------- 1 file changed, 48 insertions(+), 196 deletions(-) (limited to 'src/core/lombok/eclipse/handlers/HandleBuilder.java') diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 08ef91b5..d4cdc654 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -25,7 +25,6 @@ import static lombok.eclipse.Eclipse.*; import static lombok.core.handlers.HandlerUtil.*; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; -import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -41,7 +40,6 @@ import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; -import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FalseLiteral; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; @@ -52,7 +50,6 @@ import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; -import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; @@ -84,7 +81,6 @@ import lombok.core.HandlerPriority; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; -import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult; import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer; import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists; @@ -106,7 +102,6 @@ public class HandleBuilder extends EclipseAnnotationHandler { } private static class BuilderFieldData { - EclipseNode fieldNode; TypeReference type; char[] rawName; char[] name; @@ -160,10 +155,6 @@ public class HandleBuilder extends EclipseAnnotationHandler { String builderMethodName = builderInstance.builderMethodName(); String buildMethodName = builderInstance.buildMethodName(); String builderClassName = builderInstance.builderClassName(); - - boolean inherit = builderInstance.inherit(); - boolean extensible = inherit || builderInstance.extensible(); // inherit implies extendable - String toBuilderMethodName = "toBuilder"; boolean toBuilder = builderInstance.toBuilder(); List typeArgsForToBuilder = null; @@ -191,11 +182,9 @@ public class HandleBuilder extends EclipseAnnotationHandler { boolean addCleaning = false; boolean isStatic = true; - TypeDeclaration td = null; - if (parent.get() instanceof TypeDeclaration) { tdParent = parent; - td = (TypeDeclaration) tdParent.get(); + TypeDeclaration td = (TypeDeclaration) tdParent.get(); List allFields = new ArrayList(); boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent)); @@ -205,7 +194,6 @@ public class HandleBuilder extends EclipseAnnotationHandler { boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode)); BuilderFieldData bfd = new BuilderFieldData(); - bfd.fieldNode = fieldNode; bfd.rawName = fieldNode.getName().toCharArray(); bfd.name = removePrefixFromField(fieldNode); bfd.type = fd.type; @@ -239,29 +227,15 @@ public class HandleBuilder extends EclipseAnnotationHandler { allFields.add(fieldNode); } - if (builderClassName.isEmpty()) builderClassName = new String(td.name) + "Builder"; - - if (extensible) { - boolean callBuilderBasedSuperConstructor = td.superclass != null; - generateBuilderBasedConstructor(tdParent, builderFields, annotationNode, builderClassName, callBuilderBasedSuperConstructor); - } else { - handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, - Collections.emptyList(), annotationNode); - } + handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, + Collections.emptyList(), annotationNode); returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p); typeParams = td.typeParameters; thrownExceptions = null; nameOfStaticBuilderMethod = null; + if (builderClassName.isEmpty()) builderClassName = new String(td.name) + "Builder"; } else if (parent.get() instanceof ConstructorDeclaration) { - if (inherit) { - annotationNode.addError("@Builder(inherit=true) is only supported for type builders."); - return; - } - if (extensible) { - annotationNode.addError("@Builder(extensible=true) is only supported for type builders."); - return; - } ConstructorDeclaration cd = (ConstructorDeclaration) parent.get(); if (cd.typeParameters != null && cd.typeParameters.length > 0) { annotationNode.addError("@Builder is not supported on constructors with constructor type parameters."); @@ -269,21 +243,13 @@ public class HandleBuilder extends EclipseAnnotationHandler { } tdParent = parent.up(); - td = (TypeDeclaration) tdParent.get(); + TypeDeclaration td = (TypeDeclaration) tdParent.get(); returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p); typeParams = td.typeParameters; thrownExceptions = cd.thrownExceptions; nameOfStaticBuilderMethod = null; if (builderClassName.isEmpty()) builderClassName = new String(cd.selector) + "Builder"; } else if (parent.get() instanceof MethodDeclaration) { - if (inherit) { - annotationNode.addError("@Builder(inherit=true) is only supported for type builders."); - return; - } - if (extensible) { - annotationNode.addError("@Builder(extendable=true) is only supported for type builders."); - return; - } MethodDeclaration md = (MethodDeclaration) parent.get(); tdParent = parent.up(); isStatic = md.isStatic(); @@ -414,20 +380,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { EclipseNode builderType = findInnerClass(tdParent, builderClassName); if (builderType == null) { - String superclassBuilderClassName = null; - if (inherit) { - if (td.superclass == null) { - annotationNode.addError("@Builder(inherit = true) requires that your class has an 'extends' clause."); - return; - } - - superclassBuilderClassName = builderInstance.superclassBuilderClassName(); - if (superclassBuilderClassName == null || superclassBuilderClassName.isEmpty()) { - superclassBuilderClassName = new String(td.superclass.getLastToken()) + "Builder"; - } - } - - builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast, superclassBuilderClassName); + builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast); } else { TypeDeclaration builderTypeDeclaration = (TypeDeclaration) builderType.get(); if (isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) { @@ -491,7 +444,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { } if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) { - MethodDeclaration md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast, extensible); + MethodDeclaration md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast); if (md != null) injectMethod(builderType, md); } @@ -539,7 +492,8 @@ public class HandleBuilder extends EclipseAnnotationHandler { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; - MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); + MethodDeclaration out = new MethodDeclaration( + ((CompilationUnitDeclaration) type.top().get()).compilationResult); out.selector = methodName.toCharArray(); out.modifiers = ClassFileConstants.AccPublic; out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; @@ -577,92 +531,6 @@ public class HandleBuilder extends EclipseAnnotationHandler { } - /** - * Generates a constructor that has a builder as the only parameter. - * The values from the builder are used to initialize the fields of new instances. - * - * @param typeNode - * the type (with the {@code @Builder} annotation) for which a - * constructor should be generated. - * @param builderFields a list of fields in the builder which should be assigned to new instances. - * @param sourceNode the annotation (used for setting source code locations for the generated code). - * @param builderClassnameAsParameter - * If {@code != null}, the only parameter of the constructor will - * be a builder with this classname; the constructor will then - * use the values within this builder to assign the fields of new - * instances. - * @param callBuilderBasedSuperConstructor - * If {@code true}, the constructor will explicitly call a super - * constructor with the builder as argument. Requires - * {@code builderClassAsParameter != null}. - */ - private void generateBuilderBasedConstructor(EclipseNode typeNode, List builderFields, EclipseNode sourceNode, - String builderClassnameAsParameter, boolean callBuilderBasedSuperConstructor) { - - ASTNode source = sourceNode.get(); - - TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get()); - long p = (long) source.sourceStart << 32 | source.sourceEnd; - - ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult); - - constructor.modifiers = toEclipseModifier(AccessLevel.PROTECTED); - constructor.selector = typeDeclaration.name; - if (callBuilderBasedSuperConstructor) { - constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.Super); - constructor.constructorCall.arguments = new Expression[] {new SingleNameReference("b".toCharArray(), p)}; - } else { - constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper); - } - constructor.constructorCall.sourceStart = source.sourceStart; - constructor.constructorCall.sourceEnd = source.sourceEnd; - constructor.thrownExceptions = null; - constructor.typeParameters = null; - constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart; - constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd; - constructor.arguments = null; - - List statements = new ArrayList(); - List nullChecks = new ArrayList(); - - for (BuilderFieldData fieldNode : builderFields) { - char[] fieldName = removePrefixFromField(fieldNode.fieldNode); - FieldReference thisX = new FieldReference(fieldNode.rawName, p); - int s = (int) (p >> 32); - int e = (int) p; - thisX.receiver = new ThisReference(s, e); - - Expression assignmentExpr; - if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) { - fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode, statements, fieldNode.name, "b"); - assignmentExpr = new SingleNameReference(fieldNode.name, p); - } else { - char[][] variableInBuilder = new char[][] {"b".toCharArray(), fieldName}; - long[] positions = new long[] {p, p}; - assignmentExpr = new QualifiedNameReference(variableInBuilder, positions, s, e); - } - - Assignment assignment = new Assignment(thisX, assignmentExpr, (int) p); - statements.add(assignment); - Annotation[] nonNulls = findAnnotations((FieldDeclaration)fieldNode.fieldNode.get(), NON_NULL_PATTERN); - if (nonNulls.length != 0) { - Statement nullCheck = generateNullCheck((FieldDeclaration)fieldNode.fieldNode.get(), sourceNode); - if (nullCheck != null) { - nullChecks.add(nullCheck); - } - } - } - - nullChecks.addAll(statements); - constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[nullChecks.size()]); - constructor.arguments = new Argument[] {new Argument("b".toCharArray(), p, new SingleTypeReference(builderClassnameAsParameter.toCharArray(), p), Modifier.FINAL)}; - - constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope); - - injectMethod(typeNode, constructor); - } - private MethodDeclaration generateCleanMethod(List builderFields, EclipseNode builderType, ASTNode source) { List statements = new ArrayList(); @@ -685,60 +553,51 @@ public class HandleBuilder extends EclipseAnnotationHandler { return decl; } - /** - * @param useBuilderBasedConstructor - * if true, the {@code build()} method will use a constructor - * that takes the builder instance as parameter (instead of a - * constructor with all relevant fields as parameters) - */ - public MethodDeclaration generateBuildMethod(EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source, boolean useBuilderBasedConstructor) { + public MethodDeclaration generateBuildMethod(EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source) { MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; List statements = new ArrayList(); - List args = new ArrayList(); - // Extendable builders assign their values in the constructor, not in this build() method. - if (!useBuilderBasedConstructor) { - if (addCleaning) { - FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0); - thisUnclean.receiver = new ThisReference(0, 0); - Expression notClean = new UnaryExpression(thisUnclean, OperatorIds.NOT); - MessageSend invokeClean = new MessageSend(); - invokeClean.selector = CLEAN_METHOD_NAME; - statements.add(new IfStatement(notClean, invokeClean, 0, 0)); - } - - for (BuilderFieldData bfd : builderFields) { - if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { - bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name, "this"); - } - } - - for (BuilderFieldData bfd : builderFields) { - if (bfd.nameOfSetFlag != null) { - MessageSend inv = new MessageSend(); - inv.sourceStart = source.sourceStart; - inv.sourceEnd = source.sourceEnd; - inv.receiver = new SingleNameReference(((TypeDeclaration) tdParent.get()).name, 0L); - inv.selector = bfd.nameOfDefaultProvider; - inv.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters); - - args.add(new ConditionalExpression( - new SingleNameReference(bfd.nameOfSetFlag, 0L), - new SingleNameReference(bfd.name, 0L), - inv)); - } else { - args.add(new SingleNameReference(bfd.name, 0L)); - } + if (addCleaning) { + FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0); + thisUnclean.receiver = new ThisReference(0, 0); + Expression notClean = new UnaryExpression(thisUnclean, OperatorIds.NOT); + MessageSend invokeClean = new MessageSend(); + invokeClean.selector = CLEAN_METHOD_NAME; + statements.add(new IfStatement(notClean, invokeClean, 0, 0)); + } + + for (BuilderFieldData bfd : builderFields) { + if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { + bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name); } - - if (addCleaning) { - FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0); - thisUnclean.receiver = new ThisReference(0, 0); - statements.add(new Assignment(thisUnclean, new TrueLiteral(0, 0), 0)); + } + + List args = new ArrayList(); + for (BuilderFieldData bfd : builderFields) { + if (bfd.nameOfSetFlag != null) { + MessageSend inv = new MessageSend(); + inv.sourceStart = source.sourceStart; + inv.sourceEnd = source.sourceEnd; + inv.receiver = new SingleNameReference(((TypeDeclaration) tdParent.get()).name, 0L); + inv.selector = bfd.nameOfDefaultProvider; + inv.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters); + + args.add(new ConditionalExpression( + new SingleNameReference(bfd.nameOfSetFlag, 0L), + new SingleNameReference(bfd.name, 0L), + inv)); + } else { + args.add(new SingleNameReference(bfd.name, 0L)); } } + if (addCleaning) { + FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0); + thisUnclean.receiver = new ThisReference(0, 0); + statements.add(new Assignment(thisUnclean, new TrueLiteral(0, 0), 0)); + } + out.modifiers = ClassFileConstants.AccPublic; out.selector = name.toCharArray(); out.thrownExceptions = copyTypes(thrownExceptions); @@ -748,13 +607,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { if (staticName == null) { AllocationExpression allocationStatement = new AllocationExpression(); allocationStatement.type = copyType(out.returnType); - if (useBuilderBasedConstructor) { - // Use a constructor that only has this builder as parameter. - allocationStatement.arguments = new Expression[] {new ThisReference(0, 0)}; - } else { - // Use a constructor with all the fields. - allocationStatement.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]); - } + allocationStatement.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]); statements.add(new ReturnStatement(allocationStatement, 0, 0)); } else { MessageSend invoke = new MessageSend(); @@ -903,7 +756,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { return null; } - public EclipseNode makeBuilderClass(boolean isStatic, EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, ASTNode source, String parentBuilderClassName) { + public EclipseNode makeBuilderClass(boolean isStatic, EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, ASTNode source) { TypeDeclaration parent = (TypeDeclaration) tdParent.get(); TypeDeclaration builder = new TypeDeclaration(parent.compilationResult); builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; @@ -911,7 +764,6 @@ public class HandleBuilder extends EclipseAnnotationHandler { if (isStatic) builder.modifiers |= ClassFileConstants.AccStatic; builder.typeParameters = copyTypeParams(typeParams, source); builder.name = builderClassName.toCharArray(); - if (parentBuilderClassName != null) builder.superclass = new SingleTypeReference(parentBuilderClassName.toCharArray(), 0); builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return injectType(tdParent, builder); } -- cgit From cdee277f11becb5a3629158e0ffbe7292a85d255 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Wed, 30 May 2018 13:38:07 +0200 Subject: ecj: fixed compiler errors after revert of HandleBuilder --- src/core/lombok/eclipse/handlers/HandleBuilder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core/lombok/eclipse/handlers/HandleBuilder.java') diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index d4cdc654..331fbde4 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -434,7 +434,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) { ConstructorDeclaration cd = HandleConstructor.createConstructor( - AccessLevel.PACKAGE, builderType, Collections.emptyList(), false, + AccessLevel.PACKAGE, builderType, Collections.emptyList(), false, true, annotationNode, Collections.emptyList()); if (cd != null) injectMethod(builderType, cd); } @@ -569,7 +569,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { for (BuilderFieldData bfd : builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { - bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name); + bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name, "this"); } } @@ -640,7 +640,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { return trs; } - public MethodDeclaration generateDefaultProvider(char[] methodName, TypeParameter[] typeParameters, EclipseNode fieldNode, ASTNode source) { + public static MethodDeclaration generateDefaultProvider(char[] methodName, TypeParameter[] typeParameters, EclipseNode fieldNode, ASTNode source) { int pS = source.sourceStart, pE = source.sourceEnd; MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) fieldNode.top().get()).compilationResult); -- cgit From 32bed51fede1eebef2006d54b3e364de22ae9ac0 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Thu, 31 May 2018 18:01:43 +0200 Subject: ecj: generate default constructor for builder classes --- src/core/lombok/eclipse/handlers/HandleBuilder.java | 2 +- .../lombok/eclipse/handlers/HandleSuperBuilder.java | 17 +++++++++-------- .../transform/resource/after-ecj/SuperBuilderBasic.java | 10 ++++++++-- .../after-ecj/SuperBuilderWithCustomBuilderMethod.java | 13 +++++++++++-- .../resource/after-ecj/SuperBuilderWithGenerics.java | 13 +++++++++++-- .../resource/after-ecj/SuperBuilderWithGenerics2.java | 13 +++++++++++-- 6 files changed, 51 insertions(+), 17 deletions(-) (limited to 'src/core/lombok/eclipse/handlers/HandleBuilder.java') diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 331fbde4..fe19decd 100644 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -434,7 +434,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) { ConstructorDeclaration cd = HandleConstructor.createConstructor( - AccessLevel.PACKAGE, builderType, Collections.emptyList(), false, true, + AccessLevel.PACKAGE, builderType, Collections.emptyList(), false, annotationNode, Collections.emptyList()); if (cd != null) injectMethod(builderType, cd); } diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index 3b7e95ca..04c3b2fe 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -63,6 +63,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; +import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; @@ -337,12 +338,6 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { return; } - // Create a simple constructor for the BuilderImpl class. - ConstructorDeclaration cd = HandleConstructor.createConstructor(AccessLevel.PRIVATE, builderImplType, Collections.emptyList(), false, annotationNode, Collections.emptyList()); - if (cd != null) { - injectMethod(builderImplType, cd); - } - // Create the self() and build() methods in the BuilderImpl. injectMethod(builderImplType, generateSelfMethod(builderImplType)); injectMethod(builderImplType, generateBuildMethod(tdParent, buildMethodName, returnType, ast)); @@ -383,6 +378,8 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { builder.superclass = copyType(superclassBuilderClass, source); + builder.createDefaultConstructor(false, true); + builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return injectType(tdParent, builder); } @@ -393,6 +390,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; builder.modifiers |= ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal; builder.name = builderImplClass.toCharArray(); + // Add type params if there are any. if (typeParams != null && typeParams.length > 0) { builder.typeParameters = copyTypeParams(typeParams, source); @@ -410,6 +408,9 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { typeArgs[typeArgs.length - 1] = createTypeReferenceWithTypeParameters(builderImplClass, typeParams); builder.superclass = new ParameterizedSingleTypeReference(builderAbstractClass.toCharArray(), typeArgs, 0, 0); } + + builder.createDefaultConstructor(false, true); + builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return injectType(tdParent, builder); } @@ -526,7 +527,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult); out.selector = SELF_METHOD.toCharArray(); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - out.modifiers = ClassFileConstants.AccAbstract | ClassFileConstants.AccProtected; + out.modifiers = ClassFileConstants.AccAbstract | ClassFileConstants.AccProtected | ExtraCompilerModifiers.AccSemicolonBody; if (override) { out.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, tdParent.get())}; } @@ -550,7 +551,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) tdParent.top().get()).compilationResult); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - out.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract; + out.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract | ExtraCompilerModifiers.AccSemicolonBody; out.selector = methodName.toCharArray(); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; out.returnType = new SingleTypeReference(classGenericName.toCharArray(), 0); diff --git a/test/transform/resource/after-ecj/SuperBuilderBasic.java b/test/transform/resource/after-ecj/SuperBuilderBasic.java index 88ac7e70..11fd8498 100644 --- a/test/transform/resource/after-ecj/SuperBuilderBasic.java +++ b/test/transform/resource/after-ecj/SuperBuilderBasic.java @@ -4,6 +4,9 @@ public class SuperBuilderBasic { public static abstract @java.lang.SuppressWarnings("all") class ParentBuilder> { private @java.lang.SuppressWarnings("all") int field1; private @java.lang.SuppressWarnings("all") java.util.ArrayList items; + public ParentBuilder() { + super(); + } protected abstract @java.lang.SuppressWarnings("all") B self(); public abstract @java.lang.SuppressWarnings("all") C build(); public @java.lang.SuppressWarnings("all") B field1(final int field1) { @@ -32,7 +35,7 @@ public class SuperBuilderBasic { } } private static final @java.lang.SuppressWarnings("all") class ParentBuilderImpl extends ParentBuilder { - private @java.lang.SuppressWarnings("all") ParentBuilderImpl() { + private ParentBuilderImpl() { super(); } protected @java.lang.Override @java.lang.SuppressWarnings("all") ParentBuilderImpl self() { @@ -67,6 +70,9 @@ public class SuperBuilderBasic { public static @lombok.experimental.SuperBuilder class Child extends Parent { public static abstract @java.lang.SuppressWarnings("all") class ChildBuilder> extends Parent.ParentBuilder { private @java.lang.SuppressWarnings("all") double field3; + public ChildBuilder() { + super(); + } protected abstract @java.lang.Override @java.lang.SuppressWarnings("all") B self(); public abstract @java.lang.Override @java.lang.SuppressWarnings("all") C build(); public @java.lang.SuppressWarnings("all") B field3(final double field3) { @@ -78,7 +84,7 @@ public class SuperBuilderBasic { } } private static final @java.lang.SuppressWarnings("all") class ChildBuilderImpl extends ChildBuilder { - private @java.lang.SuppressWarnings("all") ChildBuilderImpl() { + private ChildBuilderImpl() { super(); } protected @java.lang.Override @java.lang.SuppressWarnings("all") ChildBuilderImpl self() { diff --git a/test/transform/resource/after-ecj/SuperBuilderWithCustomBuilderMethod.java b/test/transform/resource/after-ecj/SuperBuilderWithCustomBuilderMethod.java index 119fb5bb..fe4938bf 100644 --- a/test/transform/resource/after-ecj/SuperBuilderWithCustomBuilderMethod.java +++ b/test/transform/resource/after-ecj/SuperBuilderWithCustomBuilderMethod.java @@ -4,6 +4,9 @@ public class SuperBuilderWithCustomBuilderMethod { public static abstract @java.lang.SuppressWarnings("all") class ParentBuilder, B extends ParentBuilder> { private @java.lang.SuppressWarnings("all") A field1; private @java.lang.SuppressWarnings("all") java.util.ArrayList items; + public ParentBuilder() { + super(); + } protected abstract @java.lang.SuppressWarnings("all") B self(); public abstract @java.lang.SuppressWarnings("all") C build(); public @java.lang.SuppressWarnings("all") B field1(final A field1) { @@ -32,7 +35,8 @@ public class SuperBuilderWithCustomBuilderMethod { } } private static final @java.lang.SuppressWarnings("all") class ParentBuilderImpl extends ParentBuilder, ParentBuilderImpl> { - private @java.lang.SuppressWarnings("all") ParentBuilderImpl() { + private ParentBuilderImpl() { + super(); } protected @java.lang.Override @java.lang.SuppressWarnings("all") ParentBuilderImpl self() { return this; @@ -44,6 +48,7 @@ public class SuperBuilderWithCustomBuilderMethod { A field1; @lombok.Singular List items; protected @java.lang.SuppressWarnings("all") Parent(final ParentBuilder b) { + super(); this.field1 = b.field1; java.util.List items; switch (((b.items == null) ? 0 : b.items.size())) { @@ -65,6 +70,9 @@ public class SuperBuilderWithCustomBuilderMethod { public static @lombok.experimental.SuperBuilder class Child extends Parent { public static abstract @java.lang.SuppressWarnings("all") class ChildBuilder, B extends ChildBuilder> extends Parent.ParentBuilder { private @java.lang.SuppressWarnings("all") double field3; + public ChildBuilder() { + super(); + } protected abstract @java.lang.Override @java.lang.SuppressWarnings("all") B self(); public abstract @java.lang.Override @java.lang.SuppressWarnings("all") C build(); public @java.lang.SuppressWarnings("all") B field3(final double field3) { @@ -76,7 +84,8 @@ public class SuperBuilderWithCustomBuilderMethod { } } private static final @java.lang.SuppressWarnings("all") class ChildBuilderImpl extends ChildBuilder, ChildBuilderImpl> { - private @java.lang.SuppressWarnings("all") ChildBuilderImpl() { + private ChildBuilderImpl() { + super(); } protected @java.lang.Override @java.lang.SuppressWarnings("all") ChildBuilderImpl self() { return this; diff --git a/test/transform/resource/after-ecj/SuperBuilderWithGenerics.java b/test/transform/resource/after-ecj/SuperBuilderWithGenerics.java index cb717bcf..b82f25cb 100644 --- a/test/transform/resource/after-ecj/SuperBuilderWithGenerics.java +++ b/test/transform/resource/after-ecj/SuperBuilderWithGenerics.java @@ -4,6 +4,9 @@ public class SuperBuilderWithGenerics { public static abstract @java.lang.SuppressWarnings("all") class ParentBuilder, B extends ParentBuilder> { private @java.lang.SuppressWarnings("all") A field1; private @java.lang.SuppressWarnings("all") java.util.ArrayList items; + public ParentBuilder() { + super(); + } protected abstract @java.lang.SuppressWarnings("all") B self(); public abstract @java.lang.SuppressWarnings("all") C build(); public @java.lang.SuppressWarnings("all") B field1(final A field1) { @@ -32,7 +35,8 @@ public class SuperBuilderWithGenerics { } } private static final @java.lang.SuppressWarnings("all") class ParentBuilderImpl extends ParentBuilder, ParentBuilderImpl> { - private @java.lang.SuppressWarnings("all") ParentBuilderImpl() { + private ParentBuilderImpl() { + super(); } protected @java.lang.Override @java.lang.SuppressWarnings("all") ParentBuilderImpl self() { return this; @@ -44,6 +48,7 @@ public class SuperBuilderWithGenerics { A field1; @lombok.Singular List items; protected @java.lang.SuppressWarnings("all") Parent(final ParentBuilder b) { + super(); this.field1 = b.field1; java.util.List items; switch (((b.items == null) ? 0 : b.items.size())) { @@ -65,6 +70,9 @@ public class SuperBuilderWithGenerics { public static @lombok.experimental.SuperBuilder class Child extends Parent { public static abstract @java.lang.SuppressWarnings("all") class ChildBuilder, B extends ChildBuilder> extends Parent.ParentBuilder { private @java.lang.SuppressWarnings("all") double field3; + public ChildBuilder() { + super(); + } protected abstract @java.lang.Override @java.lang.SuppressWarnings("all") B self(); public abstract @java.lang.Override @java.lang.SuppressWarnings("all") C build(); public @java.lang.SuppressWarnings("all") B field3(final double field3) { @@ -76,7 +84,8 @@ public class SuperBuilderWithGenerics { } } private static final @java.lang.SuppressWarnings("all") class ChildBuilderImpl extends ChildBuilder, ChildBuilderImpl> { - private @java.lang.SuppressWarnings("all") ChildBuilderImpl() { + private ChildBuilderImpl() { + super(); } protected @java.lang.Override @java.lang.SuppressWarnings("all") ChildBuilderImpl self() { return this; diff --git a/test/transform/resource/after-ecj/SuperBuilderWithGenerics2.java b/test/transform/resource/after-ecj/SuperBuilderWithGenerics2.java index 74cf376e..7db95ea0 100644 --- a/test/transform/resource/after-ecj/SuperBuilderWithGenerics2.java +++ b/test/transform/resource/after-ecj/SuperBuilderWithGenerics2.java @@ -4,6 +4,9 @@ public class SuperBuilderWithGenerics2 { public static abstract @java.lang.SuppressWarnings("all") class ParentBuilder, B extends ParentBuilder> { private @java.lang.SuppressWarnings("all") A field1; private @java.lang.SuppressWarnings("all") java.util.ArrayList items; + public ParentBuilder() { + super(); + } protected abstract @java.lang.SuppressWarnings("all") B self(); public abstract @java.lang.SuppressWarnings("all") C build(); public @java.lang.SuppressWarnings("all") B field1(final A field1) { @@ -32,7 +35,8 @@ public class SuperBuilderWithGenerics2 { } } private static final @java.lang.SuppressWarnings("all") class ParentBuilderImpl extends ParentBuilder, ParentBuilderImpl> { - private @java.lang.SuppressWarnings("all") ParentBuilderImpl() { + private ParentBuilderImpl() { + super(); } protected @java.lang.Override @java.lang.SuppressWarnings("all") ParentBuilderImpl self() { return this; @@ -44,6 +48,7 @@ public class SuperBuilderWithGenerics2 { A field1; @lombok.Singular List items; protected @java.lang.SuppressWarnings("all") Parent(final ParentBuilder b) { + super(); this.field1 = b.field1; java.util.List items; switch (((b.items == null) ? 0 : b.items.size())) { @@ -65,6 +70,9 @@ public class SuperBuilderWithGenerics2 { public static @lombok.experimental.SuperBuilder(builderMethodName = "builder2") class Child extends Parent { public static abstract @java.lang.SuppressWarnings("all") class ChildBuilder, B extends ChildBuilder> extends Parent.ParentBuilder { private @java.lang.SuppressWarnings("all") A field3; + public ChildBuilder() { + super(); + } protected abstract @java.lang.Override @java.lang.SuppressWarnings("all") B self(); public abstract @java.lang.Override @java.lang.SuppressWarnings("all") C build(); public @java.lang.SuppressWarnings("all") B field3(final A field3) { @@ -76,7 +84,8 @@ public class SuperBuilderWithGenerics2 { } } private static final @java.lang.SuppressWarnings("all") class ChildBuilderImpl extends ChildBuilder, ChildBuilderImpl> { - private @java.lang.SuppressWarnings("all") ChildBuilderImpl() { + private ChildBuilderImpl() { + super(); } protected @java.lang.Override @java.lang.SuppressWarnings("all") ChildBuilderImpl self() { return this; -- cgit