Skip to content

Commit

Permalink
[WIP]
Browse files Browse the repository at this point in the history
  • Loading branch information
janrieke committed Mar 27, 2024
1 parent a0a2ef4 commit 7ea9570
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 4 deletions.
19 changes: 18 additions & 1 deletion src/core/lombok/core/handlers/HandlerUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public static int primeForNull() {
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;
Expand Down Expand Up @@ -423,6 +423,23 @@ public static int primeForNull() {
"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",
Expand Down
3 changes: 2 additions & 1 deletion src/core/lombok/extern/jackson/Jacksonized.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@
* {@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
Expand Down
47 changes: 45 additions & 2 deletions src/core/lombok/javac/handlers/HandleJacksonized.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
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;
Expand Down Expand Up @@ -56,7 +57,7 @@
* 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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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 ?
Expand Down
18 changes: 18 additions & 0 deletions test/transform/resource/after-delombok/JacksonizedAccessors.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
10 changes: 10 additions & 0 deletions test/transform/resource/before/JacksonizedAccessors.java
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit 7ea9570

Please sign in to comment.