mirror of
https://github.com/tiennm99/lombok.git
synced 2026-09-10 04:19:56 +00:00
@Jacksonized: modify builders that they can be used by Jackson
This commit is contained in:
@@ -76,7 +76,7 @@ public class HandlerUtil {
|
||||
return 43;
|
||||
}
|
||||
|
||||
public static final List<String> NONNULL_ANNOTATIONS, BASE_COPYABLE_ANNOTATIONS, COPY_TO_SETTER_ANNOTATIONS;
|
||||
public static final List<String> NONNULL_ANNOTATIONS, BASE_COPYABLE_ANNOTATIONS, COPY_TO_SETTER_ANNOTATIONS, JACKSON_COPY_TO_BUILDER_ANNOTATIONS;
|
||||
static {
|
||||
NONNULL_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
|
||||
"androidx.annotation.NonNull",
|
||||
@@ -315,6 +315,18 @@ public class HandlerUtil {
|
||||
"com.fasterxml.jackson.annotation.JsonProperty",
|
||||
"com.fasterxml.jackson.annotation.JsonSetter",
|
||||
}));
|
||||
JACKSON_COPY_TO_BUILDER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
|
||||
"com.fasterxml.jackson.annotation.JsonFormat",
|
||||
"com.fasterxml.jackson.annotation.JsonIgnoreProperties",
|
||||
"com.fasterxml.jackson.annotation.JsonIgnoreType",
|
||||
"com.fasterxml.jackson.annotation.JsonPropertyOrder",
|
||||
"com.fasterxml.jackson.annotation.JsonRootName",
|
||||
"com.fasterxml.jackson.annotation.JsonSubTypes",
|
||||
"com.fasterxml.jackson.annotation.JsonTypeInfo",
|
||||
"com.fasterxml.jackson.annotation.JsonTypeName",
|
||||
"com.fasterxml.jackson.annotation.JsonView",
|
||||
"com.fasterxml.jackson.databind.annotation.JsonNaming",
|
||||
}));
|
||||
}
|
||||
|
||||
/** Checks if the given name is a valid identifier.
|
||||
|
||||
@@ -1957,12 +1957,16 @@ public class EclipseHandlerUtil {
|
||||
result = addAnnotation(source, result, JAVAX_ANNOTATION_GENERATED, new StringLiteral(LOMBOK, 0, 0, 0));
|
||||
}
|
||||
if (Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_LOMBOK_GENERATED_ANNOTATIONS))) {
|
||||
result = addAnnotation(source, result, LOMBOK_GENERATED, null);
|
||||
result = addAnnotation(source, result, LOMBOK_GENERATED);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static Annotation[] addAnnotation(ASTNode source, Annotation[] originalAnnotationArray, char[][] annotationTypeFqn, ASTNode arg) {
|
||||
static Annotation[] addAnnotation(ASTNode source, Annotation[] originalAnnotationArray, char[][] annotationTypeFqn) {
|
||||
return addAnnotation(source, originalAnnotationArray, annotationTypeFqn, (ASTNode[]) null);
|
||||
}
|
||||
|
||||
static Annotation[] addAnnotation(ASTNode source, Annotation[] originalAnnotationArray, char[][] annotationTypeFqn, ASTNode... args) {
|
||||
char[] simpleName = annotationTypeFqn[annotationTypeFqn.length - 1];
|
||||
|
||||
if (originalAnnotationArray != null) for (Annotation ann : originalAnnotationArray) {
|
||||
@@ -1984,20 +1988,23 @@ public class EclipseHandlerUtil {
|
||||
QualifiedTypeReference qualifiedType = new QualifiedTypeReference(annotationTypeFqn, poss);
|
||||
setGeneratedBy(qualifiedType, source);
|
||||
Annotation ann;
|
||||
if (arg instanceof Expression) {
|
||||
if (args != null && args.length == 1 && args[0] instanceof Expression) {
|
||||
SingleMemberAnnotation sma = new SingleMemberAnnotation(qualifiedType, pS);
|
||||
sma.declarationSourceEnd = pE;
|
||||
arg.sourceStart = pS;
|
||||
arg.sourceEnd = pE;
|
||||
sma.memberValue = (Expression) arg;
|
||||
args[0].sourceStart = pS;
|
||||
args[0].sourceEnd = pE;
|
||||
sma.memberValue = (Expression) args[0];
|
||||
setGeneratedBy(sma.memberValue, source);
|
||||
ann = sma;
|
||||
} else if (arg instanceof MemberValuePair) {
|
||||
} else if (args != null && args.length >= 1 && arrayHasOnlyElementsOfType(args, MemberValuePair.class)) {
|
||||
NormalAnnotation na = new NormalAnnotation(qualifiedType, pS);
|
||||
na.declarationSourceEnd = pE;
|
||||
arg.sourceStart = pS;
|
||||
arg.sourceEnd = pE;
|
||||
na.memberValuePairs = new MemberValuePair[] {(MemberValuePair) arg};
|
||||
na.memberValuePairs = new MemberValuePair[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
args[i].sourceStart = pS;
|
||||
args[i].sourceEnd = pE;
|
||||
na.memberValuePairs[i] = (MemberValuePair) args[i];
|
||||
}
|
||||
setGeneratedBy(na.memberValuePairs[0], source);
|
||||
setGeneratedBy(na.memberValuePairs[0].value, source);
|
||||
na.memberValuePairs[0].value.sourceStart = pS;
|
||||
@@ -2016,6 +2023,14 @@ public class EclipseHandlerUtil {
|
||||
return newAnnotationArray;
|
||||
}
|
||||
|
||||
private static boolean arrayHasOnlyElementsOfType(Object[] array, Class<?> clazz) {
|
||||
for (Object element : array) {
|
||||
if (!clazz.isInstance(element))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new statement that checks if the given local variable is null, and if so, throws a specified exception with the
|
||||
* variable name as message.
|
||||
|
||||
@@ -376,32 +376,9 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
thrownExceptions = md.thrownExceptions;
|
||||
nameOfStaticBuilderMethod = md.selector;
|
||||
if (replaceNameInBuilderClassName) {
|
||||
char[] token;
|
||||
if (md.returnType instanceof QualifiedTypeReference) {
|
||||
char[][] tokens = ((QualifiedTypeReference) md.returnType).tokens;
|
||||
token = tokens[tokens.length - 1];
|
||||
} else if (md.returnType instanceof SingleTypeReference) {
|
||||
token = ((SingleTypeReference) md.returnType).token;
|
||||
if (!(md.returnType instanceof ParameterizedSingleTypeReference) && typeParams != null) {
|
||||
for (TypeParameter tp : typeParams) {
|
||||
if (Arrays.equals(tp.name, token)) {
|
||||
annotationNode.addError("@Builder requires specifying 'builderClassName' if used on methods with a type parameter as return type.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
annotationNode.addError("Unexpected kind of return type on annotated method. Specify 'builderClassName' to solve this problem.");
|
||||
char[] token = returnTypeToBuilderClassName(annotationNode, md, typeParams);
|
||||
if (token == null)
|
||||
return;
|
||||
}
|
||||
|
||||
if (Character.isLowerCase(token[0])) {
|
||||
char[] newToken = new char[token.length];
|
||||
System.arraycopy(token, 1, newToken, 1, token.length - 1);
|
||||
newToken[0] = Character.toTitleCase(token[0]);
|
||||
token = newToken;
|
||||
}
|
||||
|
||||
builderClassName = builderClassName.replace("*", new String(token));
|
||||
}
|
||||
} else {
|
||||
@@ -550,6 +527,35 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char[] returnTypeToBuilderClassName(EclipseNode annotationNode, MethodDeclaration md, TypeParameter[] typeParams) {
|
||||
char[] token;
|
||||
if (md.returnType instanceof QualifiedTypeReference) {
|
||||
char[][] tokens = ((QualifiedTypeReference) md.returnType).tokens;
|
||||
token = tokens[tokens.length - 1];
|
||||
} else if (md.returnType instanceof SingleTypeReference) {
|
||||
token = ((SingleTypeReference) md.returnType).token;
|
||||
if (!(md.returnType instanceof ParameterizedSingleTypeReference) && typeParams != null) {
|
||||
for (TypeParameter tp : typeParams) {
|
||||
if (Arrays.equals(tp.name, token)) {
|
||||
annotationNode.addError("@Builder requires specifying 'builderClassName' if used on methods with a type parameter as return type.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
annotationNode.addError("Unexpected kind of return type on annotated method. Specify 'builderClassName' to solve this problem.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Character.isLowerCase(token[0])) {
|
||||
char[] newToken = new char[token.length];
|
||||
System.arraycopy(token, 1, newToken, 1, token.length - 1);
|
||||
newToken[0] = Character.toTitleCase(token[0]);
|
||||
token = newToken;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
private static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'};
|
||||
private MethodDeclaration generateToBuilderMethod(CheckerFrameworkVersion cfv, boolean isStatic, String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source, AccessLevel access, String prefix) {
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2020 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.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
|
||||
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
|
||||
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.ConfigurationKeys;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.HandlerPriority;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.handlers.HandlerUtil;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
/**
|
||||
* This (ecj) handler deals with {@code @Jacksonized} modifying the (already
|
||||
* generated) {@code @Builder} or {@code @SuperBuilder} to conform to Jackson's
|
||||
* needs for builders.
|
||||
*/
|
||||
@ProviderFor(EclipseAnnotationHandler.class) @HandlerPriority(-512) // Above Handle(Super)Builder's level (builders must be already generated).
|
||||
public class HandleJacksonized extends EclipseAnnotationHandler<Jacksonized> {
|
||||
|
||||
private static final char[][] JSON_POJO_BUILDER_ANNOTATION = Eclipse.fromQualifiedName("com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder");
|
||||
private static final char[][] JSON_DESERIALIZE_ANNOTATION = Eclipse.fromQualifiedName("com.fasterxml.jackson.databind.annotation.JsonDeserialize");
|
||||
|
||||
@Override public void handle(AnnotationValues<Jacksonized> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
EclipseNode annotatedNode = annotationNode.up();
|
||||
|
||||
EclipseNode tdNode;
|
||||
if (annotatedNode.getKind() != Kind.TYPE)
|
||||
tdNode = annotatedNode.up(); // @Jacksonized on a constructor or a static factory method.
|
||||
else
|
||||
tdNode = annotatedNode; // @Jacksonized on the class.
|
||||
TypeDeclaration td = (TypeDeclaration) tdNode.get();
|
||||
|
||||
EclipseNode builderAnnotationNode = findAnnotation(Builder.class, annotatedNode);
|
||||
EclipseNode superBuilderAnnotationNode = findAnnotation(SuperBuilder.class, annotatedNode);
|
||||
if (builderAnnotationNode == null && superBuilderAnnotationNode == null) {
|
||||
annotationNode.addWarning("@Jacksonized requires @Builder or @SuperBuilder for it to mean anything.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (builderAnnotationNode != null && superBuilderAnnotationNode != null) {
|
||||
annotationNode.addError("@Jacksonized cannot process both @Builder and @SuperBuilder on the same class.");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isAbstract = (td.modifiers & ClassFileConstants.AccAbstract) != 0;
|
||||
if (isAbstract) {
|
||||
annotationNode.addError("Builders on abstract classes cannot be @Jacksonized (the builder would never be used).");
|
||||
return;
|
||||
}
|
||||
|
||||
AnnotationValues<Builder> builderAnnotation = builderAnnotationNode != null ? createAnnotation(Builder.class, builderAnnotationNode) : null;
|
||||
AnnotationValues<SuperBuilder> superBuilderAnnotation = superBuilderAnnotationNode != null ? createAnnotation(SuperBuilder.class, superBuilderAnnotationNode) : null;
|
||||
|
||||
String setPrefix = builderAnnotation != null ? builderAnnotation.getInstance().setterPrefix() : superBuilderAnnotation.getInstance().setterPrefix();
|
||||
String buildMethodName = builderAnnotation != null ? builderAnnotation.getInstance().buildMethodName() : superBuilderAnnotation.getInstance().buildMethodName();
|
||||
|
||||
// Now lets find the generated builder class.
|
||||
EclipseNode builderClassNode = null;
|
||||
TypeDeclaration builderClass = null;
|
||||
String builderClassName = getBuilderClassName(ast, annotationNode, annotatedNode, td, builderAnnotation);
|
||||
for (EclipseNode member : tdNode.down()) {
|
||||
ASTNode astNode = member.get();
|
||||
if (astNode instanceof TypeDeclaration && Arrays.equals(((TypeDeclaration)astNode).name, builderClassName.toCharArray())) {
|
||||
builderClassNode = member;
|
||||
builderClass = (TypeDeclaration) astNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (builderClass == null) {
|
||||
annotationNode.addError("Could not find @(Super)Builder's generated builder class for @Jacksonized processing. If there are other compiler errors, fix them first.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Insert @JsonDeserialize on annotated class.
|
||||
if (hasAnnotation("com.fasterxml.jackson.databind.annotation.JsonDeserialize", tdNode)) {
|
||||
annotationNode.addError("@JsonDeserialize already exists on class. Either delete @JsonDeserialize, or remove @Jacksonized and manually configure Jackson.");
|
||||
return;
|
||||
}
|
||||
long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
|
||||
TypeReference builderClassExpression = namePlusTypeParamsToTypeReference(builderClassNode, null, p);
|
||||
ClassLiteralAccess builderClassLiteralAccess = new ClassLiteralAccess(td.sourceEnd, builderClassExpression);
|
||||
MemberValuePair builderMvp = new MemberValuePair("builder".toCharArray(), td.sourceStart, td.sourceEnd, builderClassLiteralAccess);
|
||||
td.annotations = addAnnotation(td, td.annotations, JSON_DESERIALIZE_ANNOTATION, builderMvp);
|
||||
|
||||
// Copy annotations from the class to the builder class.
|
||||
Annotation[] copyableAnnotations = findJacksonAnnotationsOnClass(td, tdNode);
|
||||
builderClass.annotations = copyAnnotations(builderClass, builderClass.annotations, copyableAnnotations);
|
||||
|
||||
// Insert @JsonPOJOBuilder on the builder class.
|
||||
StringLiteral withPrefixLiteral = new StringLiteral(setPrefix.toCharArray(), builderClass.sourceStart, builderClass.sourceEnd, 0);
|
||||
MemberValuePair withPrefixMvp = new MemberValuePair("withPrefix".toCharArray(), builderClass.sourceStart, builderClass.sourceEnd, withPrefixLiteral);
|
||||
StringLiteral buildMethodNameLiteral = new StringLiteral(buildMethodName.toCharArray(), builderClass.sourceStart, builderClass.sourceEnd, 0);
|
||||
MemberValuePair buildMethodNameMvp = new MemberValuePair("buildMethodName".toCharArray(), builderClass.sourceStart, builderClass.sourceEnd, buildMethodNameLiteral);
|
||||
builderClass.annotations = addAnnotation(builderClass, builderClass.annotations, JSON_POJO_BUILDER_ANNOTATION, withPrefixMvp, buildMethodNameMvp);
|
||||
|
||||
// @SuperBuilder? Make it package-private!
|
||||
if (superBuilderAnnotationNode != null)
|
||||
builderClass.modifiers = builderClass.modifiers & ~ClassFileConstants.AccPrivate;
|
||||
}
|
||||
|
||||
private String getBuilderClassName(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, TypeDeclaration td, AnnotationValues<Builder> builderAnnotation) {
|
||||
String builderClassName = builderAnnotation != null ?
|
||||
builderAnnotation.getInstance().builderClassName() : null;
|
||||
if (builderClassName == null || builderClassName.isEmpty()) {
|
||||
builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
|
||||
if (builderClassName == null || builderClassName.isEmpty())
|
||||
builderClassName = "*Builder";
|
||||
|
||||
MethodDeclaration fillParametersFrom = annotatedNode.get() instanceof MethodDeclaration ? (MethodDeclaration) annotatedNode.get() : null;
|
||||
char[] replacement;
|
||||
if (fillParametersFrom != null) {
|
||||
// @Builder on a method: Use name of return type for builder class name.
|
||||
replacement = HandleBuilder.returnTypeToBuilderClassName(annotationNode, fillParametersFrom, fillParametersFrom.typeParameters);
|
||||
} else {
|
||||
// @Builder on class or constructor: Use the class name.
|
||||
replacement = td.name;
|
||||
}
|
||||
builderClassName = builderClassName.replace("*", new String(replacement));
|
||||
}
|
||||
|
||||
if (builderAnnotation == null)
|
||||
builderClassName += "Impl"; // For @SuperBuilder, all Jackson annotations must be put on the BuilderImpl class.
|
||||
|
||||
return builderClassName;
|
||||
}
|
||||
|
||||
private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY = new Annotation[0];
|
||||
|
||||
private static Annotation[] findJacksonAnnotationsOnClass(TypeDeclaration td, EclipseNode node) {
|
||||
if (td.annotations == null) return EMPTY_ANNOTATIONS_ARRAY;
|
||||
|
||||
List<Annotation> result = new ArrayList<Annotation>();
|
||||
for (Annotation annotation : td.annotations) {
|
||||
TypeReference typeRef = annotation.type;
|
||||
if (typeRef != null && typeRef.getTypeName() != null) {
|
||||
for (String bn : HandlerUtil.JACKSON_COPY_TO_BUILDER_ANNOTATIONS) {
|
||||
if (typeMatches(bn, node, typeRef)) {
|
||||
result.add(annotation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toArray(EMPTY_ANNOTATIONS_ARRAY);
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.extern.jackson;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
* The {@code @Jacksonized} annotation is an add-on annotation for
|
||||
* {@code @}{@link Builder} and {@code @}{@link SuperBuilder}. It automatically
|
||||
* configures the generated builder class to be used by Jackson's
|
||||
* deserialization. It only has an effect if present at a context where there is
|
||||
* also a {@code @Builder} or a {@code @SuperBuilder}; a warning is emitted
|
||||
* otherwise.
|
||||
* <p>
|
||||
* In particular, the annotation does the following:
|
||||
* <ul>
|
||||
* <li>Configure Jackson to use the builder for deserialization using
|
||||
* {@code @JsonDeserialize(builder=MyClass.MyClassBuilder[Impl].class))} on the
|
||||
* class. (An error is emitted if such an annotation already exists.)
|
||||
* <li>Copy Jackson-related configuration annotations (like
|
||||
* {@code @JsonIgnoreProperties}) from the class to the builder class. This is
|
||||
* necessary so that Jackson recognizes them when using the builder.
|
||||
* <li>Insert {@code @JsonPOJOBuilder(withPrefix="")} on the generated builder
|
||||
* class to override Jackson's default prefix "with". If you configured a
|
||||
* different prefix in lombok using {@code setterPrefix}, this value is used. If
|
||||
* you changed the name of the {@code build()} method using using
|
||||
* {@code buildMethodName}, this is also made known to Jackson.
|
||||
* <li>For {@code @SuperBuilder}, make the builder implementation class
|
||||
* package-private.</li>
|
||||
* </ul>
|
||||
* This annotation does <i>not</i> change the behavior of the generated builder.
|
||||
* A {@code @Jacksonized} {@code @SuperBuilder} remains fully compatible to
|
||||
* regular {@code @SuperBuilder}s.
|
||||
*/
|
||||
@Target({TYPE, METHOD, CONSTRUCTOR})
|
||||
@Retention(SOURCE)
|
||||
public @interface Jacksonized {
|
||||
}
|
||||
@@ -149,7 +149,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
if (!checkName("builderClassName", builderClassName, annotationNode)) return;
|
||||
}
|
||||
|
||||
deleteAnnotationIfNeccessary(annotationNode, Builder.class, "lombok.experimental.Builder");
|
||||
// Do not delete the Builder annotation here, we need it for @Jacksonized.
|
||||
|
||||
JavacNode parent = annotationNode.up();
|
||||
|
||||
@@ -257,38 +257,9 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
returnType = cloneType(tdParent.getTreeMaker(), returnType, ast, annotationNode.getContext());
|
||||
}
|
||||
if (replaceNameInBuilderClassName) {
|
||||
String replStr = null;
|
||||
if (returnType instanceof JCFieldAccess) {
|
||||
replStr = ((JCFieldAccess) returnType).name.toString();
|
||||
} else if (returnType instanceof JCIdent) {
|
||||
Name n = ((JCIdent) returnType).name;
|
||||
|
||||
for (JCTypeParameter tp : typeParams) {
|
||||
if (tp.name.equals(n)) {
|
||||
annotationNode.addError("@Builder requires specifying 'builderClassName' if used on methods with a type parameter as return type.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
replStr = n.toString();
|
||||
} else if (returnType instanceof JCPrimitiveTypeTree) {
|
||||
replStr = returnType.toString();
|
||||
if (Character.isLowerCase(replStr.charAt(0))) {
|
||||
replStr = Character.toTitleCase(replStr.charAt(0)) + replStr.substring(1);
|
||||
}
|
||||
} else if (returnType instanceof JCTypeApply) {
|
||||
JCExpression clazz = ((JCTypeApply) returnType).clazz;
|
||||
if (clazz instanceof JCFieldAccess) {
|
||||
replStr = ((JCFieldAccess) clazz).name.toString();
|
||||
} else if (clazz instanceof JCIdent) {
|
||||
replStr = ((JCIdent) clazz).name.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (replStr == null || replStr.isEmpty()) {
|
||||
// This shouldn't happen.
|
||||
System.err.println("Lombok bug ID#20140614-1651: javac HandleBuilder: return type to name conversion failed: " + returnType.getClass());
|
||||
replStr = td.name.toString();
|
||||
}
|
||||
String replStr = returnTypeToBuilderClassName(annotationNode, td, returnType, typeParams);
|
||||
if (replStr == null)
|
||||
return;
|
||||
builderClassName = builderClassName.replace("*", replStr);
|
||||
replaceNameInBuilderClassName = false;
|
||||
}
|
||||
@@ -507,6 +478,42 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static String returnTypeToBuilderClassName(JavacNode annotationNode, JCClassDecl td, JCExpression returnType, List<JCTypeParameter> typeParams) {
|
||||
String replStr = null;
|
||||
if (returnType instanceof JCFieldAccess) {
|
||||
replStr = ((JCFieldAccess) returnType).name.toString();
|
||||
} else if (returnType instanceof JCIdent) {
|
||||
Name n = ((JCIdent) returnType).name;
|
||||
|
||||
for (JCTypeParameter tp : typeParams) {
|
||||
if (tp.name.equals(n)) {
|
||||
annotationNode.addError("@Builder requires specifying 'builderClassName' if used on methods with a type parameter as return type.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
replStr = n.toString();
|
||||
} else if (returnType instanceof JCPrimitiveTypeTree) {
|
||||
replStr = returnType.toString();
|
||||
if (Character.isLowerCase(replStr.charAt(0))) {
|
||||
replStr = Character.toTitleCase(replStr.charAt(0)) + replStr.substring(1);
|
||||
}
|
||||
} else if (returnType instanceof JCTypeApply) {
|
||||
JCExpression clazz = ((JCTypeApply) returnType).clazz;
|
||||
if (clazz instanceof JCFieldAccess) {
|
||||
replStr = ((JCFieldAccess) clazz).name.toString();
|
||||
} else if (clazz instanceof JCIdent) {
|
||||
replStr = ((JCIdent) clazz).name.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (replStr == null || replStr.isEmpty()) {
|
||||
// This shouldn't happen.
|
||||
System.err.println("Lombok bug ID#20140614-1651: javac HandleBuilder: return type to name conversion failed: " + returnType.getClass());
|
||||
replStr = td.name.toString();
|
||||
}
|
||||
return replStr;
|
||||
}
|
||||
|
||||
private static String unpack(JCExpression expr) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.javac.handlers;
|
||||
|
||||
import static lombok.javac.handlers.JavacHandlerUtil.*;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.core.AlreadyHandledAnnotations;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.HandlerPriority;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
@HandlerPriority(65536)
|
||||
@AlreadyHandledAnnotations
|
||||
public class HandleBuilderRemove extends JavacAnnotationHandler<Builder> {
|
||||
@Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
deleteAnnotationIfNeccessary(annotationNode, Builder.class, "lombok.experimental.Builder");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.javac.handlers;
|
||||
|
||||
import static lombok.javac.handlers.JavacHandlerUtil.*;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
import com.sun.tools.javac.code.Flags;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeApply;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.ConfigurationKeys;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.HandlerPriority;
|
||||
import lombok.core.handlers.HandlerUtil;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacNode;
|
||||
import lombok.javac.JavacTreeMaker;
|
||||
|
||||
/**
|
||||
* This (javac) handler deals with {@code @Jacksonized} modifying the (already
|
||||
* generated) {@code @Builder} or {@code @SuperBuilder} to conform to Jackson's
|
||||
* needs for builders.
|
||||
*/
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
@HandlerPriority(-512) // Above Handle(Super)Builder's level (builders must be already generated).
|
||||
public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
|
||||
|
||||
@Override public void handle(AnnotationValues<Jacksonized> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
JavacNode annotatedNode = annotationNode.up();
|
||||
deleteAnnotationIfNeccessary(annotationNode, Jacksonized.class);
|
||||
|
||||
JavacNode tdNode;
|
||||
if (annotatedNode.getKind() != Kind.TYPE)
|
||||
tdNode = annotatedNode.up(); // @Jacksonized on a constructor or a static factory method.
|
||||
else
|
||||
tdNode = annotatedNode; // @Jacksonized on the class.
|
||||
JCClassDecl td = (JCClassDecl) tdNode.get();
|
||||
|
||||
JavacNode builderAnnotationNode = findAnnotation(Builder.class, annotatedNode);
|
||||
JavacNode superBuilderAnnotationNode = findAnnotation(SuperBuilder.class, annotatedNode);
|
||||
if (builderAnnotationNode == null && superBuilderAnnotationNode == null) {
|
||||
annotationNode.addWarning("@Jacksonized requires @Builder or @SuperBuilder for it to mean anything.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (builderAnnotationNode != null && superBuilderAnnotationNode != null) {
|
||||
annotationNode.addError("@Jacksonized cannot process both @Builder and @SuperBuilder on the same class.");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isAbstract = (td.mods.flags & Flags.ABSTRACT) != 0;
|
||||
if (isAbstract) {
|
||||
annotationNode.addError("Builders on abstract classes cannot be @Jacksonized (the builder would never be used).");
|
||||
return;
|
||||
}
|
||||
|
||||
AnnotationValues<Builder> builderAnnotation = builderAnnotationNode != null ?
|
||||
createAnnotation(Builder.class, builderAnnotationNode) :
|
||||
null;
|
||||
AnnotationValues<SuperBuilder> superBuilderAnnotation = superBuilderAnnotationNode != null ?
|
||||
createAnnotation(SuperBuilder.class, superBuilderAnnotationNode) :
|
||||
null;
|
||||
|
||||
String setPrefix = builderAnnotation != null ?
|
||||
builderAnnotation.getInstance().setterPrefix() :
|
||||
superBuilderAnnotation.getInstance().setterPrefix();
|
||||
String buildMethodName = builderAnnotation != null ?
|
||||
builderAnnotation.getInstance().buildMethodName() :
|
||||
superBuilderAnnotation.getInstance().buildMethodName();
|
||||
|
||||
JavacTreeMaker maker = annotatedNode.getTreeMaker();
|
||||
|
||||
// Now lets find the generated builder class.
|
||||
String builderClassName = getBuilderClassName(ast, annotationNode, annotatedNode, td, builderAnnotation, maker);
|
||||
|
||||
JCClassDecl builderClass = null;
|
||||
for (JCTree member : td.getMembers()) {
|
||||
if (member instanceof JCClassDecl && ((JCClassDecl) member).getSimpleName().contentEquals(builderClassName)) {
|
||||
builderClass = (JCClassDecl) member;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (builderClass == null) {
|
||||
annotationNode.addError("Could not find @(Super)Builder's generated builder class for @Jacksonized processing. If there are other compiler errors, fix them first.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Insert @JsonDeserialize on annotated class.
|
||||
if (hasAnnotation("com.fasterxml.jackson.databind.annotation.JsonDeserialize", tdNode)) {
|
||||
annotationNode.addError("@JsonDeserialize already exists on class. Either delete @JsonDeserialize, or remove @Jacksonized and manually configure Jackson.");
|
||||
return;
|
||||
}
|
||||
JCExpression jsonDeserializeType = chainDots(annotatedNode, "com", "fasterxml", "jackson", "databind", "annotation", "JsonDeserialize");
|
||||
JCExpression builderClassExpression = namePlusTypeParamsToTypeReference(maker, tdNode, annotationNode.toName(builderClassName), false, List.<JCTypeParameter>nil());
|
||||
JCFieldAccess builderClassReference = maker.Select(builderClassExpression, annotatedNode.toName("class"));
|
||||
JCExpression assign = maker.Assign(maker.Ident(annotationNode.toName("builder")), builderClassReference);
|
||||
JCAnnotation annotationJsonDeserialize = maker.Annotation(jsonDeserializeType, List.of(assign));
|
||||
td.mods.annotations = td.mods.annotations.append(annotationJsonDeserialize);
|
||||
|
||||
// Copy annotations from the class to the builder class.
|
||||
List<JCAnnotation> copyableAnnotations = findJacksonAnnotationsOnClass(tdNode);
|
||||
List<JCAnnotation> copiedAnnotations = copyAnnotations(copyableAnnotations);
|
||||
builderClass.mods.annotations = builderClass.mods.annotations.appendList(copiedAnnotations);
|
||||
|
||||
// Insert @JsonPOJOBuilder on the builder class.
|
||||
JCExpression jsonPOJOBuilderType = chainDots(annotatedNode, "com", "fasterxml", "jackson", "databind", "annotation", "JsonPOJOBuilder");
|
||||
JCExpression withPrefixExpr = maker.Assign(maker.Ident(annotationNode.toName("withPrefix")), maker.Literal(setPrefix));
|
||||
JCExpression buildMethodNameExpr = maker.Assign(maker.Ident(annotationNode.toName("buildMethodName")), maker.Literal(buildMethodName));
|
||||
JCAnnotation annotationJsonPOJOBuilder = maker.Annotation(jsonPOJOBuilderType, List.of(withPrefixExpr, buildMethodNameExpr));
|
||||
builderClass.mods.annotations = builderClass.mods.annotations.append(annotationJsonPOJOBuilder);
|
||||
|
||||
// @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) {
|
||||
String builderClassName = builderAnnotation != null ?
|
||||
builderAnnotation.getInstance().builderClassName() : null;
|
||||
if (builderClassName == null || builderClassName.isEmpty()) {
|
||||
builderClassName = annotationNode.getAst().readConfiguration(ConfigurationKeys.BUILDER_CLASS_NAME);
|
||||
if (builderClassName == null || builderClassName.isEmpty())
|
||||
builderClassName = "*Builder";
|
||||
|
||||
JCMethodDecl fillParametersFrom = annotatedNode.get() instanceof JCMethodDecl ? (JCMethodDecl)annotatedNode.get() : null;
|
||||
String replacement;
|
||||
if (fillParametersFrom != null && !fillParametersFrom.getName().toString().equals("<init>")) {
|
||||
// @Builder on a method: Use name of return type for builder class name.
|
||||
JCExpression returnType = fillParametersFrom.restype;
|
||||
List<JCTypeParameter> typeParams = fillParametersFrom.typarams;
|
||||
if (returnType instanceof JCTypeApply) {
|
||||
returnType = cloneType(maker, returnType, ast, annotationNode.getContext());
|
||||
}
|
||||
replacement = HandleBuilder.returnTypeToBuilderClassName(annotationNode, td, returnType, typeParams);
|
||||
} else {
|
||||
// @Builder on class or constructor: Use the class name.
|
||||
replacement = td.name.toString();
|
||||
}
|
||||
builderClassName = builderClassName.replace("*", replacement);
|
||||
}
|
||||
|
||||
if (builderAnnotation == null)
|
||||
builderClassName += "Impl"; // For @SuperBuilder, all Jackson annotations must be put on the BuilderImpl class.
|
||||
|
||||
return builderClassName;
|
||||
}
|
||||
|
||||
private static List<JCAnnotation> findJacksonAnnotationsOnClass(JavacNode node) {
|
||||
ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>();
|
||||
for (JavacNode child : node.down()) {
|
||||
if (child.getKind() == Kind.ANNOTATION) {
|
||||
JCAnnotation annotation = (JCAnnotation) child.get();
|
||||
for (String bn : HandlerUtil.JACKSON_COPY_TO_BUILDER_ANNOTATIONS) {
|
||||
if (typeMatches(bn, node, annotation.annotationType)) {
|
||||
result.append(annotation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList();
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
|
||||
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.SUPERBUILDER_FLAG_USAGE, "@SuperBuilder");
|
||||
CheckerFrameworkVersion cfv = getCheckerFrameworkVersion(annotationNode);
|
||||
SuperBuilder superbuilderAnnotation = annotation.getInstance();
|
||||
deleteAnnotationIfNeccessary(annotationNode, SuperBuilder.class);
|
||||
// Do not delete the SuperBuilder annotation here, we need it for @Jacksonized.
|
||||
|
||||
String builderMethodName = superbuilderAnnotation.builderMethodName();
|
||||
String buildMethodName = superbuilderAnnotation.buildMethodName();
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.javac.handlers;
|
||||
|
||||
import static lombok.javac.handlers.JavacHandlerUtil.*;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
|
||||
import lombok.core.AlreadyHandledAnnotations;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.HandlerPriority;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
@HandlerPriority(65536)
|
||||
@AlreadyHandledAnnotations
|
||||
public class HandleSuperBuilderRemove extends JavacAnnotationHandler<SuperBuilder> {
|
||||
@Override public void handle(AnnotationValues<SuperBuilder> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
deleteAnnotationIfNeccessary(annotationNode, SuperBuilder.class);
|
||||
}
|
||||
}
|
||||
@@ -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.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JsonIgnoreProperties {
|
||||
public boolean ignoreUnknown() default false;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.fasterxml.jackson.databind.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, ElementType.TYPE, ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JsonDeserialize {
|
||||
public Class<?> builder() default Void.class;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.fasterxml.jackson.databind.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JsonPOJOBuilder {
|
||||
public String buildMethodName() default "build";
|
||||
public String withPrefix() default "with";
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import lombok.Builder;
|
||||
@Builder
|
||||
public class BuilderDefaultsWarnings {
|
||||
long x = System.currentTimeMillis();
|
||||
final int y = 5;
|
||||
@@ -78,6 +80,7 @@ public class BuilderDefaultsWarnings {
|
||||
}
|
||||
class NoBuilderButHasDefaults {
|
||||
private final long z = 5;
|
||||
@Builder
|
||||
public NoBuilderButHasDefaults() {
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import java.util.List;
|
||||
@lombok.Builder
|
||||
class BuilderSingularNoAuto {
|
||||
private List<String> things;
|
||||
private List<String> widgets;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import java.util.List;
|
||||
@lombok.Builder(setterPrefix = "with")
|
||||
class BuilderSingularNoAutoWithSetterPrefix {
|
||||
private List<String> things;
|
||||
private List<String> widgets;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
//CONF: lombok.builder.className = Test*Name
|
||||
import java.util.List;
|
||||
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonizedBuilderComplex.TestVoidName.class)
|
||||
class JacksonizedBuilderComplex {
|
||||
private static <T extends Number> void testVoidWithGenerics(T number, int arg2, String arg3, JacksonizedBuilderComplex selfRef) {
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
@com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "with", buildMethodName = "execute")
|
||||
public static class TestVoidName<T extends Number> {
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private T number;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private int arg2;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private String arg3;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private JacksonizedBuilderComplex selfRef;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
TestVoidName() {
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public JacksonizedBuilderComplex.TestVoidName<T> withNumber(final T number) {
|
||||
this.number = number;
|
||||
return this;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public JacksonizedBuilderComplex.TestVoidName<T> withArg2(final int arg2) {
|
||||
this.arg2 = arg2;
|
||||
return this;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public JacksonizedBuilderComplex.TestVoidName<T> withArg3(final String arg3) {
|
||||
this.arg3 = arg3;
|
||||
return this;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public JacksonizedBuilderComplex.TestVoidName<T> withSelfRef(final JacksonizedBuilderComplex selfRef) {
|
||||
this.selfRef = selfRef;
|
||||
return this;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public void execute() {
|
||||
JacksonizedBuilderComplex.<T>testVoidWithGenerics(this.number, this.arg2, this.arg3, this.selfRef);
|
||||
}
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public java.lang.String toString() {
|
||||
return "JacksonizedBuilderComplex.TestVoidName(number=" + this.number + ", arg2=" + this.arg2 + ", arg3=" + this.arg3 + ", selfRef=" + this.selfRef + ")";
|
||||
}
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static <T extends Number> JacksonizedBuilderComplex.TestVoidName<T> builder() {
|
||||
return new JacksonizedBuilderComplex.TestVoidName<T>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import java.util.List;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder.class)
|
||||
class JacksonizedBuilderSimple<T> {
|
||||
private final int noshow = 0;
|
||||
private final int yes;
|
||||
private List<T> also;
|
||||
private int $butNotMe;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
JacksonizedBuilderSimple(final int yes, final List<T> also) {
|
||||
this.yes = yes;
|
||||
this.also = also;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "", buildMethodName = "build")
|
||||
protected static class JacksonizedBuilderSimpleBuilder<T> {
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private int yes;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private List<T> also;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
JacksonizedBuilderSimpleBuilder() {
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder<T> yes(final int yes) {
|
||||
this.yes = yes;
|
||||
return this;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder<T> also(final List<T> also) {
|
||||
this.also = also;
|
||||
return this;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public JacksonizedBuilderSimple<T> build() {
|
||||
return new JacksonizedBuilderSimple<T>(this.yes, this.also);
|
||||
}
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public java.lang.String toString() {
|
||||
return "JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder(yes=" + this.yes + ", also=" + this.also + ")";
|
||||
}
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected static <T> JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder<T> builder() {
|
||||
return new JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder<T>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
public class JacksonizedSuperBuilderSimple {
|
||||
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonizedSuperBuilderSimple.Parent.ParentBuilderImpl.class)
|
||||
public static class Parent {
|
||||
int field1;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static abstract class ParentBuilder<C extends JacksonizedSuperBuilderSimple.Parent, B extends JacksonizedSuperBuilderSimple.Parent.ParentBuilder<C, B>> {
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private int field1;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected abstract B self();
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public abstract C build();
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public B field1(final int field1) {
|
||||
this.field1 = field1;
|
||||
return self();
|
||||
}
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public java.lang.String toString() {
|
||||
return "JacksonizedSuperBuilderSimple.Parent.ParentBuilder(field1=" + this.field1 + ")";
|
||||
}
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "", buildMethodName = "build")
|
||||
static final class ParentBuilderImpl extends JacksonizedSuperBuilderSimple.Parent.ParentBuilder<JacksonizedSuperBuilderSimple.Parent, JacksonizedSuperBuilderSimple.Parent.ParentBuilderImpl> {
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private ParentBuilderImpl() {
|
||||
}
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected JacksonizedSuperBuilderSimple.Parent.ParentBuilderImpl self() {
|
||||
return this;
|
||||
}
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public JacksonizedSuperBuilderSimple.Parent build() {
|
||||
return new JacksonizedSuperBuilderSimple.Parent(this);
|
||||
}
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected Parent(final JacksonizedSuperBuilderSimple.Parent.ParentBuilder<?, ?> b) {
|
||||
this.field1 = b.field1;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static JacksonizedSuperBuilderSimple.Parent.ParentBuilder<?, ?> builder() {
|
||||
return new JacksonizedSuperBuilderSimple.Parent.ParentBuilderImpl();
|
||||
}
|
||||
}
|
||||
public static void test() {
|
||||
Parent x = Parent.builder().field1(5).build();
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
@lombok.experimental.SuperBuilder
|
||||
@com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
||||
public class JacksonizedSuperBuilderWithJsonDeserialize {
|
||||
int field1;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static abstract class JacksonizedSuperBuilderWithJsonDeserializeBuilder<C extends JacksonizedSuperBuilderWithJsonDeserialize, B extends JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilder<C, B>> {
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private int field1;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected abstract B self();
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public abstract C build();
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public B field1(final int field1) {
|
||||
this.field1 = field1;
|
||||
return self();
|
||||
}
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public java.lang.String toString() {
|
||||
return "JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilder(field1=" + this.field1 + ")";
|
||||
}
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private static final class JacksonizedSuperBuilderWithJsonDeserializeBuilderImpl extends JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilder<JacksonizedSuperBuilderWithJsonDeserialize, JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilderImpl> {
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private JacksonizedSuperBuilderWithJsonDeserializeBuilderImpl() {
|
||||
}
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilderImpl self() {
|
||||
return this;
|
||||
}
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public JacksonizedSuperBuilderWithJsonDeserialize build() {
|
||||
return new JacksonizedSuperBuilderWithJsonDeserialize(this);
|
||||
}
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
protected JacksonizedSuperBuilderWithJsonDeserialize(final JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilder<?, ?> b) {
|
||||
this.field1 = b.field1;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilder<?, ?> builder() {
|
||||
return new JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilderImpl();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import java.util.List;
|
||||
import lombok.Builder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonizedBuilderComplex.TestVoidName.class) class JacksonizedBuilderComplex {
|
||||
public static @java.lang.SuppressWarnings("all") @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "with",buildMethodName = "execute") class TestVoidName<T extends Number> {
|
||||
private @java.lang.SuppressWarnings("all") T number;
|
||||
private @java.lang.SuppressWarnings("all") int arg2;
|
||||
private @java.lang.SuppressWarnings("all") String arg3;
|
||||
private @java.lang.SuppressWarnings("all") JacksonizedBuilderComplex selfRef;
|
||||
@java.lang.SuppressWarnings("all") TestVoidName() {
|
||||
super();
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") JacksonizedBuilderComplex.TestVoidName<T> withNumber(final T number) {
|
||||
this.number = number;
|
||||
return this;
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") JacksonizedBuilderComplex.TestVoidName<T> withArg2(final int arg2) {
|
||||
this.arg2 = arg2;
|
||||
return this;
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") JacksonizedBuilderComplex.TestVoidName<T> withArg3(final String arg3) {
|
||||
this.arg3 = arg3;
|
||||
return this;
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") JacksonizedBuilderComplex.TestVoidName<T> withSelfRef(final JacksonizedBuilderComplex selfRef) {
|
||||
this.selfRef = selfRef;
|
||||
return this;
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") void execute() {
|
||||
JacksonizedBuilderComplex.<T>testVoidWithGenerics(this.number, this.arg2, this.arg3, this.selfRef);
|
||||
}
|
||||
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
|
||||
return (((((((("JacksonizedBuilderComplex.TestVoidName(number=" + this.number) + ", arg2=") + this.arg2) + ", arg3=") + this.arg3) + ", selfRef=") + this.selfRef) + ")");
|
||||
}
|
||||
}
|
||||
JacksonizedBuilderComplex() {
|
||||
super();
|
||||
}
|
||||
private static @Jacksonized @Builder(buildMethodName = "execute",setterPrefix = "with") <T extends Number>void testVoidWithGenerics(T number, int arg2, String arg3, JacksonizedBuilderComplex selfRef) {
|
||||
}
|
||||
public static @java.lang.SuppressWarnings("all") <T extends Number>JacksonizedBuilderComplex.TestVoidName<T> builder() {
|
||||
return new JacksonizedBuilderComplex.TestVoidName<T>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
@lombok.extern.jackson.Jacksonized @JsonIgnoreProperties(ignoreUnknown = true) @lombok.Builder(access = lombok.AccessLevel.PROTECTED) @com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder.class) class JacksonizedBuilderSimple<T> {
|
||||
protected static @java.lang.SuppressWarnings("all") @JsonIgnoreProperties(ignoreUnknown = true) @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "",buildMethodName = "build") class JacksonizedBuilderSimpleBuilder<T> {
|
||||
private @java.lang.SuppressWarnings("all") int yes;
|
||||
private @java.lang.SuppressWarnings("all") List<T> also;
|
||||
@java.lang.SuppressWarnings("all") JacksonizedBuilderSimpleBuilder() {
|
||||
super();
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder<T> yes(final int yes) {
|
||||
this.yes = yes;
|
||||
return this;
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder<T> also(final List<T> also) {
|
||||
this.also = also;
|
||||
return this;
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") JacksonizedBuilderSimple<T> build() {
|
||||
return new JacksonizedBuilderSimple<T>(this.yes, this.also);
|
||||
}
|
||||
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
|
||||
return (((("JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder(yes=" + this.yes) + ", also=") + this.also) + ")");
|
||||
}
|
||||
}
|
||||
private final int noshow = 0;
|
||||
private final int yes;
|
||||
private List<T> also;
|
||||
private int $butNotMe;
|
||||
@java.lang.SuppressWarnings("all") JacksonizedBuilderSimple(final int yes, final List<T> also) {
|
||||
super();
|
||||
this.yes = yes;
|
||||
this.also = also;
|
||||
}
|
||||
protected static @java.lang.SuppressWarnings("all") <T>JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder<T> builder() {
|
||||
return new JacksonizedBuilderSimple.JacksonizedBuilderSimpleBuilder<T>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
public class JacksonizedSuperBuilderSimple {
|
||||
public static @lombok.extern.jackson.Jacksonized @lombok.experimental.SuperBuilder @com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true) @com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonizedSuperBuilderSimple.Parent.ParentBuilderImpl.class) class Parent {
|
||||
public static abstract @java.lang.SuppressWarnings("all") class ParentBuilder<C extends JacksonizedSuperBuilderSimple.Parent, B extends JacksonizedSuperBuilderSimple.Parent.ParentBuilder<C, B>> {
|
||||
private @java.lang.SuppressWarnings("all") int field1;
|
||||
public ParentBuilder() {
|
||||
super();
|
||||
}
|
||||
protected abstract @java.lang.SuppressWarnings("all") B self();
|
||||
public abstract @java.lang.SuppressWarnings("all") C build();
|
||||
public @java.lang.SuppressWarnings("all") B field1(final int field1) {
|
||||
this.field1 = field1;
|
||||
return self();
|
||||
}
|
||||
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
|
||||
return (("JacksonizedSuperBuilderSimple.Parent.ParentBuilder(field1=" + this.field1) + ")");
|
||||
}
|
||||
}
|
||||
static final @java.lang.SuppressWarnings("all") @com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true) @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "",buildMethodName = "build") class ParentBuilderImpl extends JacksonizedSuperBuilderSimple.Parent.ParentBuilder<JacksonizedSuperBuilderSimple.Parent, JacksonizedSuperBuilderSimple.Parent.ParentBuilderImpl> {
|
||||
private ParentBuilderImpl() {
|
||||
super();
|
||||
}
|
||||
protected @java.lang.Override @java.lang.SuppressWarnings("all") JacksonizedSuperBuilderSimple.Parent.ParentBuilderImpl self() {
|
||||
return this;
|
||||
}
|
||||
public @java.lang.Override @java.lang.SuppressWarnings("all") JacksonizedSuperBuilderSimple.Parent build() {
|
||||
return new JacksonizedSuperBuilderSimple.Parent(this);
|
||||
}
|
||||
}
|
||||
int field1;
|
||||
protected @java.lang.SuppressWarnings("all") Parent(final JacksonizedSuperBuilderSimple.Parent.ParentBuilder<?, ?> b) {
|
||||
super();
|
||||
this.field1 = b.field1;
|
||||
}
|
||||
public static @java.lang.SuppressWarnings("all") JacksonizedSuperBuilderSimple.Parent.ParentBuilder<?, ?> builder() {
|
||||
return new JacksonizedSuperBuilderSimple.Parent.ParentBuilderImpl();
|
||||
}
|
||||
}
|
||||
public JacksonizedSuperBuilderSimple() {
|
||||
super();
|
||||
}
|
||||
public static void test() {
|
||||
Parent x = Parent.builder().field1(5).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
public @lombok.extern.jackson.Jacksonized @lombok.experimental.SuperBuilder @com.fasterxml.jackson.databind.annotation.JsonDeserialize class JacksonizedSuperBuilderWithJsonDeserialize {
|
||||
public static abstract @java.lang.SuppressWarnings("all") class JacksonizedSuperBuilderWithJsonDeserializeBuilder<C extends JacksonizedSuperBuilderWithJsonDeserialize, B extends JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilder<C, B>> {
|
||||
private @java.lang.SuppressWarnings("all") int field1;
|
||||
public JacksonizedSuperBuilderWithJsonDeserializeBuilder() {
|
||||
super();
|
||||
}
|
||||
protected abstract @java.lang.SuppressWarnings("all") B self();
|
||||
public abstract @java.lang.SuppressWarnings("all") C build();
|
||||
public @java.lang.SuppressWarnings("all") B field1(final int field1) {
|
||||
this.field1 = field1;
|
||||
return self();
|
||||
}
|
||||
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
|
||||
return (("JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilder(field1=" + this.field1) + ")");
|
||||
}
|
||||
}
|
||||
private static final @java.lang.SuppressWarnings("all") class JacksonizedSuperBuilderWithJsonDeserializeBuilderImpl extends JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilder<JacksonizedSuperBuilderWithJsonDeserialize, JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilderImpl> {
|
||||
private JacksonizedSuperBuilderWithJsonDeserializeBuilderImpl() {
|
||||
super();
|
||||
}
|
||||
protected @java.lang.Override @java.lang.SuppressWarnings("all") JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilderImpl self() {
|
||||
return this;
|
||||
}
|
||||
public @java.lang.Override @java.lang.SuppressWarnings("all") JacksonizedSuperBuilderWithJsonDeserialize build() {
|
||||
return new JacksonizedSuperBuilderWithJsonDeserialize(this);
|
||||
}
|
||||
}
|
||||
int field1;
|
||||
protected @java.lang.SuppressWarnings("all") JacksonizedSuperBuilderWithJsonDeserialize(final JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilder<?, ?> b) {
|
||||
super();
|
||||
this.field1 = b.field1;
|
||||
}
|
||||
public static @java.lang.SuppressWarnings("all") JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilder<?, ?> builder() {
|
||||
return new JacksonizedSuperBuilderWithJsonDeserialize.JacksonizedSuperBuilderWithJsonDeserializeBuilderImpl();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
//CONF: lombok.builder.className = Test*Name
|
||||
import java.util.List;
|
||||
import lombok.Builder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
class JacksonizedBuilderComplex {
|
||||
@Jacksonized
|
||||
@Builder(buildMethodName = "execute", setterPrefix = "with")
|
||||
private static <T extends Number> void testVoidWithGenerics(T number, int arg2, String arg3, JacksonizedBuilderComplex selfRef) {}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import java.util.List;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@lombok.extern.jackson.Jacksonized
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@lombok.Builder(access = lombok.AccessLevel.PROTECTED)
|
||||
class JacksonizedBuilderSimple<T> {
|
||||
private final int noshow = 0;
|
||||
private final int yes;
|
||||
private List<T> also;
|
||||
private int $butNotMe;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
public class JacksonizedSuperBuilderSimple {
|
||||
@lombok.extern.jackson.Jacksonized
|
||||
@lombok.experimental.SuperBuilder
|
||||
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static class Parent {
|
||||
int field1;
|
||||
}
|
||||
|
||||
public static void test() {
|
||||
Parent x = Parent.builder().field1(5).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
@lombok.extern.jackson.Jacksonized
|
||||
@lombok.experimental.SuperBuilder
|
||||
@com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
||||
public class JacksonizedSuperBuilderWithJsonDeserialize {
|
||||
int field1;
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
1 @JsonDeserialize already exists on class. Either delete @JsonDeserialize, or remove @Jacksonized and manually configure Jackson.
|
||||
+1
@@ -0,0 +1 @@
|
||||
1 @JsonDeserialize already exists on class. Either delete @JsonDeserialize, or remove @Jacksonized and manually configure Jackson.
|
||||
Reference in New Issue
Block a user