aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@zwitserloot.com>2020-04-17 01:37:08 +0200
committerGitHub <noreply@github.com>2020-04-17 01:37:08 +0200
commit20cce2049de56d5a71c6dcc376d6f4088d4552bc (patch)
treec2eeec699f50e15b07c329d9e6b969369c9e12b8
parent9d50e9f8ad16c463b6ff9dbb87fd7a012c68bfef (diff)
parentdede79bc224eb16566a027f83214c04e065b575b (diff)
downloadlombok-20cce2049de56d5a71c6dcc376d6f4088d4552bc.tar.gz
lombok-20cce2049de56d5a71c6dcc376d6f4088d4552bc.tar.bz2
lombok-20cce2049de56d5a71c6dcc376d6f4088d4552bc.zip
Merge pull request #2429 from janrieke/jacksonAndSingularAnnotationCopy
Copy more Jackson annotation to the builder, also to @Singular methods
-rw-r--r--src/core/lombok/core/handlers/HandlerUtil.java9
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java37
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java12
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java12
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java8
-rw-r--r--src/core/lombok/javac/handlers/HandleJacksonized.java1
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java18
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java16
-rw-r--r--test/stubs/com/fasterxml/jackson/annotation/JsonAnySetter.java12
-rw-r--r--test/transform/resource/after-delombok/JacksonBuilderSingular.java177
-rw-r--r--test/transform/resource/after-ecj/JacksonBuilderSingular.java164
-rw-r--r--test/transform/resource/before/JacksonBuilderSingular.java31
12 files changed, 476 insertions, 21 deletions
diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java
index 94fd21d9..a8d56041 100644
--- a/src/core/lombok/core/handlers/HandlerUtil.java
+++ b/src/core/lombok/core/handlers/HandlerUtil.java
@@ -76,7 +76,7 @@ public class HandlerUtil {
return 43;
}
- public static final List<String> NONNULL_ANNOTATIONS, BASE_COPYABLE_ANNOTATIONS, COPY_TO_SETTER_ANNOTATIONS, JACKSON_COPY_TO_BUILDER_ANNOTATIONS;
+ public static final List<String> NONNULL_ANNOTATIONS, BASE_COPYABLE_ANNOTATIONS, COPY_TO_SETTER_ANNOTATIONS, COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS, JACKSON_COPY_TO_BUILDER_ANNOTATIONS;
static {
NONNULL_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
"androidx.annotation.NonNull",
@@ -314,6 +314,13 @@ public class HandlerUtil {
COPY_TO_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
"com.fasterxml.jackson.annotation.JsonProperty",
"com.fasterxml.jackson.annotation.JsonSetter",
+ "com.fasterxml.jackson.annotation.JsonDeserialize",
+ "com.fasterxml.jackson.annotation.JsonIgnore",
+ "com.fasterxml.jackson.annotation.JacksonInject",
+ "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty",
+ }));
+ COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
+ "com.fasterxml.jackson.annotation.JsonAnySetter",
}));
JACKSON_COPY_TO_BUILDER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
"com.fasterxml.jackson.annotation.JsonFormat",
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index 2c6e1e77..6b9571c7 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -26,6 +26,7 @@ import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.EclipseAugments.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.EclipseReflectiveMembers.*;
+import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@@ -819,6 +820,20 @@ public class EclipseHandlerUtil {
* Searches the given field node for annotations that are specifically intentioned to be copied to the setter.
*/
public static Annotation[] findCopyableToSetterAnnotations(EclipseNode node) {
+ return findAnnotationsInList(node, COPY_TO_SETTER_ANNOTATIONS);
+ }
+
+ /**
+ * Searches the given field node for annotations that are specifically intentioned to be copied to the builder's singular method.
+ */
+ public static Annotation[] findCopyableToBuilderSingularSetterAnnotations(EclipseNode node) {
+ return findAnnotationsInList(node, COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS);
+ }
+
+ /**
+ * Searches the given field node for annotations that are in the given list, and returns those.
+ */
+ private static Annotation[] findAnnotationsInList(EclipseNode node, java.util.List<String> annotationsToFind) {
AbstractVariableDeclaration avd = (AbstractVariableDeclaration) node.get();
if (avd.annotations == null) return EMPTY_ANNOTATIONS_ARRAY;
List<Annotation> result = new ArrayList<Annotation>();
@@ -826,7 +841,7 @@ public class EclipseHandlerUtil {
for (Annotation annotation : avd.annotations) {
TypeReference typeRef = annotation.type;
if (typeRef != null && typeRef.getTypeName() != null) {
- for (String bn : COPY_TO_SETTER_ANNOTATIONS) if (typeMatches(bn, node, typeRef)) {
+ for (String bn : annotationsToFind) if (typeMatches(bn, node, typeRef)) {
result.add(annotation);
break;
}
@@ -2420,6 +2435,26 @@ public class EclipseHandlerUtil {
return array == null ? null : array.clone();
}
+ public static <T> T[] concat(T[] first, T[] second, Class<T> type) {
+ if (first == null)
+ return second;
+ if (second == null)
+ return first;
+ if (first.length == 0)
+ return second;
+ if (second.length == 0)
+ return first;
+ T[] result = newArray(type, first.length + second.length);
+ System.arraycopy(first, 0, result, 0, first.length);
+ System.arraycopy(second, 0, result, first.length, second.length);
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> T[] newArray(Class<T> type, int length) {
+ return (T[]) Array.newInstance(type, length);
+ }
+
public static boolean isDirectDescendantOfObject(EclipseNode typeNode) {
if (!(typeNode.get() instanceof TypeDeclaration)) throw new IllegalArgumentException("not a type node");
TypeDeclaration typeDecl = (TypeDeclaration) typeNode.get();
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
index 392418ff..395d2e59 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
@@ -175,8 +175,10 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
md.returnType = returnType;
char[] prefixedSingularName = data.getSetterPrefix().length == 0 ? data.getSingularName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getSingularName())).toCharArray();
md.selector = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray();
- md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
-
+ Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
+ Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToBuilderSingularSetterAnnotations(data.getAnnotation().up()));
+ md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class);
+
if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md);
data.setGeneratedByRecursive(md);
HandleNonNull.INSTANCE.fix(injectMethod(builderType, md));
@@ -213,8 +215,10 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
md.returnType = returnType;
char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray();
md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray();
- md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
-
+ Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
+ Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up()));
+ md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class);
+
if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md);
data.setGeneratedByRecursive(md);
injectMethod(builderType, md);
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
index 375f4e2c..deab4530 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
@@ -153,8 +153,10 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
md.returnType = returnType;
char[] prefixedSingularName = data.getSetterPrefix().length == 0 ? data.getSingularName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getSingularName())).toCharArray();
md.selector = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray();
- md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
-
+ Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
+ Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToBuilderSingularSetterAnnotations(data.getAnnotation().up()));
+ md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class);
+
if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md);
data.setGeneratedByRecursive(md);
HandleNonNull.INSTANCE.fix(injectMethod(builderType, md));
@@ -189,8 +191,10 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
md.returnType = returnType;
char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray();
md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray();
- md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
-
+ Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
+ Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up()));
+ md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class);
+
if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md);
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 cb7d9ed6..1a40369d 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
@@ -252,7 +252,9 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
String setterName = HandlerUtil.buildAccessorName(setterPrefix, name);
md.selector = setterName.toCharArray();
- md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
+ Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
+ Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToBuilderSingularSetterAnnotations(data.getAnnotation().up()));
+ md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class);
if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md);
data.setGeneratedByRecursive(md);
@@ -326,7 +328,9 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
String setterName = HandlerUtil.buildAccessorName(setterPrefix, name);
md.selector = setterName.toCharArray();
- md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
+ Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource());
+ Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up()));
+ md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class);
if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md);
data.setGeneratedByRecursive(md);
diff --git a/src/core/lombok/javac/handlers/HandleJacksonized.java b/src/core/lombok/javac/handlers/HandleJacksonized.java
index aff0bf63..0aa02d1b 100644
--- a/src/core/lombok/javac/handlers/HandleJacksonized.java
+++ b/src/core/lombok/javac/handlers/HandleJacksonized.java
@@ -149,7 +149,6 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
// @SuperBuilder? Make it package-private!
if (superBuilderAnnotationNode != null)
builderClass.mods.flags = builderClass.mods.flags & ~Flags.PRIVATE;
-
}
private String getBuilderClassName(JCAnnotation ast, JavacNode annotationNode, JavacNode annotatedNode, JCClassDecl td, AnnotationValues<Builder> builderAnnotation, JavacTreeMaker maker) {
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index a3e876c4..5241a209 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -1520,6 +1520,20 @@ public class JavacHandlerUtil {
* Searches the given field node for annotations that are specifically intentioned to be copied to the setter.
*/
public static List<JCAnnotation> findCopyableToSetterAnnotations(JavacNode node) {
+ return findAnnotationsInList(node, COPY_TO_SETTER_ANNOTATIONS);
+ }
+
+ /**
+ * Searches the given field node for annotations that are specifically intentioned to be copied to the builder's singular method.
+ */
+ public static List<JCAnnotation> findCopyableToBuilderSingularSetterAnnotations(JavacNode node) {
+ return findAnnotationsInList(node, COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS);
+ }
+
+ /**
+ * Searches the given field node for annotations that are in the given list, and returns those.
+ */
+ private static List<JCAnnotation> findAnnotationsInList(JavacNode node, java.util.List<String> annotationsToFind) {
JCAnnotation anno = null;
String annoName = null;
for (JavacNode child : node.down()) {
@@ -1537,7 +1551,7 @@ public class JavacHandlerUtil {
if (annoName == null) return List.nil();
if (!annoName.isEmpty()) {
- for (String bn : COPY_TO_SETTER_ANNOTATIONS) if (typeMatches(bn, node, anno.annotationType)) return List.of(anno);
+ for (String bn : annotationsToFind) if (typeMatches(bn, node, anno.annotationType)) return List.of(anno);
}
ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>();
@@ -1545,7 +1559,7 @@ public class JavacHandlerUtil {
if (child.getKind() == Kind.ANNOTATION) {
JCAnnotation annotation = (JCAnnotation) child.get();
boolean match = false;
- if (!match) for (String bn : COPY_TO_SETTER_ANNOTATIONS) if (typeMatches(bn, node, annotation.annotationType)) {
+ if (!match) for (String bn : annotationsToFind) if (typeMatches(bn, node, annotation.annotationType)) {
result.append(annotation);
break;
}
diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
index ba052b5a..7cd52c8c 100644
--- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
+++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
@@ -182,11 +182,12 @@ public class JavacSingularsRecipes {
return this;
}
- protected JCModifiers makeMods(JavacTreeMaker maker, CheckerFrameworkVersion cfv, JavacNode node, boolean deprecate, AccessLevel access) {
+ protected JCModifiers makeMods(JavacTreeMaker maker, CheckerFrameworkVersion cfv, JavacNode node, boolean deprecate, AccessLevel access, List<JCAnnotation> methodAnnotations) {
JCAnnotation deprecateAnn = deprecate ? maker.Annotation(genJavaLangTypeRef(node, "Deprecated"), List.<JCExpression>nil()) : null;
JCAnnotation rrAnn = cfv.generateReturnsReceiver() ? maker.Annotation(genTypeRef(node, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.<JCExpression>nil()) : null;
List<JCAnnotation> annsOnMethod = (deprecateAnn != null && rrAnn != null) ? List.of(deprecateAnn, rrAnn) : deprecateAnn != null ? List.of(deprecateAnn) : rrAnn != null ? List.of(rrAnn) : List.<JCAnnotation>nil();
+ annsOnMethod = mergeAnnotations(annsOnMethod,methodAnnotations);
return maker.Modifiers(toJavacModifier(access), annsOnMethod);
}
@@ -271,10 +272,10 @@ public class JavacSingularsRecipes {
generateClearMethod(cfv, deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, access);
}
- private void finishAndInjectMethod(CheckerFrameworkVersion cfv, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean deprecate, ListBuffer<JCStatement> statements, Name methodName, List<JCVariableDecl> jcVariableDecls, AccessLevel access, Boolean ignoreNullCollections) {
+ private void finishAndInjectMethod(CheckerFrameworkVersion cfv, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean deprecate, ListBuffer<JCStatement> statements, Name methodName, List<JCVariableDecl> jcVariableDecls, List<JCAnnotation> methodAnnotations, AccessLevel access, Boolean ignoreNullCollections) {
if (returnStatement != null) statements.append(returnStatement);
JCBlock body = maker.Block(0, statements.toList());
- JCModifiers mods = makeMods(maker, cfv, builderType, deprecate, access);
+ JCModifiers mods = makeMods(maker, cfv, builderType, deprecate, access, methodAnnotations);
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrown = List.nil();
@@ -298,7 +299,7 @@ public class JavacSingularsRecipes {
statements.add(clearStatement);
Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
- finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, methodName, List.<JCVariableDecl>nil(), access, null);
+ finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, methodName, List.<JCVariableDecl>nil(), List.<JCAnnotation>nil(), access, null);
}
protected abstract JCStatement generateClearStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType);
@@ -312,7 +313,8 @@ public class JavacSingularsRecipes {
if (!setterPrefix.isEmpty()) name = builderType.toName(HandlerUtil.buildAccessorName(setterPrefix, name.toString()));
statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
- finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, access, null);
+ List<JCAnnotation> methodAnnotations = copyAnnotations(findCopyableToBuilderSingularSetterAnnotations(data.annotation.up()));
+ finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, methodAnnotations, access, null);
}
protected JCVariableDecl generateSingularMethodParameter(int typeIndex, JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source, Name name) {
@@ -357,8 +359,10 @@ public class JavacSingularsRecipes {
} else {
statements.prepend(JavacHandlerUtil.generateNullCheck(maker, null, data.getPluralName(), builderType, "%s cannot be null"));
}
+
+ List<JCAnnotation> methodAnnotations = copyAnnotations(findCopyableToSetterAnnotations(data.annotation.up()));
- finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param), access, ignoreNullCollections);
+ finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param), methodAnnotations, access, ignoreNullCollections);
}
protected ListBuffer<JCStatement> generatePluralMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
diff --git a/test/stubs/com/fasterxml/jackson/annotation/JsonAnySetter.java b/test/stubs/com/fasterxml/jackson/annotation/JsonAnySetter.java
new file mode 100644
index 00000000..51d2c3fa
--- /dev/null
+++ b/test/stubs/com/fasterxml/jackson/annotation/JsonAnySetter.java
@@ -0,0 +1,12 @@
+package com.fasterxml.jackson.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface JsonAnySetter {
+ boolean enabled() default true;
+}
diff --git a/test/transform/resource/after-delombok/JacksonBuilderSingular.java b/test/transform/resource/after-delombok/JacksonBuilderSingular.java
new file mode 100644
index 00000000..feaa6832
--- /dev/null
+++ b/test/transform/resource/after-delombok/JacksonBuilderSingular.java
@@ -0,0 +1,177 @@
+import java.util.List;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+@com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonBuilderSingular.JacksonBuilderSingularBuilder.class)
+public class JacksonBuilderSingular {
+ @JsonAnySetter
+ private Map<String, Object> any;
+ @JsonProperty("v_a_l_u_e_s")
+ private List<String> values;
+ @JsonAnySetter
+ private ImmutableMap<String, Object> guavaAny;
+ @JsonProperty("guava_v_a_l_u_e_s")
+ private ImmutableList<String> guavaValues;
+ @java.lang.SuppressWarnings("all")
+ JacksonBuilderSingular(final Map<String, Object> any, final List<String> values, final ImmutableMap<String, Object> guavaAny, final ImmutableList<String> guavaValues) {
+ this.any = any;
+ this.values = values;
+ this.guavaAny = guavaAny;
+ this.guavaValues = guavaValues;
+ }
+ @java.lang.SuppressWarnings("all")
+ @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "", buildMethodName = "build")
+ public static class JacksonBuilderSingularBuilder {
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<String> any$key;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<Object> any$value;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<String> values;
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableMap.Builder<String, Object> guavaAny;
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableList.Builder<String> guavaValues;
+ @java.lang.SuppressWarnings("all")
+ JacksonBuilderSingularBuilder() {
+ }
+ @JsonAnySetter
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final String anyKey, final Object anyValue) {
+ if (this.any$key == null) {
+ this.any$key = new java.util.ArrayList<String>();
+ this.any$value = new java.util.ArrayList<Object>();
+ }
+ this.any$key.add(anyKey);
+ this.any$value.add(anyValue);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final java.util.Map<? extends String, ? extends Object> any) {
+ if (any == null) {
+ throw new java.lang.NullPointerException("any cannot be null");
+ }
+ if (this.any$key == null) {
+ this.any$key = new java.util.ArrayList<String>();
+ this.any$value = new java.util.ArrayList<Object>();
+ }
+ for (final java.util.Map.Entry<? extends String, ? extends Object> $lombokEntry : any.entrySet()) {
+ this.any$key.add($lombokEntry.getKey());
+ this.any$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearAny() {
+ if (this.any$key != null) {
+ this.any$key.clear();
+ this.any$value.clear();
+ }
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder value(final String value) {
+ if (this.values == null) this.values = new java.util.ArrayList<String>();
+ this.values.add(value);
+ return this;
+ }
+ @JsonProperty("v_a_l_u_e_s")
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder values(final java.util.Collection<? extends String> values) {
+ if (values == null) {
+ throw new java.lang.NullPointerException("values cannot be null");
+ }
+ if (this.values == null) this.values = new java.util.ArrayList<String>();
+ this.values.addAll(values);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearValues() {
+ if (this.values != null) this.values.clear();
+ return this;
+ }
+ @JsonAnySetter
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaAny(final String key, final Object value) {
+ if (this.guavaAny == null) this.guavaAny = com.google.common.collect.ImmutableMap.builder();
+ this.guavaAny.put(key, value);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaAny(final java.util.Map<? extends String, ? extends Object> guavaAny) {
+ if (guavaAny == null) {
+ throw new java.lang.NullPointerException("guavaAny cannot be null");
+ }
+ if (this.guavaAny == null) this.guavaAny = com.google.common.collect.ImmutableMap.builder();
+ this.guavaAny.putAll(guavaAny);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaAny() {
+ this.guavaAny = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaValue(final String guavaValue) {
+ if (this.guavaValues == null) this.guavaValues = com.google.common.collect.ImmutableList.builder();
+ this.guavaValues.add(guavaValue);
+ return this;
+ }
+ @JsonProperty("guava_v_a_l_u_e_s")
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaValues(final java.lang.Iterable<? extends String> guavaValues) {
+ if (guavaValues == null) {
+ throw new java.lang.NullPointerException("guavaValues cannot be null");
+ }
+ if (this.guavaValues == null) this.guavaValues = com.google.common.collect.ImmutableList.builder();
+ this.guavaValues.addAll(guavaValues);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaValues() {
+ this.guavaValues = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public JacksonBuilderSingular build() {
+ java.util.Map<String, Object> any;
+ switch (this.any$key == null ? 0 : this.any$key.size()) {
+ case 0:
+ any = java.util.Collections.emptyMap();
+ break;
+ case 1:
+ any = java.util.Collections.singletonMap(this.any$key.get(0), this.any$value.get(0));
+ break;
+ default:
+ any = new java.util.LinkedHashMap<String, Object>(this.any$key.size() < 1073741824 ? 1 + this.any$key.size() + (this.any$key.size() - 3) / 3 : java.lang.Integer.MAX_VALUE);
+ for (int $i = 0; $i < this.any$key.size(); $i++) any.put(this.any$key.get($i), (Object) this.any$value.get($i));
+ any = java.util.Collections.unmodifiableMap(any);
+ }
+ java.util.List<String> values;
+ switch (this.values == null ? 0 : this.values.size()) {
+ case 0:
+ values = java.util.Collections.emptyList();
+ break;
+ case 1:
+ values = java.util.Collections.singletonList(this.values.get(0));
+ break;
+ default:
+ values = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.values));
+ }
+ com.google.common.collect.ImmutableMap<String, Object> guavaAny = this.guavaAny == null ? com.google.common.collect.ImmutableMap.<String, Object>of() : this.guavaAny.build();
+ com.google.common.collect.ImmutableList<String> guavaValues = this.guavaValues == null ? com.google.common.collect.ImmutableList.<String>of() : this.guavaValues.build();
+ return new JacksonBuilderSingular(any, values, guavaAny, guavaValues);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "JacksonBuilderSingular.JacksonBuilderSingularBuilder(any$key=" + this.any$key + ", any$value=" + this.any$value + ", values=" + this.values + ", guavaAny=" + this.guavaAny + ", guavaValues=" + this.guavaValues + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static JacksonBuilderSingular.JacksonBuilderSingularBuilder builder() {
+ return new JacksonBuilderSingular.JacksonBuilderSingularBuilder();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/JacksonBuilderSingular.java b/test/transform/resource/after-ecj/JacksonBuilderSingular.java
new file mode 100644
index 00000000..50f6a797
--- /dev/null
+++ b/test/transform/resource/after-ecj/JacksonBuilderSingular.java
@@ -0,0 +1,164 @@
+import java.util.List;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import lombok.Builder;
+import lombok.Singular;
+import lombok.extern.jackson.Jacksonized;
+public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonBuilderSingular.JacksonBuilderSingularBuilder.class) class JacksonBuilderSingular {
+ public static @java.lang.SuppressWarnings("all") @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "",buildMethodName = "build") class JacksonBuilderSingularBuilder {
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<String> any$key;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<Object> any$value;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<String> values;
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableMap.Builder<String, Object> guavaAny;
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableList.Builder<String> guavaValues;
+ @java.lang.SuppressWarnings("all") JacksonBuilderSingularBuilder() {
+ super();
+ }
+ public @JsonAnySetter @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final String anyKey, final Object anyValue) {
+ if ((this.any$key == null))
+ {
+ this.any$key = new java.util.ArrayList<String>();
+ this.any$value = new java.util.ArrayList<Object>();
+ }
+ this.any$key.add(anyKey);
+ this.any$value.add(anyValue);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final java.util.Map<? extends String, ? extends Object> any) {
+ if ((any == null))
+ {
+ throw new java.lang.NullPointerException("any cannot be null");
+ }
+ if ((this.any$key == null))
+ {
+ this.any$key = new java.util.ArrayList<String>();
+ this.any$value = new java.util.ArrayList<Object>();
+ }
+ for (java.util.Map.Entry<? extends String, ? extends Object> $lombokEntry : any.entrySet())
+ {
+ this.any$key.add($lombokEntry.getKey());
+ this.any$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearAny() {
+ if ((this.any$key != null))
+ {
+ this.any$key.clear();
+ this.any$value.clear();
+ }
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder value(final String value) {
+ if ((this.values == null))
+ this.values = new java.util.ArrayList<String>();
+ this.values.add(value);
+ return this;
+ }
+ public @JsonProperty("v_a_l_u_e_s") @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder values(final java.util.Collection<? extends String> values) {
+ if ((values == null))
+ {
+ throw new java.lang.NullPointerException("values cannot be null");
+ }
+ if ((this.values == null))
+ this.values = new java.util.ArrayList<String>();
+ this.values.addAll(values);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearValues() {
+ if ((this.values != null))
+ this.values.clear();
+ return this;
+ }
+ public @JsonAnySetter @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaAny(final String key, final Object value) {
+ if ((this.guavaAny == null))
+ this.guavaAny = com.google.common.collect.ImmutableMap.builder();
+ this.guavaAny.put(key, value);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaAny(final java.util.Map<? extends String, ? extends Object> guavaAny) {
+ if ((guavaAny == null))
+ {
+ throw new java.lang.NullPointerException("guavaAny cannot be null");
+ }
+ if ((this.guavaAny == null))
+ this.guavaAny = com.google.common.collect.ImmutableMap.builder();
+ this.guavaAny.putAll(guavaAny);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaAny() {
+ this.guavaAny = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaValue(final String guavaValue) {
+ if ((this.guavaValues == null))
+ this.guavaValues = com.google.common.collect.ImmutableList.builder();
+ this.guavaValues.add(guavaValue);
+ return this;
+ }
+ public @JsonProperty("guava_v_a_l_u_e_s") @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaValues(final java.lang.Iterable<? extends String> guavaValues) {
+ if ((guavaValues == null))
+ {
+ throw new java.lang.NullPointerException("guavaValues cannot be null");
+ }
+ if ((this.guavaValues == null))
+ this.guavaValues = com.google.common.collect.ImmutableList.builder();
+ this.guavaValues.addAll(guavaValues);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaValues() {
+ this.guavaValues = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") JacksonBuilderSingular build() {
+ java.util.Map<String, Object> any;
+ switch (((this.any$key == null) ? 0 : this.any$key.size())) {
+ case 0 :
+ any = java.util.Collections.emptyMap();
+ break;
+ case 1 :
+ any = java.util.Collections.singletonMap(this.any$key.get(0), this.any$value.get(0));
+ break;
+ default :
+ any = new java.util.LinkedHashMap<String, Object>(((this.any$key.size() < 0x40000000) ? ((1 + this.any$key.size()) + ((this.any$key.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
+ for (int $i = 0;; ($i < this.any$key.size()); $i ++)
+ any.put(this.any$key.get($i), this.any$value.get($i));
+ any = java.util.Collections.unmodifiableMap(any);
+ }
+ java.util.List<String> values;
+ switch (((this.values == null) ? 0 : this.values.size())) {
+ case 0 :
+ values = java.util.Collections.emptyList();
+ break;
+ case 1 :
+ values = java.util.Collections.singletonList(this.values.get(0));
+ break;
+ default :
+ values = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.values));
+ }
+ com.google.common.collect.ImmutableMap<String, Object> guavaAny = ((this.guavaAny == null) ? com.google.common.collect.ImmutableMap.<String, Object>of() : this.guavaAny.build());
+ com.google.common.collect.ImmutableList<String> guavaValues = ((this.guavaValues == null) ? com.google.common.collect.ImmutableList.<String>of() : this.guavaValues.build());
+ return new JacksonBuilderSingular(any, values, guavaAny, guavaValues);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((((((("JacksonBuilderSingular.JacksonBuilderSingularBuilder(any$key=" + this.any$key) + ", any$value=") + this.any$value) + ", values=") + this.values) + ", guavaAny=") + this.guavaAny) + ", guavaValues=") + this.guavaValues) + ")");
+ }
+ }
+ private @JsonAnySetter @Singular("any") Map<String, Object> any;
+ private @JsonProperty("v_a_l_u_e_s") @Singular List<String> values;
+ private @JsonAnySetter @Singular("guavaAny") ImmutableMap<String, Object> guavaAny;
+ private @JsonProperty("guava_v_a_l_u_e_s") @Singular ImmutableList<String> guavaValues;
+ @java.lang.SuppressWarnings("all") JacksonBuilderSingular(final Map<String, Object> any, final List<String> values, final ImmutableMap<String, Object> guavaAny, final ImmutableList<String> guavaValues) {
+ super();
+ this.any = any;
+ this.values = values;
+ this.guavaAny = guavaAny;
+ this.guavaValues = guavaValues;
+ }
+ public static @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder builder() {
+ return new JacksonBuilderSingular.JacksonBuilderSingularBuilder();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/JacksonBuilderSingular.java b/test/transform/resource/before/JacksonBuilderSingular.java
new file mode 100644
index 00000000..c179c760
--- /dev/null
+++ b/test/transform/resource/before/JacksonBuilderSingular.java
@@ -0,0 +1,31 @@
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import lombok.Builder;
+import lombok.Singular;
+import lombok.extern.jackson.Jacksonized;
+
+@Jacksonized
+@Builder
+public class JacksonBuilderSingular {
+ @JsonAnySetter
+ @Singular("any")
+ private Map<String, Object> any;
+
+ @JsonProperty("v_a_l_u_e_s")
+ @Singular
+ private List<String> values;
+
+ @JsonAnySetter
+ @Singular("guavaAny")
+ private ImmutableMap<String, Object> guavaAny;
+
+ @JsonProperty("guava_v_a_l_u_e_s")
+ @Singular
+ private ImmutableList<String> guavaValues;
+}