From bd78d0841775b1a1c91ed4eef1defc62b33e9ed5 Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot <reinier@zwitserloot.com>
Date: Mon, 16 Nov 2015 23:46:12 +0100
Subject: [builder] Added clearX() functionality for `@Singular` annotations
 for javac. Also docs and changelog.

---
 .../singulars/EclipseGuavaSingularizer.java        |  2 +-
 .../EclipseJavaUtilListSetSingularizer.java        |  2 +-
 .../singulars/EclipseJavaUtilMapSingularizer.java  |  2 +-
 .../handlers/singulars/JavacGuavaSingularizer.java | 20 ++++++++++++++++
 .../JavacJavaUtilListSetSingularizer.java          | 24 +++++++++++++++++++
 .../singulars/JavacJavaUtilMapSingularizer.java    | 27 ++++++++++++++++++++++
 6 files changed, 74 insertions(+), 3 deletions(-)

(limited to 'src/core/lombok')

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<JCTypeParameter> typeParams = List.nil();
+		List<JCExpression> thrown = List.nil();
+		List<JCVariableDecl> 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<JCStatement> 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<JCTypeParameter> typeParams = List.nil();
+		List<JCExpression> thrown = List.nil();
+		List<JCVariableDecl> params = List.nil();
+		List<JCExpression> 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<JCStatement> 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<JCTypeParameter> typeParams = List.nil();
+		List<JCExpression> thrown = List.nil();
+		List<JCVariableDecl> params = List.nil();
+		List<JCExpression> 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<JCStatement> 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) {
-- 
cgit