From bd78d0841775b1a1c91ed4eef1defc62b33e9ed5 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 16 Nov 2015 23:46:12 +0100 Subject: [builder] Added clearX() functionality for `@Singular` annotations for javac. Also docs and changelog. --- doc/changelog.markdown | 1 + .../singulars/EclipseGuavaSingularizer.java | 2 +- .../EclipseJavaUtilListSetSingularizer.java | 2 +- .../singulars/EclipseJavaUtilMapSingularizer.java | 2 +- .../handlers/singulars/JavacGuavaSingularizer.java | 20 ++++++++++++++ .../JavacJavaUtilListSetSingularizer.java | 24 ++++++++++++++++ .../singulars/JavacJavaUtilMapSingularizer.java | 27 ++++++++++++++++++ .../BuilderSingularGuavaListsSets.java | 24 ++++++++++++++++ .../after-delombok/BuilderSingularGuavaMaps.java | 18 ++++++++++++ .../after-delombok/BuilderSingularLists.java | 18 ++++++++++++ .../after-delombok/BuilderSingularMaps.java | 32 ++++++++++++++++++++++ .../after-delombok/BuilderSingularNoAuto.java | 18 ++++++++++++ .../BuilderSingularRedirectToGuava.java | 18 ++++++++++++ .../after-delombok/BuilderSingularSets.java | 24 ++++++++++++++++ .../after-delombok/BuilderWithToBuilder.java | 6 ++++ usage_examples/BuilderExample_post.jpage | 8 ++++++ website/features/Builder.html | 7 +++-- 17 files changed, 245 insertions(+), 6 deletions(-) diff --git a/doc/changelog.markdown b/doc/changelog.markdown index da1cefce..52ed1182 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -2,6 +2,7 @@ Lombok Changelog ---------------- ### v1.16.7 "Edgy Guinea Pig" +* FEATURE: The `@Builder` annotation has received many updates: It now generates `clearFieldName()` methods if `@Singular` is used, ..... [Issue #967](https://github.com/rzwitserloot/lombok/issues/967). * FEATURE: A `lombok.config` key can now be used to make your fields `final` and/or `private`... __everywhere__. We'll be monitoring the performance impact of this for a while. We'll touch every source file if you turn these on, and even if you don't, we have to call into the lombok config system for every file. * BUGFIX: `@Value` and `@FieldDefaults` no longer make uninitialized static fields final. [Issue #928](https://github.com/rzwitserloot/lombok/issues/928). * BUGFIX: When using delombok, a source file with only `@NonNull` annotations on parameters as lombok feature would not get properly delomboked. [Issue #950](https://github.com/rzwitserloot/lombok/issues/950). diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index 622451ee..d1c4d53c 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -124,7 +124,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { thisDotField.receiver = new ThisReference(0, 0); Assignment a = new Assignment(thisDotField, new NullLiteral(0, 0), 0); md.selector = HandlerUtil.buildAccessorName("clear", new String(data.getPluralName())).toCharArray(); - md.statements = new Statement[] {a, returnStatement}; + md.statements = returnStatement != null ? new Statement[] {a, returnStatement} : new Statement[] {a}; md.returnType = returnType; injectMethod(builderType, md); } diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java index 5efb610f..2d8083d3 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java @@ -120,7 +120,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula clearMsg.receiver = thisDotField2; clearMsg.selector = "clear".toCharArray(); Statement clearStatement = new IfStatement(new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL), clearMsg, 0, 0); - md.statements = new Statement[] {clearStatement, returnStatement}; + md.statements = returnStatement != null ? new Statement[] {clearStatement, returnStatement} : new Statement[] {clearStatement}; md.returnType = returnType; injectMethod(builderType, md); } diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java index 3aaa9165..ef9e2a76 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java @@ -176,7 +176,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer Block clearMsgs = new Block(2); clearMsgs.statements = new Statement[] {clearMsg1, clearMsg2}; Statement clearStatement = new IfStatement(new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL), clearMsgs, 0, 0); - md.statements = new Statement[] {clearStatement, returnStatement}; + md.statements = returnStatement != null ? new Statement[] {clearStatement, returnStatement} : new Statement[] {clearStatement}; md.returnType = returnType; injectMethod(builderType, md); } diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java index 41e379f6..97e5f9be 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java @@ -78,6 +78,26 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer { returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(maker, CTC_VOID)); returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null; generatePluralMethod(maker, returnType, returnStatement, data, builderType, source, fluent); + + returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(maker, CTC_VOID)); + returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null; + generateClearMethod(maker, returnType, returnStatement, data, builderType, source); + } + + private void generateClearMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) { + JCModifiers mods = maker.Modifiers(Flags.PUBLIC); + List typeParams = List.nil(); + List thrown = List.nil(); + List params = List.nil(); + + JCExpression thisDotField = maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName()); + JCStatement clearField = maker.Exec(maker.Assign(thisDotField, maker.Literal(CTC_BOT, null))); + List statements = returnStatement != null ? List.of(clearField, returnStatement) : List.of(clearField); + + JCBlock body = maker.Block(0, statements); + Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString())); + JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params, thrown, body, null); + injectMethod(builderType, method); } void generateSingularMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) { diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java index 8574ddbf..e167c7e2 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java @@ -91,6 +91,30 @@ abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularize returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(maker, CTC_VOID)); returnStatement = chain ? maker.Return(maker.Ident(thisName)) : null; generatePluralMethod(maker, returnType, returnStatement, data, builderType, source, fluent); + + returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(maker, CTC_VOID)); + returnStatement = chain ? maker.Return(maker.Ident(thisName)) : null; + generateClearMethod(maker, returnType, returnStatement, data, builderType, source); + } + + private void generateClearMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) { + JCModifiers mods = maker.Modifiers(Flags.PUBLIC); + List typeParams = List.nil(); + List thrown = List.nil(); + List params = List.nil(); + List jceBlank = List.nil(); + + JCExpression thisDotField = maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName()); + JCExpression thisDotFieldDotClear = maker.Select(maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName()), builderType.toName("clear")); + JCStatement clearCall = maker.Exec(maker.Apply(jceBlank, thisDotFieldDotClear, jceBlank)); + JCExpression cond = maker.Binary(CTC_NOT_EQUAL, thisDotField, maker.Literal(CTC_BOT, null)); + JCStatement ifSetCallClear = maker.If(cond, clearCall, null); + List statements = returnStatement != null ? List.of(ifSetCallClear, returnStatement) : List.of(ifSetCallClear); + + JCBlock body = maker.Block(0, statements); + Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString())); + JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params, thrown, body, null); + injectMethod(builderType, method); } void generateSingularMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) { diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java index 0830c9c9..1acae7e3 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java @@ -115,6 +115,33 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer { returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(maker, CTC_VOID)); returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null; generatePluralMethod(maker, returnType, returnStatement, data, builderType, source, fluent); + + returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(maker, CTC_VOID)); + returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null; + generateClearMethod(maker, returnType, returnStatement, data, builderType, source); + } + + private void generateClearMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) { + JCModifiers mods = maker.Modifiers(Flags.PUBLIC); + List typeParams = List.nil(); + List thrown = List.nil(); + List params = List.nil(); + List jceBlank = List.nil(); + + JCExpression thisDotKeyField = chainDots(builderType, "this", data.getPluralName() + "$key"); + JCExpression thisDotKeyFieldDotClear = chainDots(builderType, "this", data.getPluralName() + "$key", "clear"); + JCExpression thisDotValueFieldDotClear = chainDots(builderType, "this", data.getPluralName() + "$value", "clear"); + JCStatement clearKeyCall = maker.Exec(maker.Apply(jceBlank, thisDotKeyFieldDotClear, jceBlank)); + JCStatement clearValueCall = maker.Exec(maker.Apply(jceBlank, thisDotValueFieldDotClear, jceBlank)); + JCExpression cond = maker.Binary(CTC_NOT_EQUAL, thisDotKeyField, maker.Literal(CTC_BOT, null)); + JCBlock clearCalls = maker.Block(0, List.of(clearKeyCall, clearValueCall)); + JCStatement ifSetCallClear = maker.If(cond, clearCalls, null); + List statements = returnStatement != null ? List.of(ifSetCallClear, returnStatement) : List.of(ifSetCallClear); + + JCBlock body = maker.Block(0, statements); + Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString())); + JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params, thrown, body, null); + injectMethod(builderType, method); } private void generateSingularMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) { diff --git a/test/transform/resource/after-delombok/BuilderSingularGuavaListsSets.java b/test/transform/resource/after-delombok/BuilderSingularGuavaListsSets.java index f8e0579d..3339d809 100644 --- a/test/transform/resource/after-delombok/BuilderSingularGuavaListsSets.java +++ b/test/transform/resource/after-delombok/BuilderSingularGuavaListsSets.java @@ -51,6 +51,12 @@ class BuilderSingularGuavaListsSets { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularGuavaListsSetsBuilder clearCards() { + this.cards = null; + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularGuavaListsSetsBuilder frog(final Number frog) { if (this.frogs == null) this.frogs = com.google.common.collect.ImmutableList.builder(); this.frogs.add(frog); @@ -65,6 +71,12 @@ class BuilderSingularGuavaListsSets { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularGuavaListsSetsBuilder clearFrogs() { + this.frogs = null; + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularGuavaListsSetsBuilder rawSet(final java.lang.Object rawSet) { if (this.rawSet == null) this.rawSet = com.google.common.collect.ImmutableSet.builder(); this.rawSet.add(rawSet); @@ -79,6 +91,12 @@ class BuilderSingularGuavaListsSets { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularGuavaListsSetsBuilder clearRawSet() { + this.rawSet = null; + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularGuavaListsSetsBuilder pass(final String pass) { if (this.passes == null) this.passes = com.google.common.collect.ImmutableSortedSet.naturalOrder(); this.passes.add(pass); @@ -93,6 +111,12 @@ class BuilderSingularGuavaListsSets { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularGuavaListsSetsBuilder clearPasses() { + this.passes = null; + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularGuavaListsSets build() { com.google.common.collect.ImmutableList cards = this.cards == null ? com.google.common.collect.ImmutableList.of() : this.cards.build(); com.google.common.collect.ImmutableCollection frogs = this.frogs == null ? com.google.common.collect.ImmutableList.of() : this.frogs.build(); diff --git a/test/transform/resource/after-delombok/BuilderSingularGuavaMaps.java b/test/transform/resource/after-delombok/BuilderSingularGuavaMaps.java index 0cb0001b..10545a8f 100644 --- a/test/transform/resource/after-delombok/BuilderSingularGuavaMaps.java +++ b/test/transform/resource/after-delombok/BuilderSingularGuavaMaps.java @@ -45,6 +45,12 @@ class BuilderSingularGuavaMaps { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularGuavaMapsBuilder clearBattleaxes() { + this.battleaxes = null; + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularGuavaMapsBuilder vertex(final Integer vertex$key, final V vertex$value) { if (this.vertices == null) this.vertices = com.google.common.collect.ImmutableSortedMap.naturalOrder(); this.vertices.put(vertex$key, vertex$value); @@ -59,6 +65,12 @@ class BuilderSingularGuavaMaps { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularGuavaMapsBuilder clearVertices() { + this.vertices = null; + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularGuavaMapsBuilder rawMap(final java.lang.Object rawMap$key, final java.lang.Object rawMap$value) { if (this.rawMap == null) this.rawMap = com.google.common.collect.ImmutableBiMap.builder(); this.rawMap.put(rawMap$key, rawMap$value); @@ -73,6 +85,12 @@ class BuilderSingularGuavaMaps { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularGuavaMapsBuilder clearRawMap() { + this.rawMap = null; + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularGuavaMaps build() { com.google.common.collect.ImmutableMap battleaxes = this.battleaxes == null ? com.google.common.collect.ImmutableMap.of() : this.battleaxes.build(); com.google.common.collect.ImmutableSortedMap vertices = this.vertices == null ? com.google.common.collect.ImmutableSortedMap.of() : this.vertices.build(); diff --git a/test/transform/resource/after-delombok/BuilderSingularLists.java b/test/transform/resource/after-delombok/BuilderSingularLists.java index f58934d4..9b409404 100644 --- a/test/transform/resource/after-delombok/BuilderSingularLists.java +++ b/test/transform/resource/after-delombok/BuilderSingularLists.java @@ -44,6 +44,12 @@ class BuilderSingularLists { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularListsBuilder clearChildren() { + if (this.children != null) this.children.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularListsBuilder scarf(final Number scarf) { if (this.scarves == null) this.scarves = new java.util.ArrayList(); this.scarves.add(scarf); @@ -58,6 +64,12 @@ class BuilderSingularLists { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularListsBuilder clearScarves() { + if (this.scarves != null) this.scarves.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularListsBuilder rawList(final java.lang.Object rawList) { if (this.rawList == null) this.rawList = new java.util.ArrayList(); this.rawList.add(rawList); @@ -72,6 +84,12 @@ class BuilderSingularLists { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularListsBuilder clearRawList() { + if (this.rawList != null) this.rawList.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularLists build() { java.util.List children; switch (this.children == null ? 0 : this.children.size()) { diff --git a/test/transform/resource/after-delombok/BuilderSingularMaps.java b/test/transform/resource/after-delombok/BuilderSingularMaps.java index 212ece26..257a2ec2 100644 --- a/test/transform/resource/after-delombok/BuilderSingularMaps.java +++ b/test/transform/resource/after-delombok/BuilderSingularMaps.java @@ -57,6 +57,14 @@ class BuilderSingularMaps { return this; } @SuppressWarnings("all") + public BuilderSingularMapsBuilder clearWomen() { + if (this.women$key != null) { + this.women$key.clear(); + this.women$value.clear(); + } + return this; + } + @SuppressWarnings("all") public BuilderSingularMapsBuilder man(K manKey, Number manValue) { if (this.men$key == null) { this.men$key = new java.util.ArrayList(); @@ -79,6 +87,14 @@ class BuilderSingularMaps { return this; } @SuppressWarnings("all") + public BuilderSingularMapsBuilder clearMen() { + if (this.men$key != null) { + this.men$key.clear(); + this.men$value.clear(); + } + return this; + } + @SuppressWarnings("all") public BuilderSingularMapsBuilder rawMap(Object rawMapKey, Object rawMapValue) { if (this.rawMap$key == null) { this.rawMap$key = new java.util.ArrayList(); @@ -101,6 +117,14 @@ class BuilderSingularMaps { return this; } @SuppressWarnings("all") + public BuilderSingularMapsBuilder clearRawMap() { + if (this.rawMap$key != null) { + this.rawMap$key.clear(); + this.rawMap$value.clear(); + } + return this; + } + @SuppressWarnings("all") public BuilderSingularMapsBuilder stringMap(String stringMapKey, V stringMapValue) { if (this.stringMap$key == null) { this.stringMap$key = new java.util.ArrayList(); @@ -123,6 +147,14 @@ class BuilderSingularMaps { return this; } @SuppressWarnings("all") + public BuilderSingularMapsBuilder clearStringMap() { + if (this.stringMap$key != null) { + this.stringMap$key.clear(); + this.stringMap$value.clear(); + } + return this; + } + @SuppressWarnings("all") public BuilderSingularMaps build() { java.util.Map women; switch (this.women$key == null ? 0 : this.women$key.size()) { diff --git a/test/transform/resource/after-delombok/BuilderSingularNoAuto.java b/test/transform/resource/after-delombok/BuilderSingularNoAuto.java index 0be33a84..d5cd8f41 100644 --- a/test/transform/resource/after-delombok/BuilderSingularNoAuto.java +++ b/test/transform/resource/after-delombok/BuilderSingularNoAuto.java @@ -42,6 +42,12 @@ class BuilderSingularNoAuto { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularNoAutoBuilder clearThings() { + if (this.things != null) this.things.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularNoAutoBuilder widget(final String widget) { if (this.widgets == null) this.widgets = new java.util.ArrayList(); this.widgets.add(widget); @@ -56,6 +62,12 @@ class BuilderSingularNoAuto { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularNoAutoBuilder clearWidgets() { + if (this.widgets != null) this.widgets.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularNoAutoBuilder items(final String items) { if (this.items == null) this.items = new java.util.ArrayList(); this.items.add(items); @@ -70,6 +82,12 @@ class BuilderSingularNoAuto { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularNoAutoBuilder clearItems() { + if (this.items != null) this.items.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularNoAuto build() { java.util.List things; switch (this.things == null ? 0 : this.things.size()) { diff --git a/test/transform/resource/after-delombok/BuilderSingularRedirectToGuava.java b/test/transform/resource/after-delombok/BuilderSingularRedirectToGuava.java index 0dd40c9f..506a8b4c 100644 --- a/test/transform/resource/after-delombok/BuilderSingularRedirectToGuava.java +++ b/test/transform/resource/after-delombok/BuilderSingularRedirectToGuava.java @@ -44,6 +44,12 @@ class BuilderSingularRedirectToGuava { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularRedirectToGuavaBuilder clearDangerMice() { + this.dangerMice = null; + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularRedirectToGuavaBuilder thing(final Integer thing$key, final Number thing$value) { if (this.things == null) this.things = com.google.common.collect.ImmutableSortedMap.naturalOrder(); this.things.put(thing$key, thing$value); @@ -58,6 +64,12 @@ class BuilderSingularRedirectToGuava { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularRedirectToGuavaBuilder clearThings() { + this.things = null; + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularRedirectToGuavaBuilder doohickey(final Class doohickey) { if (this.doohickeys == null) this.doohickeys = com.google.common.collect.ImmutableList.builder(); this.doohickeys.add(doohickey); @@ -72,6 +84,12 @@ class BuilderSingularRedirectToGuava { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularRedirectToGuavaBuilder clearDoohickeys() { + this.doohickeys = null; + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularRedirectToGuava build() { java.util.Set dangerMice = this.dangerMice == null ? com.google.common.collect.ImmutableSet.of() : this.dangerMice.build(); java.util.NavigableMap things = this.things == null ? com.google.common.collect.ImmutableSortedMap.of() : this.things.build(); diff --git a/test/transform/resource/after-delombok/BuilderSingularSets.java b/test/transform/resource/after-delombok/BuilderSingularSets.java index 70372b99..c794726a 100644 --- a/test/transform/resource/after-delombok/BuilderSingularSets.java +++ b/test/transform/resource/after-delombok/BuilderSingularSets.java @@ -49,6 +49,12 @@ class BuilderSingularSets { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularSetsBuilder clearDangerMice() { + if (this.dangerMice != null) this.dangerMice.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularSetsBuilder octopus(final Number octopus) { if (this.octopodes == null) this.octopodes = new java.util.ArrayList(); this.octopodes.add(octopus); @@ -63,6 +69,12 @@ class BuilderSingularSets { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularSetsBuilder clearOctopodes() { + if (this.octopodes != null) this.octopodes.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularSetsBuilder rawSet(final java.lang.Object rawSet) { if (this.rawSet == null) this.rawSet = new java.util.ArrayList(); this.rawSet.add(rawSet); @@ -77,6 +89,12 @@ class BuilderSingularSets { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularSetsBuilder clearRawSet() { + if (this.rawSet != null) this.rawSet.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularSetsBuilder stringSet(final String stringSet) { if (this.stringSet == null) this.stringSet = new java.util.ArrayList(); this.stringSet.add(stringSet); @@ -91,6 +109,12 @@ class BuilderSingularSets { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderSingularSetsBuilder clearStringSet() { + if (this.stringSet != null) this.stringSet.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderSingularSets build() { java.util.Set dangerMice; switch (this.dangerMice == null ? 0 : this.dangerMice.size()) { diff --git a/test/transform/resource/after-delombok/BuilderWithToBuilder.java b/test/transform/resource/after-delombok/BuilderWithToBuilder.java index eb61a6db..7dfb046a 100644 --- a/test/transform/resource/after-delombok/BuilderWithToBuilder.java +++ b/test/transform/resource/after-delombok/BuilderWithToBuilder.java @@ -68,6 +68,12 @@ class BuilderWithToBuilder { } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") + public BuilderWithToBuilderBuilder clearBars() { + if (this.bars != null) this.bars.clear(); + return this; + } + @java.lang.SuppressWarnings("all") + @javax.annotation.Generated("lombok") public BuilderWithToBuilder build() { java.util.List bars; switch (this.bars == null ? 0 : this.bars.size()) { diff --git a/usage_examples/BuilderExample_post.jpage b/usage_examples/BuilderExample_post.jpage index 8a1d1e69..54b064d7 100644 --- a/usage_examples/BuilderExample_post.jpage +++ b/usage_examples/BuilderExample_post.jpage @@ -51,6 +51,14 @@ public class BuilderExample { return this; } + public BuilderExampleBuilder clearOccupations() { + if (this.occupations != null) { + this.occupations.clear(); + } + + return this; + } + public BuilderExample build() { // complicated switch statement to produce a compact properly sized immutable set omitted. // go to https://projectlombok.org/features/Singular-snippet.html to see it. diff --git a/website/features/Builder.html b/website/features/Builder.html index 6cf46600..582be3b4 100644 --- a/website/features/Builder.html +++ b/website/features/Builder.html @@ -18,7 +18,8 @@ @Builder was introduced as experimental feature in lombok v0.12.0.

