aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java90
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilder.java11
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java20
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java12
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java48
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java5
6 files changed, 164 insertions, 22 deletions
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
index e61e5d68..eca918d7 100644
--- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
+++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
@@ -1,9 +1,32 @@
+/*
+ * 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;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -36,27 +59,6 @@ import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
import lombok.eclipse.EclipseNode;
-/*
- * 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.
- */
public class EclipseSingularsRecipes {
private static final EclipseSingularsRecipes INSTANCE = new EclipseSingularsRecipes();
private final Map<String, EclipseSingularizer> singularizers = new HashMap<String, EclipseSingularizer>();
@@ -164,7 +166,51 @@ public class EclipseSingularsRecipes {
protected static final long[] NULL_POSS = {0L};
public abstract LombokImmutableList<String> getSupportedTypes();
- public abstract java.util.List<EclipseNode> generateFields(SingularData data, EclipseNode builderType);
+ /** Checks if any of the to-be-generated nodes (fields, methods) already exist. If so, errors on these (singulars don't support manually writing some of it, and returns true). */
+ public boolean checkForAlreadyExistingNodesAndGenerateError(EclipseNode builderType, SingularData data) {
+ for (EclipseNode child : builderType.down()) {
+ switch (child.getKind()) {
+ case FIELD: {
+ FieldDeclaration fd = (FieldDeclaration) child.get();
+ char[] name = fd.name;
+ if (name == null) continue;
+ if (getGeneratedBy(fd) != null) continue;
+ for (char[] fieldToBeGenerated : listFieldsToBeGenerated(data)) {
+ if (!Arrays.equals(name, fieldToBeGenerated)) continue;
+ child.addError("Manually adding a field that @Singular @Builder would generate is not supported. If you want to manually manage the builder aspect for this field/parameter, don't use @Singular.");
+ return true;
+ }
+ break;
+ }
+ case METHOD: {
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration) child.get();
+ char[] name = method.selector;
+ if (name == null) continue;
+ if (getGeneratedBy(method) != null) continue;
+ for (char[] methodToBeGenerated : listMethodsToBeGenerated(data)) {
+ if (!Arrays.equals(name, methodToBeGenerated)) continue;
+ child.addError("Manually adding a method that @Singular @Builder would generate is not supported. If you want to manually manage the builder aspect for this field/parameter, don't use @Singular.");
+ return true;
+ }
+ break;
+ }}
+ }
+
+ return false;
+ }
+
+ public List<char[]> listFieldsToBeGenerated(SingularData data) {
+ return Collections.singletonList(data.pluralName);
+ }
+
+ public List<char[]> listMethodsToBeGenerated(SingularData data) {
+ char[] p = data.pluralName;
+ char[] s = data.singularName;
+ if (Arrays.equals(p, s)) return Collections.singletonList(p);
+ return Arrays.asList(p, s);
+ }
+
+ public abstract List<EclipseNode> generateFields(SingularData data, EclipseNode builderType);
public abstract void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain);
public abstract void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName);
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index b2ea7bbc..91aa3f93 100644
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -246,6 +246,17 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
builderType = makeBuilderClass(tdParent, builderClassName, typeParams, ast);
} else {
sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
+ /* generate errors for @Singular BFDs that have one already defined node. */ {
+ for (BuilderFieldData bfd : builderFields) {
+ SingularData sd = bfd.singularData;
+ if (sd == null) continue;
+ EclipseSingularizer singularizer = sd.getSingularizer();
+ if (singularizer == null) continue;
+ if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
+ bfd.singularData = null;
+ }
+ }
+ }
}
for (BuilderFieldData bfd : builderFields) {
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
index 6558baa5..ff23823b 100644
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
@@ -61,6 +61,26 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
return LombokImmutableList.of("java.util.Map", "java.util.SortedMap", "java.util.NavigableMap");
}
+ @Override public List<char[]> listFieldsToBeGenerated(SingularData data) {
+ char[] p = data.getPluralName();
+ int len = p.length;
+ char[] k = new char[len + 4];
+ char[] v = new char[len + 6];
+ System.arraycopy(p, 0, k, 0, len);
+ System.arraycopy(p, 0, v, 0, len);
+ k[len] = '$';
+ k[len + 1] = 'k';
+ k[len + 2] = 'e';
+ k[len + 3] = 'y';
+ v[len] = '$';
+ v[len + 1] = 'v';
+ v[len + 2] = 'a';
+ v[len + 3] = 'l';
+ v[len + 4] = 'u';
+ v[len + 5] = 'e';
+ return Arrays.asList(k, v);
+ }
+
@Override public java.util.List<EclipseNode> generateFields(SingularData data, EclipseNode builderType) {
char[] keyName = (new String(data.getPluralName()) + "$key").toCharArray();
char[] valueName = (new String(data.getPluralName()) + "$value").toCharArray();
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index 24e9dee4..7bb0619f 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.java
@@ -227,6 +227,18 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
builderType = makeBuilderClass(tdParent, builderClassName, typeParams, ast);
} else {
sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
+ /* generate errors for @Singular BFDs that have one already defined node. */ {
+ for (BuilderFieldData bfd : builderFields) {
+ SingularData sd = bfd.singularData;
+ if (sd == null) continue;
+ JavacSingularizer singularizer = sd.getSingularizer();
+ if (singularizer == null) continue;
+ if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
+ bfd.singularData = null;
+ }
+ }
+ }
+
}
for (BuilderFieldData bfd : builderFields) {
diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
index b21dbb0a..35bd66ed 100644
--- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
+++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
@@ -25,6 +25,8 @@ import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -38,7 +40,9 @@ import com.sun.source.tree.Tree.Kind;
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.JCWildcard;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
@@ -137,6 +141,50 @@ public class JavacSingularsRecipes {
public static abstract class JavacSingularizer {
public abstract LombokImmutableList<String> getSupportedTypes();
+ /** Checks if any of the to-be-generated nodes (fields, methods) already exist. If so, errors on these (singulars don't support manually writing some of it, and returns true). */
+ public boolean checkForAlreadyExistingNodesAndGenerateError(JavacNode builderType, SingularData data) {
+ for (JavacNode child : builderType.down()) {
+ switch (child.getKind()) {
+ case FIELD: {
+ JCVariableDecl field = (JCVariableDecl) child.get();
+ Name name = field.name;
+ if (name == null) break;
+ if (getGeneratedBy(field) != null) continue;
+ for (Name fieldToBeGenerated : listFieldsToBeGenerated(builderType, data)) {
+ if (!fieldToBeGenerated.equals(name)) continue;
+ child.addError("Manually adding a field that @Singular @Builder would generate is not supported. If you want to manually manage the builder aspect for this field/parameter, don't use @Singular.");
+ return true;
+ }
+ break;
+ }
+ case METHOD: {
+ JCMethodDecl method = (JCMethodDecl) child.get();
+ Name name = method.name;
+ if (name == null) break;
+ if (getGeneratedBy(method) != null) continue;
+ for (Name methodToBeGenerated : listMethodsToBeGenerated(builderType, data)) {
+ if (!methodToBeGenerated.equals(name)) continue;
+ child.addError("Manually adding a method that @Singular @Builder would generate is not supported. If you want to manually manage the builder aspect for this field/parameter, don't use @Singular.");
+ return true;
+ }
+ break;
+ }}
+ }
+
+ return false;
+ }
+
+ public java.util.List<Name> listFieldsToBeGenerated(JavacNode builderType, SingularData data) {
+ return Collections.singletonList(data.pluralName);
+ }
+
+ public java.util.List<Name> listMethodsToBeGenerated(JavacNode builderType, SingularData data) {
+ Name p = data.pluralName;
+ Name s = data.singularName;
+ if (p.equals(s)) return Collections.singletonList(p);
+ return Arrays.asList(p, s);
+ }
+
public abstract java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source);
public abstract void generateMethods(SingularData data, JavacNode builderType, JCTree source, boolean fluent, boolean chain);
public abstract void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName);
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
index acb1ae8f..21b25221 100644
--- a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
@@ -55,6 +55,11 @@ public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
return LombokImmutableList.of("java.util.Map", "java.util.SortedMap", "java.util.NavigableMap");
}
+ @Override public java.util.List<Name> listFieldsToBeGenerated(JavacNode builderType, SingularData data) {
+ String p = data.getPluralName().toString();
+ return Arrays.asList(builderType.toName(p + "$key"), builderType.toName(p + "$value"));
+ }
+
@Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source) {
JavacTreeMaker maker = builderType.getTreeMaker();