aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/eclipse
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@zwitserloot.com>2015-01-19 23:39:40 +0100
committerReinier Zwitserloot <reinier@zwitserloot.com>2015-01-19 23:39:40 +0100
commit519f95c2410c2e43c60e81233cad105552975606 (patch)
treebfbcdd60de47e19e5a0e510060099c0277cf7175 /src/core/lombok/eclipse
parentd6fe0a281b23f44afd241fc60f5401bbca6fa0a8 (diff)
downloadlombok-519f95c2410c2e43c60e81233cad105552975606.tar.gz
lombok-519f95c2410c2e43c60e81233cad105552975606.tar.bz2
lombok-519f95c2410c2e43c60e81233cad105552975606.zip
builder @Singleton now works fully in eclipse as well! feature done!
Diffstat (limited to 'src/core/lombok/eclipse')
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java21
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilder.java42
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java45
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java45
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java247
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java3
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java6
7 files changed, 389 insertions, 20 deletions
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
index 0157552b..e61e5d68 100644
--- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
+++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
@@ -8,9 +8,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
@@ -24,6 +27,8 @@ import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import lombok.core.LombokImmutableList;
@@ -101,14 +106,28 @@ public class EclipseSingularsRecipes {
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) {
+ public SingularData(EclipseNode annotation, char[] singularName, char[] pluralName, List<TypeReference> typeArgs, String targetFqn, EclipseSingularizer singularizer, ASTNode source) {
this.annotation = annotation;
this.singularName = singularName;
this.pluralName = pluralName;
this.typeArgs = typeArgs;
this.targetFqn = targetFqn;
this.singularizer = singularizer;
+ this.source = source;
+ }
+
+ public void setGeneratedByRecursive(ASTNode target) {
+ SetGeneratedByVisitor visitor = new SetGeneratedByVisitor(source);
+
+ if (target instanceof AbstractMethodDeclaration) {
+ ((AbstractMethodDeclaration) target).traverse(visitor, (ClassScope) null);
+ } else if (target instanceof FieldDeclaration) {
+ ((FieldDeclaration) target).traverse(visitor, (MethodScope) null);
+ } else {
+ target.traverse(visitor, null);
+ }
}
public EclipseNode getAnnotation() {
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index 365256c7..b2ea7bbc 100644
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -62,6 +62,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.mangosdk.spi.ProviderFor;
@@ -71,6 +72,7 @@ import lombok.Builder;
import lombok.ConfigurationKeys;
import lombok.Singular;
import lombok.core.AST.Kind;
+import lombok.core.handlers.HandlerUtil;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.eclipse.Eclipse;
@@ -89,6 +91,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
private static final boolean toBoolean(Object expr, boolean defaultValue) {
if (expr == null) return defaultValue;
+ if (expr instanceof FalseLiteral) return false;
+ if (expr instanceof TrueLiteral) return true;
return ((Boolean) expr).booleanValue();
}
@@ -153,7 +157,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
BuilderFieldData bfd = new BuilderFieldData();
bfd.name = removePrefixFromField(fieldNode);
bfd.type = fd.type;
- bfd.singularData = getSingularData(fieldNode);
+ bfd.singularData = getSingularData(fieldNode, ast);
builderFields.add(bfd);
allFields.add(fieldNode);
}
@@ -232,7 +236,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
Argument arg = (Argument) param.get();
bfd.name = arg.name;
bfd.type = arg.type;
- bfd.singularData = getSingularData(param);
+ bfd.singularData = getSingularData(param, ast);
builderFields.add(bfd);
}
}
@@ -253,12 +257,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
- generateBuilderFields(builderType, builderFields);
+ generateBuilderFields(builderType, builderFields, ast);
if (addCleaning) {
FieldDeclaration cleanDecl = new FieldDeclaration(CLEAN_FIELD_NAME, 0, -1);
cleanDecl.declarationSourceEnd = -1;
cleanDecl.modifiers = ClassFileConstants.AccPrivate;
cleanDecl.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
+ System.out.println("INJECTING: cleaning");
injectField(builderType, cleanDecl);
}
@@ -274,7 +279,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) {
- MethodDeclaration md = generateBuildMethod(buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning);
+ MethodDeclaration md = generateBuildMethod(buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast);
if (md != null) injectMethod(builderType, md);
}
@@ -287,17 +292,18 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
if (md != null) injectMethod(builderType, md);
}
- if (addCleaning) injectMethod(builderType, generateCleanMethod(builderFields, builderType));
+ if (addCleaning) {
+ MethodDeclaration cleanMethod = generateCleanMethod(builderFields, builderType, ast);
+ if (cleanMethod != null) injectMethod(builderType, cleanMethod);
+ }
if (methodExists(builderMethodName, tdParent, -1) == MemberExistsResult.NOT_EXISTS) {
MethodDeclaration md = generateBuilderMethod(builderMethodName, builderClassName, tdParent, typeParams, ast);
if (md != null) injectMethod(tdParent, md);
}
-
- builderType.get().traverse(new SetGeneratedByVisitor(ast), null);
}
- private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType) {
+ private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType, ASTNode source) {
List<Statement> statements = new ArrayList<Statement>();
for (BuilderFieldData bfd : builderFields) {
@@ -309,16 +315,17 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
thisUnclean.receiver = new ThisReference(0, 0);
statements.add(new Assignment(thisUnclean, new FalseLiteral(0, 0), 0));
- MethodDeclaration decl =new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ MethodDeclaration decl = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
decl.selector = CLEAN_METHOD_NAME;
decl.modifiers = ClassFileConstants.AccPrivate;
decl.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
decl.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
decl.statements = statements.toArray(new Statement[0]);
+ decl.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
return decl;
}
- public MethodDeclaration generateBuildMethod(String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning) {
+ public MethodDeclaration generateBuildMethod(String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> 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;
@@ -381,6 +388,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
}
}
out.statements = statements.isEmpty() ? null : statements.toArray(new Statement[statements.size()]);
+ out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
return out;
}
@@ -403,16 +411,14 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return out;
}
- public void generateBuilderFields(EclipseNode builderType, List<BuilderFieldData> builderFields) {
- int len = builderFields.size();
+ public void generateBuilderFields(EclipseNode builderType, List<BuilderFieldData> builderFields, ASTNode source) {
List<EclipseNode> existing = new ArrayList<EclipseNode>();
for (EclipseNode child : builderType.down()) {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
top:
- for (int i = len - 1; i >= 0; i--) {
- BuilderFieldData bfd = builderFields.get(i);
+ for (BuilderFieldData bfd : builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType));
} else {
@@ -428,6 +434,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
fd.modifiers = ClassFileConstants.AccPrivate;
fd.type = copyType(bfd.type);
+ fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
bfd.createdFields.add(injectField(builderType, fd));
}
}
@@ -457,8 +464,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
if (Arrays.equals(name, existingName)) return;
}
- boolean isBoolean = isBoolean(fd.type);
- String setterName = fluent ? fieldNode.getName() : toSetterName(builderType.getAst(), null, fieldNode.getName(), isBoolean);
+ String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName());
MethodDeclaration setter = HandleSetter.createSetter(td, fieldNode, setterName, chain, ClassFileConstants.AccPublic,
sourceNode, Collections.<Annotation>emptyList(), Collections.<Annotation>emptyList());
@@ -492,7 +498,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
*
* @param node The node (field or method param) to inspect for its name and potential {@code @Singular} annotation.
*/
- private SingularData getSingularData(EclipseNode node) {
+ private SingularData getSingularData(EclipseNode node, ASTNode source) {
for (EclipseNode child : node.down()) {
if (child.getKind() == Kind.ANNOTATION && annotationTypeMatches(Singular.class, child)) {
char[] pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((AbstractVariableDeclaration) node.get()).name;
@@ -534,7 +540,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return null;
}
- return new SingularData(child, singularName, pluralName, typeArgs == null ? Collections.<TypeReference>emptyList() : Arrays.asList(typeArgs), targetFqn, singularizer);
+ return new SingularData(child, singularName, pluralName, typeArgs == null ? Collections.<TypeReference>emptyList() : Arrays.asList(typeArgs), targetFqn, singularizer, source);
}
}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java
new file mode 100644
index 00000000..95fd8935
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.core.LombokImmutableList;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+
+@ProviderFor(EclipseSingularizer.class)
+public class EclipseGuavaMapSingularizer extends EclipseGuavaSingularizer {
+ // TODO cgcc.ImmutableMultimap, cgcc.ImmutableListMultimap, cgcc.ImmutableSetMultimap
+ // TODO cgcc.ImmutableClassToInstanceMap
+ // TODO cgcc.ImmutableRangeMap
+
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return LombokImmutableList.of(
+ "com.google.common.collect.ImmutableMap",
+ "com.google.common.collect.ImmutableBiMap",
+ "com.google.common.collect.ImmutableSortedMap");
+ }
+
+ @Override protected boolean isMap() {
+ return true;
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java
new file mode 100644
index 00000000..bc2893bf
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.core.LombokImmutableList;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+
+@ProviderFor(EclipseSingularizer.class)
+public class EclipseGuavaSetListSingularizer extends EclipseGuavaSingularizer {
+ // TODO com.google.common.collect.ImmutableTable
+ // TODO com.google.common.collect.ImmutableRangeSet
+ // TODO com.google.common.collect.ImmutableMultiset and com.google.common.collect.ImmutableSortedMultiset
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return LombokImmutableList.of(
+ "com.google.common.collect.ImmutableCollection",
+ "com.google.common.collect.ImmutableList",
+ "com.google.common.collect.ImmutableSet",
+ "com.google.common.collect.ImmutableSortedSet");
+ }
+
+ @Override protected boolean isMap() {
+ return false;
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
new file mode 100644
index 00000000..775d4ed5
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import static lombok.eclipse.Eclipse.*;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import lombok.core.handlers.HandlerUtil;
+import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+
+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.ConditionalExpression;
+import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.IfStatement;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+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.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+
+abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
+ protected static final char[][] JAVA_UTIL_MAP = {
+ {'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'M', 'a', 'p'}
+ };
+
+ protected String getSimpleTargetTypeName(SingularData data) {
+ String simpleTypeName = data.getTargetSimpleType();
+ if ("ImmutableCollection".equals(simpleTypeName)) return "ImmutableList";
+ return simpleTypeName;
+ }
+
+ protected char[] getBuilderMethodName(SingularData data) {
+ String simpleTypeName = data.getTargetSimpleType();
+ if ("ImmutableSortedSet".equals(simpleTypeName) || "ImmutableSortedMap".equals(simpleTypeName)) return "naturalOrder".toCharArray();
+ return "builder".toCharArray();
+ }
+
+ protected abstract boolean isMap();
+
+ protected char[][] makeGuavaTypeName(String simpleName, boolean addBuilder) {
+ char[][] tokenizedName = new char[addBuilder ? 6 : 5][];
+ tokenizedName[0] = new char[] {'c', 'o', 'm'};
+ tokenizedName[1] = new char[] {'g', 'o', 'o', 'g', 'l', 'e'};
+ tokenizedName[2] = new char[] {'c', 'o', 'm', 'm', 'o', 'n'};
+ tokenizedName[3] = new char[] {'c', 'o', 'l', 'l', 'e', 'c', 't'};
+ tokenizedName[4] = simpleName.toCharArray();
+ if (addBuilder) tokenizedName[5] = new char[] { 'B', 'u', 'i', 'l', 'd', 'e', 'r'};
+ return tokenizedName;
+ }
+
+ @Override public List<EclipseNode> generateFields(SingularData data, EclipseNode builderType) {
+ char[][] tokenizedName = makeGuavaTypeName(getSimpleTargetTypeName(data), true);
+ TypeReference type = new QualifiedTypeReference(tokenizedName, NULL_POSS);
+ type = addTypeArgs(isMap() ? 2 : 1, false, builderType, type, data.getTypeArgs());
+
+ FieldDeclaration buildField = new FieldDeclaration(data.getPluralName(), 0, -1);
+ buildField.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ buildField.modifiers = ClassFileConstants.AccPrivate;
+ buildField.declarationSourceEnd = -1;
+ buildField.type = type;
+ data.setGeneratedByRecursive(buildField);
+ return Collections.singletonList(injectField(builderType, buildField));
+ }
+
+ @Override public void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain) {
+ TypeReference returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ Statement returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ generateSingularMethod(returnType, returnStatement, data, builderType, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ generatePluralMethod(returnType, returnStatement, data, builderType, fluent);
+ }
+
+ void generateSingularMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ boolean mapMode = isMap();
+ char[] keyName = !mapMode ? data.getSingularName() : (new String(data.getSingularName()) + "$key").toCharArray();
+ char[] valueName = !mapMode ? null : (new String(data.getSingularName()) + "$value").toCharArray();
+
+ MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ md.modifiers = ClassFileConstants.AccPublic;
+
+ List<Statement> statements = new ArrayList<Statement>();
+ statements.add(createConstructBuilderVarIfNeeded(data, builderType));
+
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ MessageSend thisDotFieldDotAdd = new MessageSend();
+ if (mapMode) {
+ thisDotFieldDotAdd.arguments = new Expression[] {
+ new SingleNameReference(keyName, 0L),
+ new SingleNameReference(valueName, 0L)};
+ } else {
+ thisDotFieldDotAdd.arguments = new Expression[] {new SingleNameReference(keyName, 0L)};
+ }
+ thisDotFieldDotAdd.receiver = thisDotField;
+ thisDotFieldDotAdd.selector = (mapMode ? "put" : "add").toCharArray();
+ statements.add(thisDotFieldDotAdd);
+ if (returnStatement != null) statements.add(returnStatement);
+ md.statements = statements.toArray(new Statement[statements.size()]);
+
+ if (mapMode) {
+ TypeReference keyType = cloneParamType(0, data.getTypeArgs(), builderType);
+ Argument keyParam = new Argument(keyName, 0, keyType, 0);
+ TypeReference valueType = cloneParamType(1, data.getTypeArgs(), builderType);
+ Argument valueParam = new Argument(valueName, 0, valueType, 0);
+ md.arguments = new Argument[] {keyParam, valueParam};
+ } else {
+ TypeReference paramType = cloneParamType(0, data.getTypeArgs(), builderType);
+ Argument param = new Argument(keyName, 0, paramType, 0);
+ md.arguments = new Argument[] {param};
+ }
+ md.returnType = returnType;
+ md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName(mapMode ? "put" : "add", new String(data.getSingularName())).toCharArray();
+
+ data.setGeneratedByRecursive(md);
+ injectMethod(builderType, md);
+ }
+
+ void generatePluralMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ boolean mapMode = isMap();
+
+ MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ md.modifiers = ClassFileConstants.AccPublic;
+
+ List<Statement> statements = new ArrayList<Statement>();
+ statements.add(createConstructBuilderVarIfNeeded(data, builderType));
+
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ MessageSend thisDotFieldDotAddAll = new MessageSend();
+ thisDotFieldDotAddAll.arguments = new Expression[] {new SingleNameReference(data.getPluralName(), 0L)};
+ thisDotFieldDotAddAll.receiver = thisDotField;
+ thisDotFieldDotAddAll.selector = (mapMode ? "putAll" : "addAll").toCharArray();
+ statements.add(thisDotFieldDotAddAll);
+ if (returnStatement != null) statements.add(returnStatement);
+
+ md.statements = statements.toArray(new Statement[statements.size()]);
+
+ TypeReference paramType;
+ if (mapMode) {
+ paramType = new QualifiedTypeReference(JAVA_UTIL_MAP, NULL_POSS);
+ paramType = addTypeArgs(2, true, builderType, paramType, data.getTypeArgs());
+ } else {
+ paramType = new QualifiedTypeReference(TypeConstants.JAVA_LANG_ITERABLE, NULL_POSS);
+ paramType = addTypeArgs(1, true, builderType, paramType, data.getTypeArgs());
+ }
+ Argument param = new Argument(data.getPluralName(), 0, paramType, 0);
+ md.arguments = new Argument[] {param};
+ md.returnType = returnType;
+ md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName(mapMode ? "putAll" : "addAll", new String(data.getPluralName())).toCharArray();
+
+ data.setGeneratedByRecursive(md);
+ injectMethod(builderType, md);
+ }
+
+ @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName) {
+ boolean mapMode = isMap();
+ TypeReference varType = new QualifiedTypeReference(fromQualifiedName(data.getTargetFqn()), NULL_POSS);
+ varType = addTypeArgs(mapMode ? 2 : 1, false, builderType, varType, data.getTypeArgs());
+
+ MessageSend emptyInvoke; {
+ //ImmutableX.of()
+ emptyInvoke = new MessageSend();
+ emptyInvoke.selector = new char[] {'o', 'f'};
+ emptyInvoke.receiver = new QualifiedNameReference(makeGuavaTypeName(getSimpleTargetTypeName(data), false), NULL_POSS, 0, 0);
+ }
+
+ MessageSend invokeBuild; {
+ //this.pluralName.build();
+ 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);
+ invokeBuild.receiver = thisDotField;
+ }
+
+ Expression isNull; {
+ //this.pluralName == null
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ isNull = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
+ }
+
+ Expression init = new ConditionalExpression(isNull, emptyInvoke, invokeBuild);
+ LocalDeclaration varDefStat = new LocalDeclaration(data.getPluralName(), 0, 0);
+ varDefStat.type = varType;
+ varDefStat.initialization = init;
+ statements.add(varDefStat);
+ }
+
+ protected Statement createConstructBuilderVarIfNeeded(SingularData data, EclipseNode builderType) {
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ FieldReference thisDotField2 = new FieldReference(data.getPluralName(), 0L);
+ thisDotField2.receiver = new ThisReference(0, 0);
+ Expression cond = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
+
+ MessageSend createBuilderInvoke = new MessageSend();
+ char[][] tokenizedName = makeGuavaTypeName(getSimpleTargetTypeName(data), false);
+ createBuilderInvoke.receiver = new QualifiedNameReference(tokenizedName, NULL_POSS, 0, 0);
+ createBuilderInvoke.selector = getBuilderMethodName(data);
+ return new IfStatement(cond, new Assignment(thisDotField2, createBuilderInvoke, 0), 0, 0);
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
index 64b8bd40..f64748a8 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
@@ -59,6 +59,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
buildField.modifiers = ClassFileConstants.AccPrivate;
buildField.declarationSourceEnd = -1;
buildField.type = type;
+ data.setGeneratedByRecursive(buildField);
return Collections.singletonList(injectField(builderType, buildField));
}
@@ -96,6 +97,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray();
+ data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
@@ -125,6 +127,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray();
+ data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
index 8e250994..6558baa5 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
@@ -85,8 +85,10 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
buildValueField.declarationSourceEnd = -1;
buildValueField.type = type;
}
- EclipseNode valueFieldNode = injectField(builderType, buildValueField);
+ data.setGeneratedByRecursive(buildKeyField);
+ data.setGeneratedByRecursive(buildValueField);
EclipseNode keyFieldNode = injectField(builderType, buildKeyField);
+ EclipseNode valueFieldNode = injectField(builderType, buildValueField);
return Arrays.asList(keyFieldNode, valueFieldNode);
}
@@ -145,6 +147,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
md.returnType = returnType;
md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("put", new String(data.getSingularName())).toCharArray();
+ data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}
@@ -207,6 +210,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
md.returnType = returnType;
md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("putAll", new String(data.getPluralName())).toCharArray();
+ data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
}