This commit is contained in:
Jan Rieke committed 2024-03-27 11:25:00 +01:00
1 parent a0a2ef4fbc
commit 7ea95700c3
5 files changed
+93 -4

No files matched your search

+18 -1
View File
@@ -79,7 +79,7 @@ public class HandlerUtil {
return 43;
}
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;
public static final List<String> NONNULL_ANNOTATIONS, BASE_COPYABLE_ANNOTATIONS, COPY_TO_GETTER_ANNOTATIONS, COPY_TO_SETTER_ANNOTATIONS, COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS, JACKSON_COPY_TO_BUILDER_ANNOTATIONS;
static {
// This is a list of annotations with a __highly specific meaning__: All annotations in this list indicate that passing null for the relevant item is __never__ acceptable, regardless of settings or circumstance.
// In other words, things like 'this models a database table, and the db table column has a nonnull constraint', or 'this represents a web form, and if this is null, the form is invalid' __do not count__ and should not be in this list;
@@ -423,6 +423,23 @@ public class HandlerUtil {
"org.checkerframework.common.value.qual.UnknownVal",
"org.checkerframework.framework.qual.PurityUnqualified",
}));
COPY_TO_GETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
"com.fasterxml.jackson.annotation.JacksonInject",
"com.fasterxml.jackson.annotation.JsonAlias",
"com.fasterxml.jackson.annotation.JsonFormat",
"com.fasterxml.jackson.annotation.JsonIgnore",
"com.fasterxml.jackson.annotation.JsonIgnoreProperties",
"com.fasterxml.jackson.annotation.JsonProperty",
"com.fasterxml.jackson.annotation.JsonSetter",
"com.fasterxml.jackson.annotation.JsonSubTypes",
"com.fasterxml.jackson.annotation.JsonTypeInfo",
"com.fasterxml.jackson.annotation.JsonUnwrapped",
"com.fasterxml.jackson.annotation.JsonView",
"com.fasterxml.jackson.databind.annotation.JsonDeserialize",
"com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper",
"com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty",
"com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText",
}));
COPY_TO_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] {
"com.fasterxml.jackson.annotation.JacksonInject",
"com.fasterxml.jackson.annotation.JsonAlias",
+2 -1
View File
@@ -38,9 +38,10 @@ import lombok.experimental.SuperBuilder;
* {@code @}{@link Builder}, {@code @}{@link SuperBuilder}, and
* {@code @}{@link Accessors}.
* <p>
* For {@code @}{@link Accessors}{@code (fluent = true)}, it automatically
* For {@code @}{@link Accessors}{@code (fluent = true)} on a type, it automatically
* configures Jackson to use the generated setters and getters for
* (de-)serialization by inserting {@code @}{@link JsonProperty} annotations.
* (Note that {@code @Jacksonized} {@code @Accessors} on fields are not supported.)
* <p>
* For {@code @}{@link Builder} and {@code @}{@link SuperBuilder}, it
* automatically configures the generated builder class to be used by Jackson's
@@ -28,6 +28,7 @@ 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.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
@@ -56,7 +57,7 @@ import lombok.spi.Provides;
* needs for builders.
*/
@Provides
@HandlerPriority(-512) // Above Handle(Super)Builder's level (builders must be already generated).
@HandlerPriority(-512) // Above Handle(Super)Builder's level (builders must be already generated), but before all handlers generating getters/setters.
public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
@Override public void handle(AnnotationValues<Jacksonized> annotation, JCAnnotation ast, JavacNode annotationNode) {
@@ -79,7 +80,49 @@ public class HandleJacksonized extends JavacAnnotationHandler<Jacksonized> {
annotationNode.addWarning("@Jacksonized requires @Builder, @SuperBuilder, or @Accessors for it to mean anything.");
return;
}
if (builderAnnotationNode != null || superBuilderAnnotationNode != null) {
handleJacksonizedBuilder(annotationNode, annotatedNode, tdNode, td, builderAnnotationNode, superBuilderAnnotationNode);
}
if (accessorsAnnotationNode != null) {
handleJacksonizedAccessors(annotationNode, annotatedNode, tdNode, td, accessorsAnnotationNode);
}
}
private void handleJacksonizedAccessors(JavacNode annotationNode, JavacNode annotatedNode, JavacNode tdNode, JCClassDecl td, JavacNode accessorsAnnotationNode) {
AnnotationValues<Accessors> accessorsAnnotation = accessorsAnnotationNode != null ?
createAnnotation(Accessors.class, accessorsAnnotationNode) :
null;
boolean fluent = accessorsAnnotation != null && accessorsAnnotation.getInstance().fluent();
if (!fluent) {
// No changes required for chained-only accessors.
return;
}
// Add @JsonProperty to all fields. It will be automatically copied to the getter/setters later.
for (JavacNode javacNode : tdNode.down()) {
if (javacNode.getKind() == Kind.FIELD) {
createJsonPropertyForField(javacNode, annotationNode);
}
}
}
private void createJsonPropertyForField(JavacNode fieldNode, JavacNode annotationNode) {
if (hasAnnotation("com.fasterxml.jackson.annotation.JsonProperty", fieldNode)) {
return;
}
JavacTreeMaker maker = fieldNode.getTreeMaker();
JCExpression jsonPropertyType = chainDots(fieldNode, "com", "fasterxml", "jackson", "annotation", "JsonProperty");
JCAnnotation annotationJsonProperty = maker.Annotation(jsonPropertyType, List.of(maker.Literal(fieldNode.getName())));
recursiveSetGeneratedBy(annotationJsonProperty, annotationNode);
JCVariableDecl fieldDecl = ((JCVariableDecl)fieldNode.get());
fieldDecl.mods.annotations = fieldDecl.mods.annotations.append(annotationJsonProperty);
}
private void handleJacksonizedBuilder(JavacNode annotationNode, JavacNode annotatedNode, JavacNode tdNode, JCClassDecl td, JavacNode builderAnnotationNode, JavacNode superBuilderAnnotationNode) {
if (builderAnnotationNode != null && superBuilderAnnotationNode != null) {
annotationNode.addError("@Jacksonized cannot process both @Builder and @SuperBuilder on the same class.");
return;
@@ -155,7 +198,7 @@ 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(JavacNode annotationNode, JavacNode annotatedNode, JCClassDecl td, AnnotationValues<Builder> builderAnnotation, JavacTreeMaker maker) {
String builderClassName = builderAnnotation != null ?
@@ -0,0 +1,18 @@
public class JacksonizedAccessors {
@com.fasterxml.jackson.annotation.JsonProperty("intValue")
private int intValue;
@java.lang.SuppressWarnings("all")
@com.fasterxml.jackson.annotation.JsonProperty("intValue")
public int intValue() {
return this.intValue;
}
/**
* @return {@code this}.
*/
@java.lang.SuppressWarnings("all")
@com.fasterxml.jackson.annotation.JsonProperty("intValue")
public JacksonizedAccessors intValue(final int intValue) {
this.intValue = intValue;
return this;
}
}
@@ -0,0 +1,10 @@
import lombok.Getter;
import lombok.experimental.Accessors;
import lombok.extern.jackson.Jacksonized;
@Jacksonized
@Accessors(fluent = true)
@Getter
public class JacksonizedAccessors {
private int intValue;
}