@Builder gained @Singular support and was promoted to the main lombok package since lombok v1.16.0. -

+

+ @Builder with @Singular adds a clear method since lombok v1.16.8.

Overview

@@ -82,11 +83,11 @@

By annotating one of the parameters (if annotating a static method or constructor with @Builder) or fields (if annotating a class with @Builder) with the @Singular annotation, lombok will treat that builder node as a collection, and it generates 2 'adder' methods instead of a 'setter' method. One which adds a single element to the collection, and one - which adds all elements of another collection to the collection. No setter to just set the collection (replacing whatever was already added) will be generated. These 'singular' builders + which adds all elements of another collection to the collection. No setter to just set the collection (replacing whatever was already added) will be generated. A 'clear' method is also generated. These 'singular' builders are very complicated in order to guarantee the following properties:

  • When invoking build(), the produced collection will be immutable.
  • -
  • Calling one of the 'adder' methods after invoking build() does not modify any already generated objects, and, if build() is later called again, another collection with all the elements added since the creation of the builder is generated.
  • +
  • Calling one of the 'adder' methods, or the 'clear' method, after invoking build() does not modify any already generated objects, and, if build() is later called again, another collection with all the elements added since the creation of the builder is generated.
  • The produced collection will be compacted to the smallest feasible format while remaining efficient.

-- cgit