From 54d57f896d1374eb9ea169b1e11ccd06403c1ef5 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Sat, 6 Jan 2024 00:32:51 +0100 Subject: [PATCH 01/22] rename Jacksonized test file --- ...r.java => JacksonizedBuilderSingular.java} | 44 +++++++++---------- ...r.java => JacksonizedBuilderSingular.java} | 42 +++++++++--------- ...r.java => JacksonizedBuilderSingular.java} | 2 +- 3 files changed, 44 insertions(+), 44 deletions(-) rename test/transform/resource/after-delombok/{JacksonBuilderSingular.java => JacksonizedBuilderSingular.java} (71%) rename test/transform/resource/after-ecj/{JacksonBuilderSingular.java => JacksonizedBuilderSingular.java} (68%) rename test/transform/resource/before/{JacksonBuilderSingular.java => JacksonizedBuilderSingular.java} (94%) diff --git a/test/transform/resource/after-delombok/JacksonBuilderSingular.java b/test/transform/resource/after-delombok/JacksonizedBuilderSingular.java similarity index 71% rename from test/transform/resource/after-delombok/JacksonBuilderSingular.java rename to test/transform/resource/after-delombok/JacksonizedBuilderSingular.java index b2bbfa5a..279210a8 100644 --- a/test/transform/resource/after-delombok/JacksonBuilderSingular.java +++ b/test/transform/resource/after-delombok/JacksonizedBuilderSingular.java @@ -5,8 +5,8 @@ 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 { +@com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder.class) +public class JacksonizedBuilderSingular { @JsonAnySetter private Map any; @JsonProperty("v_a_l_u_e_s") @@ -16,7 +16,7 @@ public class JacksonBuilderSingular { @JsonProperty("guava_v_a_l_u_e_s") private ImmutableList guavaValues; @java.lang.SuppressWarnings("all") - JacksonBuilderSingular(final Map any, final List values, final ImmutableMap guavaAny, final ImmutableList guavaValues) { + JacksonizedBuilderSingular(final Map any, final List values, final ImmutableMap guavaAny, final ImmutableList guavaValues) { this.any = any; this.values = values; this.guavaAny = guavaAny; @@ -24,7 +24,7 @@ public class JacksonBuilderSingular { } @java.lang.SuppressWarnings("all") @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "", buildMethodName = "build") - public static class JacksonBuilderSingularBuilder { + public static class JacksonizedBuilderSingularBuilder { @java.lang.SuppressWarnings("all") private java.util.ArrayList any$key; @java.lang.SuppressWarnings("all") @@ -36,11 +36,11 @@ public class JacksonBuilderSingular { @java.lang.SuppressWarnings("all") private com.google.common.collect.ImmutableList.Builder guavaValues; @java.lang.SuppressWarnings("all") - JacksonBuilderSingularBuilder() { + JacksonizedBuilderSingularBuilder() { } @JsonAnySetter @java.lang.SuppressWarnings("all") - public JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final String anyKey, final Object anyValue) { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder any(final String anyKey, final Object anyValue) { if (this.any$key == null) { this.any$key = new java.util.ArrayList(); this.any$value = new java.util.ArrayList(); @@ -50,7 +50,7 @@ public class JacksonBuilderSingular { return this; } @java.lang.SuppressWarnings("all") - public JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final java.util.Map any) { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder any(final java.util.Map any) { if (any == null) { throw new java.lang.NullPointerException("any cannot be null"); } @@ -65,7 +65,7 @@ public class JacksonBuilderSingular { return this; } @java.lang.SuppressWarnings("all") - public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearAny() { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearAny() { if (this.any$key != null) { this.any$key.clear(); this.any$value.clear(); @@ -73,14 +73,14 @@ public class JacksonBuilderSingular { return this; } @java.lang.SuppressWarnings("all") - public JacksonBuilderSingular.JacksonBuilderSingularBuilder value(final String value) { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder value(final String value) { if (this.values == null) this.values = new java.util.ArrayList(); 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 values) { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder values(final java.util.Collection values) { if (values == null) { throw new java.lang.NullPointerException("values cannot be null"); } @@ -89,19 +89,19 @@ public class JacksonBuilderSingular { return this; } @java.lang.SuppressWarnings("all") - public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearValues() { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder 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) { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder 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 guavaAny) { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaAny(final java.util.Map guavaAny) { if (guavaAny == null) { throw new java.lang.NullPointerException("guavaAny cannot be null"); } @@ -110,19 +110,19 @@ public class JacksonBuilderSingular { return this; } @java.lang.SuppressWarnings("all") - public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaAny() { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearGuavaAny() { this.guavaAny = null; return this; } @java.lang.SuppressWarnings("all") - public JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaValue(final String guavaValue) { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder 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 guavaValues) { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaValues(final java.lang.Iterable guavaValues) { if (guavaValues == null) { throw new java.lang.NullPointerException("guavaValues cannot be null"); } @@ -131,12 +131,12 @@ public class JacksonBuilderSingular { return this; } @java.lang.SuppressWarnings("all") - public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaValues() { + public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearGuavaValues() { this.guavaValues = null; return this; } @java.lang.SuppressWarnings("all") - public JacksonBuilderSingular build() { + public JacksonizedBuilderSingular build() { java.util.Map any; switch (this.any$key == null ? 0 : this.any$key.size()) { case 0: @@ -163,16 +163,16 @@ public class JacksonBuilderSingular { } com.google.common.collect.ImmutableMap guavaAny = this.guavaAny == null ? com.google.common.collect.ImmutableMap.of() : this.guavaAny.build(); com.google.common.collect.ImmutableList guavaValues = this.guavaValues == null ? com.google.common.collect.ImmutableList.of() : this.guavaValues.build(); - return new JacksonBuilderSingular(any, values, guavaAny, guavaValues); + return new JacksonizedBuilderSingular(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 + ")"; + return "JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder(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(); + public static JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder builder() { + return new JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder(); } } \ No newline at end of file diff --git a/test/transform/resource/after-ecj/JacksonBuilderSingular.java b/test/transform/resource/after-ecj/JacksonizedBuilderSingular.java similarity index 68% rename from test/transform/resource/after-ecj/JacksonBuilderSingular.java rename to test/transform/resource/after-ecj/JacksonizedBuilderSingular.java index 50f6a797..09cc706f 100644 --- a/test/transform/resource/after-ecj/JacksonBuilderSingular.java +++ b/test/transform/resource/after-ecj/JacksonizedBuilderSingular.java @@ -7,17 +7,17 @@ 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 { +public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder.class) class JacksonizedBuilderSingular { + public static @java.lang.SuppressWarnings("all") @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "",buildMethodName = "build") class JacksonizedBuilderSingularBuilder { private @java.lang.SuppressWarnings("all") java.util.ArrayList any$key; private @java.lang.SuppressWarnings("all") java.util.ArrayList any$value; private @java.lang.SuppressWarnings("all") java.util.ArrayList values; private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableMap.Builder guavaAny; private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableList.Builder guavaValues; - @java.lang.SuppressWarnings("all") JacksonBuilderSingularBuilder() { + @java.lang.SuppressWarnings("all") JacksonizedBuilderSingularBuilder() { super(); } - public @JsonAnySetter @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final String anyKey, final Object anyValue) { + public @JsonAnySetter @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder any(final String anyKey, final Object anyValue) { if ((this.any$key == null)) { this.any$key = new java.util.ArrayList(); @@ -27,7 +27,7 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese this.any$value.add(anyValue); return this; } - public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final java.util.Map any) { + public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder any(final java.util.Map any) { if ((any == null)) { throw new java.lang.NullPointerException("any cannot be null"); @@ -44,7 +44,7 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese } return this; } - public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearAny() { + public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearAny() { if ((this.any$key != null)) { this.any$key.clear(); @@ -52,13 +52,13 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese } return this; } - public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder value(final String value) { + public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder value(final String value) { if ((this.values == null)) this.values = new java.util.ArrayList(); 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 values) { + public @JsonProperty("v_a_l_u_e_s") @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder values(final java.util.Collection values) { if ((values == null)) { throw new java.lang.NullPointerException("values cannot be null"); @@ -68,18 +68,18 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese this.values.addAll(values); return this; } - public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearValues() { + public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder 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) { + public @JsonAnySetter @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder 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 guavaAny) { + public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaAny(final java.util.Map guavaAny) { if ((guavaAny == null)) { throw new java.lang.NullPointerException("guavaAny cannot be null"); @@ -89,17 +89,17 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese this.guavaAny.putAll(guavaAny); return this; } - public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaAny() { + public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearGuavaAny() { this.guavaAny = null; return this; } - public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaValue(final String guavaValue) { + public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder 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 guavaValues) { + public @JsonProperty("guava_v_a_l_u_e_s") @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaValues(final java.lang.Iterable guavaValues) { if ((guavaValues == null)) { throw new java.lang.NullPointerException("guavaValues cannot be null"); @@ -109,11 +109,11 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese this.guavaValues.addAll(guavaValues); return this; } - public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaValues() { + public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearGuavaValues() { this.guavaValues = null; return this; } - public @java.lang.SuppressWarnings("all") JacksonBuilderSingular build() { + public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular build() { java.util.Map any; switch (((this.any$key == null) ? 0 : this.any$key.size())) { case 0 : @@ -141,24 +141,24 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese } com.google.common.collect.ImmutableMap guavaAny = ((this.guavaAny == null) ? com.google.common.collect.ImmutableMap.of() : this.guavaAny.build()); com.google.common.collect.ImmutableList guavaValues = ((this.guavaValues == null) ? com.google.common.collect.ImmutableList.of() : this.guavaValues.build()); - return new JacksonBuilderSingular(any, values, guavaAny, guavaValues); + return new JacksonizedBuilderSingular(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) + ")"); + return (((((((((("JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder(any$key=" + this.any$key) + ", any$value=") + this.any$value) + ", values=") + this.values) + ", guavaAny=") + this.guavaAny) + ", guavaValues=") + this.guavaValues) + ")"); } } private @JsonAnySetter @Singular("any") Map any; private @JsonProperty("v_a_l_u_e_s") @Singular List values; private @JsonAnySetter @Singular("guavaAny") ImmutableMap guavaAny; private @JsonProperty("guava_v_a_l_u_e_s") @Singular ImmutableList guavaValues; - @java.lang.SuppressWarnings("all") JacksonBuilderSingular(final Map any, final List values, final ImmutableMap guavaAny, final ImmutableList guavaValues) { + @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular(final Map any, final List values, final ImmutableMap guavaAny, final ImmutableList 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(); + public static @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder builder() { + return new JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder(); } } \ No newline at end of file diff --git a/test/transform/resource/before/JacksonBuilderSingular.java b/test/transform/resource/before/JacksonizedBuilderSingular.java similarity index 94% rename from test/transform/resource/before/JacksonBuilderSingular.java rename to test/transform/resource/before/JacksonizedBuilderSingular.java index 20d6979a..a34ab9c4 100644 --- a/test/transform/resource/before/JacksonBuilderSingular.java +++ b/test/transform/resource/before/JacksonizedBuilderSingular.java @@ -13,7 +13,7 @@ import lombok.extern.jackson.Jacksonized; @Jacksonized @Builder -public class JacksonBuilderSingular { +public class JacksonizedBuilderSingular { @JsonAnySetter @Singular("any") private Map any; From a0a2ef4fbc3f2b4913a7c3b75287872d9f67a079 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Sun, 21 Jan 2024 23:07:48 +0100 Subject: [PATCH 02/22] [WIP] --- .../lombok/extern/jackson/Jacksonized.java | 24 +++++++++++++------ .../javac/handlers/HandleJacksonized.java | 6 +++-- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/core/lombok/extern/jackson/Jacksonized.java b/src/core/lombok/extern/jackson/Jacksonized.java index 801ddbcb..bba654c3 100644 --- a/src/core/lombok/extern/jackson/Jacksonized.java +++ b/src/core/lombok/extern/jackson/Jacksonized.java @@ -27,13 +27,23 @@ import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import com.fasterxml.jackson.annotation.JsonProperty; + import lombok.Builder; +import lombok.experimental.Accessors; 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 + * {@code @}{@link Builder}, {@code @}{@link SuperBuilder}, and + * {@code @}{@link Accessors}. + *

+ * For {@code @}{@link Accessors}{@code (fluent = true)}, it automatically + * configures Jackson to use the generated setters and getters for + * (de-)serialization by inserting {@code @}{@link JsonProperty} annotations. + *

+ * 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. @@ -41,8 +51,8 @@ import lombok.experimental.SuperBuilder; * In particular, the annotation does the following: *

    *
  • Configure Jackson to use the builder for deserialization using - * {@code @JsonDeserialize(builder=Foobar.FoobarBuilder[Impl].class)} - * on the class (where Foobar is the name of the annotated class).
  • + * {@code @JsonDeserialize(builder=Foobar.FoobarBuilder[Impl].class)} on the + * class (where Foobar is the name of the annotated class). *
  • 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.
  • @@ -54,9 +64,9 @@ import lombok.experimental.SuperBuilder; *
  • For {@code @SuperBuilder}, make the builder implementation class * package-private.
  • *
- * This annotation does not change the behavior of the generated builder. - * A {@code @Jacksonized} {@code @SuperBuilder} remains fully compatible to - * regular {@code @SuperBuilder}s. + * This annotation does not 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) diff --git a/src/core/lombok/javac/handlers/HandleJacksonized.java b/src/core/lombok/javac/handlers/HandleJacksonized.java index 3ee0eec4..7b1cb63f 100644 --- a/src/core/lombok/javac/handlers/HandleJacksonized.java +++ b/src/core/lombok/javac/handlers/HandleJacksonized.java @@ -42,6 +42,7 @@ import lombok.core.AST.Kind; import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; import lombok.core.handlers.HandlerUtil; +import lombok.experimental.Accessors; import lombok.experimental.SuperBuilder; import lombok.extern.jackson.Jacksonized; import lombok.javac.JavacAnnotationHandler; @@ -73,8 +74,9 @@ public class HandleJacksonized extends JavacAnnotationHandler { 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."); + JavacNode accessorsAnnotationNode = findAnnotation(Accessors.class, annotatedNode); + if (builderAnnotationNode == null && superBuilderAnnotationNode == null && accessorsAnnotationNode == null) { + annotationNode.addWarning("@Jacksonized requires @Builder, @SuperBuilder, or @Accessors for it to mean anything."); return; } From 7ea95700c3dfe10edd630079423035453701e1c9 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Wed, 27 Mar 2024 11:24:14 +0100 Subject: [PATCH 03/22] [WIP] --- .../lombok/core/handlers/HandlerUtil.java | 19 +++++++- .../lombok/extern/jackson/Jacksonized.java | 3 +- .../javac/handlers/HandleJacksonized.java | 47 ++++++++++++++++++- .../after-delombok/JacksonizedAccessors.java | 18 +++++++ .../resource/before/JacksonizedAccessors.java | 10 ++++ 5 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 test/transform/resource/after-delombok/JacksonizedAccessors.java create mode 100644 test/transform/resource/before/JacksonizedAccessors.java diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index 07704aa8..e8b89aad 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -79,7 +79,7 @@ public class HandlerUtil { return 43; } - public static final List NONNULL_ANNOTATIONS, BASE_COPYABLE_ANNOTATIONS, COPY_TO_SETTER_ANNOTATIONS, COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS, JACKSON_COPY_TO_BUILDER_ANNOTATIONS; + public static final List 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", diff --git a/src/core/lombok/extern/jackson/Jacksonized.java b/src/core/lombok/extern/jackson/Jacksonized.java index bba654c3..4b7d7e54 100644 --- a/src/core/lombok/extern/jackson/Jacksonized.java +++ b/src/core/lombok/extern/jackson/Jacksonized.java @@ -38,9 +38,10 @@ import lombok.experimental.SuperBuilder; * {@code @}{@link Builder}, {@code @}{@link SuperBuilder}, and * {@code @}{@link Accessors}. *

- * 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.) *

* For {@code @}{@link Builder} and {@code @}{@link SuperBuilder}, it * automatically configures the generated builder class to be used by Jackson's diff --git a/src/core/lombok/javac/handlers/HandleJacksonized.java b/src/core/lombok/javac/handlers/HandleJacksonized.java index 7b1cb63f..b7e57012 100644 --- a/src/core/lombok/javac/handlers/HandleJacksonized.java +++ b/src/core/lombok/javac/handlers/HandleJacksonized.java @@ -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 { @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { @@ -79,7 +80,49 @@ public class HandleJacksonized extends JavacAnnotationHandler { 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 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 { // @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 builderAnnotation, JavacTreeMaker maker) { String builderClassName = builderAnnotation != null ? diff --git a/test/transform/resource/after-delombok/JacksonizedAccessors.java b/test/transform/resource/after-delombok/JacksonizedAccessors.java new file mode 100644 index 00000000..7ffa312a --- /dev/null +++ b/test/transform/resource/after-delombok/JacksonizedAccessors.java @@ -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; + } +} \ No newline at end of file diff --git a/test/transform/resource/before/JacksonizedAccessors.java b/test/transform/resource/before/JacksonizedAccessors.java new file mode 100644 index 00000000..f6df4b01 --- /dev/null +++ b/test/transform/resource/before/JacksonizedAccessors.java @@ -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; +} From 20ed4a4818348592e2f7428f899e16b431ddd5a7 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Mon, 24 Jun 2024 11:44:51 +0200 Subject: [PATCH 04/22] use COPY_TO_GETTER_ANNOTATIONS when generating getters --- .../lombok/core/handlers/HandlerUtil.java | 4 -- .../eclipse/handlers/EclipseHandlerUtil.java | 7 ++++ .../lombok/eclipse/handlers/HandleGetter.java | 31 +++++++------- .../lombok/javac/handlers/HandleGetter.java | 41 +++++++++++-------- .../javac/handlers/HandleJacksonized.java | 2 +- .../lombok/javac/handlers/HandleSetter.java | 29 +++++++------ .../javac/handlers/JavacHandlerUtil.java | 13 ++++-- .../after-delombok/JacksonizedAccessors.java | 4 +- .../resource/before/JacksonizedAccessors.java | 2 + 9 files changed, 78 insertions(+), 55 deletions(-) diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index defa746c..efc5b020 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -425,18 +425,14 @@ public class HandlerUtil { "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", diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index ef7a7c3a..33601e83 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -817,6 +817,13 @@ public class EclipseHandlerUtil { return result.toArray(EMPTY_ANNOTATIONS_ARRAY); } + /** + * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. + */ + public static Annotation[] findCopyableToGetterAnnotations(EclipseNode node) { + return findAnnotationsInList(node, COPY_TO_GETTER_ANNOTATIONS); + } + /** * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. */ diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java index 5ed2c2d9..1426d40a 100644 --- a/src/core/lombok/eclipse/handlers/HandleGetter.java +++ b/src/core/lombok/eclipse/handlers/HandleGetter.java @@ -21,7 +21,7 @@ */ package lombok.eclipse.handlers; -import static lombok.core.handlers.HandlerUtil.*; +import static lombok.core.handlers.HandlerUtil.handleFlagUsage; import static lombok.eclipse.Eclipse.*; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; @@ -32,19 +32,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import lombok.AccessLevel; -import lombok.ConfigurationKeys; -import lombok.experimental.Accessors; -import lombok.experimental.Delegate; -import lombok.spi.Provides; -import lombok.Getter; -import lombok.core.AST.Kind; -import lombok.core.AnnotationValues; -import lombok.core.configuration.CheckerFrameworkVersion; -import lombok.eclipse.EclipseAnnotationHandler; -import lombok.eclipse.EclipseNode; -import lombok.eclipse.agent.PatchDelegate; - import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; @@ -76,6 +63,21 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import lombok.AccessLevel; +import lombok.ConfigurationKeys; +import lombok.Getter; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.core.configuration.CheckerFrameworkVersion; +import lombok.core.handlers.HandlerUtil.FieldAccess; +import lombok.eclipse.EclipseAnnotationHandler; +import lombok.eclipse.EclipseNode; +import lombok.eclipse.agent.PatchDelegate; +import lombok.eclipse.handlers.EclipseHandlerUtil.CopyJavadoc; +import lombok.experimental.Accessors; +import lombok.experimental.Delegate; +import lombok.spi.Provides; + /** * Handles the {@code lombok.Getter} annotation for eclipse. */ @@ -279,6 +281,7 @@ public class HandleGetter extends EclipseAnnotationHandler { method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), findCopyableAnnotations(fieldNode), + findCopyableToGetterAnnotations(fieldNode), findDelegatesAndMarkAsHandled(fieldNode), checkerFramework, deprecated); diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index dac524dd..acc2bba4 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -21,32 +21,18 @@ */ package lombok.javac.handlers; -import static lombok.core.handlers.HandlerUtil.*; +import static lombok.core.handlers.HandlerUtil.handleFlagUsage; import static lombok.javac.Javac.*; import static lombok.javac.JavacAugments.JCTree_keepPosition; -import static lombok.javac.JavacTreeMaker.TypeTag.*; +import static lombok.javac.JavacTreeMaker.TypeTag.typeTag; import static lombok.javac.handlers.JavacHandlerUtil.*; +import static lombok.javac.handlers.JavacHandlerUtil.isFieldDeprecated; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import lombok.AccessLevel; -import lombok.ConfigurationKeys; -import lombok.experimental.Accessors; -import lombok.experimental.Delegate; -import lombok.Getter; -import lombok.core.AST.Kind; -import lombok.core.AnnotationValues; -import lombok.core.configuration.CheckerFrameworkVersion; -import lombok.delombok.LombokOptionsFactory; -import lombok.javac.JavacAnnotationHandler; -import lombok.javac.JavacNode; -import lombok.javac.JavacTreeMaker; -import lombok.javac.JavacTreeMaker.TypeTag; -import lombok.spi.Provides; - import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBinary; @@ -66,6 +52,23 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; +import lombok.AccessLevel; +import lombok.ConfigurationKeys; +import lombok.Getter; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.core.configuration.CheckerFrameworkVersion; +import lombok.core.handlers.HandlerUtil.FieldAccess; +import lombok.delombok.LombokOptionsFactory; +import lombok.experimental.Accessors; +import lombok.experimental.Delegate; +import lombok.javac.JavacAnnotationHandler; +import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; +import lombok.javac.JavacTreeMaker.TypeTag; +import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc; +import lombok.spi.Provides; + /** * Handles the {@code lombok.Getter} annotation for javac. */ @@ -246,8 +249,10 @@ public class HandleGetter extends JavacAnnotationHandler { JCExpression annotationMethodDefaultValue = null; List copyableAnnotations = findCopyableAnnotations(field); + List copyableToGetterAnnotations = copyAnnotations(findCopyableToGetterAnnotations(field)); + List delegates = findDelegatesAndRemoveFromField(field); - List annsOnMethod = copyAnnotations(onMethod).appendList(copyableAnnotations); + List annsOnMethod = copyAnnotations(onMethod).appendList(copyableAnnotations).appendList(copyableToGetterAnnotations); if (field.isFinal()) { if (getCheckerFrameworkVersion(field).generatePure()) annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genTypeRef(field, CheckerFrameworkVersion.NAME__PURE), List.nil())); } else { diff --git a/src/core/lombok/javac/handlers/HandleJacksonized.java b/src/core/lombok/javac/handlers/HandleJacksonized.java index b7e57012..f956d782 100644 --- a/src/core/lombok/javac/handlers/HandleJacksonized.java +++ b/src/core/lombok/javac/handlers/HandleJacksonized.java @@ -28,12 +28,12 @@ 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; import com.sun.tools.javac.tree.JCTree.JCTypeApply; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 04fa8b77..055f1e0f 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -21,24 +21,13 @@ */ package lombok.javac.handlers; +import static lombok.core.handlers.HandlerUtil.handleFlagUsage; import static lombok.javac.Javac.*; -import static lombok.core.handlers.HandlerUtil.*; import static lombok.javac.handlers.JavacHandlerUtil.*; +import static lombok.javac.handlers.JavacHandlerUtil.isFieldDeprecated; import java.util.Collection; -import lombok.AccessLevel; -import lombok.ConfigurationKeys; -import lombok.Setter; -import lombok.core.AST.Kind; -import lombok.experimental.Accessors; -import lombok.core.AnnotationValues; -import lombok.javac.Javac; -import lombok.javac.JavacAnnotationHandler; -import lombok.javac.JavacNode; -import lombok.javac.JavacTreeMaker; -import lombok.spi.Provides; - import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssign; @@ -53,6 +42,20 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; +import lombok.AccessLevel; +import lombok.ConfigurationKeys; +import lombok.Setter; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.core.handlers.HandlerUtil.FieldAccess; +import lombok.experimental.Accessors; +import lombok.javac.Javac; +import lombok.javac.JavacAnnotationHandler; +import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; +import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc; +import lombok.spi.Provides; + /** * Handles the {@code lombok.Setter} annotation for javac. */ diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 8b563824..1a411ddd 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -24,8 +24,7 @@ package lombok.javac.handlers; import static com.sun.tools.javac.code.Flags.GENERATEDCONSTR; import static lombok.core.handlers.HandlerUtil.*; import static lombok.javac.Javac.*; -import static lombok.javac.JavacAugments.JCTree_generatedNode; -import static lombok.javac.JavacAugments.JCTree_keepPosition; +import static lombok.javac.JavacAugments.*; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; @@ -100,6 +99,7 @@ import lombok.core.configuration.NullCheckExceptionType; import lombok.core.configuration.TypeName; import lombok.core.handlers.HandlerUtil; import lombok.core.handlers.HandlerUtil.FieldAccess; +import lombok.core.handlers.HandlerUtil.JavadocTag; import lombok.delombok.LombokOptionsFactory; import lombok.experimental.Accessors; import lombok.experimental.Tolerate; @@ -1734,6 +1734,13 @@ public class JavacHandlerUtil { return copyAnnotations(result.toList()); } + /** + * Searches the given field node for annotations that are specifically intentioned to be copied to the getter. + */ + public static List findCopyableToGetterAnnotations(JavacNode node) { + return findAnnotationsInList(node, COPY_TO_GETTER_ANNOTATIONS); + } + /** * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. */ @@ -1769,7 +1776,7 @@ public class JavacHandlerUtil { if (annoName == null) return List.nil(); if (!annoName.isEmpty()) { - for (String bn : annotationsToFind) if (typeMatches(bn, node, annoName)) return List.of(anno); + for (String bn : annotationsToFind) if (typeMatches(bn, node, annoName)) return copyAnnotations(List.of(anno)); } ListBuffer result = new ListBuffer(); diff --git a/test/transform/resource/after-delombok/JacksonizedAccessors.java b/test/transform/resource/after-delombok/JacksonizedAccessors.java index 7ffa312a..7dc1d974 100644 --- a/test/transform/resource/after-delombok/JacksonizedAccessors.java +++ b/test/transform/resource/after-delombok/JacksonizedAccessors.java @@ -1,16 +1,16 @@ public class JacksonizedAccessors { @com.fasterxml.jackson.annotation.JsonProperty("intValue") private int intValue; - @java.lang.SuppressWarnings("all") @com.fasterxml.jackson.annotation.JsonProperty("intValue") + @java.lang.SuppressWarnings("all") public int intValue() { return this.intValue; } /** * @return {@code this}. */ - @java.lang.SuppressWarnings("all") @com.fasterxml.jackson.annotation.JsonProperty("intValue") + @java.lang.SuppressWarnings("all") public JacksonizedAccessors intValue(final int intValue) { this.intValue = intValue; return this; diff --git a/test/transform/resource/before/JacksonizedAccessors.java b/test/transform/resource/before/JacksonizedAccessors.java index f6df4b01..3242890e 100644 --- a/test/transform/resource/before/JacksonizedAccessors.java +++ b/test/transform/resource/before/JacksonizedAccessors.java @@ -1,10 +1,12 @@ import lombok.Getter; +import lombok.Setter; import lombok.experimental.Accessors; import lombok.extern.jackson.Jacksonized; @Jacksonized @Accessors(fluent = true) @Getter +@Setter public class JacksonizedAccessors { private int intValue; } From 26cbd8b34750800fb2cff89050f399a9536567d6 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Fri, 1 Nov 2024 15:06:53 +0100 Subject: [PATCH 05/22] add @Generated to expected test results --- .../after-delombok/JacksonizedAccessors.java | 2 + .../JacksonizedBuilderSingular.java | 23 ++++++++++ .../after-ecj/JacksonizedBuilderSingular.java | 46 +++++++++---------- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/test/transform/resource/after-delombok/JacksonizedAccessors.java b/test/transform/resource/after-delombok/JacksonizedAccessors.java index 7dc1d974..4e16a167 100644 --- a/test/transform/resource/after-delombok/JacksonizedAccessors.java +++ b/test/transform/resource/after-delombok/JacksonizedAccessors.java @@ -3,6 +3,7 @@ public class JacksonizedAccessors { private int intValue; @com.fasterxml.jackson.annotation.JsonProperty("intValue") @java.lang.SuppressWarnings("all") + @lombok.Generated public int intValue() { return this.intValue; } @@ -11,6 +12,7 @@ public class JacksonizedAccessors { */ @com.fasterxml.jackson.annotation.JsonProperty("intValue") @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedAccessors intValue(final int intValue) { this.intValue = intValue; return this; diff --git a/test/transform/resource/after-delombok/JacksonizedBuilderSingular.java b/test/transform/resource/after-delombok/JacksonizedBuilderSingular.java index 279210a8..fffbcf61 100644 --- a/test/transform/resource/after-delombok/JacksonizedBuilderSingular.java +++ b/test/transform/resource/after-delombok/JacksonizedBuilderSingular.java @@ -16,6 +16,7 @@ public class JacksonizedBuilderSingular { @JsonProperty("guava_v_a_l_u_e_s") private ImmutableList guavaValues; @java.lang.SuppressWarnings("all") + @lombok.Generated JacksonizedBuilderSingular(final Map any, final List values, final ImmutableMap guavaAny, final ImmutableList guavaValues) { this.any = any; this.values = values; @@ -23,23 +24,31 @@ public class JacksonizedBuilderSingular { this.guavaValues = guavaValues; } @java.lang.SuppressWarnings("all") + @lombok.Generated @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "", buildMethodName = "build") public static class JacksonizedBuilderSingularBuilder { @java.lang.SuppressWarnings("all") + @lombok.Generated private java.util.ArrayList any$key; @java.lang.SuppressWarnings("all") + @lombok.Generated private java.util.ArrayList any$value; @java.lang.SuppressWarnings("all") + @lombok.Generated private java.util.ArrayList values; @java.lang.SuppressWarnings("all") + @lombok.Generated private com.google.common.collect.ImmutableMap.Builder guavaAny; @java.lang.SuppressWarnings("all") + @lombok.Generated private com.google.common.collect.ImmutableList.Builder guavaValues; @java.lang.SuppressWarnings("all") + @lombok.Generated JacksonizedBuilderSingularBuilder() { } @JsonAnySetter @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder any(final String anyKey, final Object anyValue) { if (this.any$key == null) { this.any$key = new java.util.ArrayList(); @@ -50,6 +59,7 @@ public class JacksonizedBuilderSingular { return this; } @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder any(final java.util.Map any) { if (any == null) { throw new java.lang.NullPointerException("any cannot be null"); @@ -65,6 +75,7 @@ public class JacksonizedBuilderSingular { return this; } @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearAny() { if (this.any$key != null) { this.any$key.clear(); @@ -73,6 +84,7 @@ public class JacksonizedBuilderSingular { return this; } @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder value(final String value) { if (this.values == null) this.values = new java.util.ArrayList(); this.values.add(value); @@ -80,6 +92,7 @@ public class JacksonizedBuilderSingular { } @JsonProperty("v_a_l_u_e_s") @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder values(final java.util.Collection values) { if (values == null) { throw new java.lang.NullPointerException("values cannot be null"); @@ -89,18 +102,21 @@ public class JacksonizedBuilderSingular { return this; } @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearValues() { if (this.values != null) this.values.clear(); return this; } @JsonAnySetter @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder 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") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaAny(final java.util.Map guavaAny) { if (guavaAny == null) { throw new java.lang.NullPointerException("guavaAny cannot be null"); @@ -110,11 +126,13 @@ public class JacksonizedBuilderSingular { return this; } @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearGuavaAny() { this.guavaAny = null; return this; } @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaValue(final String guavaValue) { if (this.guavaValues == null) this.guavaValues = com.google.common.collect.ImmutableList.builder(); this.guavaValues.add(guavaValue); @@ -122,6 +140,7 @@ public class JacksonizedBuilderSingular { } @JsonProperty("guava_v_a_l_u_e_s") @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaValues(final java.lang.Iterable guavaValues) { if (guavaValues == null) { throw new java.lang.NullPointerException("guavaValues cannot be null"); @@ -131,11 +150,13 @@ public class JacksonizedBuilderSingular { return this; } @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearGuavaValues() { this.guavaValues = null; return this; } @java.lang.SuppressWarnings("all") + @lombok.Generated public JacksonizedBuilderSingular build() { java.util.Map any; switch (this.any$key == null ? 0 : this.any$key.size()) { @@ -167,11 +188,13 @@ public class JacksonizedBuilderSingular { } @java.lang.Override @java.lang.SuppressWarnings("all") + @lombok.Generated public java.lang.String toString() { return "JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder(any$key=" + this.any$key + ", any$value=" + this.any$value + ", values=" + this.values + ", guavaAny=" + this.guavaAny + ", guavaValues=" + this.guavaValues + ")"; } } @java.lang.SuppressWarnings("all") + @lombok.Generated public static JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder builder() { return new JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder(); } diff --git a/test/transform/resource/after-ecj/JacksonizedBuilderSingular.java b/test/transform/resource/after-ecj/JacksonizedBuilderSingular.java index 09cc706f..29a28076 100644 --- a/test/transform/resource/after-ecj/JacksonizedBuilderSingular.java +++ b/test/transform/resource/after-ecj/JacksonizedBuilderSingular.java @@ -8,16 +8,16 @@ import lombok.Builder; import lombok.Singular; import lombok.extern.jackson.Jacksonized; public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder.class) class JacksonizedBuilderSingular { - public static @java.lang.SuppressWarnings("all") @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "",buildMethodName = "build") class JacksonizedBuilderSingularBuilder { - private @java.lang.SuppressWarnings("all") java.util.ArrayList any$key; - private @java.lang.SuppressWarnings("all") java.util.ArrayList any$value; - private @java.lang.SuppressWarnings("all") java.util.ArrayList values; - private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableMap.Builder guavaAny; - private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableList.Builder guavaValues; - @java.lang.SuppressWarnings("all") JacksonizedBuilderSingularBuilder() { + public static @java.lang.SuppressWarnings("all") @lombok.Generated @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "",buildMethodName = "build") class JacksonizedBuilderSingularBuilder { + private @java.lang.SuppressWarnings("all") @lombok.Generated java.util.ArrayList any$key; + private @java.lang.SuppressWarnings("all") @lombok.Generated java.util.ArrayList any$value; + private @java.lang.SuppressWarnings("all") @lombok.Generated java.util.ArrayList values; + private @java.lang.SuppressWarnings("all") @lombok.Generated com.google.common.collect.ImmutableMap.Builder guavaAny; + private @java.lang.SuppressWarnings("all") @lombok.Generated com.google.common.collect.ImmutableList.Builder guavaValues; + @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingularBuilder() { super(); } - public @JsonAnySetter @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder any(final String anyKey, final Object anyValue) { + public @JsonAnySetter @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder any(final String anyKey, final Object anyValue) { if ((this.any$key == null)) { this.any$key = new java.util.ArrayList(); @@ -27,7 +27,7 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese this.any$value.add(anyValue); return this; } - public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder any(final java.util.Map any) { + public @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder any(final java.util.Map any) { if ((any == null)) { throw new java.lang.NullPointerException("any cannot be null"); @@ -44,7 +44,7 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese } return this; } - public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearAny() { + public @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearAny() { if ((this.any$key != null)) { this.any$key.clear(); @@ -52,13 +52,13 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese } return this; } - public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder value(final String value) { + public @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder value(final String value) { if ((this.values == null)) this.values = new java.util.ArrayList(); this.values.add(value); return this; } - public @JsonProperty("v_a_l_u_e_s") @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder values(final java.util.Collection values) { + public @JsonProperty("v_a_l_u_e_s") @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder values(final java.util.Collection values) { if ((values == null)) { throw new java.lang.NullPointerException("values cannot be null"); @@ -68,18 +68,18 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese this.values.addAll(values); return this; } - public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearValues() { + public @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearValues() { if ((this.values != null)) this.values.clear(); return this; } - public @JsonAnySetter @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaAny(final String key, final Object value) { + public @JsonAnySetter @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder 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") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaAny(final java.util.Map guavaAny) { + public @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaAny(final java.util.Map guavaAny) { if ((guavaAny == null)) { throw new java.lang.NullPointerException("guavaAny cannot be null"); @@ -89,17 +89,17 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese this.guavaAny.putAll(guavaAny); return this; } - public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearGuavaAny() { + public @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearGuavaAny() { this.guavaAny = null; return this; } - public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaValue(final String guavaValue) { + public @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder 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") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaValues(final java.lang.Iterable guavaValues) { + public @JsonProperty("guava_v_a_l_u_e_s") @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder guavaValues(final java.lang.Iterable guavaValues) { if ((guavaValues == null)) { throw new java.lang.NullPointerException("guavaValues cannot be null"); @@ -109,11 +109,11 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese this.guavaValues.addAll(guavaValues); return this; } - public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearGuavaValues() { + public @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder clearGuavaValues() { this.guavaValues = null; return this; } - public @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular build() { + public @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular build() { java.util.Map any; switch (((this.any$key == null) ? 0 : this.any$key.size())) { case 0 : @@ -143,7 +143,7 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese com.google.common.collect.ImmutableList guavaValues = ((this.guavaValues == null) ? com.google.common.collect.ImmutableList.of() : this.guavaValues.build()); return new JacksonizedBuilderSingular(any, values, guavaAny, guavaValues); } - public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + public @java.lang.Override @java.lang.SuppressWarnings("all") @lombok.Generated java.lang.String toString() { return (((((((((("JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder(any$key=" + this.any$key) + ", any$value=") + this.any$value) + ", values=") + this.values) + ", guavaAny=") + this.guavaAny) + ", guavaValues=") + this.guavaValues) + ")"); } } @@ -151,14 +151,14 @@ public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDese private @JsonProperty("v_a_l_u_e_s") @Singular List values; private @JsonAnySetter @Singular("guavaAny") ImmutableMap guavaAny; private @JsonProperty("guava_v_a_l_u_e_s") @Singular ImmutableList guavaValues; - @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular(final Map any, final List values, final ImmutableMap guavaAny, final ImmutableList guavaValues) { + @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular(final Map any, final List values, final ImmutableMap guavaAny, final ImmutableList guavaValues) { super(); this.any = any; this.values = values; this.guavaAny = guavaAny; this.guavaValues = guavaValues; } - public static @java.lang.SuppressWarnings("all") JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder builder() { + public static @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder builder() { return new JacksonizedBuilderSingular.JacksonizedBuilderSingularBuilder(); } } \ No newline at end of file From b4ee8aea7ba1ff71506b836f95fd68ec527764c3 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Fri, 1 Nov 2024 23:09:48 +0100 Subject: [PATCH 06/22] document rationale behind Jackson annotation copying --- .../lombok/core/handlers/HandlerUtil.java | 25 ++++++++++++++++--- .../eclipse/handlers/EclipseHandlerUtil.java | 6 ++--- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index 73c6ece2..ae0ba9ca 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -79,7 +79,7 @@ public class HandlerUtil { return 43; } - public static final List NONNULL_ANNOTATIONS, BASE_COPYABLE_ANNOTATIONS, COPY_TO_GETTER_ANNOTATIONS, COPY_TO_SETTER_ANNOTATIONS, COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS, JACKSON_COPY_TO_BUILDER_ANNOTATIONS; + public static final List NONNULL_ANNOTATIONS, BASE_COPYABLE_ANNOTATIONS, JACKSON_COPY_TO_GETTER_ANNOTATIONS, JACKSON_COPY_TO_SETTER_ANNOTATIONS, JACKSON_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; @@ -424,7 +424,22 @@ public class HandlerUtil { "org.checkerframework.common.value.qual.UnknownVal", "org.checkerframework.framework.qual.PurityUnqualified", })); - COPY_TO_GETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { + + // The following two lists contain all annotations that (in some cases) should be copied from the field to the getter or + // setter. Right now, it only contains Jackson annotations. + // Jackson's annotation processing roughly works as follows: To calculate the annotation for a JSON property, Jackson + // builds a triple of the Java field and the corresponding setter and getter methods. It is sufficient for an annotation + // to be present on one of those to become effective. E.g., a @JsonIgnore on a setter completely ignores the JSON property, + // not only during deserialization, but also when serializing. Therefore, in most cases it is _not_ necessary to copy the + // annotations. + // However, there are two exceptions: + // 1. When using a builder to deserialize, Jackson does _not_ consider the setter methods of the builder, i.e. annotations + // like @JsonIgnore on the field will not be respected. Thus, those annotations should be copied to the builder's setters. + // 2. If the getter/setter methods to not follow the exact beanspec naming strategy, Jackson will not correctly detect the + // field-getter-setter triple, and annotations may not work as intended. + // However, we cannot know what the user's intention is. Thus, lombok should only fix those cases where it is obvious + // what the user wants. That is the case for a @Jacksonized @Accessors(fluent=true). + JACKSON_COPY_TO_GETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { "com.fasterxml.jackson.annotation.JsonFormat", "com.fasterxml.jackson.annotation.JsonIgnore", "com.fasterxml.jackson.annotation.JsonIgnoreProperties", @@ -437,7 +452,7 @@ public class HandlerUtil { "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty", "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText", })); - COPY_TO_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { + JACKSON_COPY_TO_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { "com.fasterxml.jackson.annotation.JacksonInject", "com.fasterxml.jackson.annotation.JsonAlias", "com.fasterxml.jackson.annotation.JsonFormat", @@ -454,9 +469,11 @@ public class HandlerUtil { "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty", "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText", })); - COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { + JACKSON_COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { "com.fasterxml.jackson.annotation.JsonAnySetter", })); + // In order to let Jackson recognize certain configuration annotations when deserializing using a builder, those must + // be copied to the generated builder class. JACKSON_COPY_TO_BUILDER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { "com.fasterxml.jackson.annotation.JsonAutoDetect", "com.fasterxml.jackson.annotation.JsonFormat", diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index c60e65a2..f357a6c4 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -823,21 +823,21 @@ public class EclipseHandlerUtil { * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. */ public static Annotation[] findCopyableToGetterAnnotations(EclipseNode node) { - return findAnnotationsInList(node, COPY_TO_GETTER_ANNOTATIONS); + return findAnnotationsInList(node, JACKSON_COPY_TO_GETTER_ANNOTATIONS); } /** * 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); + return findAnnotationsInList(node, JACKSON_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); + return findAnnotationsInList(node, JACKSON_COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS); } /** From 4fbf2480547aca7aed714f9e2a5f4961ab812d6d Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Fri, 1 Nov 2024 23:18:18 +0100 Subject: [PATCH 07/22] document rationale behind Jackson annotation copying --- src/core/lombok/core/handlers/HandlerUtil.java | 14 ++++++++------ .../lombok/javac/handlers/JavacHandlerUtil.java | 6 +++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index ae0ba9ca..9c2fbe83 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -431,14 +431,16 @@ public class HandlerUtil { // builds a triple of the Java field and the corresponding setter and getter methods. It is sufficient for an annotation // to be present on one of those to become effective. E.g., a @JsonIgnore on a setter completely ignores the JSON property, // not only during deserialization, but also when serializing. Therefore, in most cases it is _not_ necessary to copy the - // annotations. - // However, there are two exceptions: - // 1. When using a builder to deserialize, Jackson does _not_ consider the setter methods of the builder, i.e. annotations - // like @JsonIgnore on the field will not be respected. Thus, those annotations should be copied to the builder's setters. + // annotations. It may even harm, as Jackson considers some annotations inheritable, and this "virtual inheritance" only + // affects annotations on setter/getter, but not on private fields. + // However, there are two exceptions where we need it: + // 1. When using a builder to deserialize, Jackson does _not_ "propagate" the annotations to the setter methods of the + // builder, i.e. annotations like @JsonIgnore on the field will not be respected when deserializing with a builder. + // Thus, those annotations should be copied to the builder's setters. // 2. If the getter/setter methods to not follow the exact beanspec naming strategy, Jackson will not correctly detect the // field-getter-setter triple, and annotations may not work as intended. - // However, we cannot know what the user's intention is. Thus, lombok should only fix those cases where it is obvious - // what the user wants. That is the case for a @Jacksonized @Accessors(fluent=true). + // However, we cannot always know what the user's intention is. Thus, lombok should only fix those cases where it is + // obvious what the user wants. That is the case for a @Jacksonized @Accessors(fluent=true). JACKSON_COPY_TO_GETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { "com.fasterxml.jackson.annotation.JsonFormat", "com.fasterxml.jackson.annotation.JsonIgnore", diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index a4c04524..c503c477 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1753,21 +1753,21 @@ public class JavacHandlerUtil { * Searches the given field node for annotations that are specifically intentioned to be copied to the getter. */ public static List findCopyableToGetterAnnotations(JavacNode node) { - return findAnnotationsInList(node, COPY_TO_GETTER_ANNOTATIONS); + return findAnnotationsInList(node, JACKSON_COPY_TO_GETTER_ANNOTATIONS); } /** * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. */ public static List findCopyableToSetterAnnotations(JavacNode node) { - return findAnnotationsInList(node, COPY_TO_SETTER_ANNOTATIONS); + return findAnnotationsInList(node, JACKSON_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 findCopyableToBuilderSingularSetterAnnotations(JavacNode node) { - return findAnnotationsInList(node, COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS); + return findAnnotationsInList(node, JACKSON_COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS); } /** From ef4afa4957555dc4aed93d6a5017e82b4acc53aa Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Sat, 2 Nov 2024 00:09:58 +0100 Subject: [PATCH 08/22] add config key for copy-to-setter --- src/core/lombok/ConfigurationKeys.java | 8 +++++++ .../lombok/javac/handlers/HandleBuilder.java | 4 ++-- .../lombok/javac/handlers/HandleSetter.java | 22 +++++++++++-------- .../javac/handlers/HandleSuperBuilder.java | 4 ++-- .../javac/handlers/JavacHandlerUtil.java | 6 ++++- .../javac/handlers/JavacSingularsRecipes.java | 2 +- 6 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index b19dccfc..b54e4d30 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -743,4 +743,12 @@ public class ConfigurationKeys { * If set, any usage of {@code @StandardException} results in a warning / error. */ public static final ConfigurationKey STANDARD_EXCEPTION_FLAG_USAGE = new ConfigurationKey("lombok.standardException.flagUsage", "Emit a warning or error if @StandardException is used.") {}; + + /** + * lombok configuration: {@code lombok.copyJacksonAnnotationsToSetters} = {@code true} | {@code false}. + * + * If true, copy certain Jackson annotations from a field to its corresponding getter. This was the behavior from lombok 1.18.16 to 1.18.34. + * However, it turned out to be harmful in certain situations. Thus, the default is now false. + */ + public static final ConfigurationKey COPY_JACKSON_ANNOTATIONS_TO_SETTERS = new ConfigurationKey("lombok.copyJacksonAnnotationsToSetters", "Copy these annotations to getters, setters, with methods, builder-setters, etc.") {}; } diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index d814c05a..4e67ea7e 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -930,8 +930,8 @@ public class HandleBuilder extends JavacAnnotationHandler { JavacTreeMaker maker = fieldNode.getTreeMaker(); - List methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(bfd.originalFieldNode); - JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(job.accessInners), deprecate, fieldNode, maker, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, job.sourceNode, methodAnns, bfd.annotations); + List methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(bfd.originalFieldNode, true); + JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(job.accessInners), deprecate, fieldNode, maker, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, job.sourceNode, methodAnns, bfd.annotations, false); recursiveSetGeneratedBy(newMethod, job.sourceNode); if (job.sourceNode.up().getKind() == Kind.METHOD) { copyJavadocFromParam(bfd.originalFieldNode.up(), newMethod, bfd.name.toString()); diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 826400eb..746277ab 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -198,11 +198,15 @@ public class HandleSetter extends JavacAnnotationHandler { AnnotationValues accessors = JavacHandlerUtil.getAccessorsForField(field); String setterName = toSetterName(field, accessors); boolean returnThis = shouldReturnThis(field, accessors); - JCMethodDecl setter = createSetter(access, false, field, treeMaker, setterName, null, null, returnThis, source, onMethod, onParam); + boolean fluent = accessors.isExplicit("fluent"); + Boolean fluentConfig = field.getAst().readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT); + if (fluentConfig != null && fluentConfig) fluent = fluentConfig; + + JCMethodDecl setter = createSetter(access, false, field, treeMaker, setterName, null, null, returnThis, source, onMethod, onParam, fluent); return setter; } - public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List onMethod, List onParam) { + public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List onMethod, List onParam, boolean forceAnnotationCopying) { JCExpression returnType = null; JCReturn returnStatement = null; if (shouldReturnThis) { @@ -211,10 +215,10 @@ public class HandleSetter extends JavacAnnotationHandler { returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this"))); } - return createSetter(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam); + return createSetter(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam, forceAnnotationCopying); } - public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List onMethod, List onParam, JCVariableDecl recv) { + public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List onMethod, List onParam, JCVariableDecl recv, boolean forceAnnotationCopying) { JCExpression returnType = null; JCReturn returnStatement = null; if (shouldReturnThis) { @@ -223,15 +227,15 @@ public class HandleSetter extends JavacAnnotationHandler { returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this"))); } - JCMethodDecl d = createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam, recv); + JCMethodDecl d = createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam, recv, forceAnnotationCopying); return d; } - public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List onMethod, List onParam) { - return createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, methodType, returnStatement, source, onMethod, onParam, null); + public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List onMethod, List onParam, boolean forceAnnotationCopying) { + return createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, methodType, returnStatement, source, onMethod, onParam, null, forceAnnotationCopying); } - public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List onMethod, List onParam, JCVariableDecl recv) { + public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List onMethod, List onParam, JCVariableDecl recv, boolean forceAnnotationCopying) { if (setterName == null) return null; JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); @@ -277,7 +281,7 @@ public class HandleSetter extends JavacAnnotationHandler { List throwsClauses = List.nil(); JCExpression annotationMethodDefaultValue = null; - List annsOnMethod = mergeAnnotations(copyAnnotations(onMethod), findCopyableToSetterAnnotations(field)); + List annsOnMethod = mergeAnnotations(copyAnnotations(onMethod), findCopyableToSetterAnnotations(field, forceAnnotationCopying)); if (isFieldDeprecated(field) || deprecate) { annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.nil())); } diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index c468fb77..3669bf2e 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -965,10 +965,10 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { JavacTreeMaker maker = fieldNode.getTreeMaker(); - List methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode); + List methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode, true); returnType = addCheckerFrameworkReturnsReceiver(returnType, maker, job.builderType, job.checkerFramework); - JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam); + JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam, false); if (job.sourceNode.up().getKind() == Kind.METHOD) { copyJavadocFromParam(originalFieldNode.up(), newMethod, paramName.toString()); } else { diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index c503c477..529bafb2 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1759,7 +1759,11 @@ public class JavacHandlerUtil { /** * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. */ - public static List findCopyableToSetterAnnotations(JavacNode node) { + public static List findCopyableToSetterAnnotations(JavacNode node, boolean forceCopy) { + if (!forceCopy) { + Boolean copyAnnotations = node.getAst().readConfiguration(ConfigurationKeys.COPY_JACKSON_ANNOTATIONS_TO_SETTERS); + if (copyAnnotations == null || !copyAnnotations) return List.nil(); + } return findAnnotationsInList(node, JACKSON_COPY_TO_SETTER_ANNOTATIONS); } diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java index 4954a610..512bb3c5 100644 --- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java +++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java @@ -362,7 +362,7 @@ public class JavacSingularsRecipes { statements.prepend(JavacHandlerUtil.generateNullCheck(maker, null, data.getPluralName(), builderType, "%s cannot be null")); } - List methodAnnotations = copyAnnotations(findCopyableToSetterAnnotations(data.annotation.up())); + List methodAnnotations = copyAnnotations(findCopyableToSetterAnnotations(data.annotation.up(), true)); finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param), methodAnnotations, access, ignoreNullCollections); } From 70dd3f09404eaa3addcf029b9cbd273e928ebe25 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Thu, 27 Mar 2025 14:06:27 +0100 Subject: [PATCH 09/22] ecj: Jacksonized for accessors [WIP] --- src/core/lombok/ConfigurationKeys.java | 2 +- .../eclipse/handlers/EclipseHandlerUtil.java | 8 ++- .../eclipse/handlers/HandleBuilder.java | 2 +- .../eclipse/handlers/HandleJacksonized.java | 52 ++++++++++++++++++- .../lombok/eclipse/handlers/HandleSetter.java | 2 +- .../eclipse/handlers/HandleSuperBuilder.java | 2 +- .../singulars/EclipseGuavaSingularizer.java | 2 +- .../EclipseJavaUtilListSetSingularizer.java | 2 +- .../EclipseJavaUtilMapSingularizer.java | 2 +- .../lombok/extern/jackson/Jacksonized.java | 2 - .../javac/handlers/HandleJacksonized.java | 2 +- .../javac/handlers/HandleSuperBuilder.java | 4 +- .../after-ecj/JacksonizedAccessors.java | 16 ++++++ .../resource/before/JacksonizedAccessors.java | 15 ++---- 14 files changed, 88 insertions(+), 25 deletions(-) create mode 100644 test/transform/resource/after-ecj/JacksonizedAccessors.java diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index b54e4d30..18d7cb9a 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -747,7 +747,7 @@ public class ConfigurationKeys { /** * lombok configuration: {@code lombok.copyJacksonAnnotationsToSetters} = {@code true} | {@code false}. * - * If true, copy certain Jackson annotations from a field to its corresponding getter. This was the behavior from lombok 1.18.16 to 1.18.34. + * If true, copy certain Jackson annotations from a field to its corresponding getter. This was the behavior from lombok 1.18.16 to 1.18.36. * However, it turned out to be harmful in certain situations. Thus, the default is now false. */ public static final ConfigurationKey COPY_JACKSON_ANNOTATIONS_TO_SETTERS = new ConfigurationKey("lombok.copyJacksonAnnotationsToSetters", "Copy these annotations to getters, setters, with methods, builder-setters, etc.") {}; diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index f357a6c4..3a18d049 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -828,8 +828,14 @@ public class EclipseHandlerUtil { /** * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. + * + * @param forceCopy If true, always copy the annotations regardless of the lombok configuration. */ - public static Annotation[] findCopyableToSetterAnnotations(EclipseNode node) { + public static Annotation[] findCopyableToSetterAnnotations(EclipseNode node, boolean forceCopy) { + if (!forceCopy) { + Boolean copyAnnotations = node.getAst().readConfiguration(ConfigurationKeys.COPY_JACKSON_ANNOTATIONS_TO_SETTERS); + if (copyAnnotations == null || !copyAnnotations) return EMPTY_ANNOTATIONS_ARRAY; + } return findAnnotationsInList(node, JACKSON_COPY_TO_SETTER_ANNOTATIONS); } diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index a63d3b36..a22eb49b 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -1047,7 +1047,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { } List methodAnnsList = Collections.emptyList(); - Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(bfd.originalFieldNode); + Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(bfd.originalFieldNode, true); if (methodAnns != null && methodAnns.length > 0) methodAnnsList = Arrays.asList(methodAnns); ASTNode source = job.sourceNode.get(); MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, toEclipseModifier(job.accessInners), diff --git a/src/core/lombok/eclipse/handlers/HandleJacksonized.java b/src/core/lombok/eclipse/handlers/HandleJacksonized.java index 466cc338..abb50fe0 100644 --- a/src/core/lombok/eclipse/handlers/HandleJacksonized.java +++ b/src/core/lombok/eclipse/handlers/HandleJacksonized.java @@ -31,6 +31,7 @@ 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.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.StringLiteral; @@ -47,6 +48,7 @@ import lombok.core.handlers.HandlerUtil; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; +import lombok.experimental.Accessors; import lombok.experimental.SuperBuilder; import lombok.extern.jackson.Jacksonized; import lombok.spi.Provides; @@ -62,6 +64,7 @@ public class HandleJacksonized extends EclipseAnnotationHandler { 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"); + private static final char[][] JSON_PROPERTY_ANNOTATION = Eclipse.fromQualifiedName("com.fasterxml.jackson.annotation.JsonProperty"); @Override public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) { handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.JACKSONIZED_FLAG_USAGE, "@Jacksonized"); @@ -77,8 +80,10 @@ public class HandleJacksonized extends EclipseAnnotationHandler { 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."); + EclipseNode accessorsAnnotationNode = (annotatedNode.getKind() == Kind.TYPE) ? findAnnotation(Accessors.class, annotatedNode) : null; + + if (builderAnnotationNode == null && superBuilderAnnotationNode == null && accessorsAnnotationNode == null) { + annotationNode.addWarning("@Jacksonized requires @Builder, @SuperBuilder, or @Accessors for it to mean anything."); return; } @@ -92,7 +97,18 @@ public class HandleJacksonized extends EclipseAnnotationHandler { annotationNode.addError("Builders on abstract classes cannot be @Jacksonized (the builder would never be used)."); return; } + + if (builderAnnotationNode != null || superBuilderAnnotationNode != null) { + handleJacksonizedBuilder(ast, annotationNode, annotatedNode, tdNode, td, builderAnnotationNode, superBuilderAnnotationNode); + } + + if (accessorsAnnotationNode != null) { + handleJacksonizedAccessors(ast, annotationNode, annotatedNode, tdNode, td, accessorsAnnotationNode); + } + } + + private void handleJacksonizedBuilder(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, EclipseNode tdNode, TypeDeclaration td, EclipseNode builderAnnotationNode, EclipseNode superBuilderAnnotationNode) { AnnotationValues builderAnnotation = builderAnnotationNode != null ? createAnnotation(Builder.class, builderAnnotationNode) : null; AnnotationValues superBuilderAnnotation = superBuilderAnnotationNode != null ? createAnnotation(SuperBuilder.class, superBuilderAnnotationNode) : null; @@ -144,6 +160,38 @@ public class HandleJacksonized extends EclipseAnnotationHandler { builderClass.modifiers = builderClass.modifiers & ~ClassFileConstants.AccPrivate; } + private void handleJacksonizedAccessors(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, EclipseNode tdNode, TypeDeclaration td, EclipseNode accessorsAnnotationNode) { + AnnotationValues 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 (EclipseNode eclipseNode : tdNode.down()) { + if (eclipseNode.getKind() == Kind.FIELD) { + createJsonPropertyForField(eclipseNode, annotationNode); + } + } + } + + private void createJsonPropertyForField(EclipseNode fieldNode, EclipseNode annotationNode) { + if (hasAnnotation("com.fasterxml.jackson.annotation.JsonProperty", fieldNode)) { + return; + } + ASTNode astNode = fieldNode.get(); + if (astNode instanceof FieldDeclaration) { + FieldDeclaration fd = (FieldDeclaration)astNode; + StringLiteral fieldName = new StringLiteral(fd.name, 0, 0, 0); + ((FieldDeclaration)astNode).annotations = addAnnotation(fieldNode.get(), fd.annotations, JSON_PROPERTY_ANNOTATION, fieldName); + } + } + + private String getBuilderClassName(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, TypeDeclaration td, AnnotationValues builderAnnotation) { String builderClassName = builderAnnotation != null ? builderAnnotation.getInstance().builderClassName() : null; diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index 99552efc..5c372019 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -228,7 +228,7 @@ public class HandleSetter extends EclipseAnnotationHandler { if (isFieldDeprecated(fieldNode) || deprecate) { deprecated = new Annotation[] { generateDeprecatedAnnotation(source) }; } - method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated, findCopyableToSetterAnnotations(fieldNode)); + method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated, findCopyableToSetterAnnotations(fieldNode, false)); Argument param = new Argument(paramName, p, copyType(field.type, source), Modifier.FINAL); param.sourceStart = pS; param.sourceEnd = pE; method.arguments = new Argument[] { param }; diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index 82e561de..c37da9d7 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -1007,7 +1007,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { if (Arrays.equals(setterName.toCharArray(), existingName) && !isTolerate(fieldNode, existing[i])) return; } - List methodAnnsList = Arrays.asList(EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode)); + List methodAnnsList = Arrays.asList(EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode, true)); addCheckerFrameworkReturnsReceiver(returnType, job.source, job.checkerFramework); MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, returnType, returnStatement, ClassFileConstants.AccPublic, job.sourceNode, methodAnnsList, annosOnParam != null ? Arrays.asList(copyAnnotations(job.source, annosOnParam)) : Collections.emptyList()); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index a43e0331..eff24cd4 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -219,7 +219,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(builderType, new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName(builderType, "addAll", new String(data.getPluralName())).toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, data.getSource()); - Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up())); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up(), false)); md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java index 810a7878..c94666e0 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java @@ -195,7 +195,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(builderType, new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName(builderType, "addAll", new String(data.getPluralName())).toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, data.getSource()); - Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up())); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up(), false)); md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java index 16ed2d44..0e3ab0dd 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java @@ -332,7 +332,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer md.selector = setterName.toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, data.getSource()); - Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up())); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up(), false)); md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); diff --git a/src/core/lombok/extern/jackson/Jacksonized.java b/src/core/lombok/extern/jackson/Jacksonized.java index 4b7d7e54..fd482d00 100644 --- a/src/core/lombok/extern/jackson/Jacksonized.java +++ b/src/core/lombok/extern/jackson/Jacksonized.java @@ -27,8 +27,6 @@ import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.Retention; import java.lang.annotation.Target; -import com.fasterxml.jackson.annotation.JsonProperty; - import lombok.Builder; import lombok.experimental.Accessors; import lombok.experimental.SuperBuilder; diff --git a/src/core/lombok/javac/handlers/HandleJacksonized.java b/src/core/lombok/javac/handlers/HandleJacksonized.java index f956d782..7b41ec13 100644 --- a/src/core/lombok/javac/handlers/HandleJacksonized.java +++ b/src/core/lombok/javac/handlers/HandleJacksonized.java @@ -116,7 +116,7 @@ public class HandleJacksonized extends JavacAnnotationHandler { JavacTreeMaker maker = fieldNode.getTreeMaker(); JCExpression jsonPropertyType = chainDots(fieldNode, "com", "fasterxml", "jackson", "annotation", "JsonProperty"); - JCAnnotation annotationJsonProperty = maker.Annotation(jsonPropertyType, List.of(maker.Literal(fieldNode.getName()))); + 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); diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 3669bf2e..2390c7aa 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -21,9 +21,9 @@ */ package lombok.javac.handlers; -import static lombok.javac.handlers.HandleBuilder.*; import static lombok.core.handlers.HandlerUtil.*; import static lombok.javac.Javac.*; +import static lombok.javac.handlers.HandleBuilder.*; import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.ArrayList; @@ -968,7 +968,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { List methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode, true); returnType = addCheckerFrameworkReturnsReceiver(returnType, maker, job.builderType, job.checkerFramework); - JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam, false); + JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam, true); if (job.sourceNode.up().getKind() == Kind.METHOD) { copyJavadocFromParam(originalFieldNode.up(), newMethod, paramName.toString()); } else { diff --git a/test/transform/resource/after-ecj/JacksonizedAccessors.java b/test/transform/resource/after-ecj/JacksonizedAccessors.java new file mode 100644 index 00000000..83fe581c --- /dev/null +++ b/test/transform/resource/after-ecj/JacksonizedAccessors.java @@ -0,0 +1,16 @@ +public @lombok.extern.jackson.Jacksonized @lombok.experimental.Accessors(fluent = true) @lombok.Getter @lombok.Setter class JacksonizedAccessors { + private @com.fasterxml.jackson.annotation.JsonProperty("intValue") int intValue; + public JacksonizedAccessors() { + super(); + } + public @java.lang.SuppressWarnings("all") @lombok.Generated @com.fasterxml.jackson.annotation.JsonProperty("intValue") int intValue() { + return this.intValue; + } + /** + * @return {@code this}. + */ + public @java.lang.SuppressWarnings("all") @lombok.Generated @com.fasterxml.jackson.annotation.JsonProperty("intValue") JacksonizedAccessors intValue(final int intValue) { + this.intValue = intValue; + return this; + } +} \ No newline at end of file diff --git a/test/transform/resource/before/JacksonizedAccessors.java b/test/transform/resource/before/JacksonizedAccessors.java index 3242890e..0fe01684 100644 --- a/test/transform/resource/before/JacksonizedAccessors.java +++ b/test/transform/resource/before/JacksonizedAccessors.java @@ -1,12 +1,7 @@ -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import lombok.extern.jackson.Jacksonized; - -@Jacksonized -@Accessors(fluent = true) -@Getter -@Setter +@lombok.extern.jackson.Jacksonized +@lombok.experimental.Accessors(fluent = true) +@lombok.Getter +@lombok.Setter public class JacksonizedAccessors { private int intValue; -} +} \ No newline at end of file From 5c2ddc8ddba46863bdd52f8a69e35e31dbd8ea7d Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Fri, 28 Mar 2025 17:42:09 +0100 Subject: [PATCH 10/22] ecj: Jacksonized for accessors --- .../lombok/eclipse/handlers/HandleJacksonized.java | 1 + src/core/lombok/eclipse/handlers/HandleSetter.java | 10 ++++++++++ .../resource/after-ecj/JacksonizedAccessors.java | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/core/lombok/eclipse/handlers/HandleJacksonized.java b/src/core/lombok/eclipse/handlers/HandleJacksonized.java index abb50fe0..10d5dcbc 100644 --- a/src/core/lombok/eclipse/handlers/HandleJacksonized.java +++ b/src/core/lombok/eclipse/handlers/HandleJacksonized.java @@ -177,6 +177,7 @@ public class HandleJacksonized extends EclipseAnnotationHandler { createJsonPropertyForField(eclipseNode, annotationNode); } } + tdNode.rebuild(); } private void createJsonPropertyForField(EclipseNode fieldNode, EclipseNode annotationNode) { diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index 5c372019..c607a6c6 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -27,6 +27,7 @@ import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -59,6 +60,8 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; +import com.google.common.collect.Lists; + /** * Handles the {@code lombok.Setter} annotation for eclipse. */ @@ -109,6 +112,13 @@ public class HandleSetter extends EclipseAnnotationHandler { //The annotation will make it happen, so we can skip it. return; } + + // If a fluent setter should be generated, force-copy annotations from the field. + AnnotationValues accessorsForField = EclipseHandlerUtil.getAccessorsForField(fieldNode); + Annotation[] copyableToSetterAnnotations = findCopyableToSetterAnnotations(fieldNode, accessorsForField.isExplicit("fluent")); + onMethod = Lists.newArrayList(onMethod); + onMethod.addAll(Arrays.asList(copyableToSetterAnnotations)); + createSetterForField(level, fieldNode, sourceNode, false, onMethod, onParam); } diff --git a/test/transform/resource/after-ecj/JacksonizedAccessors.java b/test/transform/resource/after-ecj/JacksonizedAccessors.java index 83fe581c..dd15a397 100644 --- a/test/transform/resource/after-ecj/JacksonizedAccessors.java +++ b/test/transform/resource/after-ecj/JacksonizedAccessors.java @@ -3,13 +3,13 @@ public @lombok.extern.jackson.Jacksonized @lombok.experimental.Accessors(fluent public JacksonizedAccessors() { super(); } - public @java.lang.SuppressWarnings("all") @lombok.Generated @com.fasterxml.jackson.annotation.JsonProperty("intValue") int intValue() { + public @com.fasterxml.jackson.annotation.JsonProperty("intValue") @java.lang.SuppressWarnings("all") @lombok.Generated int intValue() { return this.intValue; } /** * @return {@code this}. */ - public @java.lang.SuppressWarnings("all") @lombok.Generated @com.fasterxml.jackson.annotation.JsonProperty("intValue") JacksonizedAccessors intValue(final int intValue) { + public @com.fasterxml.jackson.annotation.JsonProperty("intValue") @java.lang.SuppressWarnings("all") @lombok.Generated JacksonizedAccessors intValue(final int intValue) { this.intValue = intValue; return this; } From 66a6c5a883f0b320b58c289859f19a384ec09945 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Fri, 28 Mar 2025 17:43:11 +0100 Subject: [PATCH 11/22] fix compile --- src/core/lombok/eclipse/handlers/HandleSetter.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index c607a6c6..d05d923e 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -60,8 +60,6 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; -import com.google.common.collect.Lists; - /** * Handles the {@code lombok.Setter} annotation for eclipse. */ @@ -116,7 +114,7 @@ public class HandleSetter extends EclipseAnnotationHandler { // If a fluent setter should be generated, force-copy annotations from the field. AnnotationValues accessorsForField = EclipseHandlerUtil.getAccessorsForField(fieldNode); Annotation[] copyableToSetterAnnotations = findCopyableToSetterAnnotations(fieldNode, accessorsForField.isExplicit("fluent")); - onMethod = Lists.newArrayList(onMethod); + onMethod = new ArrayList(onMethod); onMethod.addAll(Arrays.asList(copyableToSetterAnnotations)); createSetterForField(level, fieldNode, sourceNode, false, onMethod, onParam); From 26c7ad1eb055ab26bcbe0a032a61f5d7f89ff76c Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Mon, 31 Mar 2025 11:48:17 +0200 Subject: [PATCH 12/22] copy Jackson annotations to the plural builder setter method --- src/core/lombok/ConfigurationKeys.java | 2 +- src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java | 6 +++--- src/core/lombok/eclipse/handlers/HandleSetter.java | 1 + .../handlers/singulars/EclipseGuavaSingularizer.java | 2 +- .../singulars/EclipseJavaUtilListSetSingularizer.java | 2 +- .../handlers/singulars/EclipseJavaUtilMapSingularizer.java | 2 +- test/transform/resource/before/JacksonJsonProperty.java | 1 + 7 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 18d7cb9a..e2ec1426 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -747,7 +747,7 @@ public class ConfigurationKeys { /** * lombok configuration: {@code lombok.copyJacksonAnnotationsToSetters} = {@code true} | {@code false}. * - * If true, copy certain Jackson annotations from a field to its corresponding getter. This was the behavior from lombok 1.18.16 to 1.18.36. + * If true, copy certain Jackson annotations from a field to its corresponding getter. This was the behavior from lombok 1.18.16 to 1.18.38. * However, it turned out to be harmful in certain situations. Thus, the default is now false. */ public static final ConfigurationKey COPY_JACKSON_ANNOTATIONS_TO_SETTERS = new ConfigurationKey("lombok.copyJacksonAnnotationsToSetters", "Copy these annotations to getters, setters, with methods, builder-setters, etc.") {}; diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 3a18d049..6f5ae8bc 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -829,10 +829,10 @@ public class EclipseHandlerUtil { /** * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. * - * @param forceCopy If true, always copy the annotations regardless of the lombok configuration. + * @param forceCopyJacksonAnnotations If true, always copy the annotations regardless of the lombok configuration. */ - public static Annotation[] findCopyableToSetterAnnotations(EclipseNode node, boolean forceCopy) { - if (!forceCopy) { + public static Annotation[] findCopyableToSetterAnnotations(EclipseNode node, boolean forceCopyJacksonAnnotations) { + if (!forceCopyJacksonAnnotations) { Boolean copyAnnotations = node.getAst().readConfiguration(ConfigurationKeys.COPY_JACKSON_ANNOTATIONS_TO_SETTERS); if (copyAnnotations == null || !copyAnnotations) return EMPTY_ANNOTATIONS_ARRAY; } diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index d05d923e..e0bea89b 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -113,6 +113,7 @@ public class HandleSetter extends EclipseAnnotationHandler { // If a fluent setter should be generated, force-copy annotations from the field. AnnotationValues accessorsForField = EclipseHandlerUtil.getAccessorsForField(fieldNode); + // Copying Jackson annotations is required for fluent accessors (otherwise Jackson would not find the accessor). Annotation[] copyableToSetterAnnotations = findCopyableToSetterAnnotations(fieldNode, accessorsForField.isExplicit("fluent")); onMethod = new ArrayList(onMethod); onMethod.addAll(Arrays.asList(copyableToSetterAnnotations)); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index eff24cd4..e77bde74 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -219,7 +219,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(builderType, new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName(builderType, "addAll", new String(data.getPluralName())).toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, data.getSource()); - Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up(), false)); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up(), true)); md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java index c94666e0..2802bf7a 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java @@ -195,7 +195,7 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(builderType, new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName(builderType, "addAll", new String(data.getPluralName())).toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, data.getSource()); - Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up(), false)); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up(), true)); md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java index 0e3ab0dd..e9ee2252 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java @@ -332,7 +332,7 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer md.selector = setterName.toCharArray(); Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, data.getSource()); - Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up(), false)); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up(), true)); md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); diff --git a/test/transform/resource/before/JacksonJsonProperty.java b/test/transform/resource/before/JacksonJsonProperty.java index c0bccfae..4d3018cc 100644 --- a/test/transform/resource/before/JacksonJsonProperty.java +++ b/test/transform/resource/before/JacksonJsonProperty.java @@ -1,3 +1,4 @@ +//CONF: lombok.copyJacksonAnnotationsToSetters = true //version 8: Jackson deps are at least Java7+. import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; From 513805d0ed78cc0a457f637d7a100f254e359767 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Mon, 31 Mar 2025 13:32:22 +0200 Subject: [PATCH 13/22] reduce parameter count --- .../lombok/javac/handlers/HandleBuilder.java | 2 +- .../lombok/javac/handlers/HandleSetter.java | 28 ++++++++++--------- .../javac/handlers/HandleSuperBuilder.java | 2 +- .../javac/handlers/JavacHandlerUtil.java | 6 ++-- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 4e67ea7e..17fdc64d 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -931,7 +931,7 @@ public class HandleBuilder extends JavacAnnotationHandler { JavacTreeMaker maker = fieldNode.getTreeMaker(); List methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(bfd.originalFieldNode, true); - JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(job.accessInners), deprecate, fieldNode, maker, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, job.sourceNode, methodAnns, bfd.annotations, false); + JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(job.accessInners), deprecate, fieldNode, maker, setterName, bfd.name, bfd.nameOfSetFlag, job.oldChain, job.sourceNode, methodAnns, bfd.annotations); recursiveSetGeneratedBy(newMethod, job.sourceNode); if (job.sourceNode.up().getKind() == Kind.METHOD) { copyJavadocFromParam(bfd.originalFieldNode.up(), newMethod, bfd.name.toString()); diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 746277ab..0dfd2312 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -198,15 +198,12 @@ public class HandleSetter extends JavacAnnotationHandler { AnnotationValues accessors = JavacHandlerUtil.getAccessorsForField(field); String setterName = toSetterName(field, accessors); boolean returnThis = shouldReturnThis(field, accessors); - boolean fluent = accessors.isExplicit("fluent"); - Boolean fluentConfig = field.getAst().readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT); - if (fluentConfig != null && fluentConfig) fluent = fluentConfig; - JCMethodDecl setter = createSetter(access, false, field, treeMaker, setterName, null, null, returnThis, source, onMethod, onParam, fluent); + JCMethodDecl setter = createSetter(access, false, field, treeMaker, setterName, null, null, returnThis, source, onMethod, onParam); return setter; } - public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List onMethod, List onParam, boolean forceAnnotationCopying) { + public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List onMethod, List onParam) { JCExpression returnType = null; JCReturn returnStatement = null; if (shouldReturnThis) { @@ -215,7 +212,7 @@ public class HandleSetter extends JavacAnnotationHandler { returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this"))); } - return createSetter(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam, forceAnnotationCopying); + return createSetter(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam); } public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List onMethod, List onParam, JCVariableDecl recv, boolean forceAnnotationCopying) { @@ -227,15 +224,15 @@ public class HandleSetter extends JavacAnnotationHandler { returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this"))); } - JCMethodDecl d = createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam, recv, forceAnnotationCopying); + JCMethodDecl d = createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam, recv); return d; } - public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List onMethod, List onParam, boolean forceAnnotationCopying) { - return createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, methodType, returnStatement, source, onMethod, onParam, null, forceAnnotationCopying); + public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List onMethod, List onParam) { + return createSetterWithRecv(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, methodType, returnStatement, source, onMethod, onParam, null); } - public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List onMethod, List onParam, JCVariableDecl recv, boolean forceAnnotationCopying) { + public static JCMethodDecl createSetterWithRecv(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List onMethod, List onParam, JCVariableDecl recv) { if (setterName == null) return null; JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); @@ -281,12 +278,17 @@ public class HandleSetter extends JavacAnnotationHandler { List throwsClauses = List.nil(); JCExpression annotationMethodDefaultValue = null; - List annsOnMethod = mergeAnnotations(copyAnnotations(onMethod), findCopyableToSetterAnnotations(field, forceAnnotationCopying)); + // Copying Jackson annotations is required for fluent accessors (otherwise Jackson would not find the accessor). + AnnotationValues accessors = JavacHandlerUtil.getAccessorsForField(field); + boolean fluent = accessors.isExplicit("fluent"); + Boolean fluentConfig = field.getAst().readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT); + if (fluentConfig != null && fluentConfig) fluent = fluentConfig; + + List annsOnMethod = mergeAnnotations(copyAnnotations(onMethod), findCopyableToSetterAnnotations(field, fluent)); if (isFieldDeprecated(field) || deprecate) { annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.nil())); } - - AnnotationValues accessors = JavacHandlerUtil.getAccessorsForField(field); + if (shouldMakeFinal(field, accessors)) access |= Flags.FINAL; JCMethodDecl methodDef; if (recv != null && treeMaker.hasMethodDefWithRecvParam()) { diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 2390c7aa..eb18c863 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -968,7 +968,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { List methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode, true); returnType = addCheckerFrameworkReturnsReceiver(returnType, maker, job.builderType, job.checkerFramework); - JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam, true); + JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, job.sourceNode, methodAnns, annosOnParam); if (job.sourceNode.up().getKind() == Kind.METHOD) { copyJavadocFromParam(originalFieldNode.up(), newMethod, paramName.toString()); } else { diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 529bafb2..7e67aee3 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1758,9 +1758,11 @@ public class JavacHandlerUtil { /** * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. + * + * @param forceCopyJacksonAnnotations If true, always copy the annotations regardless of the lombok configuration. */ - public static List findCopyableToSetterAnnotations(JavacNode node, boolean forceCopy) { - if (!forceCopy) { + public static List findCopyableToSetterAnnotations(JavacNode node, boolean forceCopyJacksonAnnotations) { + if (!forceCopyJacksonAnnotations) { Boolean copyAnnotations = node.getAst().readConfiguration(ConfigurationKeys.COPY_JACKSON_ANNOTATIONS_TO_SETTERS); if (copyAnnotations == null || !copyAnnotations) return List.nil(); } From 592882feefcac110ec800ecb10d81f0328c62685 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Mon, 31 Mar 2025 23:47:50 +0200 Subject: [PATCH 14/22] also include getters, rename to copyJacksonAnnotationsToAccessors --- src/core/lombok/ConfigurationKeys.java | 6 +++--- src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java | 8 ++++++-- src/core/lombok/eclipse/handlers/HandleGetter.java | 7 ++++++- src/core/lombok/javac/handlers/HandleGetter.java | 7 ++++++- src/core/lombok/javac/handlers/JavacHandlerUtil.java | 8 ++++++-- test/transform/resource/before/JacksonJsonProperty.java | 2 +- 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index c060d7b0..948f55d6 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -746,10 +746,10 @@ public class ConfigurationKeys { public static final ConfigurationKey STANDARD_EXCEPTION_FLAG_USAGE = new ConfigurationKey("lombok.standardException.flagUsage", "Emit a warning or error if @StandardException is used.") {}; /** - * lombok configuration: {@code lombok.copyJacksonAnnotationsToSetters} = {@code true} | {@code false}. + * lombok configuration: {@code lombok.copyJacksonAnnotationsToAccessors} = {@code true} | {@code false}. * - * If true, copy certain Jackson annotations from a field to its corresponding getter. This was the behavior from lombok 1.18.16 to 1.18.38. + * If true, copy certain Jackson annotations from a field to its corresponding accessors (getter/setters). This was the behavior from lombok 1.18.16 to 1.18.38. * However, it turned out to be harmful in certain situations. Thus, the default is now false. */ - public static final ConfigurationKey COPY_JACKSON_ANNOTATIONS_TO_SETTERS = new ConfigurationKey("lombok.copyJacksonAnnotationsToSetters", "Copy these annotations to getters, setters, with methods, builder-setters, etc.") {}; + public static final ConfigurationKey COPY_JACKSON_ANNOTATIONS_TO_ACCESSORS = new ConfigurationKey("lombok.copyJacksonAnnotationsToAccessors", "Copy Jackson annotations from fields to their getters and setters.") {}; } diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index eeed200f..410015a6 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -822,7 +822,11 @@ public class EclipseHandlerUtil { /** * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. */ - public static Annotation[] findCopyableToGetterAnnotations(EclipseNode node) { + public static Annotation[] findCopyableToGetterAnnotations(EclipseNode node, boolean forceCopyJacksonAnnotations) { + if (!forceCopyJacksonAnnotations) { + Boolean copyAnnotations = node.getAst().readConfiguration(ConfigurationKeys.COPY_JACKSON_ANNOTATIONS_TO_ACCESSORS); + if (copyAnnotations == null || !copyAnnotations) return EMPTY_ANNOTATIONS_ARRAY; + } return findAnnotationsInList(node, JACKSON_COPY_TO_GETTER_ANNOTATIONS); } @@ -833,7 +837,7 @@ public class EclipseHandlerUtil { */ public static Annotation[] findCopyableToSetterAnnotations(EclipseNode node, boolean forceCopyJacksonAnnotations) { if (!forceCopyJacksonAnnotations) { - Boolean copyAnnotations = node.getAst().readConfiguration(ConfigurationKeys.COPY_JACKSON_ANNOTATIONS_TO_SETTERS); + Boolean copyAnnotations = node.getAst().readConfiguration(ConfigurationKeys.COPY_JACKSON_ANNOTATIONS_TO_ACCESSORS); if (copyAnnotations == null || !copyAnnotations) return EMPTY_ANNOTATIONS_ARRAY; } return findAnnotationsInList(node, JACKSON_COPY_TO_SETTER_ANNOTATIONS); diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java index 2af5ba1f..3e1abcc8 100644 --- a/src/core/lombok/eclipse/handlers/HandleGetter.java +++ b/src/core/lombok/eclipse/handlers/HandleGetter.java @@ -281,10 +281,15 @@ public class HandleGetter extends EclipseAnnotationHandler { if (getCheckerFrameworkVersion(fieldNode).generateSideEffectFree()) checkerFramework = new Annotation[] { generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) }; } + // Copying Jackson annotations is required for fluent accessors (otherwise Jackson would not find the accessor). + boolean fluent = accessors.isExplicit("fluent"); + Boolean fluentConfig = fieldNode.getAst().readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT); + if (fluentConfig != null && fluentConfig) fluent = fluentConfig; + method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), findCopyableAnnotations(fieldNode), - findCopyableToGetterAnnotations(fieldNode), + findCopyableToGetterAnnotations(fieldNode, fluent), findDelegatesAndMarkAsHandled(fieldNode), checkerFramework, deprecated); diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 64dcfb68..9806a550 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -252,7 +252,12 @@ public class HandleGetter extends JavacAnnotationHandler { JCExpression annotationMethodDefaultValue = null; List copyableAnnotations = findCopyableAnnotations(field); - List copyableToGetterAnnotations = copyAnnotations(findCopyableToGetterAnnotations(field), treeMaker); + + // Copying Jackson annotations is required for fluent accessors (otherwise Jackson would not find the accessor). + boolean fluent = accessors.isExplicit("fluent"); + Boolean fluentConfig = field.getAst().readConfiguration(ConfigurationKeys.ACCESSORS_FLUENT); + if (fluentConfig != null && fluentConfig) fluent = fluentConfig; + List copyableToGetterAnnotations = copyAnnotations(findCopyableToGetterAnnotations(field, fluent), treeMaker); List delegates = findDelegatesAndRemoveFromField(field); List annsOnMethod = copyAnnotations(onMethod, treeMaker).appendList(copyableAnnotations).appendList(copyableToGetterAnnotations); diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 94b58fff..b1f0be1a 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1759,7 +1759,11 @@ public class JavacHandlerUtil { /** * Searches the given field node for annotations that are specifically intentioned to be copied to the getter. */ - public static List findCopyableToGetterAnnotations(JavacNode node) { + public static List findCopyableToGetterAnnotations(JavacNode node, boolean forceCopyJacksonAnnotations) { + if (!forceCopyJacksonAnnotations) { + Boolean copyAnnotations = node.getAst().readConfiguration(ConfigurationKeys.COPY_JACKSON_ANNOTATIONS_TO_ACCESSORS); + if (copyAnnotations == null || !copyAnnotations) return List.nil(); + } return findAnnotationsInList(node, JACKSON_COPY_TO_GETTER_ANNOTATIONS); } @@ -1770,7 +1774,7 @@ public class JavacHandlerUtil { */ public static List findCopyableToSetterAnnotations(JavacNode node, boolean forceCopyJacksonAnnotations) { if (!forceCopyJacksonAnnotations) { - Boolean copyAnnotations = node.getAst().readConfiguration(ConfigurationKeys.COPY_JACKSON_ANNOTATIONS_TO_SETTERS); + Boolean copyAnnotations = node.getAst().readConfiguration(ConfigurationKeys.COPY_JACKSON_ANNOTATIONS_TO_ACCESSORS); if (copyAnnotations == null || !copyAnnotations) return List.nil(); } return findAnnotationsInList(node, JACKSON_COPY_TO_SETTER_ANNOTATIONS); diff --git a/test/transform/resource/before/JacksonJsonProperty.java b/test/transform/resource/before/JacksonJsonProperty.java index 4d3018cc..716298f2 100644 --- a/test/transform/resource/before/JacksonJsonProperty.java +++ b/test/transform/resource/before/JacksonJsonProperty.java @@ -1,4 +1,4 @@ -//CONF: lombok.copyJacksonAnnotationsToSetters = true +//CONF: lombok.copyJacksonAnnotationsToAccessors = true //version 8: Jackson deps are at least Java7+. import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; From 4db804f082621d516a058eea1216bea4cc9ef606 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Tue, 1 Apr 2025 11:19:25 +0200 Subject: [PATCH 15/22] add warning when Jacksonized is used on non-fluent accessors revert unnecessary import changes --- .../lombok/eclipse/handlers/HandleGetter.java | 30 ++++++++--------- .../eclipse/handlers/HandleJacksonized.java | 28 +++++++++------- .../javac/handlers/HandleJacksonized.java | 6 ++-- .../lombok/javac/handlers/HandleSetter.java | 32 ++++++++----------- .../javac/handlers/HandleSuperBuilder.java | 2 +- .../javac/handlers/JavacHandlerUtil.java | 4 +-- 6 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java index 3e1abcc8..ad528929 100644 --- a/src/core/lombok/eclipse/handlers/HandleGetter.java +++ b/src/core/lombok/eclipse/handlers/HandleGetter.java @@ -21,7 +21,7 @@ */ package lombok.eclipse.handlers; -import static lombok.core.handlers.HandlerUtil.handleFlagUsage; +import static lombok.core.handlers.HandlerUtil.*; import static lombok.eclipse.Eclipse.*; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; @@ -32,6 +32,19 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import lombok.AccessLevel; +import lombok.ConfigurationKeys; +import lombok.experimental.Accessors; +import lombok.experimental.Delegate; +import lombok.spi.Provides; +import lombok.Getter; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.core.configuration.CheckerFrameworkVersion; +import lombok.eclipse.EclipseAnnotationHandler; +import lombok.eclipse.EclipseNode; +import lombok.eclipse.agent.PatchDelegate; + import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; @@ -63,21 +76,6 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; -import lombok.AccessLevel; -import lombok.ConfigurationKeys; -import lombok.Getter; -import lombok.core.AST.Kind; -import lombok.core.AnnotationValues; -import lombok.core.configuration.CheckerFrameworkVersion; -import lombok.core.handlers.HandlerUtil.FieldAccess; -import lombok.eclipse.EclipseAnnotationHandler; -import lombok.eclipse.EclipseNode; -import lombok.eclipse.agent.PatchDelegate; -import lombok.eclipse.handlers.EclipseHandlerUtil.CopyJavadoc; -import lombok.experimental.Accessors; -import lombok.experimental.Delegate; -import lombok.spi.Provides; - /** * Handles the {@code lombok.Getter} annotation for eclipse. */ diff --git a/src/core/lombok/eclipse/handlers/HandleJacksonized.java b/src/core/lombok/eclipse/handlers/HandleJacksonized.java index 10d5dcbc..79015362 100644 --- a/src/core/lombok/eclipse/handlers/HandleJacksonized.java +++ b/src/core/lombok/eclipse/handlers/HandleJacksonized.java @@ -92,23 +92,24 @@ public class HandleJacksonized extends EclipseAnnotationHandler { return; } + boolean jacksonizedBuilder = builderAnnotationNode != null || superBuilderAnnotationNode != null; + if (jacksonizedBuilder) { + handleJacksonizedBuilder(ast, annotationNode, annotatedNode, tdNode, td, builderAnnotationNode, superBuilderAnnotationNode); + } + + if (accessorsAnnotationNode != null) { + handleJacksonizedAccessors(ast, annotationNode, annotatedNode, tdNode, td, accessorsAnnotationNode, jacksonizedBuilder); + } + + } + + private void handleJacksonizedBuilder(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, EclipseNode tdNode, TypeDeclaration td, EclipseNode builderAnnotationNode, EclipseNode superBuilderAnnotationNode) { 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; } - if (builderAnnotationNode != null || superBuilderAnnotationNode != null) { - handleJacksonizedBuilder(ast, annotationNode, annotatedNode, tdNode, td, builderAnnotationNode, superBuilderAnnotationNode); - } - - if (accessorsAnnotationNode != null) { - handleJacksonizedAccessors(ast, annotationNode, annotatedNode, tdNode, td, accessorsAnnotationNode); - } - - } - - private void handleJacksonizedBuilder(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, EclipseNode tdNode, TypeDeclaration td, EclipseNode builderAnnotationNode, EclipseNode superBuilderAnnotationNode) { AnnotationValues builderAnnotation = builderAnnotationNode != null ? createAnnotation(Builder.class, builderAnnotationNode) : null; AnnotationValues superBuilderAnnotation = superBuilderAnnotationNode != null ? createAnnotation(SuperBuilder.class, superBuilderAnnotationNode) : null; @@ -160,7 +161,7 @@ public class HandleJacksonized extends EclipseAnnotationHandler { builderClass.modifiers = builderClass.modifiers & ~ClassFileConstants.AccPrivate; } - private void handleJacksonizedAccessors(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, EclipseNode tdNode, TypeDeclaration td, EclipseNode accessorsAnnotationNode) { + private void handleJacksonizedAccessors(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, EclipseNode tdNode, TypeDeclaration td, EclipseNode accessorsAnnotationNode, boolean jacksonizedBuilder) { AnnotationValues accessorsAnnotation = accessorsAnnotationNode != null ? createAnnotation(Accessors.class, accessorsAnnotationNode) : null; @@ -168,6 +169,9 @@ public class HandleJacksonized extends EclipseAnnotationHandler { if (!fluent) { // No changes required for chained-only accessors. + if (!jacksonizedBuilder) { + annotationNode.addWarning("@Jacksonized only affects fluent accessors (@Accessors(fluent=true))."); + } return; } diff --git a/src/core/lombok/javac/handlers/HandleJacksonized.java b/src/core/lombok/javac/handlers/HandleJacksonized.java index b6788ac5..c0cff164 100644 --- a/src/core/lombok/javac/handlers/HandleJacksonized.java +++ b/src/core/lombok/javac/handlers/HandleJacksonized.java @@ -86,11 +86,11 @@ public class HandleJacksonized extends JavacAnnotationHandler { } if (accessorsAnnotationNode != null) { - handleJacksonizedAccessors(annotationNode, annotatedNode, tdNode, td, accessorsAnnotationNode); + handleJacksonizedAccessors(annotationNode, annotatedNode, tdNode, td, accessorsAnnotationNode, builderAnnotationNode != null || superBuilderAnnotationNode != null); } } - private void handleJacksonizedAccessors(JavacNode annotationNode, JavacNode annotatedNode, JavacNode tdNode, JCClassDecl td, JavacNode accessorsAnnotationNode) { + private void handleJacksonizedAccessors(JavacNode annotationNode, JavacNode annotatedNode, JavacNode tdNode, JCClassDecl td, JavacNode accessorsAnnotationNode, boolean jacksonizedBuilder) { AnnotationValues accessorsAnnotation = accessorsAnnotationNode != null ? createAnnotation(Accessors.class, accessorsAnnotationNode) : null; @@ -98,6 +98,8 @@ public class HandleJacksonized extends JavacAnnotationHandler { if (!fluent) { // No changes required for chained-only accessors. + if (!jacksonizedBuilder) + annotationNode.addWarning("@Jacksonized only affects fluent accessors (@Accessors(fluent=true))."); return; } diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 438e7b8f..d2816b58 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -21,13 +21,24 @@ */ package lombok.javac.handlers; -import static lombok.core.handlers.HandlerUtil.handleFlagUsage; import static lombok.javac.Javac.*; +import static lombok.core.handlers.HandlerUtil.*; import static lombok.javac.handlers.JavacHandlerUtil.*; -import static lombok.javac.handlers.JavacHandlerUtil.isFieldDeprecated; import java.util.Collection; +import lombok.AccessLevel; +import lombok.ConfigurationKeys; +import lombok.Setter; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.experimental.Accessors; +import lombok.javac.Javac; +import lombok.javac.JavacAnnotationHandler; +import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; +import lombok.spi.Provides; + import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssign; @@ -42,20 +53,6 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; -import lombok.AccessLevel; -import lombok.ConfigurationKeys; -import lombok.Setter; -import lombok.core.AST.Kind; -import lombok.core.AnnotationValues; -import lombok.core.handlers.HandlerUtil.FieldAccess; -import lombok.experimental.Accessors; -import lombok.javac.Javac; -import lombok.javac.JavacAnnotationHandler; -import lombok.javac.JavacNode; -import lombok.javac.JavacTreeMaker; -import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc; -import lombok.spi.Provides; - /** * Handles the {@code lombok.Setter} annotation for javac. */ @@ -198,7 +195,6 @@ public class HandleSetter extends JavacAnnotationHandler { AnnotationValues accessors = JavacHandlerUtil.getAccessorsForField(field); String setterName = toSetterName(field, accessors); boolean returnThis = shouldReturnThis(field, accessors); - JCMethodDecl setter = createSetter(access, false, field, treeMaker, setterName, null, null, returnThis, source, onMethod, onParam); return setter; } @@ -288,7 +284,7 @@ public class HandleSetter extends JavacAnnotationHandler { if (isFieldDeprecated(field) || deprecate) { annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.nil())); } - + if (shouldMakeFinal(field, accessors)) access |= Flags.FINAL; JCMethodDecl methodDef; if (recv != null && treeMaker.hasMethodDefWithRecvParam()) { diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index eb18c863..04fa99b8 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -21,9 +21,9 @@ */ package lombok.javac.handlers; +import static lombok.javac.handlers.HandleBuilder.*; import static lombok.core.handlers.HandlerUtil.*; import static lombok.javac.Javac.*; -import static lombok.javac.handlers.HandleBuilder.*; import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.ArrayList; diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index b1f0be1a..acab62f8 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -24,7 +24,8 @@ package lombok.javac.handlers; import static com.sun.tools.javac.code.Flags.GENERATEDCONSTR; import static lombok.core.handlers.HandlerUtil.*; import static lombok.javac.Javac.*; -import static lombok.javac.JavacAugments.*; +import static lombok.javac.JavacAugments.JCTree_generatedNode; +import static lombok.javac.JavacAugments.JCTree_keepPosition; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; @@ -101,7 +102,6 @@ import lombok.core.configuration.NullCheckExceptionType; import lombok.core.configuration.TypeName; import lombok.core.handlers.HandlerUtil; import lombok.core.handlers.HandlerUtil.FieldAccess; -import lombok.core.handlers.HandlerUtil.JavadocTag; import lombok.delombok.LombokOptionsFactory; import lombok.experimental.Accessors; import lombok.experimental.Tolerate; From 17f451077f48754c52e231457f30631fee85ff8e Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Tue, 1 Apr 2025 11:55:19 +0200 Subject: [PATCH 16/22] changelog --- doc/changelog.markdown | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 7430a99d..df131f72 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -1,6 +1,10 @@ Lombok Changelog ---------------- +### v1.18.37 "Edgy Guinea Pig" +* FEATURE: `@Jacksonized @Accessors(fluent=true)` automatically creates the relevant annotations such that Jackson correctly identifies fluent accessors. +* IMPROBABLE BREAKING CHANGE: From versions 1.18.16 to 1.18.38, lombok automatically copies certain Jackson annotations (e.g., `@JsonProperty`) from fields to their corresponding accessors (getters/setters). However, it turned out to be harmful in certain situations. Thus, Lombok does not automatically copy those annotations any more. You can restore the old behavior using the [config key](https://projectlombok.org/features/configuration) `lombok.copyJacksonAnnotationsToAccessors = true`. + ### v1.18.38 (March 31st, 2025) * PLATFORM: JDK24 support added. * FEATURE: Lombok's nullity annotation now supports [JSpecify](https://jspecify.dev) out of the box, using [config key](https://projectlombok.org/features/configuration) `jspecify`. From b470299a9820c5113f9627e7e5106c8229ec51ce Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Tue, 1 Apr 2025 11:56:27 +0200 Subject: [PATCH 17/22] changelog --- doc/changelog.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/changelog.markdown b/doc/changelog.markdown index df131f72..97093f55 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -1,7 +1,7 @@ Lombok Changelog ---------------- -### v1.18.37 "Edgy Guinea Pig" +### v1.18.39 "Edgy Guinea Pig" * FEATURE: `@Jacksonized @Accessors(fluent=true)` automatically creates the relevant annotations such that Jackson correctly identifies fluent accessors. * IMPROBABLE BREAKING CHANGE: From versions 1.18.16 to 1.18.38, lombok automatically copies certain Jackson annotations (e.g., `@JsonProperty`) from fields to their corresponding accessors (getters/setters). However, it turned out to be harmful in certain situations. Thus, Lombok does not automatically copy those annotations any more. You can restore the old behavior using the [config key](https://projectlombok.org/features/configuration) `lombok.copyJacksonAnnotationsToAccessors = true`. From 1b4bd8c91fae2860733635aa88eb2b5f7795684c Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Tue, 1 Apr 2025 12:02:00 +0200 Subject: [PATCH 18/22] typo --- src/core/lombok/core/handlers/HandlerUtil.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index 65fc4a05..3f737e8a 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -425,19 +425,19 @@ public class HandlerUtil { "org.checkerframework.framework.qual.PurityUnqualified", })); - // The following two lists contain all annotations that (in some cases) should be copied from the field to the getter or - // setter. Right now, it only contains Jackson annotations. + // The following two lists contain all annotations that can be copied from the field to the getter or setter. + // Right now, it only contains Jackson annotations. // Jackson's annotation processing roughly works as follows: To calculate the annotation for a JSON property, Jackson // builds a triple of the Java field and the corresponding setter and getter methods. It is sufficient for an annotation // to be present on one of those to become effective. E.g., a @JsonIgnore on a setter completely ignores the JSON property, // not only during deserialization, but also when serializing. Therefore, in most cases it is _not_ necessary to copy the // annotations. It may even harm, as Jackson considers some annotations inheritable, and this "virtual inheritance" only // affects annotations on setter/getter, but not on private fields. - // However, there are two exceptions where we need it: + // However, there are two exceptions where we have to copy the annotations: // 1. When using a builder to deserialize, Jackson does _not_ "propagate" the annotations to the setter methods of the // builder, i.e. annotations like @JsonIgnore on the field will not be respected when deserializing with a builder. // Thus, those annotations should be copied to the builder's setters. - // 2. If the getter/setter methods to not follow the exact beanspec naming strategy, Jackson will not correctly detect the + // 2. If the getter/setter methods do not follow the exact beanspec naming strategy, Jackson will not correctly detect the // field-getter-setter triple, and annotations may not work as intended. // However, we cannot always know what the user's intention is. Thus, lombok should only fix those cases where it is // obvious what the user wants. That is the case for a @Jacksonized @Accessors(fluent=true). From dc690df1eebe5b4144dd0b567fec17f509b41b57 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Tue, 1 Apr 2025 12:17:28 +0200 Subject: [PATCH 19/22] typo, imports, etc. --- doc/changelog.markdown | 2 +- src/core/lombok/ConfigurationKeys.java | 2 +- .../eclipse/handlers/HandleJacksonized.java | 2 +- .../lombok/javac/handlers/HandleGetter.java | 37 +++++++++---------- .../lombok/javac/handlers/HandleSetter.java | 2 +- 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 97093f55..756b859f 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -3,7 +3,7 @@ Lombok Changelog ### v1.18.39 "Edgy Guinea Pig" * FEATURE: `@Jacksonized @Accessors(fluent=true)` automatically creates the relevant annotations such that Jackson correctly identifies fluent accessors. -* IMPROBABLE BREAKING CHANGE: From versions 1.18.16 to 1.18.38, lombok automatically copies certain Jackson annotations (e.g., `@JsonProperty`) from fields to their corresponding accessors (getters/setters). However, it turned out to be harmful in certain situations. Thus, Lombok does not automatically copy those annotations any more. You can restore the old behavior using the [config key](https://projectlombok.org/features/configuration) `lombok.copyJacksonAnnotationsToAccessors = true`. +* IMPROBABLE BREAKING CHANGE: From versions 1.18.16 to 1.18.38, lombok automatically copies certain Jackson annotations (e.g., `@JsonProperty`) from fields to the corresponding accessors (getters/setters). However, it turned out to be harmful in certain situations. Thus, Lombok does not automatically copy those annotations any more. You can restore the old behavior using the [config key](https://projectlombok.org/features/configuration) `lombok.copyJacksonAnnotationsToAccessors = true`. ### v1.18.38 (March 31st, 2025) * PLATFORM: JDK24 support added. diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 948f55d6..50d8fc90 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -751,5 +751,5 @@ public class ConfigurationKeys { * If true, copy certain Jackson annotations from a field to its corresponding accessors (getter/setters). This was the behavior from lombok 1.18.16 to 1.18.38. * However, it turned out to be harmful in certain situations. Thus, the default is now false. */ - public static final ConfigurationKey COPY_JACKSON_ANNOTATIONS_TO_ACCESSORS = new ConfigurationKey("lombok.copyJacksonAnnotationsToAccessors", "Copy Jackson annotations from fields to their getters and setters.") {}; + public static final ConfigurationKey COPY_JACKSON_ANNOTATIONS_TO_ACCESSORS = new ConfigurationKey("lombok.copyJacksonAnnotationsToAccessors", "Copy Jackson annotations from fields to the corresponding getters and setters.") {}; } diff --git a/src/core/lombok/eclipse/handlers/HandleJacksonized.java b/src/core/lombok/eclipse/handlers/HandleJacksonized.java index 79015362..a8ff2faa 100644 --- a/src/core/lombok/eclipse/handlers/HandleJacksonized.java +++ b/src/core/lombok/eclipse/handlers/HandleJacksonized.java @@ -109,7 +109,7 @@ public class HandleJacksonized extends EclipseAnnotationHandler { annotationNode.addError("Builders on abstract classes cannot be @Jacksonized (the builder would never be used)."); return; } - + AnnotationValues builderAnnotation = builderAnnotationNode != null ? createAnnotation(Builder.class, builderAnnotationNode) : null; AnnotationValues superBuilderAnnotation = superBuilderAnnotationNode != null ? createAnnotation(SuperBuilder.class, superBuilderAnnotationNode) : null; diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 9806a550..8c130b6a 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -21,18 +21,32 @@ */ package lombok.javac.handlers; -import static lombok.core.handlers.HandlerUtil.handleFlagUsage; +import static lombok.core.handlers.HandlerUtil.*; import static lombok.javac.Javac.*; import static lombok.javac.JavacAugments.JCTree_keepPosition; -import static lombok.javac.JavacTreeMaker.TypeTag.typeTag; +import static lombok.javac.JavacTreeMaker.TypeTag.*; import static lombok.javac.handlers.JavacHandlerUtil.*; -import static lombok.javac.handlers.JavacHandlerUtil.isFieldDeprecated; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import lombok.AccessLevel; +import lombok.ConfigurationKeys; +import lombok.experimental.Accessors; +import lombok.experimental.Delegate; +import lombok.Getter; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.core.configuration.CheckerFrameworkVersion; +import lombok.delombok.LombokOptionsFactory; +import lombok.javac.JavacAnnotationHandler; +import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; +import lombok.javac.JavacTreeMaker.TypeTag; +import lombok.spi.Provides; + import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBinary; @@ -52,23 +66,6 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; -import lombok.AccessLevel; -import lombok.ConfigurationKeys; -import lombok.Getter; -import lombok.core.AST.Kind; -import lombok.core.AnnotationValues; -import lombok.core.configuration.CheckerFrameworkVersion; -import lombok.core.handlers.HandlerUtil.FieldAccess; -import lombok.delombok.LombokOptionsFactory; -import lombok.experimental.Accessors; -import lombok.experimental.Delegate; -import lombok.javac.JavacAnnotationHandler; -import lombok.javac.JavacNode; -import lombok.javac.JavacTreeMaker; -import lombok.javac.JavacTreeMaker.TypeTag; -import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc; -import lombok.spi.Provides; - /** * Handles the {@code lombok.Getter} annotation for javac. */ diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index d2816b58..d76c7ab6 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -31,8 +31,8 @@ import lombok.AccessLevel; import lombok.ConfigurationKeys; import lombok.Setter; import lombok.core.AST.Kind; -import lombok.core.AnnotationValues; import lombok.experimental.Accessors; +import lombok.core.AnnotationValues; import lombok.javac.Javac; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; From aa13671e407db6346023b876b90a6e675c408400 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Fri, 23 May 2025 02:47:04 +0200 Subject: [PATCH 20/22] [javadoc] doc comments now a bit more consistent; e.g. use `{@code}` everywhere where it can be used. --- src/core/lombok/Builder.java | 2 +- src/core/lombok/ConfigurationKeys.java | 8 ++++---- .../core/configuration/ConfigurationValueType.java | 6 +++--- src/core/lombok/core/handlers/HandlerUtil.java | 2 +- src/core/lombok/eclipse/TransformEclipseAST.java | 4 ++-- .../eclipse/handlers/EclipseHandlerUtil.java | 10 ++++++---- .../eclipse/handlers/EclipseSingularsRecipes.java | 2 +- .../eclipse/handlers/HandleSuperBuilder.java | 8 ++++---- src/core/lombok/experimental/SuperBuilder.java | 6 +++--- src/core/lombok/experimental/UtilityClass.java | 2 +- .../lombok/javac/handlers/HandleSuperBuilder.java | 14 +++++++++----- .../lombok/javac/handlers/JavacHandlerUtil.java | 10 ++++++---- .../lombok/eclipse/agent/PatchJavadoc.java | 4 ++-- src/launch/lombok/launch/ShadowClassLoader.java | 6 +++--- 14 files changed, 46 insertions(+), 38 deletions(-) diff --git a/src/core/lombok/Builder.java b/src/core/lombok/Builder.java index 06ca3853..da707082 100644 --- a/src/core/lombok/Builder.java +++ b/src/core/lombok/Builder.java @@ -46,7 +46,7 @@ import java.lang.annotation.Target; *

* The TBuilder class contains 1 method for each parameter of the annotated * constructor / method (each field, when annotating a class), which returns the builder itself. - * The builder also has a build() method which returns a completed instance of the original type, + * The builder also has a {@code build()} method which returns a completed instance of the original type, * created by passing all parameters as set via the various other methods in the builder to the constructor * or method that was annotated with {@code @Builder}. The return type of this method will be the same * as the relevant class, unless a method has been annotated, in which case it'll be equal to the diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 50d8fc90..d2381807 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -606,14 +606,14 @@ public class ConfigurationKeys { /** * lombok configuration: {@code lombok.fieldDefaults.defaultPrivate} = {@code true} | {@code false}. * - * If set to true any field without an access modifier or {@code @PackagePrivate} is marked as {@code private} by lombok, in all source files compiled. + * If set to {@code true} any field without an access modifier or {@code @PackagePrivate} is marked as {@code private} by lombok, in all source files compiled. */ public static final ConfigurationKey FIELD_DEFAULTS_PRIVATE_EVERYWHERE = new ConfigurationKey("lombok.fieldDefaults.defaultPrivate", "If true, fields without any access modifier, in any file (lombok annotated or not) are marked as private. Use @PackagePrivate or an explicit modifier to override this.") {}; /** * lombok configuration: {@code lombok.fieldDefaults.defaultFinal} = {@code true} | {@code false}. * - * If set to true any field without {@code @NonFinal} is marked as {@code final} by lombok, in all source files compiled. + * If set to {@code true} any field without {@code @NonFinal} is marked as {@code final} by lombok, in all source files compiled. */ public static final ConfigurationKey FIELD_DEFAULTS_FINAL_EVERYWHERE = new ConfigurationKey("lombok.fieldDefaults.defaultFinal", "If true, fields, in any file (lombok annotated or not) are marked as final. Use @NonFinal to override this.") {}; @@ -748,8 +748,8 @@ public class ConfigurationKeys { /** * lombok configuration: {@code lombok.copyJacksonAnnotationsToAccessors} = {@code true} | {@code false}. * - * If true, copy certain Jackson annotations from a field to its corresponding accessors (getter/setters). This was the behavior from lombok 1.18.16 to 1.18.38. - * However, it turned out to be harmful in certain situations. Thus, the default is now false. + * If {@code true}, copy certain Jackson annotations from a field to its corresponding accessors (getter/setters). This was the behavior from lombok 1.18.16 to 1.18.38. + * However, it turned out to be harmful in certain situations. Thus, the default is now {@code false}. */ public static final ConfigurationKey COPY_JACKSON_ANNOTATIONS_TO_ACCESSORS = new ConfigurationKey("lombok.copyJacksonAnnotationsToAccessors", "Copy Jackson annotations from fields to the corresponding getters and setters.") {}; } diff --git a/src/core/lombok/core/configuration/ConfigurationValueType.java b/src/core/lombok/core/configuration/ConfigurationValueType.java index a44a5a83..e752232a 100644 --- a/src/core/lombok/core/configuration/ConfigurationValueType.java +++ b/src/core/lombok/core/configuration/ConfigurationValueType.java @@ -25,9 +25,9 @@ package lombok.core.configuration; * If a type used in {@link ConfigurationKey} type argument implements this interface, * it is expected to provide the following three static methods: *

    - *
  • public static SELF valueOf(String value) - *
  • public static String description() - *
  • public static String exampleValue() + *
  • public static SELF valueOf(String value)
  • + *
  • public static String description()
  • + *
  • public static String exampleValue()
  • *
* None of them should throw checked exceptions. * Based on these methods, an instance of {@link ConfigurationValueParser} is created diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index 3f737e8a..53ca16f5 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -440,7 +440,7 @@ public class HandlerUtil { // 2. If the getter/setter methods do not follow the exact beanspec naming strategy, Jackson will not correctly detect the // field-getter-setter triple, and annotations may not work as intended. // However, we cannot always know what the user's intention is. Thus, lombok should only fix those cases where it is - // obvious what the user wants. That is the case for a @Jacksonized @Accessors(fluent=true). + // obvious what the user wants. That is the case for a `@Jacksonized @Accessors(fluent=true)`. JACKSON_COPY_TO_GETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { "com.fasterxml.jackson.annotation.JsonFormat", "com.fasterxml.jackson.annotation.JsonIgnore", diff --git a/src/core/lombok/eclipse/TransformEclipseAST.java b/src/core/lombok/eclipse/TransformEclipseAST.java index df9e5451..16075857 100644 --- a/src/core/lombok/eclipse/TransformEclipseAST.java +++ b/src/core/lombok/eclipse/TransformEclipseAST.java @@ -129,14 +129,14 @@ public class TransformEclipseAST { /** * Check if lombok already handled the given AST. This method will return - * true once for diet mode and once for full mode. + * {@code true} once for diet mode and once for full mode. * * The reason for this is that Eclipse invokes the transform method multiple * times during compilation and it is enough to transform it once and not * repeat the whole thing over and over again. * * @param ast The AST node belonging to the compilation unit (java speak for a single source file). - * @return true if this AST was already handled by lombok. + * @return {@code true} if this AST was already handled by lombok. */ public static boolean alreadyTransformed(CompilationUnitDeclaration ast) { TransformationState state = CompilationUnitDeclaration_transformationState.get(ast); diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 410015a6..78e0bf73 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -820,7 +820,9 @@ public class EclipseHandlerUtil { } /** - * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. + * Searches the given field node for annotations that are specifically intended to be copied to the getter. + * + * @param forceCopyJacksonAnnotations If {@code true}, always copy the annotations regardless of regardless of lombok configuration key {@code lombok.copyJacksonAnnotationsToAccessors}. */ public static Annotation[] findCopyableToGetterAnnotations(EclipseNode node, boolean forceCopyJacksonAnnotations) { if (!forceCopyJacksonAnnotations) { @@ -831,9 +833,9 @@ public class EclipseHandlerUtil { } /** - * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. + * Searches the given field node for annotations that are specifically intended to be copied to the setter. * - * @param forceCopyJacksonAnnotations If true, always copy the annotations regardless of the lombok configuration. + * @param forceCopyJacksonAnnotations If {@code true}, always copy the annotations regardless of regardless of lombok configuration key {@code lombok.copyJacksonAnnotationsToAccessors}. */ public static Annotation[] findCopyableToSetterAnnotations(EclipseNode node, boolean forceCopyJacksonAnnotations) { if (!forceCopyJacksonAnnotations) { @@ -844,7 +846,7 @@ public class EclipseHandlerUtil { } /** - * Searches the given field node for annotations that are specifically intentioned to be copied to the builder's singular method. + * Searches the given field node for annotations that are specifically intended to be copied to the builder's singular method. */ public static Annotation[] findCopyableToBuilderSingularSetterAnnotations(EclipseNode node) { return findAnnotationsInList(node, JACKSON_COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS); diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java index 54f1a551..df611f78 100755 --- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java +++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java @@ -422,7 +422,7 @@ public class EclipseSingularsRecipes { return new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS); } - /** @return a {@code SingleNameReference} to the builder in the variable builderVariable. If {@ code builderVariable == "this"}, a {@code ThisReference} is returned. */ + /** @return a {@code SingleNameReference} to the builder in the variable {@code builderVariable}. If {@code builderVariable == "this"}, a {@code ThisReference} is returned. */ protected static Reference getBuilderReference(String builderVariable) { if ("this".equals(builderVariable)) { return new ThisReference(0, 0); diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index c37da9d7..4712af65 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -657,7 +657,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { } /** - * Generates a toBuilder() method in the annotated class that looks like this: + * Generates a {@code toBuilder()} method in the annotated class that looks like this: *
 	 * public Foobar.FoobarBuilder<?, ?> toBuilder() {
 	 *     return new .FoobarBuilderImpl().$fillValuesFrom(this);
@@ -698,8 +698,8 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler {
 	}
 
 	/**
-	 * Generates a $fillValuesFrom() method in the abstract builder class that looks
-	 * like this:
+	 * Generates a {@code $fillValuesFrom()} method in the abstract builder class.
+	 * It looks like:
 	 * 
 	 * protected B $fillValuesFrom(final C instance) {
 	 *     super.$fillValuesFrom(instance);
@@ -749,7 +749,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler {
 	}
 
 	/**
-	 * Generates a $fillValuesFromInstanceIntoBuilder() method in
+	 * Generates a {@code $fillValuesFromInstanceIntoBuilder()} method in
 	 * the builder implementation class that copies all fields from the instance
 	 * to the builder. It looks like this:
 	 * 
diff --git a/src/core/lombok/experimental/SuperBuilder.java b/src/core/lombok/experimental/SuperBuilder.java
index 193bda0f..f265e65c 100644
--- a/src/core/lombok/experimental/SuperBuilder.java
+++ b/src/core/lombok/experimental/SuperBuilder.java
@@ -40,7 +40,7 @@ import lombok.Singular;
  * 

* The TBuilder class contains 1 method for each parameter of the annotated * constructor / method (each field, when annotating a class), which returns the builder itself. - * The builder also has a build() method which returns a completed instance of the original type. + * The builder also has a {@code build()} method which returns a completed instance of the original type. *

* Complete documentation is found at the project lombok features page for @SuperBuilder. * @@ -56,8 +56,8 @@ public @interface SuperBuilder { String buildMethodName() default "build"; /** - * If true, generate an instance method to obtain a builder that is initialized with the values of this instance. - * In this case, all superclasses must also have toBuilder=true. + * If {@code true}, generate an instance method to obtain a builder that is initialized with the values of this instance. + * In this case, all superclasses must also have {@code toBuilder=true}. * * @return Whether to generate a {@code toBuilder()} method. */ diff --git a/src/core/lombok/experimental/UtilityClass.java b/src/core/lombok/experimental/UtilityClass.java index f8281660..4e3098e5 100644 --- a/src/core/lombok/experimental/UtilityClass.java +++ b/src/core/lombok/experimental/UtilityClass.java @@ -34,7 +34,7 @@ import java.lang.annotation.Target; *

  • If any constructors are declared in it, an error is generated. Otherwise, a private no-args constructor is generated; it throws a {@code UnsupportedOperationException}.
  • *
  • All methods, inner classes, and fields in the class are marked static.
  • *
  • WARNING: Do not use non-star static imports to import these members; javac won't be able to figure it out. Use either: - * import static ThisType.*; or don't static-import.
  • + * {@code import static ThisType.*;} or don't static-import. * */ @Target({ElementType.TYPE}) diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 04fa99b8..ffcbe21f 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -624,7 +624,9 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { } /** - * Generates a toBuilder() method in the annotated class that looks like this: + * Generates a {@code toBuilder()} method in the annotated class. + * + * It looks like: *
     	 * public ParentBuilder<?, ?> toBuilder() {
     	 *     return new FoobarBuilderImpl().$fillValuesFrom(this);
    @@ -659,8 +661,9 @@ public class HandleSuperBuilder extends JavacAnnotationHandler {
     	}
     
     	/**
    -	 * Generates a $fillValuesFrom() method in the abstract builder class that looks
    -	 * like this:
    +	 * Generates a {@code $fillValuesFrom()} method in the abstract builder class.
    +	 * 
    +	 * It looks like:
     	 * 
     	 * protected B $fillValuesFrom(final C instance) {
     	 *     super.$fillValuesFrom(instance);
    @@ -708,9 +711,10 @@ public class HandleSuperBuilder extends JavacAnnotationHandler {
     	}
     
     	/**
    -	 * Generates a $fillValuesFromInstanceIntoBuilder() method in
    +	 * Generates a {@code $fillValuesFromInstanceIntoBuilder()} method in
     	 * the builder implementation class that copies all fields from the instance
    -	 * to the builder. It looks like this:
    +	 * to the builder.
    +	 * It looks like:
     	 * 
     	 * 
     	 * protected B $fillValuesFromInstanceIntoBuilder(Foobar instance, FoobarBuilder<?, ?> b) {
    diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
    index acab62f8..f243c56a 100644
    --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
    +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
    @@ -1757,7 +1757,9 @@ public class JavacHandlerUtil {
     	}
     	
     	/**
    -	 * Searches the given field node for annotations that are specifically intentioned to be copied to the getter.
    +	 * Searches the given field node for annotations that are specifically intended to be copied to the getter.
    +	 * 
    +	 * @param forceCopyJacksonAnnotations If {@code true}, always copy the annotations regardless of lombok configuration key {@code lombok.copyJacksonAnnotationsToAccessors}.
     	 */
     	public static List findCopyableToGetterAnnotations(JavacNode node, boolean forceCopyJacksonAnnotations) {
     		if (!forceCopyJacksonAnnotations) {
    @@ -1768,9 +1770,9 @@ public class JavacHandlerUtil {
     	}
     
     	/**
    -	 * Searches the given field node for annotations that are specifically intentioned to be copied to the setter.
    +	 * Searches the given field node for annotations that are specifically intended to be copied to the setter.
     	 * 
    -	 * @param forceCopyJacksonAnnotations If true, always copy the annotations regardless of the lombok configuration.
    +	 * @param forceCopyJacksonAnnotations If {@code true}, always copy the annotations regardless of lombok configuration key {@code lombok.copyJacksonAnnotationsToAccessors}.
     	 */
     	public static List findCopyableToSetterAnnotations(JavacNode node, boolean forceCopyJacksonAnnotations) {
     		if (!forceCopyJacksonAnnotations) {
    @@ -1781,7 +1783,7 @@ public class JavacHandlerUtil {
     	}
     
     	/**
    -	 * Searches the given field node for annotations that are specifically intentioned to be copied to the builder's singular method.
    +	 * Searches the given field node for annotations that are specifically intended to be copied to the builder's singular method.
     	 */
     	public static List findCopyableToBuilderSingularSetterAnnotations(JavacNode node) {
     		return findAnnotationsInList(node, JACKSON_COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS);
    diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java b/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java
    index caa94e2f..09d26242 100644
    --- a/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java
    +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java
    @@ -78,8 +78,8 @@ public class PatchJavadoc {
     	}
     	
     	/**
    -	 * The method javadoc2HTML changed 2014-12 to accept an
    -	 * additional IJavaElement parameter. To support older versions, try to
    +	 * The method {@code javadoc2HTML} changed 2014-12 to accept an
    +	 * additional {@code IJavaElement} parameter. To support older versions, try to
     	 * find that one too.
     	 */
     	private static class Reflection {
    diff --git a/src/launch/lombok/launch/ShadowClassLoader.java b/src/launch/lombok/launch/ShadowClassLoader.java
    index 5b8e3211..b681e293 100644
    --- a/src/launch/lombok/launch/ShadowClassLoader.java
    +++ b/src/launch/lombok/launch/ShadowClassLoader.java
    @@ -67,14 +67,14 @@ import java.util.zip.ZipInputStream;
      * 

    * Load order is as follows if at least one override is present: *

  • First, if the resource is found in one of the paths stated in the shadow classpath, find that. - *
  • Next, ask the parent loader, which is passed during construction of the ShadowClassLoader. + *
  • Next, ask the {@code parent} loader, which is passed during construction of the ShadowClassLoader. *
  • Notably, this jar's contents are always skipped! (The idea of the shadow classpath is that this jar only functions as a launcher, not as a source of your actual application). * * * If no overrides are present, the load order is as follows: *
  • First, if the resource is found in our own jar (trying ".SCL.sclSuffix" first for any resource request ending in ".class"), return that. - *
  • Next, check any jar files other than our own, loading them via this classloader, if they have a file META-INF/ShadowClassLoader that contains a line of text with sclSuffix. - *
  • Next, ask the parent loader. + *
  • Next, check any jar files other than our own, loading them via this classloader, if they have a file {@code META-INF/ShadowClassLoader} that contains a line of text with sclSuffix. + *
  • Next, ask the {@code parent} loader. * * * Use ShadowClassLoader to accomplish the following things:
      From 2001aa12b54b2fa49ac3156fcdaa36f91e9b023e Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Fri, 23 May 2025 02:49:37 +0200 Subject: [PATCH 21/22] [trivial][style] --- src/core/lombok/ConfigurationKeys.java | 6 +- .../eclipse/handlers/EclipseHandlerUtil.java | 4 +- .../lombok/eclipse/handlers/HandleGetter.java | 2 +- .../eclipse/handlers/HandleJacksonized.java | 45 ++++++-------- .../eclipse/handlers/HandleSuperBuilder.java | 46 ++++++--------- .../javac/handlers/HandleJacksonized.java | 59 ++++++++----------- .../javac/handlers/HandleSuperBuilder.java | 57 ++++++++---------- 7 files changed, 89 insertions(+), 130 deletions(-) diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index d2381807..5459b1eb 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -721,7 +721,7 @@ public class ConfigurationKeys { * If set to {@code true}, no further {@code lombok.config} files will be checked. */ public static final ConfigurationKey STOP_BUBBLING = new ConfigurationKey("config.stopBubbling", "Tell the configuration system it should stop looking for other configuration files (default: false).") {}; - + /** * lombok configuration: {@code lombok.copyableAnnotations} += <TypeName: fully-qualified annotation class name>. * @@ -737,14 +737,14 @@ public class ConfigurationKeys { * checkerframework.org version will be generated. */ public static final ConfigurationKey CHECKER_FRAMEWORK = new ConfigurationKey("checkerframework", "If set with the version of checkerframework.org (in major.minor, or just 'true' for the latest supported version), create relevant checkerframework.org annotations for code lombok generates (default: false).") {}; - + /** * lombok configuration: {@code lombok.standardException.flagUsage} = {@code WARNING} | {@code ERROR}. * * If set, any usage of {@code @StandardException} results in a warning / error. */ public static final ConfigurationKey STANDARD_EXCEPTION_FLAG_USAGE = new ConfigurationKey("lombok.standardException.flagUsage", "Emit a warning or error if @StandardException is used.") {}; - + /** * lombok configuration: {@code lombok.copyJacksonAnnotationsToAccessors} = {@code true} | {@code false}. * diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 78e0bf73..c45d95a1 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -831,7 +831,7 @@ public class EclipseHandlerUtil { } return findAnnotationsInList(node, JACKSON_COPY_TO_GETTER_ANNOTATIONS); } - + /** * Searches the given field node for annotations that are specifically intended to be copied to the setter. * @@ -844,7 +844,7 @@ public class EclipseHandlerUtil { } return findAnnotationsInList(node, JACKSON_COPY_TO_SETTER_ANNOTATIONS); } - + /** * Searches the given field node for annotations that are specifically intended to be copied to the builder's singular method. */ diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java index ad528929..88d5fe24 100644 --- a/src/core/lombok/eclipse/handlers/HandleGetter.java +++ b/src/core/lombok/eclipse/handlers/HandleGetter.java @@ -83,7 +83,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; public class HandleGetter extends EclipseAnnotationHandler { private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY = new Annotation[0]; private static final String GETTER_NODE_NOT_SUPPORTED_ERR = "@Getter is only supported on a class, an enum, or a field."; - + public boolean generateGetterForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean checkForTypeLevelGetter, List onMethod) { if (checkForTypeLevelGetter) { if (hasAnnotation(Getter.class, typeNode)) { diff --git a/src/core/lombok/eclipse/handlers/HandleJacksonized.java b/src/core/lombok/eclipse/handlers/HandleJacksonized.java index a8ff2faa..ee0108d7 100644 --- a/src/core/lombok/eclipse/handlers/HandleJacksonized.java +++ b/src/core/lombok/eclipse/handlers/HandleJacksonized.java @@ -65,23 +65,21 @@ public class HandleJacksonized extends EclipseAnnotationHandler { 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"); private static final char[][] JSON_PROPERTY_ANNOTATION = Eclipse.fromQualifiedName("com.fasterxml.jackson.annotation.JsonProperty"); - + @Override public void handle(AnnotationValues annotation, Annotation ast, EclipseNode annotationNode) { handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.JACKSONIZED_FLAG_USAGE, "@Jacksonized"); - + 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. + 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); EclipseNode accessorsAnnotationNode = (annotatedNode.getKind() == Kind.TYPE) ? findAnnotation(Accessors.class, annotatedNode) : null; - + if (builderAnnotationNode == null && superBuilderAnnotationNode == null && accessorsAnnotationNode == null) { annotationNode.addWarning("@Jacksonized requires @Builder, @SuperBuilder, or @Accessors for it to mean anything."); return; @@ -96,13 +94,12 @@ public class HandleJacksonized extends EclipseAnnotationHandler { if (jacksonizedBuilder) { handleJacksonizedBuilder(ast, annotationNode, annotatedNode, tdNode, td, builderAnnotationNode, superBuilderAnnotationNode); } - + if (accessorsAnnotationNode != null) { handleJacksonizedAccessors(ast, annotationNode, annotatedNode, tdNode, td, accessorsAnnotationNode, jacksonizedBuilder); } - } - + private void handleJacksonizedBuilder(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, EclipseNode tdNode, TypeDeclaration td, EclipseNode builderAnnotationNode, EclipseNode superBuilderAnnotationNode) { boolean isAbstract = (td.modifiers & ClassFileConstants.AccAbstract) != 0; if (isAbstract) { @@ -163,8 +160,7 @@ public class HandleJacksonized extends EclipseAnnotationHandler { private void handleJacksonizedAccessors(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, EclipseNode tdNode, TypeDeclaration td, EclipseNode accessorsAnnotationNode, boolean jacksonizedBuilder) { AnnotationValues accessorsAnnotation = accessorsAnnotationNode != null ? - createAnnotation(Accessors.class, accessorsAnnotationNode) : - null; + createAnnotation(Accessors.class, accessorsAnnotationNode) : null; boolean fluent = accessorsAnnotation != null && accessorsAnnotation.getInstance().fluent(); if (!fluent) { @@ -183,28 +179,24 @@ public class HandleJacksonized extends EclipseAnnotationHandler { } tdNode.rebuild(); } - + private void createJsonPropertyForField(EclipseNode fieldNode, EclipseNode annotationNode) { - if (hasAnnotation("com.fasterxml.jackson.annotation.JsonProperty", fieldNode)) { - return; - } + if (hasAnnotation("com.fasterxml.jackson.annotation.JsonProperty", fieldNode)) return; ASTNode astNode = fieldNode.get(); if (astNode instanceof FieldDeclaration) { FieldDeclaration fd = (FieldDeclaration)astNode; StringLiteral fieldName = new StringLiteral(fd.name, 0, 0, 0); - ((FieldDeclaration)astNode).annotations = addAnnotation(fieldNode.get(), fd.annotations, JSON_PROPERTY_ANNOTATION, fieldName); + ((FieldDeclaration) astNode).annotations = addAnnotation(fieldNode.get(), fd.annotations, JSON_PROPERTY_ANNOTATION, fieldName); } } - private String getBuilderClassName(Annotation ast, EclipseNode annotationNode, EclipseNode annotatedNode, TypeDeclaration td, AnnotationValues 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"; - + if (builderClassName == null || builderClassName.isEmpty()) builderClassName = "*Builder"; + MethodDeclaration fillParametersFrom = annotatedNode.get() instanceof MethodDeclaration ? (MethodDeclaration) annotatedNode.get() : null; char[] replacement; if (fillParametersFrom != null) { @@ -216,23 +208,22 @@ public class HandleJacksonized extends EclipseAnnotationHandler { } builderClassName = builderClassName.replace("*", new String(replacement)); } - - if (builderAnnotation == null) - builderClassName += "Impl"; // For @SuperBuilder, all Jackson annotations must be put on the BuilderImpl class. + + 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 result = new ArrayList(); for (Annotation annotation : td.annotations) { TypeReference typeRef = annotation.type; if (typeRef != null && typeRef.getTypeName() != null) { - for (String bn : HandlerUtil.JACKSON_COPY_TO_BUILDER_ANNOTATIONS) { + for (String bn : HandlerUtil.JACKSON_COPY_TO_BUILDER_ANNOTATIONS) { if (typeMatches(bn, node, typeRef)) { result.add(annotation); break; diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index 4712af65..d2741a13 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -162,13 +162,9 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { job.init(annotation, annInstance, annotationNode); boolean generateBuilderMethod; - if (job.builderMethodName.isEmpty()) { - generateBuilderMethod = false; - } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) { - return; - } else { - generateBuilderMethod = true; - } + if (job.builderMethodName.isEmpty()) generateBuilderMethod = false; + else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) return; + else generateBuilderMethod = true; if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return; @@ -343,9 +339,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { if (sd == null) continue; EclipseSingularizer singularizer = sd.getSingularizer(); if (singularizer == null) continue; - if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderAbstractType, sd)) { - bfd.singularData = null; - } + if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderAbstractType, sd)) bfd.singularData = null; } } @@ -407,9 +401,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { } // Let toString() call super.toString() if there is a superclass, so that it also shows fields from the superclass' builder. MethodDeclaration md = HandleToString.createToString(job.builderType, fieldNodes, true, superclassBuilderClass != null, ast, FieldAccess.ALWAYS_FIELD); - if (md != null) { - injectMethod(job.builderType, md); - } + if (md != null) injectMethod(job.builderType, md); } if (addCleaning) { @@ -593,7 +585,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { char[][] setVariableInBuilder = new char[][] {BUILDER_VARIABLE_NAME, fieldNode.nameOfSetFlag}; long[] positions = new long[] {p, p}; QualifiedNameReference setVariableInBuilderRef = new QualifiedNameReference(setVariableInBuilder, positions, s, e); - + MessageSend defaultMethodCall = new MessageSend(); defaultMethodCall.sourceStart = job.source.sourceStart; defaultMethodCall.sourceEnd = job.source.sourceEnd; @@ -696,7 +688,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.parentType.get()).scope); return out; } - + /** * Generates a {@code $fillValuesFrom()} method in the abstract builder class. * It looks like: @@ -718,9 +710,9 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { TypeReference builderType = new SingleTypeReference(classGenericName.toCharArray(), 0); out.arguments = new Argument[] {new Argument(INSTANCE_VARIABLE_NAME, 0, builderType, Modifier.FINAL)}; - + List body = new ArrayList(); - + if (inherited) { // Call super. MessageSend callToSuper = new MessageSend(); @@ -729,14 +721,14 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { callToSuper.arguments = new Expression[] {new SingleNameReference(INSTANCE_VARIABLE_NAME, 0)}; body.add(callToSuper); } - + // Call the builder implemention's helper method that actually fills the values from the instance. MessageSend callStaticFillValuesMethod = new MessageSend(); callStaticFillValuesMethod.receiver = generateNameReference(job.parentType, job.builderAbstractClassNameArr, 0); callStaticFillValuesMethod.selector = FILL_VALUES_STATIC_METHOD_NAME; callStaticFillValuesMethod.arguments = new Expression[] {new SingleNameReference(INSTANCE_VARIABLE_NAME, 0), new ThisReference(0, 0)}; body.add(callStaticFillValuesMethod); - + // Return self(). MessageSend returnCall = new MessageSend(); returnCall.receiver = ThisReference.implicitThis(); @@ -747,7 +739,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { return out; } - + /** * Generates a {@code $fillValuesFromInstanceIntoBuilder()} method in * the builder implementation class that copies all fields from the instance @@ -1095,8 +1087,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { java.util.HashSet usedNames = new HashSet(); // 1. Add type parameter names. - for (TypeParameter typeParam : typeParams) - usedNames.add(typeParam.toString()); + for (TypeParameter typeParam : typeParams) usedNames.add(typeParam.toString()); // 2. Add class name. usedNames.add(String.valueOf(td.name)); @@ -1119,14 +1110,12 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { return usedNames; } - + private void addFirstToken(java.util.Set usedNames, TypeReference type) { - if (type == null) - return; + if (type == null) return; // Add the first token, because only that can collide. char[][] typeName = type.getTypeName(); - if (typeName != null && typeName.length >= 1) - usedNames.add(String.valueOf(typeName[0])); + if (typeName != null && typeName.length >= 1) usedNames.add(String.valueOf(typeName[0])); } private String generateNonclashingNameFor(String classGenericName, java.util.Set typeParamStrings) { @@ -1227,8 +1216,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { // Cannot use typeMatches() here, because the parameter could be fully-qualified, partially-qualified, or not qualified. // A string-compare of the last part should work. If it's a false-positive, users could still @Tolerate it. char[] typeName = def.arguments[0].type.getLastToken(); - if (builderClassName.equals(String.valueOf(typeName))) - return true; + if (builderClassName.equals(String.valueOf(typeName))) return true; } } } diff --git a/src/core/lombok/javac/handlers/HandleJacksonized.java b/src/core/lombok/javac/handlers/HandleJacksonized.java index c0cff164..d0988ad7 100644 --- a/src/core/lombok/javac/handlers/HandleJacksonized.java +++ b/src/core/lombok/javac/handlers/HandleJacksonized.java @@ -62,17 +62,15 @@ public class HandleJacksonized extends JavacAnnotationHandler { @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.JACKSONIZED_FLAG_USAGE, "@Jacksonized"); - + 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. + 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); JavacNode accessorsAnnotationNode = findAnnotation(Accessors.class, annotatedNode); @@ -88,12 +86,11 @@ public class HandleJacksonized extends JavacAnnotationHandler { if (accessorsAnnotationNode != null) { handleJacksonizedAccessors(annotationNode, annotatedNode, tdNode, td, accessorsAnnotationNode, builderAnnotationNode != null || superBuilderAnnotationNode != null); } - } - + } + private void handleJacksonizedAccessors(JavacNode annotationNode, JavacNode annotatedNode, JavacNode tdNode, JCClassDecl td, JavacNode accessorsAnnotationNode, boolean jacksonizedBuilder) { AnnotationValues accessorsAnnotation = accessorsAnnotationNode != null ? - createAnnotation(Accessors.class, accessorsAnnotationNode) : - null; + createAnnotation(Accessors.class, accessorsAnnotationNode) : null; boolean fluent = accessorsAnnotation != null && accessorsAnnotation.getInstance().fluent(); if (!fluent) { @@ -110,7 +107,7 @@ public class HandleJacksonized extends JavacAnnotationHandler { } } } - + private void createJsonPropertyForField(JavacNode fieldNode, JavacNode annotationNode) { if (hasAnnotation("com.fasterxml.jackson.annotation.JsonProperty", fieldNode)) { return; @@ -123,13 +120,13 @@ public class HandleJacksonized extends JavacAnnotationHandler { 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; } - + 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)."); @@ -137,24 +134,22 @@ public class HandleJacksonized extends JavacAnnotationHandler { } AnnotationValues builderAnnotation = builderAnnotationNode != null ? - createAnnotation(Builder.class, builderAnnotationNode) : - null; + createAnnotation(Builder.class, builderAnnotationNode) : null; AnnotationValues superBuilderAnnotation = superBuilderAnnotationNode != null ? - createAnnotation(SuperBuilder.class, superBuilderAnnotationNode) : - null; + createAnnotation(SuperBuilder.class, superBuilderAnnotationNode) : null; String setPrefix = builderAnnotation != null ? builderAnnotation.getInstance().setterPrefix() : - superBuilderAnnotation.getInstance().setterPrefix(); + superBuilderAnnotation.getInstance().setterPrefix(); String buildMethodName = builderAnnotation != null ? builderAnnotation.getInstance().buildMethodName() : - superBuilderAnnotation.getInstance().buildMethodName(); + superBuilderAnnotation.getInstance().buildMethodName(); JavacTreeMaker maker = annotatedNode.getTreeMaker(); - + // Now lets find the generated builder class. String builderClassName = getBuilderClassName(annotationNode, annotatedNode, td, builderAnnotation, maker); - + JCClassDecl builderClass = null; for (JCTree member : td.getMembers()) { if (member instanceof JCClassDecl && ((JCClassDecl) member).getSimpleName().contentEquals(builderClassName)) { @@ -196,20 +191,17 @@ public class HandleJacksonized extends JavacAnnotationHandler { JCAnnotation annotationJsonPOJOBuilder = maker.Annotation(jsonPOJOBuilderType, List.of(withPrefixExpr, buildMethodNameExpr)); recursiveSetGeneratedBy(annotationJsonPOJOBuilder, annotatedNode); builderClass.mods.annotations = builderClass.mods.annotations.append(annotationJsonPOJOBuilder); - + // @SuperBuilder? Make it package-private! - if (superBuilderAnnotationNode != null) - builderClass.mods.flags = builderClass.mods.flags & ~Flags.PRIVATE; + if (superBuilderAnnotationNode != null) builderClass.mods.flags = builderClass.mods.flags & ~Flags.PRIVATE; } - + private String getBuilderClassName(JavacNode annotationNode, JavacNode annotatedNode, JCClassDecl td, AnnotationValues builderAnnotation, JavacTreeMaker maker) { - String builderClassName = builderAnnotation != null ? - builderAnnotation.getInstance().builderClassName() : null; + 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"; - + 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("")) { @@ -226,9 +218,8 @@ public class HandleJacksonized extends JavacAnnotationHandler { } builderClassName = builderClassName.replace("*", replacement); } - - if (builderAnnotation == null) - builderClassName += "Impl"; // For @SuperBuilder, all Jackson annotations must be put on the BuilderImpl class. + + if (builderAnnotation == null) builderClassName += "Impl"; // For @SuperBuilder, all Jackson annotations must be put on the BuilderImpl class. return builderClassName; } @@ -238,7 +229,7 @@ public class HandleJacksonized extends JavacAnnotationHandler { for (JavacNode child : node.down()) { if (child.getKind() == Kind.ANNOTATION) { JCAnnotation annotation = (JCAnnotation) child.get(); - for (String bn : HandlerUtil.JACKSON_COPY_TO_BUILDER_ANNOTATIONS) { + for (String bn : HandlerUtil.JACKSON_COPY_TO_BUILDER_ANNOTATIONS) { if (typeMatches(bn, node, annotation.annotationType)) { result.append(annotation); break; diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index ffcbe21f..08a16b92 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -143,13 +143,10 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { job.init(annotation, annInstance, annotationNode); boolean generateBuilderMethod; - if (job.builderMethodName.isEmpty()) { - generateBuilderMethod = false; - } else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) { - return; - } else { - generateBuilderMethod = true; - } + if (job.builderMethodName.isEmpty()) generateBuilderMethod = false; + else if (!checkName("builderMethodName", job.builderMethodName, annotationNode)) return; + else generateBuilderMethod = true; + if (!checkName("buildMethodName", job.buildMethodName, annotationNode)) return; // Do not delete the SuperBuilder annotation here, we need it for @Jacksonized. @@ -313,9 +310,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { if (sd == null) continue; JavacSingularizer singularizer = sd.getSingularizer(); if (singularizer == null) continue; - if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderAbstractType, sd)) { - bfd.singularData = null; - } + if (singularizer.checkForAlreadyExistingNodesAndGenerateError(job.builderAbstractType, sd)) bfd.singularData = null; } } @@ -389,7 +384,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { } sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(job.builderImplType, annotationNode); } - + // Create a simple constructor for the BuilderImpl class. JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PRIVATE, List.nil(), job.builderImplType, List.nil(), false, annotationNode); if (cd != null) injectMethod(job.builderImplType, cd); @@ -515,7 +510,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { recursiveSetGeneratedBy(builder, job.sourceNode); return injectType(job.parentType, builder); } - + /** * Generates a constructor that has a builder as the only parameter. * The values from the builder are used to initialize the fields of new instances. @@ -582,8 +577,8 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { if (callBuilderBasedSuperConstructor) { // The first statement must be the call to the super constructor. JCMethodInvocation callToSuperConstructor = maker.Apply(List.nil(), - maker.Ident(job.toName("super")), - List.of(maker.Ident(builderVariableName))); + maker.Ident(job.toName("super")), + List.of(maker.Ident(builderVariableName))); statements.prepend(maker.Exec(callToSuperConstructor)); } @@ -659,7 +654,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { createRelevantNonNullAnnotation(job.parentType, methodDef); return methodDef; } - + /** * Generates a {@code $fillValuesFrom()} method in the abstract builder class. * @@ -685,7 +680,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { JCExpression classGenericNameExpr = maker.Ident(job.toName(classGenericName)); JCVariableDecl param = maker.VarDef(maker.Modifiers(Flags.PARAMETER | Flags.FINAL), job.toName(INSTANCE_VARIABLE_NAME), classGenericNameExpr, null); - + ListBuffer body = new ListBuffer(); if (inherited) { @@ -709,7 +704,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { return maker.MethodDef(modifiers, name, returnType, List.nil(), List.of(param), List.nil(), bodyBlock, null); } - + /** * Generates a {@code $fillValuesFromInstanceIntoBuilder()} method in * the builder implementation class that copies all fields from the instance @@ -731,7 +726,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { // 1st parameter: "Foobar instance" JCVariableDecl paramInstance = maker.VarDef(maker.Modifiers(Flags.PARAMETER | Flags.FINAL), job.toName(INSTANCE_VARIABLE_NAME), cloneSelfType(job.parentType), null); - + // 2nd parameter: "FoobarBuilder b" (plus generics on the annotated type) // First add all generics that are present on the parent type. ListBuffer typeParamsForBuilderParameter = getTypeParamExpressions(job.typeParams, maker, job.sourceNode); @@ -804,7 +799,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { Name name = job.toName(SELF_METHOD); JCExpression returnType = maker.Ident(job.toName(builderGenericName)); returnType = addCheckerFrameworkReturnsReceiver(returnType, maker, job.builderType, job.checkerFramework); - + return maker.MethodDef(modifiers, name, returnType, List.nil(), List.nil(), List.nil(), null, null); } @@ -1050,8 +1045,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { java.util.HashSet usedNames = new HashSet(); // 1. Add type parameter names. - for (JCTypeParameter typeParam : typeParams) - usedNames.add(typeParam.getName().toString()); + for (JCTypeParameter typeParam : typeParams) usedNames.add(typeParam.getName().toString()); // 2. Add class name. usedNames.add(td.name.toString()); @@ -1060,16 +1054,13 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { for (JCTree member : td.getMembers()) { if (member.getKind() == com.sun.source.tree.Tree.Kind.VARIABLE && member instanceof JCVariableDecl) { JCTree type = ((JCVariableDecl)member).getType(); - if (type instanceof JCIdent) - usedNames.add(((JCIdent)type).getName().toString()); + if (type instanceof JCIdent) usedNames.add(((JCIdent)type).getName().toString()); } } // 4. Add extends and implements clauses. addFirstToken(usedNames, Javac.getExtendsClause(td)); - for (JCExpression impl : td.getImplementsClause()) { - addFirstToken(usedNames, impl); - } + for (JCExpression impl : td.getImplementsClause()) addFirstToken(usedNames, impl); return usedNames; } @@ -1082,7 +1073,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { } while (type instanceof JCFieldAccess && ((JCFieldAccess)type).selected != null) { // Add the first token, because only that can collide. - type = ((JCFieldAccess)type).selected; + type = ((JCFieldAccess) type).selected; } usedNames.add(type.toString()); } @@ -1122,7 +1113,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { } return typeParamsForBuilderParameter; } - + private JCExpression copySelect(JavacTreeMaker maker, JCFieldAccess typeParam) { java.util.List chainNames = new ArrayList(); JCExpression expression = typeParam; @@ -1135,7 +1126,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { expression = null; } } - + Collections.reverse(chainNames); JCExpression typeParameter = null; for (Name name : chainNames) { @@ -1158,18 +1149,16 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { JCMethodDecl md = (JCMethodDecl) def; String name = md.name.toString(); boolean matches = name.equals(""); - if (isTolerate(type, md)) - continue; + if (isTolerate(type, md)) continue; if (matches && md.params != null && md.params.length() == 1) { // Cannot use typeMatches() here, because the parameter could be fully-qualified, partially-qualified, or not qualified. // A string-compare of the last part should work. If it's a false-positive, users could still @Tolerate it. String typeName = md.params.get(0).getType().toString(); int lastIndexOfDot = typeName.lastIndexOf('.'); if (lastIndexOfDot >= 0) { - typeName = typeName.substring(lastIndexOfDot+1); + typeName = typeName.substring(lastIndexOfDot + 1); } - if ((builderClassName+"").equals(typeName)) - return true; + if ((builderClassName+"").equals(typeName)) return true; } } } From ddbdaba889faf3e7450ed7e6303dd8b9fc1989ad Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Fri, 23 May 2025 02:50:09 +0200 Subject: [PATCH 22/22] [trivial] Update copyright years --- src/core/lombok/Builder.java | 2 +- src/core/lombok/ConfigurationKeys.java | 2 +- src/core/lombok/core/configuration/ConfigurationValueType.java | 2 +- src/core/lombok/eclipse/TransformEclipseAST.java | 2 +- src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java | 2 +- src/core/lombok/eclipse/handlers/HandleGetter.java | 2 +- src/core/lombok/eclipse/handlers/HandleJacksonized.java | 2 +- src/core/lombok/eclipse/handlers/HandleSetter.java | 2 +- src/core/lombok/eclipse/handlers/HandleSuperBuilder.java | 2 +- .../eclipse/handlers/singulars/EclipseGuavaSingularizer.java | 2 +- .../handlers/singulars/EclipseJavaUtilMapSingularizer.java | 2 +- .../handlers/singulars/EclipseJavaUtilSetSingularizer.java | 2 +- src/core/lombok/experimental/SuperBuilder.java | 2 +- src/core/lombok/experimental/UtilityClass.java | 2 +- src/core/lombok/extern/jackson/Jacksonized.java | 2 +- src/core/lombok/javac/handlers/HandleBuilder.java | 2 +- src/core/lombok/javac/handlers/HandleGetter.java | 2 +- src/core/lombok/javac/handlers/HandleJacksonized.java | 2 +- src/core/lombok/javac/handlers/HandleSetter.java | 2 +- src/core/lombok/javac/handlers/HandleSuperBuilder.java | 2 +- src/core/lombok/javac/handlers/JavacSingularsRecipes.java | 2 +- src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java | 2 +- src/launch/lombok/launch/ShadowClassLoader.java | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/core/lombok/Builder.java b/src/core/lombok/Builder.java index da707082..efa60710 100644 --- a/src/core/lombok/Builder.java +++ b/src/core/lombok/Builder.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2018 The Project Lombok Authors. + * Copyright (C) 2013-2025 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 diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 5459b1eb..ce31bddf 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2023 The Project Lombok Authors. + * Copyright (C) 2013-2025 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 diff --git a/src/core/lombok/core/configuration/ConfigurationValueType.java b/src/core/lombok/core/configuration/ConfigurationValueType.java index e752232a..c1d2e4e6 100644 --- a/src/core/lombok/core/configuration/ConfigurationValueType.java +++ b/src/core/lombok/core/configuration/ConfigurationValueType.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Project Lombok Authors. + * Copyright (C) 2019-2025 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 diff --git a/src/core/lombok/eclipse/TransformEclipseAST.java b/src/core/lombok/eclipse/TransformEclipseAST.java index 16075857..bedf46dd 100644 --- a/src/core/lombok/eclipse/TransformEclipseAST.java +++ b/src/core/lombok/eclipse/TransformEclipseAST.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2023 The Project Lombok Authors. + * Copyright (C) 2009-2025 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 diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java index df611f78..61e49326 100755 --- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java +++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2021 The Project Lombok Authors. + * Copyright (C) 2015-2025 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 diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java index 88d5fe24..9bec523a 100644 --- a/src/core/lombok/eclipse/handlers/HandleGetter.java +++ b/src/core/lombok/eclipse/handlers/HandleGetter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2024 The Project Lombok Authors. + * Copyright (C) 2009-2025 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 diff --git a/src/core/lombok/eclipse/handlers/HandleJacksonized.java b/src/core/lombok/eclipse/handlers/HandleJacksonized.java index ee0108d7..0a3f5dba 100644 --- a/src/core/lombok/eclipse/handlers/HandleJacksonized.java +++ b/src/core/lombok/eclipse/handlers/HandleJacksonized.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2021 The Project Lombok Authors. + * Copyright (C) 2020-2025 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 diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index e0bea89b..dc2c2139 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2024 The Project Lombok Authors. + * Copyright (C) 2009-2025 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 diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index d2741a13..096398b8 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2021 The Project Lombok Authors. + * Copyright (C) 2013-2025 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 diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index e77bde74..85c7d605 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2021 The Project Lombok Authors. + * Copyright (C) 2015-2025 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 diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java index e9ee2252..eee849f2 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2021 The Project Lombok Authors. + * Copyright (C) 2015-2025 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 diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java index a432f3fe..be6d13f7 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2021 The Project Lombok Authors. + * Copyright (C) 2015-2025 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 diff --git a/src/core/lombok/experimental/SuperBuilder.java b/src/core/lombok/experimental/SuperBuilder.java index f265e65c..630fb73b 100644 --- a/src/core/lombok/experimental/SuperBuilder.java +++ b/src/core/lombok/experimental/SuperBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Project Lombok Authors. + * Copyright (C) 2018-2025 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 diff --git a/src/core/lombok/experimental/UtilityClass.java b/src/core/lombok/experimental/UtilityClass.java index 4e3098e5..81c01cec 100644 --- a/src/core/lombok/experimental/UtilityClass.java +++ b/src/core/lombok/experimental/UtilityClass.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 The Project Lombok Authors. + * Copyright (C) 2015-2025 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 diff --git a/src/core/lombok/extern/jackson/Jacksonized.java b/src/core/lombok/extern/jackson/Jacksonized.java index fd482d00..5e28bf07 100644 --- a/src/core/lombok/extern/jackson/Jacksonized.java +++ b/src/core/lombok/extern/jackson/Jacksonized.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Project Lombok Authors. + * Copyright (C) 2020-2025 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 diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 17fdc64d..1e023f20 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2021 The Project Lombok Authors. + * Copyright (C) 2013-2025 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 diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 8c130b6a..f6b28ffb 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2024 The Project Lombok Authors. + * Copyright (C) 2009-2025 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 diff --git a/src/core/lombok/javac/handlers/HandleJacksonized.java b/src/core/lombok/javac/handlers/HandleJacksonized.java index d0988ad7..689e3d6d 100644 --- a/src/core/lombok/javac/handlers/HandleJacksonized.java +++ b/src/core/lombok/javac/handlers/HandleJacksonized.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 The Project Lombok Authors. + * Copyright (C) 2020-2025 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 diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index d76c7ab6..0764c768 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2024 The Project Lombok Authors. + * Copyright (C) 2009-2025 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 diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 08a16b92..11b3d39d 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2021 The Project Lombok Authors. + * Copyright (C) 2013-2025 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 diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java index 78e4bcdf..58433d6d 100644 --- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java +++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2021 The Project Lombok Authors. + * Copyright (C) 2015-2025 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 diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java b/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java index 09d26242..2d39f8b4 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchJavadoc.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2024 The Project Lombok Authors. + * Copyright (C) 2020-2025 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 diff --git a/src/launch/lombok/launch/ShadowClassLoader.java b/src/launch/lombok/launch/ShadowClassLoader.java index b681e293..a646f954 100644 --- a/src/launch/lombok/launch/ShadowClassLoader.java +++ b/src/launch/lombok/launch/ShadowClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2023 The Project Lombok Authors. + * Copyright (C) 2014-2025 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