diff options
| author | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2019-12-11 01:59:05 +0100 |
|---|---|---|
| committer | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2019-12-11 01:59:05 +0100 |
| commit | f8ecfafbcd30fdbb3b94a4b0bd1dd50fcf4e4b9e (patch) | |
| tree | 0a4598d5e68232dc95aea8e58e8837088abc9462 | |
| parent | ad2cc23d2cc6b47c1453122505a3e589c3c0668f (diff) | |
| parent | 870937a46f912592206abda57638d142ae81e763 (diff) | |
| download | lombok-f8ecfafbcd30fdbb3b94a4b0bd1dd50fcf4e4b9e.tar.gz lombok-f8ecfafbcd30fdbb3b94a4b0bd1dd50fcf4e4b9e.tar.bz2 lombok-f8ecfafbcd30fdbb3b94a4b0bd1dd50fcf4e4b9e.zip | |
Merge branch 'floralvikings-feature/builder-setter-prefixes'
83 files changed, 4310 insertions, 51 deletions
@@ -15,10 +15,11 @@ /.factorypath /lombok.iml /.idea +*.iml *.markdown.html /junit*.properties /eclipse.location /.apt_generated/ /out /website/lombokSupporters -/pom.xml
\ No newline at end of file +/pom.xml @@ -2,6 +2,7 @@ Lombok contributors in alphabetical order: Adam Juraszek <juriad@gmail.com> Bulgakov Alexander <buls@yandex.ru> +Caleb Brinkman <floralvikings@gmail.com> Christian Nüssgens <christian@nuessgens.com> Christian Sterzl <christian.sterzl@gmail.com> DaveLaw <project.lombok@apconsult.de> diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 44b7f553..b859c5a8 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -3,6 +3,7 @@ Lombok Changelog ### v1.18.11 "Edgy Guinea Pig" * PLATFORM: Support for JDK13 (including `yield` in switch expressions, as well as delombok having a nicer style for arrow-style switch blocks, and text blocks). +* FEATURE: You can now configure a builder's 'setter' prefixes via `@Builder(setterPrefix = "set")` for example. We discourage doing this, but if some library you use requires them, have at it. [Pull Request #2174](https://github.com/rzwitserloot/lombok/pull/2174], [Issue #1805](https://github.com/rzwitserloot/lombok/issues/1805). ### v1.18.10 (September 10th, 2019) diff --git a/src/core/lombok/Builder.java b/src/core/lombok/Builder.java index dfa5ecb5..4ca3da65 100644 --- a/src/core/lombok/Builder.java +++ b/src/core/lombok/Builder.java @@ -153,6 +153,22 @@ public @interface Builder { * @return The builder class will be generated with this access modifier. */ AccessLevel access() default lombok.AccessLevel.PUBLIC; + + /** + * Prefix to prepend to 'set' methods in the generated builder class. By default, generated methods do not include a prefix. + * + * For example, a method normally generated as {@code someField(String someField)} would instead be + * generated as {@code withSomeField(String someField)} if using {@code @Builder(setterPrefix = "with")}. + * + * Note that using "with" to prefix builder setter methods is strongly discouraged as as "with" normally + * suggests immutable data structures, and builders by definition are mutable objects. + * + * For {@code @Singular} fields, the generated methods are called {@code withName}, {@code withNames}, and {@code clearNames}, instead of + * the default {@code name}, {@code names}, and {@code clearNames}. + * + * @return The prefix to prepend to generated method names. + */ + String setterPrefix() default ""; /** * Put on a field (in case of {@code @Builder} on a type) or a parameter (for {@code @Builder} on a constructor or static method) to diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java index 483431cc..cb2ebe18 100755 --- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java +++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java @@ -122,12 +122,17 @@ public class EclipseSingularsRecipes { private final EclipseNode annotation; private final char[] singularName; private final char[] pluralName; + private final char[] setterPrefix; private final List<TypeReference> typeArgs; private final String targetFqn; private final EclipseSingularizer singularizer; private final ASTNode source; public SingularData(EclipseNode annotation, char[] singularName, char[] pluralName, List<TypeReference> typeArgs, String targetFqn, EclipseSingularizer singularizer, ASTNode source) { + this(annotation, singularName, pluralName, typeArgs, targetFqn, singularizer, source, new char[0]); + } + + public SingularData(EclipseNode annotation, char[] singularName, char[] pluralName, List<TypeReference> typeArgs, String targetFqn, EclipseSingularizer singularizer, ASTNode source, char[] setterPrefix) { this.annotation = annotation; this.singularName = singularName; this.pluralName = pluralName; @@ -135,6 +140,7 @@ public class EclipseSingularsRecipes { this.targetFqn = targetFqn; this.singularizer = singularizer; this.source = source; + this.setterPrefix = setterPrefix; } public void setGeneratedByRecursive(ASTNode target) { @@ -165,6 +171,10 @@ public class EclipseSingularsRecipes { return pluralName; } + public char[] getSetterPrefix() { + return setterPrefix; + } + public List<TypeReference> getTypeArgs() { return typeArgs; } diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 8bfdeb65..70978e23 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -239,7 +239,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { bfd.builderFieldName = bfd.name; bfd.annotations = copyAnnotations(fd, copyableAnnotations); bfd.type = fd.type; - bfd.singularData = getSingularData(fieldNode, ast); + bfd.singularData = getSingularData(fieldNode, ast, builderInstance.setterPrefix()); bfd.originalFieldNode = fieldNode; if (bfd.singularData != null && isDefault != null) { @@ -422,7 +422,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { bfd.builderFieldName = bfd.name; bfd.annotations = copyAnnotations(arg, copyableAnnotations); bfd.type = arg.type; - bfd.singularData = getSingularData(param, ast); + bfd.singularData = getSingularData(param, ast, builderInstance.setterPrefix()); bfd.originalFieldNode = param; addObtainVia(bfd, param); builderFields.add(bfd); @@ -492,7 +492,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } for (BuilderFieldData bfd : builderFields) { - makeSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners, bfd.originalFieldNode); + makePrefixedSetterMethodsForBuilder(cfv, builderType, bfd, annotationNode, fluent, chain, accessForInners, bfd.originalFieldNode, builderInstance.setterPrefix()); } { @@ -539,7 +539,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { tps[i].name = typeArgsForToBuilder.get(i); } } - MethodDeclaration md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters); + MethodDeclaration md = generateToBuilderMethod(cfv, toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters, builderInstance.setterPrefix()); if (md != null) injectMethod(tdParent, md); } @@ -552,7 +552,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } private static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'}; - private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source, AccessLevel access) { + private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source, AccessLevel access, String prefix) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; @@ -567,7 +567,10 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { Expression receiver = invoke; List<Statement> statements = null; for (BuilderFieldData bfd : builderFields) { - char[] setterName = fluent ? bfd.name : HandlerUtil.buildAccessorName("set", new String(bfd.name)).toCharArray(); + String setterName = new String(bfd.name); + String setterPrefix = !prefix.isEmpty() ? prefix : fluent ? "" : "set"; + if (!setterPrefix.isEmpty()) setterName = HandlerUtil.buildAccessorName(setterPrefix, setterName); + MessageSend ms = new MessageSend(); Expression[] tgt = new Expression[bfd.singularData == null ? 1 : 2]; @@ -600,7 +603,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } } - ms.selector = setterName; + ms.selector = setterName.toCharArray(); if (bfd.singularData == null) { ms.arguments = tgt; ms.receiver = receiver; @@ -634,7 +637,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope); return out; - } private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType, ASTNode source) { @@ -746,10 +748,11 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { } else { MessageSend invoke = new MessageSend(); invoke.selector = staticName; - if (isStatic) + if (isStatic) { invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), 0); - else + } else { invoke.receiver = new QualifiedThisReference(new SingleTypeReference(type.up().getName().toCharArray(), 0) , 0, 0); + } invoke.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters); invoke.arguments = args.isEmpty() ? null : args.toArray(new Expression[0]); @@ -862,33 +865,39 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { private static final AbstractMethodDeclaration[] EMPTY = {}; - public void makeSetterMethodsForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain, AccessLevel access, EclipseNode originalFieldNode) { + public void makePrefixedSetterMethodsForBuilder(CheckerFrameworkVersion cfv, EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain, AccessLevel access, EclipseNode originalFieldNode, String prefix) { boolean deprecate = isFieldDeprecated(bfd.originalFieldNode); |
