diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/lombok/Builder.java | 23 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleBuilder.java | 15 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleBuilder.java | 18 |
3 files changed, 45 insertions, 11 deletions
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,15 +123,30 @@ 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.<br> + * 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()}. <br> + * 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}). <br> + * Note that this builder must be a type {@code @Builder}; this feature does + * neither work for constructor nor method {@code @Builder}s.<br> + * 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<Builder> { 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<Builder> { 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.<Annotation>emptyList(), annotationNode, builderClassName, callSuperConstructor); + Collections.<Annotation>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<Builder> { 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<Builder> { 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<Builder> { } 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<Builder> { 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<Builder> { superclassBuilderClassName = extendsClause + "Builder"; } - boolean callSuperConstructor = inherit && extendsClause != null; - new HandleConstructor().generateConstructor(tdParent, AccessLevel.PROTECTED, List.<JCAnnotation>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.<JCAnnotation>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<Builder> { 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<Builder> { 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<Builder> { } 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); } |