From 736904298202bb75c27243f930c9e48bf2139be9 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Thu, 26 Mar 2020 23:21:44 +0100 Subject: [SuperBuilder] test qualified type references in extends clause --- test/transform/resource/after-delombok/SuperBuilderBasic.java | 4 ++-- test/transform/resource/after-ecj/SuperBuilderBasic.java | 4 ++-- test/transform/resource/before/SuperBuilderBasic.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'test/transform/resource') diff --git a/test/transform/resource/after-delombok/SuperBuilderBasic.java b/test/transform/resource/after-delombok/SuperBuilderBasic.java index c347e41c..c3fa86f2 100644 --- a/test/transform/resource/after-delombok/SuperBuilderBasic.java +++ b/test/transform/resource/after-delombok/SuperBuilderBasic.java @@ -81,10 +81,10 @@ public class SuperBuilderBasic { return new SuperBuilderBasic.Parent.ParentBuilderImpl(); } } - public static class Child extends Parent { + public static class Child extends SuperBuilderBasic.Parent { double field3; @java.lang.SuppressWarnings("all") - public static abstract class ChildBuilder> extends Parent.ParentBuilder { + public static abstract class ChildBuilder> extends SuperBuilderBasic.Parent.ParentBuilder { @java.lang.SuppressWarnings("all") private double field3; @java.lang.Override diff --git a/test/transform/resource/after-ecj/SuperBuilderBasic.java b/test/transform/resource/after-ecj/SuperBuilderBasic.java index b47f318d..7902c95f 100644 --- a/test/transform/resource/after-ecj/SuperBuilderBasic.java +++ b/test/transform/resource/after-ecj/SuperBuilderBasic.java @@ -71,8 +71,8 @@ public class SuperBuilderBasic { return new SuperBuilderBasic.Parent.ParentBuilderImpl(); } } - public static @lombok.experimental.SuperBuilder class Child extends Parent { - public static abstract @java.lang.SuppressWarnings("all") class ChildBuilder> extends Parent.ParentBuilder { + public static @lombok.experimental.SuperBuilder class Child extends SuperBuilderBasic.Parent { + public static abstract @java.lang.SuppressWarnings("all") class ChildBuilder> extends SuperBuilderBasic.Parent.ParentBuilder { private @java.lang.SuppressWarnings("all") double field3; public ChildBuilder() { super(); diff --git a/test/transform/resource/before/SuperBuilderBasic.java b/test/transform/resource/before/SuperBuilderBasic.java index f4e8c670..99d7284e 100644 --- a/test/transform/resource/before/SuperBuilderBasic.java +++ b/test/transform/resource/before/SuperBuilderBasic.java @@ -8,7 +8,7 @@ public class SuperBuilderBasic { } @lombok.experimental.SuperBuilder - public static class Child extends Parent { + public static class Child extends SuperBuilderBasic.Parent { double field3; } -- cgit From d34fdeb3b4b44aae8c03cee0d3b1dd35a3d74e31 Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Tue, 14 Apr 2020 23:15:50 +0200 Subject: [fixes #2246] Add null check --- src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java | 8 +++++--- test/transform/resource/after-delombok/TypeUseAnnotations.java | 10 ++++++++++ test/transform/resource/after-ecj/TypeUseAnnotations.java | 9 +++++++++ test/transform/resource/before/TypeUseAnnotations.java | 2 ++ 4 files changed, 26 insertions(+), 3 deletions(-) (limited to 'test/transform/resource') diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 4df7a90b..2c6e1e77 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -660,9 +660,11 @@ public class EclipseHandlerUtil { Annotation[][] b = new Annotation[a.length][]; for (int i = 0; i < a.length; i++) { - b[i] = new Annotation[a[i].length]; - for (int j = 0 ; j < a[i].length; j++) { - b[i][j] = copyAnnotation(a[i][j], a[i][j]); + if (a[i] != null) { + b[i] = new Annotation[a[i].length]; + for (int j = 0 ; j < a[i].length; j++) { + b[i][j] = copyAnnotation(a[i][j], a[i][j]); + } } } diff --git a/test/transform/resource/after-delombok/TypeUseAnnotations.java b/test/transform/resource/after-delombok/TypeUseAnnotations.java index 1e1536bf..fbf32577 100644 --- a/test/transform/resource/after-delombok/TypeUseAnnotations.java +++ b/test/transform/resource/after-delombok/TypeUseAnnotations.java @@ -7,8 +7,18 @@ import java.util.List; } class TypeUseAnnotations { List<@TA(x = 5) String> foo; + List bar; + + class Inner { + } + @java.lang.SuppressWarnings("all") public List<@TA(x = 5) String> getFoo() { return this.foo; } + + @java.lang.SuppressWarnings("all") + public List getBar() { + return this.bar; + } } diff --git a/test/transform/resource/after-ecj/TypeUseAnnotations.java b/test/transform/resource/after-ecj/TypeUseAnnotations.java index 156643b9..7041b59e 100644 --- a/test/transform/resource/after-ecj/TypeUseAnnotations.java +++ b/test/transform/resource/after-ecj/TypeUseAnnotations.java @@ -5,11 +5,20 @@ import java.util.List; int x(); } class TypeUseAnnotations { + class Inner { + Inner() { + super(); + } + } @lombok.Getter List<@TA(x = 5) String> foo; + @lombok.Getter List bar; TypeUseAnnotations() { super(); } public @java.lang.SuppressWarnings("all") List<@TA(x = 5) String> getFoo() { return this.foo; } + public @java.lang.SuppressWarnings("all") List getBar() { + return this.bar; + } } \ No newline at end of file diff --git a/test/transform/resource/before/TypeUseAnnotations.java b/test/transform/resource/before/TypeUseAnnotations.java index c09a291d..7175930f 100644 --- a/test/transform/resource/before/TypeUseAnnotations.java +++ b/test/transform/resource/before/TypeUseAnnotations.java @@ -8,4 +8,6 @@ import java.util.List; } class TypeUseAnnotations { @lombok.Getter List<@TA(x=5) String> foo; + @lombok.Getter List bar; + class Inner { } } -- cgit From dede79bc224eb16566a027f83214c04e065b575b Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Mon, 6 Apr 2020 21:43:58 +0200 Subject: copy more Jackson annotation to the builder, also for @Singular methods --- src/core/lombok/core/handlers/HandlerUtil.java | 9 +- .../eclipse/handlers/EclipseHandlerUtil.java | 37 ++++- .../singulars/EclipseGuavaSingularizer.java | 12 +- .../EclipseJavaUtilListSetSingularizer.java | 12 +- .../singulars/EclipseJavaUtilMapSingularizer.java | 8 +- .../lombok/javac/handlers/HandleJacksonized.java | 1 - .../lombok/javac/handlers/JavacHandlerUtil.java | 18 ++- .../javac/handlers/JavacSingularsRecipes.java | 16 +- .../jackson/annotation/JsonAnySetter.java | 12 ++ .../after-delombok/JacksonBuilderSingular.java | 177 +++++++++++++++++++++ .../resource/after-ecj/JacksonBuilderSingular.java | 164 +++++++++++++++++++ .../resource/before/JacksonBuilderSingular.java | 31 ++++ 12 files changed, 476 insertions(+), 21 deletions(-) create mode 100644 test/stubs/com/fasterxml/jackson/annotation/JsonAnySetter.java create mode 100644 test/transform/resource/after-delombok/JacksonBuilderSingular.java create mode 100644 test/transform/resource/after-ecj/JacksonBuilderSingular.java create mode 100644 test/transform/resource/before/JacksonBuilderSingular.java (limited to 'test/transform/resource') diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index 94fd21d9..a8d56041 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -76,7 +76,7 @@ public class HandlerUtil { return 43; } - public static final List NONNULL_ANNOTATIONS, BASE_COPYABLE_ANNOTATIONS, COPY_TO_SETTER_ANNOTATIONS, JACKSON_COPY_TO_BUILDER_ANNOTATIONS; + public static final List NONNULL_ANNOTATIONS, BASE_COPYABLE_ANNOTATIONS, COPY_TO_SETTER_ANNOTATIONS, COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS, JACKSON_COPY_TO_BUILDER_ANNOTATIONS; static { NONNULL_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { "androidx.annotation.NonNull", @@ -314,6 +314,13 @@ public class HandlerUtil { COPY_TO_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { "com.fasterxml.jackson.annotation.JsonProperty", "com.fasterxml.jackson.annotation.JsonSetter", + "com.fasterxml.jackson.annotation.JsonDeserialize", + "com.fasterxml.jackson.annotation.JsonIgnore", + "com.fasterxml.jackson.annotation.JacksonInject", + "com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty", + })); + COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { + "com.fasterxml.jackson.annotation.JsonAnySetter", })); JACKSON_COPY_TO_BUILDER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { "com.fasterxml.jackson.annotation.JsonFormat", diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 4df7a90b..d066dc0f 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -26,6 +26,7 @@ import static lombok.eclipse.Eclipse.*; import static lombok.eclipse.EclipseAugments.*; import static lombok.eclipse.handlers.EclipseHandlerUtil.EclipseReflectiveMembers.*; +import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -817,6 +818,20 @@ public class EclipseHandlerUtil { * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. */ public static Annotation[] findCopyableToSetterAnnotations(EclipseNode node) { + return findAnnotationsInList(node, COPY_TO_SETTER_ANNOTATIONS); + } + + /** + * Searches the given field node for annotations that are specifically intentioned to be copied to the builder's singular method. + */ + public static Annotation[] findCopyableToBuilderSingularSetterAnnotations(EclipseNode node) { + return findAnnotationsInList(node, COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS); + } + + /** + * Searches the given field node for annotations that are in the given list, and returns those. + */ + private static Annotation[] findAnnotationsInList(EclipseNode node, java.util.List annotationsToFind) { AbstractVariableDeclaration avd = (AbstractVariableDeclaration) node.get(); if (avd.annotations == null) return EMPTY_ANNOTATIONS_ARRAY; List result = new ArrayList(); @@ -824,7 +839,7 @@ public class EclipseHandlerUtil { for (Annotation annotation : avd.annotations) { TypeReference typeRef = annotation.type; if (typeRef != null && typeRef.getTypeName() != null) { - for (String bn : COPY_TO_SETTER_ANNOTATIONS) if (typeMatches(bn, node, typeRef)) { + for (String bn : annotationsToFind) if (typeMatches(bn, node, typeRef)) { result.add(annotation); break; } @@ -2418,6 +2433,26 @@ public class EclipseHandlerUtil { return array == null ? null : array.clone(); } + public static T[] concat(T[] first, T[] second, Class type) { + if (first == null) + return second; + if (second == null) + return first; + if (first.length == 0) + return second; + if (second.length == 0) + return first; + T[] result = newArray(type, first.length + second.length); + System.arraycopy(first, 0, result, 0, first.length); + System.arraycopy(second, 0, result, first.length, second.length); + return result; + } + + @SuppressWarnings("unchecked") + private static T[] newArray(Class type, int length) { + return (T[]) Array.newInstance(type, length); + } + public static boolean isDirectDescendantOfObject(EclipseNode typeNode) { if (!(typeNode.get() instanceof TypeDeclaration)) throw new IllegalArgumentException("not a type node"); TypeDeclaration typeDecl = (TypeDeclaration) typeNode.get(); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index 392418ff..395d2e59 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -175,8 +175,10 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { md.returnType = returnType; char[] prefixedSingularName = data.getSetterPrefix().length == 0 ? data.getSingularName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getSingularName())).toCharArray(); md.selector = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray(); - md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); - + Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToBuilderSingularSetterAnnotations(data.getAnnotation().up())); + md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); + if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); data.setGeneratedByRecursive(md); HandleNonNull.INSTANCE.fix(injectMethod(builderType, md)); @@ -213,8 +215,10 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { md.returnType = returnType; char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray(); - md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); - + Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up())); + md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); + if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); data.setGeneratedByRecursive(md); injectMethod(builderType, md); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java index 375f4e2c..deab4530 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java @@ -153,8 +153,10 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula md.returnType = returnType; char[] prefixedSingularName = data.getSetterPrefix().length == 0 ? data.getSingularName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getSingularName())).toCharArray(); md.selector = fluent ? prefixedSingularName : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray(); - md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); - + Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToBuilderSingularSetterAnnotations(data.getAnnotation().up())); + md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); + if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); data.setGeneratedByRecursive(md); HandleNonNull.INSTANCE.fix(injectMethod(builderType, md)); @@ -189,8 +191,10 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula md.returnType = returnType; char[] prefixedSelector = data.getSetterPrefix().length == 0 ? data.getPluralName() : HandlerUtil.buildAccessorName(new String(data.getSetterPrefix()), new String(data.getPluralName())).toCharArray(); md.selector = fluent ? prefixedSelector : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray(); - md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); - + Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up())); + md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); + if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); data.setGeneratedByRecursive(md); injectMethod(builderType, md); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java index cb7d9ed6..1a40369d 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java @@ -252,7 +252,9 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer String setterName = HandlerUtil.buildAccessorName(setterPrefix, name); md.selector = setterName.toCharArray(); - md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); + Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToBuilderSingularSetterAnnotations(data.getAnnotation().up())); + md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); data.setGeneratedByRecursive(md); @@ -326,7 +328,9 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer String setterName = HandlerUtil.buildAccessorName(setterPrefix, name); md.selector = setterName.toCharArray(); - md.annotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); + Annotation[] selfReturnAnnotations = generateSelfReturnAnnotations(deprecate, cfv, data.getSource()); + Annotation[] copyToSetterAnnotations = copyAnnotations(md, findCopyableToSetterAnnotations(data.getAnnotation().up())); + md.annotations = concat(selfReturnAnnotations, copyToSetterAnnotations, Annotation.class); if (returnStatement != null) createRelevantNonNullAnnotation(builderType, md); data.setGeneratedByRecursive(md); diff --git a/src/core/lombok/javac/handlers/HandleJacksonized.java b/src/core/lombok/javac/handlers/HandleJacksonized.java index aff0bf63..0aa02d1b 100644 --- a/src/core/lombok/javac/handlers/HandleJacksonized.java +++ b/src/core/lombok/javac/handlers/HandleJacksonized.java @@ -149,7 +149,6 @@ public class HandleJacksonized extends JavacAnnotationHandler { // @SuperBuilder? Make it package-private! if (superBuilderAnnotationNode != null) builderClass.mods.flags = builderClass.mods.flags & ~Flags.PRIVATE; - } private String getBuilderClassName(JCAnnotation ast, JavacNode annotationNode, JavacNode annotatedNode, JCClassDecl td, AnnotationValues builderAnnotation, JavacTreeMaker maker) { diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index a3e876c4..5241a209 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1520,6 +1520,20 @@ public class JavacHandlerUtil { * Searches the given field node for annotations that are specifically intentioned to be copied to the setter. */ public static List findCopyableToSetterAnnotations(JavacNode node) { + return findAnnotationsInList(node, COPY_TO_SETTER_ANNOTATIONS); + } + + /** + * Searches the given field node for annotations that are specifically intentioned to be copied to the builder's singular method. + */ + public static List findCopyableToBuilderSingularSetterAnnotations(JavacNode node) { + return findAnnotationsInList(node, COPY_TO_BUILDER_SINGULAR_SETTER_ANNOTATIONS); + } + + /** + * Searches the given field node for annotations that are in the given list, and returns those. + */ + private static List findAnnotationsInList(JavacNode node, java.util.List annotationsToFind) { JCAnnotation anno = null; String annoName = null; for (JavacNode child : node.down()) { @@ -1537,7 +1551,7 @@ public class JavacHandlerUtil { if (annoName == null) return List.nil(); if (!annoName.isEmpty()) { - for (String bn : COPY_TO_SETTER_ANNOTATIONS) if (typeMatches(bn, node, anno.annotationType)) return List.of(anno); + for (String bn : annotationsToFind) if (typeMatches(bn, node, anno.annotationType)) return List.of(anno); } ListBuffer result = new ListBuffer(); @@ -1545,7 +1559,7 @@ public class JavacHandlerUtil { if (child.getKind() == Kind.ANNOTATION) { JCAnnotation annotation = (JCAnnotation) child.get(); boolean match = false; - if (!match) for (String bn : COPY_TO_SETTER_ANNOTATIONS) if (typeMatches(bn, node, annotation.annotationType)) { + if (!match) for (String bn : annotationsToFind) if (typeMatches(bn, node, annotation.annotationType)) { result.append(annotation); break; } diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java index ba052b5a..7cd52c8c 100644 --- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java +++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java @@ -182,11 +182,12 @@ public class JavacSingularsRecipes { return this; } - protected JCModifiers makeMods(JavacTreeMaker maker, CheckerFrameworkVersion cfv, JavacNode node, boolean deprecate, AccessLevel access) { + protected JCModifiers makeMods(JavacTreeMaker maker, CheckerFrameworkVersion cfv, JavacNode node, boolean deprecate, AccessLevel access, List methodAnnotations) { JCAnnotation deprecateAnn = deprecate ? maker.Annotation(genJavaLangTypeRef(node, "Deprecated"), List.nil()) : null; JCAnnotation rrAnn = cfv.generateReturnsReceiver() ? maker.Annotation(genTypeRef(node, CheckerFrameworkVersion.NAME__RETURNS_RECEIVER), List.nil()) : null; List annsOnMethod = (deprecateAnn != null && rrAnn != null) ? List.of(deprecateAnn, rrAnn) : deprecateAnn != null ? List.of(deprecateAnn) : rrAnn != null ? List.of(rrAnn) : List.nil(); + annsOnMethod = mergeAnnotations(annsOnMethod,methodAnnotations); return maker.Modifiers(toJavacModifier(access), annsOnMethod); } @@ -271,10 +272,10 @@ public class JavacSingularsRecipes { generateClearMethod(cfv, deprecate, maker, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, source, access); } - private void finishAndInjectMethod(CheckerFrameworkVersion cfv, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean deprecate, ListBuffer statements, Name methodName, List jcVariableDecls, AccessLevel access, Boolean ignoreNullCollections) { + private void finishAndInjectMethod(CheckerFrameworkVersion cfv, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean deprecate, ListBuffer statements, Name methodName, List jcVariableDecls, List methodAnnotations, AccessLevel access, Boolean ignoreNullCollections) { if (returnStatement != null) statements.append(returnStatement); JCBlock body = maker.Block(0, statements.toList()); - JCModifiers mods = makeMods(maker, cfv, builderType, deprecate, access); + JCModifiers mods = makeMods(maker, cfv, builderType, deprecate, access, methodAnnotations); List typeParams = List.nil(); List thrown = List.nil(); @@ -298,7 +299,7 @@ public class JavacSingularsRecipes { statements.add(clearStatement); Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString())); - finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, methodName, List.nil(), access, null); + finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, methodName, List.nil(), List.nil(), access, null); } protected abstract JCStatement generateClearStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType); @@ -312,7 +313,8 @@ public class JavacSingularsRecipes { if (!setterPrefix.isEmpty()) name = builderType.toName(HandlerUtil.buildAccessorName(setterPrefix, name.toString())); statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source)); - finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, access, null); + List methodAnnotations = copyAnnotations(findCopyableToBuilderSingularSetterAnnotations(data.annotation.up())); + finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, params, methodAnnotations, access, null); } protected JCVariableDecl generateSingularMethodParameter(int typeIndex, JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source, Name name) { @@ -357,8 +359,10 @@ public class JavacSingularsRecipes { } else { statements.prepend(JavacHandlerUtil.generateNullCheck(maker, null, data.getPluralName(), builderType, "%s cannot be null")); } + + List methodAnnotations = copyAnnotations(findCopyableToSetterAnnotations(data.annotation.up())); - finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param), access, ignoreNullCollections); + finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param), methodAnnotations, access, ignoreNullCollections); } protected ListBuffer generatePluralMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) { diff --git a/test/stubs/com/fasterxml/jackson/annotation/JsonAnySetter.java b/test/stubs/com/fasterxml/jackson/annotation/JsonAnySetter.java new file mode 100644 index 00000000..51d2c3fa --- /dev/null +++ b/test/stubs/com/fasterxml/jackson/annotation/JsonAnySetter.java @@ -0,0 +1,12 @@ +package com.fasterxml.jackson.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface JsonAnySetter { + boolean enabled() default true; +} diff --git a/test/transform/resource/after-delombok/JacksonBuilderSingular.java b/test/transform/resource/after-delombok/JacksonBuilderSingular.java new file mode 100644 index 00000000..feaa6832 --- /dev/null +++ b/test/transform/resource/after-delombok/JacksonBuilderSingular.java @@ -0,0 +1,177 @@ +import java.util.List; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +@com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonBuilderSingular.JacksonBuilderSingularBuilder.class) +public class JacksonBuilderSingular { + @JsonAnySetter + private Map any; + @JsonProperty("v_a_l_u_e_s") + private List values; + @JsonAnySetter + private ImmutableMap guavaAny; + @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) { + this.any = any; + this.values = values; + this.guavaAny = guavaAny; + this.guavaValues = guavaValues; + } + @java.lang.SuppressWarnings("all") + @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "", buildMethodName = "build") + public static class JacksonBuilderSingularBuilder { + @java.lang.SuppressWarnings("all") + private java.util.ArrayList any$key; + @java.lang.SuppressWarnings("all") + private java.util.ArrayList any$value; + @java.lang.SuppressWarnings("all") + private java.util.ArrayList values; + @java.lang.SuppressWarnings("all") + private com.google.common.collect.ImmutableMap.Builder guavaAny; + @java.lang.SuppressWarnings("all") + private com.google.common.collect.ImmutableList.Builder guavaValues; + @java.lang.SuppressWarnings("all") + JacksonBuilderSingularBuilder() { + } + @JsonAnySetter + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final String anyKey, final Object anyValue) { + if (this.any$key == null) { + this.any$key = new java.util.ArrayList(); + this.any$value = new java.util.ArrayList(); + } + this.any$key.add(anyKey); + this.any$value.add(anyValue); + return this; + } + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final java.util.Map any) { + if (any == null) { + throw new java.lang.NullPointerException("any cannot be null"); + } + if (this.any$key == null) { + this.any$key = new java.util.ArrayList(); + this.any$value = new java.util.ArrayList(); + } + for (final java.util.Map.Entry $lombokEntry : any.entrySet()) { + this.any$key.add($lombokEntry.getKey()); + this.any$value.add($lombokEntry.getValue()); + } + return this; + } + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearAny() { + if (this.any$key != null) { + this.any$key.clear(); + this.any$value.clear(); + } + return this; + } + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular.JacksonBuilderSingularBuilder value(final String value) { + if (this.values == null) this.values = new java.util.ArrayList(); + 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) { + if (values == null) { + throw new java.lang.NullPointerException("values cannot be null"); + } + if (this.values == null) this.values = new java.util.ArrayList(); + this.values.addAll(values); + return this; + } + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearValues() { + if (this.values != null) this.values.clear(); + return this; + } + @JsonAnySetter + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaAny(final String key, final Object value) { + if (this.guavaAny == null) this.guavaAny = com.google.common.collect.ImmutableMap.builder(); + this.guavaAny.put(key, value); + return this; + } + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaAny(final java.util.Map guavaAny) { + if (guavaAny == null) { + throw new java.lang.NullPointerException("guavaAny cannot be null"); + } + if (this.guavaAny == null) this.guavaAny = com.google.common.collect.ImmutableMap.builder(); + this.guavaAny.putAll(guavaAny); + return this; + } + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaAny() { + this.guavaAny = null; + return this; + } + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaValue(final String guavaValue) { + if (this.guavaValues == null) this.guavaValues = com.google.common.collect.ImmutableList.builder(); + this.guavaValues.add(guavaValue); + return this; + } + @JsonProperty("guava_v_a_l_u_e_s") + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaValues(final java.lang.Iterable guavaValues) { + if (guavaValues == null) { + throw new java.lang.NullPointerException("guavaValues cannot be null"); + } + if (this.guavaValues == null) this.guavaValues = com.google.common.collect.ImmutableList.builder(); + this.guavaValues.addAll(guavaValues); + return this; + } + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaValues() { + this.guavaValues = null; + return this; + } + @java.lang.SuppressWarnings("all") + public JacksonBuilderSingular build() { + java.util.Map any; + switch (this.any$key == null ? 0 : this.any$key.size()) { + case 0: + any = java.util.Collections.emptyMap(); + break; + case 1: + any = java.util.Collections.singletonMap(this.any$key.get(0), this.any$value.get(0)); + break; + default: + any = new java.util.LinkedHashMap(this.any$key.size() < 1073741824 ? 1 + this.any$key.size() + (this.any$key.size() - 3) / 3 : java.lang.Integer.MAX_VALUE); + for (int $i = 0; $i < this.any$key.size(); $i++) any.put(this.any$key.get($i), (Object) this.any$value.get($i)); + any = java.util.Collections.unmodifiableMap(any); + } + java.util.List values; + switch (this.values == null ? 0 : this.values.size()) { + case 0: + values = java.util.Collections.emptyList(); + break; + case 1: + values = java.util.Collections.singletonList(this.values.get(0)); + break; + default: + values = java.util.Collections.unmodifiableList(new java.util.ArrayList(this.values)); + } + 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); + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "JacksonBuilderSingular.JacksonBuilderSingularBuilder(any$key=" + this.any$key + ", any$value=" + this.any$value + ", values=" + this.values + ", guavaAny=" + this.guavaAny + ", guavaValues=" + this.guavaValues + ")"; + } + } + @java.lang.SuppressWarnings("all") + public static JacksonBuilderSingular.JacksonBuilderSingularBuilder builder() { + return new JacksonBuilderSingular.JacksonBuilderSingularBuilder(); + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/JacksonBuilderSingular.java b/test/transform/resource/after-ecj/JacksonBuilderSingular.java new file mode 100644 index 00000000..50f6a797 --- /dev/null +++ b/test/transform/resource/after-ecj/JacksonBuilderSingular.java @@ -0,0 +1,164 @@ +import java.util.List; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import lombok.Builder; +import lombok.Singular; +import lombok.extern.jackson.Jacksonized; +public @Jacksonized @Builder @com.fasterxml.jackson.databind.annotation.JsonDeserialize(builder = JacksonBuilderSingular.JacksonBuilderSingularBuilder.class) class JacksonBuilderSingular { + public static @java.lang.SuppressWarnings("all") @com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder(withPrefix = "",buildMethodName = "build") class JacksonBuilderSingularBuilder { + private @java.lang.SuppressWarnings("all") java.util.ArrayList 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() { + super(); + } + public @JsonAnySetter @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final String anyKey, final Object anyValue) { + if ((this.any$key == null)) + { + this.any$key = new java.util.ArrayList(); + this.any$value = new java.util.ArrayList(); + } + this.any$key.add(anyKey); + this.any$value.add(anyValue); + return this; + } + public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder any(final java.util.Map any) { + if ((any == null)) + { + throw new java.lang.NullPointerException("any cannot be null"); + } + if ((this.any$key == null)) + { + this.any$key = new java.util.ArrayList(); + this.any$value = new java.util.ArrayList(); + } + for (java.util.Map.Entry $lombokEntry : any.entrySet()) + { + this.any$key.add($lombokEntry.getKey()); + this.any$value.add($lombokEntry.getValue()); + } + return this; + } + public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearAny() { + if ((this.any$key != null)) + { + this.any$key.clear(); + this.any$value.clear(); + } + return this; + } + public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder value(final String value) { + if ((this.values == null)) + this.values = new java.util.ArrayList(); + 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) { + if ((values == null)) + { + throw new java.lang.NullPointerException("values cannot be null"); + } + if ((this.values == null)) + this.values = new java.util.ArrayList(); + this.values.addAll(values); + return this; + } + public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearValues() { + if ((this.values != null)) + this.values.clear(); + return this; + } + public @JsonAnySetter @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaAny(final String key, final Object value) { + if ((this.guavaAny == null)) + this.guavaAny = com.google.common.collect.ImmutableMap.builder(); + this.guavaAny.put(key, value); + return this; + } + public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaAny(final java.util.Map guavaAny) { + if ((guavaAny == null)) + { + throw new java.lang.NullPointerException("guavaAny cannot be null"); + } + if ((this.guavaAny == null)) + this.guavaAny = com.google.common.collect.ImmutableMap.builder(); + this.guavaAny.putAll(guavaAny); + return this; + } + public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaAny() { + this.guavaAny = null; + return this; + } + public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaValue(final String guavaValue) { + if ((this.guavaValues == null)) + this.guavaValues = com.google.common.collect.ImmutableList.builder(); + this.guavaValues.add(guavaValue); + return this; + } + public @JsonProperty("guava_v_a_l_u_e_s") @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder guavaValues(final java.lang.Iterable guavaValues) { + if ((guavaValues == null)) + { + throw new java.lang.NullPointerException("guavaValues cannot be null"); + } + if ((this.guavaValues == null)) + this.guavaValues = com.google.common.collect.ImmutableList.builder(); + this.guavaValues.addAll(guavaValues); + return this; + } + public @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder clearGuavaValues() { + this.guavaValues = null; + return this; + } + public @java.lang.SuppressWarnings("all") JacksonBuilderSingular build() { + java.util.Map any; + switch (((this.any$key == null) ? 0 : this.any$key.size())) { + case 0 : + any = java.util.Collections.emptyMap(); + break; + case 1 : + any = java.util.Collections.singletonMap(this.any$key.get(0), this.any$value.get(0)); + break; + default : + any = new java.util.LinkedHashMap(((this.any$key.size() < 0x40000000) ? ((1 + this.any$key.size()) + ((this.any$key.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE)); + for (int $i = 0;; ($i < this.any$key.size()); $i ++) + any.put(this.any$key.get($i), this.any$value.get($i)); + any = java.util.Collections.unmodifiableMap(any); + } + java.util.List values; + switch (((this.values == null) ? 0 : this.values.size())) { + case 0 : + values = java.util.Collections.emptyList(); + break; + case 1 : + values = java.util.Collections.singletonList(this.values.get(0)); + break; + default : + values = java.util.Collections.unmodifiableList(new java.util.ArrayList(this.values)); + } + 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); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (((((((((("JacksonBuilderSingular.JacksonBuilderSingularBuilder(any$key=" + this.any$key) + ", any$value=") + this.any$value) + ", values=") + this.values) + ", guavaAny=") + this.guavaAny) + ", guavaValues=") + this.guavaValues) + ")"); + } + } + private @JsonAnySetter @Singular("any") Map 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) { + super(); + this.any = any; + this.values = values; + this.guavaAny = guavaAny; + this.guavaValues = guavaValues; + } + public static @java.lang.SuppressWarnings("all") JacksonBuilderSingular.JacksonBuilderSingularBuilder builder() { + return new JacksonBuilderSingular.JacksonBuilderSingularBuilder(); + } +} \ No newline at end of file diff --git a/test/transform/resource/before/JacksonBuilderSingular.java b/test/transform/resource/before/JacksonBuilderSingular.java new file mode 100644 index 00000000..c179c760 --- /dev/null +++ b/test/transform/resource/before/JacksonBuilderSingular.java @@ -0,0 +1,31 @@ +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +import lombok.Builder; +import lombok.Singular; +import lombok.extern.jackson.Jacksonized; + +@Jacksonized +@Builder +public class JacksonBuilderSingular { + @JsonAnySetter + @Singular("any") + private Map any; + + @JsonProperty("v_a_l_u_e_s") + @Singular + private List values; + + @JsonAnySetter + @Singular("guavaAny") + private ImmutableMap guavaAny; + + @JsonProperty("guava_v_a_l_u_e_s") + @Singular + private ImmutableList guavaValues; +} -- cgit From 48b1f17f7ef0e0b3d90dee74ee1b490a02cacff2 Mon Sep 17 00:00:00 2001 From: Jan Rieke Date: Fri, 1 May 2020 23:56:17 +0200 Subject: [SuperBuilder] allow constructor customization --- .../eclipse/handlers/HandleSuperBuilder.java | 28 +++++++++++++++-- .../lombok/javac/handlers/HandleSuperBuilder.java | 35 ++++++++++++++++++++-- .../after-delombok/SuperBuilderCustomized.java | 15 +++++----- .../resource/after-ecj/SuperBuilderCustomized.java | 8 +++-- .../resource/before/SuperBuilderCustomized.java | 10 +++++++ 5 files changed, 81 insertions(+), 15 deletions(-) (limited to 'test/transform/resource') diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index a49c20a4..455d40ed 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -274,8 +274,10 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { // If there is no superclass, superclassBuilderClassExpression is still == null at this point. // You can use it to check whether to inherit or not. - generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName, - superclassBuilderClass != null); + if (!constructorExists(tdParent, builderClassName)) { + generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName, + superclassBuilderClass != null); + } // Create the abstract builder class, or reuse an existing one. EclipseNode builderType = findInnerClass(tdParent, builderClassName); @@ -1159,4 +1161,26 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { System.arraycopy(name, 0, out, prefix.length, name.length); return out; } + + private boolean constructorExists(EclipseNode type, String builderClassName) { + if (type != null && type.get() instanceof TypeDeclaration) { + TypeDeclaration typeDecl = (TypeDeclaration)type.get(); + if (typeDecl.methods != null) for (AbstractMethodDeclaration def : typeDecl.methods) { + if (def instanceof ConstructorDeclaration) { + if ((def.bits & ASTNode.IsDefaultConstructor) != 0) continue; + if (!def.isConstructor()) continue; + if (isTolerate(type, def)) continue; + if (def.arguments.length != 1) continue; + + // 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; + } + } + } + + return false; + } } diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 2dc3247d..b7cd6f9a 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -354,8 +354,10 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { } // Generate a constructor in the annotated class that takes a builder as argument. - generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName, - superclassBuilderClassExpression != null); + if (!constructorExists(tdParent, builderClassName)) { + generateBuilderBasedConstructor(cfv, tdParent, typeParams, builderFields, annotationNode, builderClassName, + superclassBuilderClassExpression != null); + } if (isAbstract) { // Only non-abstract classes get the builder() and toBuilder() methods. @@ -1070,4 +1072,33 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { } return typeParameter; } + + /** + * Checks if there is a manual constructor in the given type with a single parameter (builder). + */ + private boolean constructorExists(JavacNode type, String builderClassName) { + if (type != null && type.get() instanceof JCClassDecl) { + for (JCTree def : ((JCClassDecl)type.get()).defs) { + if (def instanceof JCMethodDecl) { + JCMethodDecl md = (JCMethodDecl) def; + String name = md.name.toString(); + boolean matches = name.equals(""); + 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); + } + if ((builderClassName+"").equals(typeName)) + return true; + } + } + } + } + return false; + } } diff --git a/test/transform/resource/after-delombok/SuperBuilderCustomized.java b/test/transform/resource/after-delombok/SuperBuilderCustomized.java index bffa72fa..f66133c9 100644 --- a/test/transform/resource/after-delombok/SuperBuilderCustomized.java +++ b/test/transform/resource/after-delombok/SuperBuilderCustomized.java @@ -23,6 +23,13 @@ public class SuperBuilderCustomized { } } int field1; + protected Parent(ParentBuilder b) { + if (b.field1 == 0) throw new IllegalArgumentException("field1 must be != 0"); + this.field1 = b.field1; + } + public static SuperBuilderCustomized.Parent.ParentBuilder builder(int field1) { + return new SuperBuilderCustomized.Parent.ParentBuilderImpl().field1(field1); + } @java.lang.SuppressWarnings("all") private static final class ParentBuilderImpl extends SuperBuilderCustomized.Parent.ParentBuilder { @java.lang.SuppressWarnings("all") @@ -39,14 +46,6 @@ public class SuperBuilderCustomized { return new SuperBuilderCustomized.Parent(this); } } - @java.lang.SuppressWarnings("all") - protected Parent(final SuperBuilderCustomized.Parent.ParentBuilder b) { - this.field1 = b.field1; - } - @java.lang.SuppressWarnings("all") - public static SuperBuilderCustomized.Parent.ParentBuilder builder() { - return new SuperBuilderCustomized.Parent.ParentBuilderImpl(); - } } public static class Child extends Parent { private static final class ChildBuilderImpl extends ChildBuilder { diff --git a/test/transform/resource/after-ecj/SuperBuilderCustomized.java b/test/transform/resource/after-ecj/SuperBuilderCustomized.java index 32317f6a..fe0e1238 100644 --- a/test/transform/resource/after-ecj/SuperBuilderCustomized.java +++ b/test/transform/resource/after-ecj/SuperBuilderCustomized.java @@ -32,12 +32,14 @@ public class SuperBuilderCustomized { } } int field1; - protected @java.lang.SuppressWarnings("all") Parent(final SuperBuilderCustomized.Parent.ParentBuilder b) { + protected Parent(ParentBuilder b) { super(); + if ((b.field1 == 0)) + throw new IllegalArgumentException("field1 must be != 0"); this.field1 = b.field1; } - public static @java.lang.SuppressWarnings("all") SuperBuilderCustomized.Parent.ParentBuilder builder() { - return new SuperBuilderCustomized.Parent.ParentBuilderImpl(); + public static SuperBuilderCustomized.Parent.ParentBuilder builder(int field1) { + return new SuperBuilderCustomized.Parent.ParentBuilderImpl().field1(field1); } } public static @lombok.experimental.SuperBuilder class Child extends Parent { diff --git a/test/transform/resource/before/SuperBuilderCustomized.java b/test/transform/resource/before/SuperBuilderCustomized.java index 77830587..8e641d90 100644 --- a/test/transform/resource/before/SuperBuilderCustomized.java +++ b/test/transform/resource/before/SuperBuilderCustomized.java @@ -14,6 +14,16 @@ public class SuperBuilderCustomized { } } int field1; + + protected Parent(ParentBuilder b) { + if (b.field1 == 0) + throw new IllegalArgumentException("field1 must be != 0"); + this.field1 = b.field1; + } + + public static SuperBuilderCustomized.Parent.ParentBuilder builder(int field1) { + return new SuperBuilderCustomized.Parent.ParentBuilderImpl().field1(field1); + } } @lombok.experimental.SuperBuilder -- cgit From 7d08af7d856b41580fa4b913e2b0c9002a8fc341 Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Sat, 9 May 2020 13:19:17 +0200 Subject: [fixes #2382] Handle generic supertypes --- src/core/lombok/javac/handlers/HandleDelegate.java | 9 +++--- .../resource/after-delombok/DelegateGenerics.java | 32 ++++++++++++++++++++++ .../resource/after-ecj/DelegateGenerics.java | 24 ++++++++++++++++ .../resource/before/DelegateGenerics.java | 14 ++++++++++ 4 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 test/transform/resource/after-delombok/DelegateGenerics.java create mode 100644 test/transform/resource/after-ecj/DelegateGenerics.java create mode 100644 test/transform/resource/before/DelegateGenerics.java (limited to 'test/transform/resource') diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java index 367b2cff..c19540fa 100644 --- a/src/core/lombok/javac/handlers/HandleDelegate.java +++ b/src/core/lombok/javac/handlers/HandleDelegate.java @@ -389,10 +389,11 @@ public class HandleDelegate extends JavacAnnotationHandler { boolean isDeprecated = (member.flags() & DEPRECATED) != 0; signatures.add(new MethodSig(member.name, methodType, isDeprecated, exElem)); } - - if (ct.supertype_field instanceof ClassType) addMethodBindings(signatures, (ClassType) ct.supertype_field, types, banList); - if (ct.interfaces_field != null) for (Type iface : ct.interfaces_field) { - if (iface instanceof ClassType) addMethodBindings(signatures, (ClassType) iface, types, banList); + + for (Type type : types.directSupertypes(ct)) { + if (type instanceof ClassType) { + addMethodBindings(signatures, (ClassType) type, types, banList); + } } } diff --git a/test/transform/resource/after-delombok/DelegateGenerics.java b/test/transform/resource/after-delombok/DelegateGenerics.java new file mode 100644 index 00000000..894776ea --- /dev/null +++ b/test/transform/resource/after-delombok/DelegateGenerics.java @@ -0,0 +1,32 @@ +public class DelegateGenerics { + I1 target; + + @java.lang.SuppressWarnings("all") + public java.lang.Integer t(final java.lang.Integer t) { + return this.target.t(t); + } + + @java.lang.SuppressWarnings("all") + public java.lang.String i(final java.lang.String a) { + return this.target.i(a); + } + + @java.lang.SuppressWarnings("all") + public T a(final T a) { + return this.target.a(a); + } +} + +interface I1 extends I2 { +} + +interface I2 extends I3 { +} + +interface I3 { + T t(T t); + + I i(I a); + + A a(A a); +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/DelegateGenerics.java b/test/transform/resource/after-ecj/DelegateGenerics.java new file mode 100644 index 00000000..97b05102 --- /dev/null +++ b/test/transform/resource/after-ecj/DelegateGenerics.java @@ -0,0 +1,24 @@ +public class DelegateGenerics { + @lombok.experimental.Delegate I1 target; + public DelegateGenerics() { + super(); + } + public @java.lang.SuppressWarnings("all") T a(final T a) { + return this.target.a(a); + } + public @java.lang.SuppressWarnings("all") java.lang.String i(final java.lang.String a) { + return this.target.i(a); + } + public @java.lang.SuppressWarnings("all") java.lang.Integer t(final java.lang.Integer t) { + return this.target.t(t); + } +} +interface I1 extends I2 { +} +interface I2 extends I3 { +} +interface I3 { + public T t(T t); + public I i(I a); + public A a(A a); +} \ No newline at end of file diff --git a/test/transform/resource/before/DelegateGenerics.java b/test/transform/resource/before/DelegateGenerics.java new file mode 100644 index 00000000..e89158a9 --- /dev/null +++ b/test/transform/resource/before/DelegateGenerics.java @@ -0,0 +1,14 @@ +public class DelegateGenerics { + @lombok.experimental.Delegate + I1 target; +} + +interface I1 extends I2 { +} +interface I2 extends I3 { +} +interface I3 { + public T t(T t); + public I i(I a); + public A a(A a); +} \ No newline at end of file -- cgit From a2a194f32da2058e8783cd664d74799cf418d03d Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Sat, 16 May 2020 11:54:56 +0200 Subject: [fixes #2006] Delegate now excludes already implemented methods --- src/core/lombok/javac/handlers/HandleDelegate.java | 13 ++-- .../lombok/eclipse/agent/PatchDelegate.java | 73 +++++++++++++++++++++- .../after-delombok/DelegateAlreadyImplemented.java | 43 +++++++++++++ .../after-ecj/DelegateAlreadyImplemented.java | 29 +++++++++ .../before/DelegateAlreadyImplemented.java | 45 +++++++++++++ 5 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 test/transform/resource/after-delombok/DelegateAlreadyImplemented.java create mode 100644 test/transform/resource/after-ecj/DelegateAlreadyImplemented.java create mode 100644 test/transform/resource/before/DelegateAlreadyImplemented.java (limited to 'test/transform/resource') diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java index c19540fa..d6e76ab1 100644 --- a/src/core/lombok/javac/handlers/HandleDelegate.java +++ b/src/core/lombok/javac/handlers/HandleDelegate.java @@ -48,6 +48,7 @@ import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Attribute.Compound; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.ClassType; @@ -175,14 +176,14 @@ public class HandleDelegate extends JavacAnnotationHandler { List signaturesToExclude = new ArrayList(); Set banList = new HashSet(); banList.addAll(METHODS_IN_OBJECT); - /* To exclude all methods in the class itself, try this: - for (Symbol member : ((JCClassDecl)typeNode.get()).sym.getEnclosedElements()) { - if (member instanceof MethodSymbol) { - MethodSymbol method = (MethodSymbol) member; - banList.add(printSig((ExecutableType) method.asType(), method.name, annotationNode.getTypesUtil())); + + // Add already implemented methods to ban list + JavacNode typeNode = upToTypeNode(annotationNode); + for (Symbol m : ((JCClassDecl)typeNode.get()).sym.getEnclosedElements()) { + if (m instanceof MethodSymbol) { + banList.add(printSig((ExecutableType) m.asType(), m.name, annotationNode.getTypesUtil())); } } - */ try { for (Type t : toExclude) { diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java index 02760e35..ebd60ce9 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java @@ -29,11 +29,14 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import lombok.core.AST.Kind; +import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAST; import lombok.eclipse.EclipseNode; import lombok.eclipse.TransformEclipseAST; @@ -67,6 +70,7 @@ import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; +import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; @@ -214,7 +218,7 @@ public class PatchDelegate { addAllMethodBindings(methodsToExclude, cla.type.resolveType(decl.initializerScope), new HashSet(), field.name, ann); } - Set banList = new HashSet(); + Set banList = findAlreadyImplementedMethods(decl); for (BindingTuple excluded : methodsToExclude) banList.add(printSig(excluded.parameterized)); if (rawTypes.isEmpty()) { @@ -283,8 +287,8 @@ public class PatchDelegate { for (ClassLiteralAccess cla : excludedRawTypes) { addAllMethodBindings(methodsToExclude, cla.type.resolveType(decl.initializerScope), new HashSet(), method.selector, ann); } - - Set banList = new HashSet(); + + Set banList = findAlreadyImplementedMethods(decl); for (BindingTuple excluded : methodsToExclude) banList.add(printSig(excluded.parameterized)); if (rawTypes.isEmpty()) { @@ -764,6 +768,21 @@ public class PatchDelegate { } } + private static Set findAlreadyImplementedMethods(TypeDeclaration decl) { + Set sigs = new HashSet(); + for (AbstractMethodDeclaration md : decl.methods) { + if (md.isStatic()) continue; + if ((md.modifiers & ClassFileConstants.AccBridge) != 0) continue; + if (md.isConstructor()) continue; + if ((md.modifiers & ExtraCompilerModifiers.AccDefaultAbstract) != 0) continue; + if ((md.modifiers & ClassFileConstants.AccPublic) == 0) continue; + if ((md.modifiers & ClassFileConstants.AccSynthetic) != 0) continue; + + sigs.add(printSig(md, decl.scope)); + } + return sigs; + } + private static final char[] STRING_LOMBOK = new char[] {'l', 'o', 'm', 'b', 'o', 'k'}; private static final char[] STRING_EXPERIMENTAL = new char[] {'e', 'x', 'p', 'e', 'r', 'i', 'm', 'e', 'n', 't', 'a', 'l'}; private static final char[] STRING_DELEGATE = new char[] {'D', 'e', 'l', 'e', 'g', 'a', 't', 'e'}; @@ -839,6 +858,54 @@ public class PatchDelegate { return signature.toString(); } + private static String printSig(AbstractMethodDeclaration md, ClassScope scope) { + StringBuilder signature = new StringBuilder(); + + signature.append(md.selector); + signature.append("("); + boolean first = true; + if (md.arguments != null) { + TypeParameter[] typeParameters = md.typeParameters(); + Map typeParametersMap = new HashMap(); + if (typeParameters != null) { + for (TypeParameter typeParameter : typeParameters) { + typeParametersMap.put(new String(typeParameter.name), typeParameter); + } + } + + for (Argument argument : md.arguments) { + TypeBinding typeBinding = makeTypeBinding(argument.type, typeParametersMap, scope); + + if (!first) signature.append(", "); + first = false; + signature.append(typeBindingToSignature(typeBinding)); + } + } + signature.append(")"); + + return signature.toString(); + } + + private static TypeBinding makeTypeBinding(TypeReference typeReference, Map typeParametersMap, ClassScope scope) { + char[][] typeName = typeReference.getTypeName(); + String typeNameString = Eclipse.toQualifiedName(typeName); + + TypeParameter typeParameter = typeParametersMap.get(typeNameString); + if (typeParameter != null) { + if (typeParameter.type != null) { + typeName = typeParameter.type.getTypeName(); + } else { + typeName = TypeConstants.JAVA_LANG_OBJECT; + } + } + + TypeBinding typeBinding = scope.getType(typeName, typeName.length); + if (typeReference.dimensions() > 0) { + typeBinding = scope.createArrayType(typeBinding, typeReference.dimensions()); + } + return typeBinding; + } + private static String typeBindingToSignature(TypeBinding binding) { binding = binding.erasure(); if (binding != null && binding.isBaseType()) { diff --git a/test/transform/resource/after-delombok/DelegateAlreadyImplemented.java b/test/transform/resource/after-delombok/DelegateAlreadyImplemented.java new file mode 100644 index 00000000..c876d8ce --- /dev/null +++ b/test/transform/resource/after-delombok/DelegateAlreadyImplemented.java @@ -0,0 +1,43 @@ +public class DelegateAlreadyImplemented { + private A a; + + public void a() { + } + + public void b(java.util.List l) { + } + + public void c(java.util.List l, String[] a, Integer... varargs) { + } + + public void d(String[][][][] d) { + } + + public void e(Y x) { + } + + @SuppressWarnings("unchecked") + public void f(T s, java.util.List l, T[] a, T... varargs) { + } + + public void g(Number g) { + } +} + +interface A { + void a(); + + void b(java.util.List l); + + @SuppressWarnings("unchecked") + void c(java.util.List l, String[] a, T... varargs); + + void d(String[][][][] d); + + X e(X x); + + @SuppressWarnings("unchecked") + void f(T2 s, java.util.List l, T2[] a, T2... varargs); + + void g(G g); +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/DelegateAlreadyImplemented.java b/test/transform/resource/after-ecj/DelegateAlreadyImplemented.java new file mode 100644 index 00000000..1e12f405 --- /dev/null +++ b/test/transform/resource/after-ecj/DelegateAlreadyImplemented.java @@ -0,0 +1,29 @@ +public class DelegateAlreadyImplemented { + private @lombok.experimental.Delegate A a; + public DelegateAlreadyImplemented() { + super(); + } + public void a() { + } + public void b(java.util.List l) { + } + public void c(java.util.List l, String[] a, Integer... varargs) { + } + public void d(String[][][][] d) { + } + public void e(Y x) { + } + public @SuppressWarnings("unchecked") void f(T s, java.util.List l, T[] a, T... varargs) { + } + public void g(Number g) { + } +} +interface A { + public void a(); + public void b(java.util.List l); + public @SuppressWarnings("unchecked") void c(java.util.List l, String[] a, T... varargs); + public void d(String[][][][] d); + public X e(X x); + public @SuppressWarnings("unchecked") void f(T2 s, java.util.List l, T2[] a, T2... varargs); + public void g(G g); +} \ No newline at end of file diff --git a/test/transform/resource/before/DelegateAlreadyImplemented.java b/test/transform/resource/before/DelegateAlreadyImplemented.java new file mode 100644 index 00000000..c43c1949 --- /dev/null +++ b/test/transform/resource/before/DelegateAlreadyImplemented.java @@ -0,0 +1,45 @@ +public class DelegateAlreadyImplemented { + + @lombok.experimental.Delegate + private A a; + + public void a() { + } + + public void b(java.util.List l) { + } + + public void c(java.util.List l, String[] a, Integer... varargs) { + } + + public void d(String[][][][] d) { + } + + public void e(Y x) { + } + + @SuppressWarnings("unchecked") + public void f(T s, java.util.List l, T[] a, T... varargs) { + } + + public void g(Number g) { + } +} + +interface A { + public void a(); + + public void b(java.util.List l); + + @SuppressWarnings("unchecked") + public void c(java.util.List l, String[] a, T... varargs); + + public void d(String[][][][] d); + + public X e(X x); + + @SuppressWarnings("unchecked") + public void f(T2 s, java.util.List l, T2[] a, T2... varargs); + + public void g(G g); +} \ No newline at end of file -- cgit From a2941041d4d4b3db2a12a38212226f36c11219ab Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Wed, 10 Jun 2020 10:18:15 +0200 Subject: [fixes #2481] Copy constructor javadoc to builder methods --- src/core/lombok/javac/handlers/HandleBuilder.java | 24 +++++- .../after-delombok/BuilderConstructorJavadoc.java | 85 ++++++++++++++++++++++ .../after-ecj/BuilderConstructorJavadoc.java | 40 ++++++++++ .../resource/before/BuilderConstructorJavadoc.java | 35 +++++++++ 4 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 test/transform/resource/after-delombok/BuilderConstructorJavadoc.java create mode 100644 test/transform/resource/after-ecj/BuilderConstructorJavadoc.java create mode 100644 test/transform/resource/before/BuilderConstructorJavadoc.java (limited to 'test/transform/resource') diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 91a74d62..95be28f3 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -27,6 +27,8 @@ import static lombok.javac.JavacTreeMaker.TypeTag.typeTag; import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.lang.model.element.Modifier; @@ -38,6 +40,7 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCIdent; @@ -845,11 +848,30 @@ public class HandleBuilder extends JavacAnnotationHandler { newMethod.params = List.of(recv, newMethod.params.get(0)); } recursiveSetGeneratedBy(newMethod, source.get(), builderType.getContext()); - copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER, true); + if (source.up().getKind() == Kind.METHOD) { + copyJavadocFromParam(originalFieldNode.up(), newMethod, paramName.toString()); + } else { + copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER, true); + } injectMethod(builderType, newMethod); } + private void copyJavadocFromParam(JavacNode from, JCMethodDecl to, String param) { + try { + JCCompilationUnit cu = ((JCCompilationUnit) from.top().get()); + String methodComment = Javac.getDocComment(cu, from.get()); + if (methodComment == null) return; + + Pattern pattern = Pattern.compile("@param " + param + " (\\S|\\s)+?(?=^ ?@)", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(methodComment); + if (matcher.find()) { + String newJavadoc = addReturnsThisIfNeeded(matcher.group()); + Javac.setDocComment(cu, to, newJavadoc); + } + } catch (Exception ignore) {} + } + public JavacNode makeBuilderClass(boolean isStatic, JavacNode source, JavacNode tdParent, String builderClassName, List typeParams, JCAnnotation ast, AccessLevel access) { JavacTreeMaker maker = tdParent.getTreeMaker(); int modifiers = toJavacModifier(access); diff --git a/test/transform/resource/after-delombok/BuilderConstructorJavadoc.java b/test/transform/resource/after-delombok/BuilderConstructorJavadoc.java new file mode 100644 index 00000000..96673b1a --- /dev/null +++ b/test/transform/resource/after-delombok/BuilderConstructorJavadoc.java @@ -0,0 +1,85 @@ +import java.util.List; + +class BuilderConstructorJavadoc { + /** + * This is a comment + * + * @param basic tag is moved to the setter + * @param multiline a param comment + * can be on multiple lines and can use + * {@code @code} or tags + * @param predef don't copy this one + * @param predefWithJavadoc don't copy this one + */ + BuilderConstructorJavadoc(int basic, int multiline, int predef, int predefWithJavadoc) { + } + + + public static class BuilderConstructorJavadocBuilder { + @java.lang.SuppressWarnings("all") + private int basic; + @java.lang.SuppressWarnings("all") + private int multiline; + @java.lang.SuppressWarnings("all") + private int predef; + @java.lang.SuppressWarnings("all") + private int predefWithJavadoc; + + public BuilderConstructorJavadocBuilder predef(final int x) { + this.predef = x; + return this; + } + + /** + * This javadoc remains untouched. + * @param x 1/100 of the thing + * @return the updated builder + */ + public BuilderConstructorJavadocBuilder predefWithJavadoc(final int x) { + this.predefWithJavadoc = x; + return this; + } + + @java.lang.SuppressWarnings("all") + BuilderConstructorJavadocBuilder() { + } + + /** + * @param basic tag is moved to the setter + * @return {@code this}. + */ + @java.lang.SuppressWarnings("all") + public BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder basic(final int basic) { + this.basic = basic; + return this; + } + + /** + * @param multiline a param comment + * can be on multiple lines and can use + * {@code @code} or tags + * @return {@code this}. + */ + @java.lang.SuppressWarnings("all") + public BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder multiline(final int multiline) { + this.multiline = multiline; + return this; + } + + @java.lang.SuppressWarnings("all") + public BuilderConstructorJavadoc build() { + return new BuilderConstructorJavadoc(this.basic, this.multiline, this.predef, this.predefWithJavadoc); + } + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder(basic=" + this.basic + ", multiline=" + this.multiline + ", predef=" + this.predef + ", predefWithJavadoc=" + this.predefWithJavadoc + ")"; + } + } + + @java.lang.SuppressWarnings("all") + public static BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder builder() { + return new BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder(); + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/BuilderConstructorJavadoc.java b/test/transform/resource/after-ecj/BuilderConstructorJavadoc.java new file mode 100644 index 00000000..bb3916e8 --- /dev/null +++ b/test/transform/resource/after-ecj/BuilderConstructorJavadoc.java @@ -0,0 +1,40 @@ +import java.util.List; +class BuilderConstructorJavadoc { + public static class BuilderConstructorJavadocBuilder { + private @java.lang.SuppressWarnings("all") int basic; + private @java.lang.SuppressWarnings("all") int multiline; + private @java.lang.SuppressWarnings("all") int predef; + private @java.lang.SuppressWarnings("all") int predefWithJavadoc; + public BuilderConstructorJavadocBuilder predef(final int x) { + this.predef = x; + return this; + } + public BuilderConstructorJavadocBuilder predefWithJavadoc(final int x) { + this.predefWithJavadoc = x; + return this; + } + @java.lang.SuppressWarnings("all") BuilderConstructorJavadocBuilder() { + super(); + } + public @java.lang.SuppressWarnings("all") BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder basic(final int basic) { + this.basic = basic; + return this; + } + public @java.lang.SuppressWarnings("all") BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder multiline(final int multiline) { + this.multiline = multiline; + return this; + } + public @java.lang.SuppressWarnings("all") BuilderConstructorJavadoc build() { + return new BuilderConstructorJavadoc(this.basic, this.multiline, this.predef, this.predefWithJavadoc); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (((((((("BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder(basic=" + this.basic) + ", multiline=") + this.multiline) + ", predef=") + this.predef) + ", predefWithJavadoc=") + this.predefWithJavadoc) + ")"); + } + } + @lombok.Builder BuilderConstructorJavadoc(int basic, int multiline, int predef, int predefWithJavadoc) { + super(); + } + public static @java.lang.SuppressWarnings("all") BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder builder() { + return new BuilderConstructorJavadoc.BuilderConstructorJavadocBuilder(); + } +} \ No newline at end of file diff --git a/test/transform/resource/before/BuilderConstructorJavadoc.java b/test/transform/resource/before/BuilderConstructorJavadoc.java new file mode 100644 index 00000000..ebbd473f --- /dev/null +++ b/test/transform/resource/before/BuilderConstructorJavadoc.java @@ -0,0 +1,35 @@ +import java.util.List; + +class BuilderConstructorJavadoc { + /** + * This is a comment + * + * @param basic tag is moved to the setter + * @param multiline a param comment + * can be on multiple lines and can use + * {@code @code} or tags + * @param predef don't copy this one + * @param predefWithJavadoc don't copy this one + */ + @lombok.Builder + BuilderConstructorJavadoc(int basic, int multiline, int predef, int predefWithJavadoc) { + + } + + public static class BuilderConstructorJavadocBuilder { + public BuilderConstructorJavadocBuilder predef(final int x) { + this.predef = x; + return this; + } + + /** + * This javadoc remains untouched. + * @param x 1/100 of the thing + * @return the updated builder + */ + public BuilderConstructorJavadocBuilder predefWithJavadoc(final int x) { + this.predefWithJavadoc = x; + return this; + } + } +} -- cgit From db59aa442b4bfe9b048e7667c5da140cd9c19ee8 Mon Sep 17 00:00:00 2001 From: samukce Date: Fri, 5 Jun 2020 01:19:16 -0700 Subject: Add tests classes for rank property --- .../after-delombok/EqualsAndHashCodeRank.java | 31 +++++++++++++++++++ .../resource/after-ecj/EqualsAndHashCodeRank.java | 36 ++++++++++++++++++++++ .../resource/before/EqualsAndHashCodeRank.java | 7 +++++ 3 files changed, 74 insertions(+) create mode 100644 test/transform/resource/after-delombok/EqualsAndHashCodeRank.java create mode 100644 test/transform/resource/after-ecj/EqualsAndHashCodeRank.java create mode 100644 test/transform/resource/before/EqualsAndHashCodeRank.java (limited to 'test/transform/resource') diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeRank.java b/test/transform/resource/after-delombok/EqualsAndHashCodeRank.java new file mode 100644 index 00000000..ad2ddbb1 --- /dev/null +++ b/test/transform/resource/after-delombok/EqualsAndHashCodeRank.java @@ -0,0 +1,31 @@ +public class EqualsAndHashCodeRank { + int a; + int b; + int c; + @java.lang.Override + @java.lang.SuppressWarnings("all") + public boolean equals(final java.lang.Object o) { + if (o == this) return true; + if (!(o instanceof EqualsAndHashCodeRank)) return false; + final EqualsAndHashCodeRank other = (EqualsAndHashCodeRank) o; + if (!other.canEqual((java.lang.Object) this)) return false; + if (this.b != other.b) return false; + if (this.a != other.a) return false; + if (this.c != other.c) return false; + return true; + } + @java.lang.SuppressWarnings("all") + protected boolean canEqual(final java.lang.Object other) { + return other instanceof EqualsAndHashCodeRank; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.b; + result = result * PRIME + this.a; + result = result * PRIME + this.c; + return result; + } +} diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeRank.java b/test/transform/resource/after-ecj/EqualsAndHashCodeRank.java new file mode 100644 index 00000000..1ea899a8 --- /dev/null +++ b/test/transform/resource/after-ecj/EqualsAndHashCodeRank.java @@ -0,0 +1,36 @@ +import lombok.EqualsAndHashCode; +public @EqualsAndHashCode class EqualsAndHashCodeRank { + @EqualsAndHashCode.Include int a; + @EqualsAndHashCode.Include(rank = 10) int b; + @EqualsAndHashCode.Include int c; + public EqualsAndHashCodeRank() { + super(); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { + if (o == this) + return true; + if (!(o instanceof EqualsAndHashCodeRank)) + return false; + final EqualsAndHashCodeRank other = (EqualsAndHashCodeRank) o; + if (!other.canEqual((java.lang.Object) this)) + return false; + if (this.b != other.b) + return false; + if (this.a != other.a) + return false; + if (this.c != other.c) + return false; + return true; + } + protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) { + return (other instanceof EqualsAndHashCodeRank); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.b; + result = result * PRIME + this.a; + result = result * PRIME + this.c; + return result; + } +} diff --git a/test/transform/resource/before/EqualsAndHashCodeRank.java b/test/transform/resource/before/EqualsAndHashCodeRank.java new file mode 100644 index 00000000..5dda54f8 --- /dev/null +++ b/test/transform/resource/before/EqualsAndHashCodeRank.java @@ -0,0 +1,7 @@ +import lombok.EqualsAndHashCode; +@EqualsAndHashCode +public class EqualsAndHashCodeRank { + @EqualsAndHashCode.Include int a; + @EqualsAndHashCode.Include(rank = 10) int b; + @EqualsAndHashCode.Include int c; +} -- cgit From 39d2c280fbaced63f5697481af6b37ab81891798 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Thu, 18 Jun 2020 22:08:25 +0200 Subject: Fixes #1543: in equals, by default first compare the primitives --- doc/changelog.markdown | 3 +++ src/core/lombok/EqualsAndHashCode.java | 4 +++- src/core/lombok/core/LombokNode.java | 1 + .../core/handlers/InclusionExclusionUtils.java | 18 ++++++++++++------ src/core/lombok/eclipse/EclipseNode.java | 19 +++++++++++++++---- src/core/lombok/eclipse/handlers/HandleBuilder.java | 2 +- .../lombok/eclipse/handlers/HandleSuperBuilder.java | 2 +- src/core/lombok/javac/JavacNode.java | 20 +++++++++++++++----- src/core/lombok/javac/handlers/HandleBuilder.java | 2 +- .../lombok/javac/handlers/HandleSuperBuilder.java | 2 +- .../resource/after-delombok/BuilderDefaults.java | 8 ++++---- .../after-delombok/EqualsAndHashCodeRank.java | 6 +++--- .../resource/after-ecj/BuilderDefaults.java | 10 +++++----- .../resource/after-ecj/EqualsAndHashCodeRank.java | 18 +++++++++--------- 14 files changed, 74 insertions(+), 41 deletions(-) (limited to 'test/transform/resource') diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 00545483..af77d480 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -2,6 +2,8 @@ Lombok Changelog ---------------- ### v1.18.13 "Edgy Guinea Pig" +* PERFORMANCE: The generated equals method will first compare primitives. Manual re-ordering is possible using `@Include(rank=n)`. [Pull Request #2485](https://github.com/rzwitserloot/lombok/pull/2485), [Issue #1543](https://github.com/rzwitserloot/lombok/issues/1543) +* IMPROBABLE BREAKING CHANGE: The generated hashcode has changed for classes that include both primitive fields and reference fields. * PLATFORM: Added support for compiling projects with OpenJ9 [Pull Request #2437](https://github.com/rzwitserloot/lombok/pull/2437) * BREAKING CHANGE: mapstruct users should now add a dependency to lombok-mapstruct-binding. This solves compiling modules with lombok (and mapstruct). * FEATURE: Similar to `@Builder`, you can now configure a `@SuperBuilder`'s 'setter' prefixes via `@SuperBuilder(setterPrefix = "set")` for example. We still discourage doing this. [Pull Request #2357](https://github.com/rzwitserloot/lombok/pull/2357). @@ -14,6 +16,7 @@ Lombok Changelog * BUGFIX: Javac sets incorrect annotated type on with methods. [Issue #2463](https://github.com/rzwitserloot/lombok/issues/2463) * FEATURE: `@Jacksonized` on a `@Builder` or `@SuperBuilder` will configure [Jackson](https://github.com/FasterXML/jackson) to use this builder when deserializing. [Pull Request #2387](https://github.com/rzwitserloot/lombok/pull/2387) thanks to __@JanRieke__. [@Jacksonized documentation](https://projectlombok.org/features/experimental/Jacksonized). + ### v1.18.12 (February 1st, 2020) * PLATFORM: Support for JDK13 (including `yield` in switch expressions, as well as delombok having a nicer style for arrow-style switch blocks, and text blocks). * PLATFORM: Support for JDK14 (including `pattern match` instanceof expressions). diff --git a/src/core/lombok/EqualsAndHashCode.java b/src/core/lombok/EqualsAndHashCode.java index 02596f24..2f53bdec 100644 --- a/src/core/lombok/EqualsAndHashCode.java +++ b/src/core/lombok/EqualsAndHashCode.java @@ -125,7 +125,9 @@ public @interface EqualsAndHashCode { /** * Higher ranks are considered first. Members of the same rank are considered in the order they appear in the source file. - * + * + * If not explicitly set, the {@code default} rank for primitives is 1000. + * * @return ordering within the generating {@code equals} and {@code hashCode} methods; higher numbers are considered first. */ int rank() default 0; diff --git a/src/core/lombok/core/LombokNode.java b/src/core/lombok/core/LombokNode.java index e52cd5b3..46054077 100644 --- a/src/core/lombok/core/LombokNode.java +++ b/src/core/lombok/core/LombokNode.java @@ -288,6 +288,7 @@ public abstract class LombokNode, L extends LombokNode type) { @@ -164,13 +170,13 @@ public class InclusionExclusionUtils { if (n.isEmpty()) n = name; namesToAutoExclude.add(n); } - members.add(new Included(child, inc, false)); + members.add(new Included(child, inc, false, markInclude.isExplicit("rank"))); continue; } if (onlyExplicitlyIncluded) continue; if (oldIncludes != null) { - if (child.getKind() == Kind.FIELD && oldIncludes.contains(name)) members.add(new Included(child, null, false)); + if (child.getKind() == Kind.FIELD && oldIncludes.contains(name)) members.add(new Included(child, null, false, false)); continue; } if (child.getKind() != Kind.FIELD) continue; @@ -178,7 +184,7 @@ public class InclusionExclusionUtils { if (child.isTransient() && !includeTransient) continue; if (name.startsWith("$")) continue; if (child.isEnumMember()) continue; - members.add(new Included(child, null, true)); + members.add(new Included(child, null, true, false)); } /* delete default-included fields with the same name as an explicit inclusion */ { @@ -219,8 +225,8 @@ public class InclusionExclusionUtils { Collections.sort(members, new Comparator>() { @Override public int compare(Included a, Included b) { - int ra = a.getInc() == null ? 0 : a.getInc().rank(); - int rb = b.getInc() == null ? 0 : b.getInc().rank(); + int ra = a.hasExplicitRank() ? a.getInc().rank() : a.node.isPrimitive() ? 1000 : 0; + int rb = b.hasExplicitRank() ? b.getInc().rank() : b.node.isPrimitive() ? 1000 : 0; return compareRankOrPosition(ra, rb, a.getNode(), b.getNode()); } diff --git a/src/core/lombok/eclipse/EclipseNode.java b/src/core/lombok/eclipse/EclipseNode.java index 9db491f5..5aa29466 100644 --- a/src/core/lombok/eclipse/EclipseNode.java +++ b/src/core/lombok/eclipse/EclipseNode.java @@ -23,10 +23,6 @@ package lombok.eclipse; import java.util.List; -import lombok.core.AnnotationValues; -import lombok.core.AST.Kind; -import lombok.eclipse.handlers.EclipseHandlerUtil; - import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; @@ -36,11 +32,16 @@ import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.Initializer; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; +import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.eclipse.handlers.EclipseHandlerUtil; + /** * Eclipse specific version of the LombokNode class. */ @@ -264,6 +265,16 @@ public class EclipseNode extends lombok.core.LombokNode { List> fieldNodes = new ArrayList>(); for (BuilderFieldData bfd : builderFields) { for (EclipseNode f : bfd.createdFields) { - fieldNodes.add(new Included(f, null, true)); + fieldNodes.add(new Included(f, null, true, false)); } } MethodDeclaration md = HandleToString.createToString(builderType, fieldNodes, true, false, ast, FieldAccess.ALWAYS_FIELD); diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index 7c8e4ea3..cc4d55be 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -354,7 +354,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { List> fieldNodes = new ArrayList>(); for (BuilderFieldData bfd : builderFields) { for (EclipseNode f : bfd.createdFields) { - fieldNodes.add(new Included(f, null, true)); + fieldNodes.add(new Included(f, null, true, false)); } } // Let toString() call super.toString() if there is a superclass, so that it also shows fields from the superclass' builder. diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java index 19bbeae3..08d22d98 100644 --- a/src/core/lombok/javac/JavacNode.java +++ b/src/core/lombok/javac/JavacNode.java @@ -27,10 +27,6 @@ import java.util.List; import javax.lang.model.element.Element; import javax.tools.Diagnostic; -import lombok.core.AnnotationValues; -import lombok.core.AST.Kind; -import lombok.javac.handlers.JavacHandlerUtil; - import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.model.JavacTypes; @@ -43,8 +39,12 @@ import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCModifiers; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +import com.sun.tools.javac.util.Name; + +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.javac.handlers.JavacHandlerUtil; /** * Javac specific version of the LombokNode class. @@ -345,6 +345,16 @@ public class JavacNode extends lombok.core.LombokNode { java.util.List> fieldNodes = new ArrayList>(); for (BuilderFieldData bfd : builderFields) { for (JavacNode f : bfd.createdFields) { - fieldNodes.add(new Included(f, null, true)); + fieldNodes.add(new Included(f, null, true, false)); } } diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 4cd64b77..f6bf9e1f 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -304,7 +304,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler { java.util.List> fieldNodes = new ArrayList>(); for (BuilderFieldData bfd : builderFields) { for (JavacNode f : bfd.createdFields) { - fieldNodes.add(new Included(f, null, true)); + fieldNodes.add(new Included(f, null, true, false)); } } diff --git a/test/transform/resource/after-delombok/BuilderDefaults.java b/test/transform/resource/after-delombok/BuilderDefaults.java index 5a563024..42b751ce 100644 --- a/test/transform/resource/after-delombok/BuilderDefaults.java +++ b/test/transform/resource/after-delombok/BuilderDefaults.java @@ -85,10 +85,10 @@ public final class BuilderDefaults { if (!(o instanceof BuilderDefaults)) return false; final BuilderDefaults other = (BuilderDefaults) o; if (this.getX() != other.getX()) return false; + if (this.getZ() != other.getZ()) return false; final java.lang.Object this$name = this.getName(); final java.lang.Object other$name = other.getName(); if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; - if (this.getZ() != other.getZ()) return false; return true; } @java.lang.Override @@ -97,10 +97,10 @@ public final class BuilderDefaults { final int PRIME = 59; int result = 1; result = result * PRIME + this.getX(); - final java.lang.Object $name = this.getName(); - result = result * PRIME + ($name == null ? 43 : $name.hashCode()); final long $z = this.getZ(); result = result * PRIME + (int) ($z >>> 32 ^ $z); + final java.lang.Object $name = this.getName(); + result = result * PRIME + ($name == null ? 43 : $name.hashCode()); return result; } @java.lang.Override @@ -108,4 +108,4 @@ public final class BuilderDefaults { public java.lang.String toString() { return "BuilderDefaults(x=" + this.getX() + ", name=" + this.getName() + ", z=" + this.getZ() + ")"; } -} +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeRank.java b/test/transform/resource/after-delombok/EqualsAndHashCodeRank.java index ad2ddbb1..fcf371b6 100644 --- a/test/transform/resource/after-delombok/EqualsAndHashCodeRank.java +++ b/test/transform/resource/after-delombok/EqualsAndHashCodeRank.java @@ -9,9 +9,9 @@ public class EqualsAndHashCodeRank { if (!(o instanceof EqualsAndHashCodeRank)) return false; final EqualsAndHashCodeRank other = (EqualsAndHashCodeRank) o; if (!other.canEqual((java.lang.Object) this)) return false; - if (this.b != other.b) return false; if (this.a != other.a) return false; if (this.c != other.c) return false; + if (this.b != other.b) return false; return true; } @java.lang.SuppressWarnings("all") @@ -23,9 +23,9 @@ public class EqualsAndHashCodeRank { public int hashCode() { final int PRIME = 59; int result = 1; - result = result * PRIME + this.b; result = result * PRIME + this.a; result = result * PRIME + this.c; + result = result * PRIME + this.b; return result; } -} +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/BuilderDefaults.java b/test/transform/resource/after-ecj/BuilderDefaults.java index 46f55bef..c9be219d 100644 --- a/test/transform/resource/after-ecj/BuilderDefaults.java +++ b/test/transform/resource/after-ecj/BuilderDefaults.java @@ -72,25 +72,25 @@ public final @Value @Builder class BuilderDefaults { final BuilderDefaults other = (BuilderDefaults) o; if ((this.getX() != other.getX())) return false; + if ((this.getZ() != other.getZ())) + return false; final java.lang.Object this$name = this.getName(); final java.lang.Object other$name = other.getName(); if (((this$name == null) ? (other$name != null) : (! this$name.equals(other$name)))) return false; - if ((this.getZ() != other.getZ())) - return false; return true; } public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { final int PRIME = 59; int result = 1; result = ((result * PRIME) + this.getX()); - final java.lang.Object $name = this.getName(); - result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode())); final long $z = this.getZ(); result = ((result * PRIME) + (int) ($z ^ ($z >>> 32))); + final java.lang.Object $name = this.getName(); + result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode())); return result; } public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { return (((((("BuilderDefaults(x=" + this.getX()) + ", name=") + this.getName()) + ", z=") + this.getZ()) + ")"); } -} +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeRank.java b/test/transform/resource/after-ecj/EqualsAndHashCodeRank.java index 1ea899a8..ef221261 100644 --- a/test/transform/resource/after-ecj/EqualsAndHashCodeRank.java +++ b/test/transform/resource/after-ecj/EqualsAndHashCodeRank.java @@ -7,18 +7,18 @@ public @EqualsAndHashCode class EqualsAndHashCodeRank { super(); } public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { - if (o == this) + if ((o == this)) return true; - if (!(o instanceof EqualsAndHashCodeRank)) + if ((! (o instanceof EqualsAndHashCodeRank))) return false; final EqualsAndHashCodeRank other = (EqualsAndHashCodeRank) o; - if (!other.canEqual((java.lang.Object) this)) + if ((! other.canEqual((java.lang.Object) this))) return false; - if (this.b != other.b) + if ((this.a != other.a)) return false; - if (this.a != other.a) + if ((this.c != other.c)) return false; - if (this.c != other.c) + if ((this.b != other.b)) return false; return true; } @@ -28,9 +28,9 @@ public @EqualsAndHashCode class EqualsAndHashCodeRank { public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { final int PRIME = 59; int result = 1; - result = result * PRIME + this.b; - result = result * PRIME + this.a; - result = result * PRIME + this.c; + result = ((result * PRIME) + this.a); + result = ((result * PRIME) + this.c); + result = ((result * PRIME) + this.b); return result; } } -- cgit From ed8ea0d8043cb8df6ae3fb962ab3a2087f4adeb6 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Fri, 19 Jun 2020 00:47:00 +0200 Subject: #1543: First primitives, then primitive wrappers, then other references --- doc/changelog.markdown | 2 +- src/core/lombok/EqualsAndHashCode.java | 2 +- src/core/lombok/core/LombokNode.java | 13 ++++++++++++ src/core/lombok/core/handlers/HandlerUtil.java | 21 ++++++++++++++++++++ .../core/handlers/InclusionExclusionUtils.java | 4 ++-- src/core/lombok/eclipse/EclipseNode.java | 23 ++++++++++++++++++++++ src/core/lombok/javac/JavacNode.java | 13 ++++++++++++ src/utils/lombok/eclipse/Eclipse.java | 7 ++----- src/utils/lombok/javac/Javac.java | 19 ++++++++---------- .../after-delombok/ValueStaticConstructorOf.java | 10 +++++----- .../after-ecj/ValueStaticConstructorOf.java | 14 ++++++------- 11 files changed, 96 insertions(+), 32 deletions(-) (limited to 'test/transform/resource') diff --git a/doc/changelog.markdown b/doc/changelog.markdown index af77d480..952d9384 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -2,7 +2,7 @@ Lombok Changelog ---------------- ### v1.18.13 "Edgy Guinea Pig" -* PERFORMANCE: The generated equals method will first compare primitives. Manual re-ordering is possible using `@Include(rank=n)`. [Pull Request #2485](https://github.com/rzwitserloot/lombok/pull/2485), [Issue #1543](https://github.com/rzwitserloot/lombok/issues/1543) +* PERFORMANCE: The generated equals method will first compare primitives, then primitive wrappers and then reference fields. Manual re-ordering is possible using `@Include(rank=n)`. [Pull Request #2485](https://github.com/rzwitserloot/lombok/pull/2485), [Issue #1543](https://github.com/rzwitserloot/lombok/issues/1543) * IMPROBABLE BREAKING CHANGE: The generated hashcode has changed for classes that include both primitive fields and reference fields. * PLATFORM: Added support for compiling projects with OpenJ9 [Pull Request #2437](https://github.com/rzwitserloot/lombok/pull/2437) * BREAKING CHANGE: mapstruct users should now add a dependency to lombok-mapstruct-binding. This solves compiling modules with lombok (and mapstruct). diff --git a/src/core/lombok/EqualsAndHashCode.java b/src/core/lombok/EqualsAndHashCode.java index 2f53bdec..6805d214 100644 --- a/src/core/lombok/EqualsAndHashCode.java +++ b/src/core/lombok/EqualsAndHashCode.java @@ -126,7 +126,7 @@ public @interface EqualsAndHashCode { /** * Higher ranks are considered first. Members of the same rank are considered in the order they appear in the source file. * - * If not explicitly set, the {@code default} rank for primitives is 1000. + * If not explicitly set, the {@code default} rank for primitives is 1000, and for primitive wrappers 800. * * @return ordering within the generating {@code equals} and {@code hashCode} methods; higher numbers are considered first. */ diff --git a/src/core/lombok/core/LombokNode.java b/src/core/lombok/core/LombokNode.java index 46054077..abfc66a6 100644 --- a/src/core/lombok/core/LombokNode.java +++ b/src/core/lombok/core/LombokNode.java @@ -292,6 +292,19 @@ public abstract class LombokNode, L extends LombokNode node, ConfigurationKey key, String featureName) { FlagUsageType fut = node.getAst().readConfiguration(key); @@ -742,4 +744,23 @@ public class HandlerUtil { } return b.toString(); } + + /** Matches any of the 8 primitive names, such as {@code boolean}. */ + private static final Pattern PRIMITIVE_TYPE_NAME_PATTERN = Pattern.compile("^(?:boolean|byte|short|int|long|float|double|char)$"); + + public static boolean isPrimitive(String typeName) { + return PRIMITIVE_TYPE_NAME_PATTERN.matcher(typeName).matches(); + } + + /** Matches any of the 8 primitive wrapper names, such as {@code Boolean}. */ + private static final Pattern PRIMITIVE_WRAPPER_TYPE_NAME_PATTERN = Pattern.compile("^(?:java\\.lang\\.)?(?:Boolean|Byte|Short|Integer|Long|Float|Double|Character)$"); + + public static int defaultEqualsAndHashcodeIncludeRank(String typeName) { + // Modification in this code should be documented + // 1. In the changelog this should be marked as an INPROBABLE BREAKING CHANGE, since the hashcode will change + // 2. In the javadoc of EqualsAndHashcode.Include#rank + if (isPrimitive(typeName)) return 1000; + if (PRIMITIVE_WRAPPER_TYPE_NAME_PATTERN.matcher(typeName).matches()) return 800; + return 0; + } } diff --git a/src/core/lombok/core/handlers/InclusionExclusionUtils.java b/src/core/lombok/core/handlers/InclusionExclusionUtils.java index 609a5e36..e785db3f 100644 --- a/src/core/lombok/core/handlers/InclusionExclusionUtils.java +++ b/src/core/lombok/core/handlers/InclusionExclusionUtils.java @@ -225,8 +225,8 @@ public class InclusionExclusionUtils { Collections.sort(members, new Comparator>() { @Override public int compare(Included a, Included b) { - int ra = a.hasExplicitRank() ? a.getInc().rank() : a.node.isPrimitive() ? 1000 : 0; - int rb = b.hasExplicitRank() ? b.getInc().rank() : b.node.isPrimitive() ? 1000 : 0; + int ra = a.hasExplicitRank() ? a.getInc().rank() : HandlerUtil.defaultEqualsAndHashcodeIncludeRank(a.node.fieldOrMethodBaseType()); + int rb = b.hasExplicitRank() ? b.getInc().rank() : HandlerUtil.defaultEqualsAndHashcodeIncludeRank(b.node.fieldOrMethodBaseType()); return compareRankOrPosition(ra, rb, a.getNode(), b.getNode()); } diff --git a/src/core/lombok/eclipse/EclipseNode.java b/src/core/lombok/eclipse/EclipseNode.java index 5aa29466..12e9ccdb 100644 --- a/src/core/lombok/eclipse/EclipseNode.java +++ b/src/core/lombok/eclipse/EclipseNode.java @@ -275,6 +275,29 @@ public class EclipseNode extends lombok.core.LombokNode 0) return false; - return PRIMITIVE_TYPE_NAME_PATTERN.matcher(toQualifiedName(ref.getTypeName())).matches(); + return HandlerUtil.isPrimitive(toQualifiedName(ref.getTypeName())); } /** diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java index 3cc72f4e..234c7f73 100644 --- a/src/utils/lombok/javac/Javac.java +++ b/src/utils/lombok/javac/Javac.java @@ -37,12 +37,6 @@ import javax.lang.model.type.NoType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeVisitor; -import lombok.core.ClassLiteral; -import lombok.core.FieldSelect; -import lombok.javac.JavacTreeMaker.TreeTag; -import lombok.javac.JavacTreeMaker.TypeTag; -import lombok.permit.Permit; - import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Source; import com.sun.tools.javac.code.Symtab; @@ -61,6 +55,13 @@ import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +import lombok.core.ClassLiteral; +import lombok.core.FieldSelect; +import lombok.core.handlers.HandlerUtil; +import lombok.javac.JavacTreeMaker.TreeTag; +import lombok.javac.JavacTreeMaker.TypeTag; +import lombok.permit.Permit; + /** * Container for static utility methods relevant to lombok's operation on javac. */ @@ -69,9 +70,6 @@ public class Javac { // prevent instantiation } - /** Matches any of the 8 primitive names, such as {@code boolean}. */ - private static final Pattern PRIMITIVE_TYPE_NAME_PATTERN = Pattern.compile("^(boolean|byte|short|int|long|float|double|char)$"); - private static final Pattern VERSION_PARSER = Pattern.compile("^(\\d{1,6})\\.?(\\d{1,6})?.*$"); private static final Pattern SOURCE_PARSER = Pattern.compile("^JDK(\\d{1,6})_?(\\d{1,6})?.*$"); @@ -135,8 +133,7 @@ public class Javac { * expression) represents a primitive type. */ public static boolean isPrimitive(JCExpression ref) { - String typeName = ref.toString(); - return PRIMITIVE_TYPE_NAME_PATTERN.matcher(typeName).matches(); + return HandlerUtil.isPrimitive(ref.toString()); } /** diff --git a/test/transform/resource/after-delombok/ValueStaticConstructorOf.java b/test/transform/resource/after-delombok/ValueStaticConstructorOf.java index fe75f823..e4564628 100644 --- a/test/transform/resource/after-delombok/ValueStaticConstructorOf.java +++ b/test/transform/resource/after-delombok/ValueStaticConstructorOf.java @@ -23,12 +23,12 @@ public final class ValueStaticConstructorOf { if (o == this) return true; if (!(o instanceof ValueStaticConstructorOf)) return false; final ValueStaticConstructorOf other = (ValueStaticConstructorOf) o; - final java.lang.Object this$name = this.getName(); - final java.lang.Object other$name = other.getName(); - if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; final java.lang.Object this$price = this.getPrice(); final java.lang.Object other$price = other.getPrice(); if (this$price == null ? other$price != null : !this$price.equals(other$price)) return false; + final java.lang.Object this$name = this.getName(); + final java.lang.Object other$name = other.getName(); + if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; return true; } @java.lang.Override @@ -36,10 +36,10 @@ public final class ValueStaticConstructorOf { public int hashCode() { final int PRIME = 59; int result = 1; - final java.lang.Object $name = this.getName(); - result = result * PRIME + ($name == null ? 43 : $name.hashCode()); final java.lang.Object $price = this.getPrice(); result = result * PRIME + ($price == null ? 43 : $price.hashCode()); + final java.lang.Object $name = this.getName(); + result = result * PRIME + ($name == null ? 43 : $name.hashCode()); return result; } @java.lang.Override diff --git a/test/transform/resource/after-ecj/ValueStaticConstructorOf.java b/test/transform/resource/after-ecj/ValueStaticConstructorOf.java index 6cf71ed4..87883566 100644 --- a/test/transform/resource/after-ecj/ValueStaticConstructorOf.java +++ b/test/transform/resource/after-ecj/ValueStaticConstructorOf.java @@ -19,23 +19,23 @@ public final @Value(staticConstructor = "of") class ValueStaticConstructorOf { if ((! (o instanceof ValueStaticConstructorOf))) return false; final ValueStaticConstructorOf other = (ValueStaticConstructorOf) o; - final java.lang.Object this$name = this.getName(); - final java.lang.Object other$name = other.getName(); - if (((this$name == null) ? (other$name != null) : (! this$name.equals(other$name)))) - return false; final java.lang.Object this$price = this.getPrice(); final java.lang.Object other$price = other.getPrice(); if (((this$price == null) ? (other$price != null) : (! this$price.equals(other$price)))) return false; + final java.lang.Object this$name = this.getName(); + final java.lang.Object other$name = other.getName(); + if (((this$name == null) ? (other$name != null) : (! this$name.equals(other$name)))) + return false; return true; } public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { final int PRIME = 59; int result = 1; - final java.lang.Object $name = this.getName(); - result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode())); final java.lang.Object $price = this.getPrice(); result = ((result * PRIME) + (($price == null) ? 43 : $price.hashCode())); + final java.lang.Object $name = this.getName(); + result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode())); return result; } public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { @@ -44,4 +44,4 @@ public final @Value(staticConstructor = "of") class ValueStaticConstructorOf { public static @java.lang.SuppressWarnings("all") ValueStaticConstructorOf of(final String name, final Double price) { return new ValueStaticConstructorOf(name, price); } -} \ No newline at end of file +} -- cgit From a3d71d68473d23f5cf722d8c1bff31781d6d9c66 Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Wed, 24 Jun 2020 19:31:09 +0200 Subject: Fix broken test cases --- .../lombok/eclipse/handlers/HandleBuilder.java | 27 +++++++++++----------- .../eclipse/handlers/HandleSuperBuilder.java | 16 ++++++------- .../after-ecj/CheckerFrameworkSuperBuilder.java | 5 ++++ .../resource/after-ecj/SimpleTypeResolution.java | 2 ++ .../CheckerFrameworkBasic.java.messages | 2 +- .../CheckerFrameworkSuperBuilder.java.messages | 2 +- 6 files changed, 31 insertions(+), 23 deletions(-) (limited to 'test/transform/resource') diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index f848469f..801fe7e7 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -57,6 +57,7 @@ import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; +import org.eclipse.jdt.internal.compiler.ast.Receiver; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; @@ -683,7 +684,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { return decl; } - static Argument[] generateBuildArgs(CheckerFrameworkVersion cfv, EclipseNode type, List builderFields, ASTNode source) { + static Receiver generateBuildReceiver(CheckerFrameworkVersion cfv, EclipseNode type, List builderFields, ASTNode source) { if (!cfv.generateCalledMethods()) return null; List mandatories = new ArrayList(); @@ -706,9 +707,11 @@ public class HandleBuilder extends EclipseAnnotationHandler { } ann.memberValue = arr; } - Argument arg = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, generateTypeReference(type, source.sourceStart), Modifier.FINAL); - arg.annotations = new Annotation[] {ann}; - return new Argument[] {arg}; + + QualifiedTypeReference typeReference = (QualifiedTypeReference) generateTypeReference(type, source.sourceStart); + typeReference.annotations = new Annotation[typeReference.tokens.length][]; + typeReference.annotations[0] = new Annotation[] {ann}; + return new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, Modifier.FINAL); } public MethodDeclaration generateBuildMethod(CheckerFrameworkVersion cfv, EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source, AccessLevel access) { @@ -802,7 +805,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { if (cfv.generateSideEffectFree()) { out.annotations = new Annotation[] {generateNamedAnnotation(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE)}; } - out.arguments = generateBuildArgs(cfv, type, builderFields, source); + out.receiver = generateBuildReceiver(cfv, type, builderFields, source); if (staticName == null) createRelevantNonNullAnnotation(type, out); out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return out; @@ -953,16 +956,14 @@ public class HandleBuilder extends EclipseAnnotationHandler { MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, chain, toEclipseModifier(access), sourceNode, methodAnnsList, annotations != null ? Arrays.asList(copyAnnotations(source, annotations)) : Collections.emptyList()); if (cfv.generateCalledMethods()) { - Argument[] arr = setter.arguments == null ? new Argument[0] : setter.arguments; - Argument[] newArr = new Argument[arr.length + 1]; - System.arraycopy(arr, 0, newArr, 1, arr.length); - newArr[0] = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, generateTypeReference(builderType, 0), Modifier.FINAL); char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED); - SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss( - source, nameNotCalled.length)), source.sourceStart); + SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(source, nameNotCalled.length)), source.sourceStart); ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0); - newArr[0].annotations = new Annotation[] {ann}; - setter.arguments = newArr; + + QualifiedTypeReference typeReference = (QualifiedTypeReference) generateTypeReference(builderType, 0); + typeReference.annotations = new Annotation[typeReference.tokens.length][]; + typeReference.annotations[0] = new Annotation[] {ann}; + setter.receiver = new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, Modifier.FINAL); } injectMethod(builderType, setter); } diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index cc4d55be..2ba456da 100644 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -57,6 +57,7 @@ import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; +import org.eclipse.jdt.internal.compiler.ast.Receiver; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; @@ -831,7 +832,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { if (overrideAnn != null && sefAnn != null) out.annotations = new Annotation[] {overrideAnn, sefAnn}; else if (overrideAnn != null) out.annotations = new Annotation[] {overrideAnn}; else if (sefAnn != null) out.annotations = new Annotation[] {sefAnn}; - out.arguments = HandleBuilder.generateBuildArgs(cfv, builderType, builderFields, source); + out.receiver = HandleBuilder.generateBuildReceiver(cfv, builderType, builderFields, source); out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return out; } @@ -856,7 +857,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { allocationStatement.arguments = new Expression[] {new ThisReference(0, 0)}; statements.add(new ReturnStatement(allocationStatement, 0, 0)); out.statements = statements.isEmpty() ? null : statements.toArray(new Statement[0]); - out.arguments = HandleBuilder.generateBuildArgs(cfv, builderType, builderFields, source); + out.receiver = HandleBuilder.generateBuildReceiver(cfv, builderType, builderFields, source); createRelevantNonNullAnnotation(builderType, out); out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); return out; @@ -970,15 +971,14 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, returnType, returnStatement, ClassFileConstants.AccPublic, sourceNode, methodAnnsList, annosOnParam != null ? Arrays.asList(copyAnnotations(source, annosOnParam)) : Collections.emptyList()); if (cfv.generateCalledMethods()) { - Argument[] arr = setter.arguments == null ? new Argument[0] : setter.arguments; - Argument[] newArr = new Argument[arr.length + 1]; - System.arraycopy(arr, 0, newArr, 1, arr.length); - newArr[0] = new Argument(new char[] { 't', 'h', 'i', 's' }, 0, generateTypeReference(builderType, 0), Modifier.FINAL); char[][] nameNotCalled = fromQualifiedName(CheckerFrameworkVersion.NAME__NOT_CALLED); SingleMemberAnnotation ann = new SingleMemberAnnotation(new QualifiedTypeReference(nameNotCalled, poss(source, nameNotCalled.length)), source.sourceStart); ann.memberValue = new StringLiteral(setterName.toCharArray(), 0, 0, 0); - newArr[0].annotations = new Annotation[] {ann}; - setter.arguments = newArr; + + QualifiedTypeReference typeReference = (QualifiedTypeReference) generateTypeReference(builderType, 0); + typeReference.annotations = new Annotation[typeReference.tokens.length][]; + typeReference.annotations[0] = new Annotation[] {ann}; + setter.receiver = new Receiver(new char[] { 't', 'h', 'i', 's' }, 0, typeReference, null, Modifier.FINAL); } injectMethod(builderType, setter); } diff --git a/test/transform/resource/after-ecj/CheckerFrameworkSuperBuilder.java b/test/transform/resource/after-ecj/CheckerFrameworkSuperBuilder.java index 5bd4e1b3..43568236 100644 --- a/test/transform/resource/after-ecj/CheckerFrameworkSuperBuilder.java +++ b/test/transform/resource/after-ecj/CheckerFrameworkSuperBuilder.java @@ -9,6 +9,7 @@ class CheckerFrameworkSuperBuilder { private @java.lang.SuppressWarnings("all") int z; private @java.lang.SuppressWarnings("all") java.util.ArrayList names; public ParentBuilder() { + super(); } protected abstract @org.checkerframework.checker.builder.qual.ReturnsReceiver @org.checkerframework.dataflow.qual.Pure @java.lang.SuppressWarnings("all") B self(); public abstract @org.checkerframework.dataflow.qual.SideEffectFree @java.lang.SuppressWarnings("all") C build(final @org.checkerframework.checker.builder.qual.CalledMethods({"y", "z"}) CheckerFrameworkSuperBuilder.Parent.ParentBuilder this); @@ -52,6 +53,7 @@ class CheckerFrameworkSuperBuilder { } private static final @java.lang.SuppressWarnings("all") class ParentBuilderImpl extends CheckerFrameworkSuperBuilder.Parent.ParentBuilder { private ParentBuilderImpl() { + super(); } protected @java.lang.Override @org.checkerframework.checker.builder.qual.ReturnsReceiver @org.checkerframework.dataflow.qual.Pure @java.lang.SuppressWarnings("all") CheckerFrameworkSuperBuilder.Parent.ParentBuilderImpl self() { return this; @@ -98,6 +100,7 @@ class CheckerFrameworkSuperBuilder { private @java.lang.SuppressWarnings("all") boolean a$set; private @java.lang.SuppressWarnings("all") int b; public ChildBuilder() { + super(); } protected abstract @java.lang.Override @org.checkerframework.checker.builder.qual.ReturnsReceiver @org.checkerframework.dataflow.qual.Pure @java.lang.SuppressWarnings("all") B self(); public abstract @java.lang.Override @org.checkerframework.dataflow.qual.SideEffectFree @java.lang.SuppressWarnings("all") C build(final @org.checkerframework.checker.builder.qual.CalledMethods("b") CheckerFrameworkSuperBuilder.Child.ChildBuilder this); @@ -116,6 +119,7 @@ class CheckerFrameworkSuperBuilder { } private static final @java.lang.SuppressWarnings("all") class ChildBuilderImpl extends CheckerFrameworkSuperBuilder.Child.ChildBuilder { private ChildBuilderImpl() { + super(); } protected @java.lang.Override @org.checkerframework.checker.builder.qual.ReturnsReceiver @org.checkerframework.dataflow.qual.Pure @java.lang.SuppressWarnings("all") CheckerFrameworkSuperBuilder.Child.ChildBuilderImpl self() { return this; @@ -142,5 +146,6 @@ class CheckerFrameworkSuperBuilder { } } CheckerFrameworkSuperBuilder() { + super(); } } diff --git a/test/transform/resource/after-ecj/SimpleTypeResolution.java b/test/transform/resource/after-ecj/SimpleTypeResolution.java index c413623e..d8321ca4 100644 --- a/test/transform/resource/after-ecj/SimpleTypeResolution.java +++ b/test/transform/resource/after-ecj/SimpleTypeResolution.java @@ -1,11 +1,13 @@ class SimpleTypeResolutionFail { private @Getter int x; SimpleTypeResolutionFail() { + super(); } } class SimpleTypeResolutionSuccess { private @lombok.Getter int x; SimpleTypeResolutionSuccess() { + super(); } public @java.lang.SuppressWarnings("all") int getX() { return this.x; diff --git a/test/transform/resource/messages-ecj/CheckerFrameworkBasic.java.messages b/test/transform/resource/messages-ecj/CheckerFrameworkBasic.java.messages index 9bfcba0c..8cc7fb58 100644 --- a/test/transform/resource/messages-ecj/CheckerFrameworkBasic.java.messages +++ b/test/transform/resource/messages-ecj/CheckerFrameworkBasic.java.messages @@ -1 +1 @@ -8 org.checkerframework cannot be resolved to a type +6 org.checkerframework.common cannot be resolved to a type diff --git a/test/transform/resource/messages-ecj/CheckerFrameworkSuperBuilder.java.messages b/test/transform/resource/messages-ecj/CheckerFrameworkSuperBuilder.java.messages index d385a95c..8cc7fb58 100644 --- a/test/transform/resource/messages-ecj/CheckerFrameworkSuperBuilder.java.messages +++ b/test/transform/resource/messages-ecj/CheckerFrameworkSuperBuilder.java.messages @@ -1 +1 @@ -6 org.checkerframework cannot be resolved to a type +6 org.checkerframework.common cannot be resolved to a type -- cgit From 9425e99b49d1a203c692fd2001ff3fd3d1612303 Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Sun, 28 Jun 2020 00:58:54 +0200 Subject: [fixes #2469] Support static reference as logger topic --- src/core/lombok/core/AnnotationValues.java | 8 +++++ .../eclipse/handlers/EclipseHandlerUtil.java | 21 ++++++++++--- src/core/lombok/eclipse/handlers/HandleLog.java | 36 ++++++++++++---------- src/core/lombok/javac/handlers/HandleLog.java | 33 +++++++++++--------- .../resource/after-delombok/LoggerCommons.java | 5 +++ .../LoggerCustomWithTopicAndName.java | 6 ++++ .../resource/after-delombok/LoggerJBossLog.java | 6 ++++ .../resource/after-delombok/LoggerJul.java | 5 +++ .../resource/after-delombok/LoggerLog4j.java | 5 +++ .../resource/after-delombok/LoggerLog4j2.java | 5 +++ .../resource/after-delombok/LoggerSlf4j.java | 17 ++++++++++ .../after-delombok/LoggerSlf4jInvalidTopic.java | 5 +++ .../resource/after-delombok/LoggerXSlf4j.java | 5 +++ .../resource/after-ecj/LoggerCommons.java | 9 ++++++ .../after-ecj/LoggerCustomWithTopicAndName.java | 9 ++++++ .../resource/after-ecj/LoggerJBossLog.java | 9 ++++++ test/transform/resource/after-ecj/LoggerJul.java | 9 ++++++ test/transform/resource/after-ecj/LoggerLog4j.java | 9 ++++++ .../transform/resource/after-ecj/LoggerLog4j2.java | 9 ++++++ test/transform/resource/after-ecj/LoggerSlf4j.java | 27 ++++++++++++++++ .../after-ecj/LoggerSlf4jInvalidTopic.java | 9 ++++++ .../transform/resource/after-ecj/LoggerXSlf4j.java | 11 ++++++- test/transform/resource/before/LoggerCommons.java | 5 +++ .../before/LoggerCustomWithTopicAndName.java | 5 +++ test/transform/resource/before/LoggerJBossLog.java | 5 +++ test/transform/resource/before/LoggerJul.java | 5 +++ test/transform/resource/before/LoggerLog4j.java | 5 +++ test/transform/resource/before/LoggerLog4j2.java | 5 +++ test/transform/resource/before/LoggerSlf4j.java | 14 +++++++++ .../resource/before/LoggerSlf4jInvalidTopic.java | 5 +++ test/transform/resource/before/LoggerXSlf4j.java | 5 +++ .../LoggerSlf4jInvalidTopic.java.messages | 2 ++ .../LoggerSlf4jInvalidTopic.java.messages | 1 + .../LoggerSlf4jInvalidTopic.java.messages | 1 + 34 files changed, 279 insertions(+), 37 deletions(-) create mode 100644 test/transform/resource/after-delombok/LoggerSlf4jInvalidTopic.java create mode 100644 test/transform/resource/after-ecj/LoggerSlf4jInvalidTopic.java create mode 100644 test/transform/resource/before/LoggerSlf4jInvalidTopic.java create mode 100644 test/transform/resource/messages-delombok/LoggerSlf4jInvalidTopic.java.messages create mode 100644 test/transform/resource/messages-ecj/LoggerSlf4jInvalidTopic.java.messages create mode 100644 test/transform/resource/messages-idempotent/LoggerSlf4jInvalidTopic.java.messages (limited to 'test/transform/resource') diff --git a/src/core/lombok/core/AnnotationValues.java b/src/core/lombok/core/AnnotationValues.java index eec5abd8..78bb1fb5 100644 --- a/src/core/lombok/core/AnnotationValues.java +++ b/src/core/lombok/core/AnnotationValues.java @@ -411,6 +411,14 @@ public class AnnotationValues { List l = getActualExpressions(annotationMethodName); return l.isEmpty() ? null : l.get(0); } + + /** + * Returns the guessed value for the provided {@code annotationMethodName}. + */ + public Object getValueGuess(String annotationMethodName) { + AnnotationValue v = values.get(annotationMethodName); + return v == null || v.valueGuesses.isEmpty() ? null : v.valueGuesses.get(0); + } /** Generates an error message on the stated annotation value (you should only call this method if you know it's there!) */ public void setError(String annotationMethodName, String message) { diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 1b4f510c..e674409c 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -49,6 +49,7 @@ import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference; import org.eclipse.jdt.internal.compiler.ast.AssertStatement; +import org.eclipse.jdt.internal.compiler.ast.BinaryExpression; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.CastExpression; import org.eclipse.jdt.internal.compiler.ast.CharLiteral; @@ -380,7 +381,7 @@ public class EclipseHandlerUtil { } } - private static Expression copyAnnotationMemberValue(Expression in) { + public static Expression copyAnnotationMemberValue(Expression in) { Expression out = copyAnnotationMemberValue0(in); out.constant = in.constant; return out; @@ -421,12 +422,11 @@ public class EclipseHandlerUtil { if (in instanceof SingleNameReference) { SingleNameReference snr = (SingleNameReference) in; - long p = (long) s << 32 | e; - return new SingleNameReference(snr.token, p); + return new SingleNameReference(snr.token, pos(in)); } if (in instanceof QualifiedNameReference) { QualifiedNameReference qnr = (QualifiedNameReference) in; - return new QualifiedNameReference(qnr.tokens, qnr.sourcePositions, s, e); + return new QualifiedNameReference(qnr.tokens, poss(in, qnr.tokens.length), s, e); } // class refs @@ -442,11 +442,22 @@ public class EclipseHandlerUtil { out.sourceEnd = e; out.bits = in.bits; out.implicitConversion = in.implicitConversion; - out.statementEnd = in.statementEnd; + out.statementEnd = e; out.expressions = copy; return out; } + if (in instanceof BinaryExpression) { + BinaryExpression be = (BinaryExpression) in; + BinaryExpression out = new BinaryExpression(be); + out.left = copyAnnotationMemberValue(be.left); + out.right = copyAnnotationMemberValue(be.right); + out.sourceStart = s; + out.sourceEnd = e; + out.statementEnd = e; + return out; + } + return in; } diff --git a/src/core/lombok/eclipse/handlers/HandleLog.java b/src/core/lombok/eclipse/handlers/HandleLog.java index 7a140193..a0e431e5 100644 --- a/src/core/lombok/eclipse/handlers/HandleLog.java +++ b/src/core/lombok/eclipse/handlers/HandleLog.java @@ -51,6 +51,7 @@ import lombok.core.configuration.LogDeclaration.LogFactoryParameter; import lombok.core.handlers.LoggingFramework; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; +import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult; public class HandleLog { private static final IdentifierName LOG = IdentifierName.valueOf("log"); @@ -59,7 +60,7 @@ public class HandleLog { throw new UnsupportedOperationException(); } - public static void processAnnotation(LoggingFramework framework, AnnotationValues annotation, Annotation source, EclipseNode annotationNode, String loggerTopic) { + public static void processAnnotation(LoggingFramework framework, AnnotationValues annotation, Annotation source, EclipseNode annotationNode) { EclipseNode owner = annotationNode.up(); switch (owner.getKind()) { @@ -84,15 +85,18 @@ public class HandleLog { annotationNode.addWarning("Field '" + logFieldName + "' already exists."); return; } - - if (loggerTopic != null && loggerTopic.trim().isEmpty()) loggerTopic = null; + + Object valueGuess = annotation.getValueGuess("topic"); + Expression loggerTopic = (Expression) annotation.getActualExpression("topic"); + + if (valueGuess instanceof String && ((String) valueGuess).trim().isEmpty()) loggerTopic = null; if (framework.getDeclaration().getParametersWithTopic() == null && loggerTopic != null) { annotationNode.addError(framework.getAnnotationAsString() + " does not allow a topic."); loggerTopic = null; } if (framework.getDeclaration().getParametersWithoutTopic() == null && loggerTopic == null) { annotationNode.addError(framework.getAnnotationAsString() + " requires a topic."); - loggerTopic = ""; + loggerTopic = new StringLiteral(new char[]{}, 0, 0, 0); } ClassLiteralAccess loggingType = selfType(owner, source); @@ -122,7 +126,7 @@ public class HandleLog { return result; } - private static FieldDeclaration createField(LoggingFramework framework, Annotation source, ClassLiteralAccess loggingType, String logFieldName, boolean useStatic, String loggerTopic) { + private static FieldDeclaration createField(LoggingFramework framework, Annotation source, ClassLiteralAccess loggingType, String logFieldName, boolean useStatic, Expression loggerTopic) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; @@ -165,7 +169,7 @@ public class HandleLog { return typeReference; } - private static final Expression[] createFactoryParameters(ClassLiteralAccess loggingType, Annotation source, List parameters, String loggerTopic) { + private static final Expression[] createFactoryParameters(ClassLiteralAccess loggingType, Annotation source, List parameters, Expression loggerTopic) { Expression[] expressions = new Expression[parameters.size()]; int pS = source.sourceStart, pE = source.sourceEnd; @@ -192,7 +196,7 @@ public class HandleLog { expressions[i] = factoryParameterCall; break; case TOPIC: - expressions[i] = new StringLiteral(loggerTopic.toCharArray(), pS, pE, 0); + expressions[i] = EclipseHandlerUtil.copyAnnotationMemberValue(loggerTopic); break; case NULL: expressions[i] = new NullLiteral(pS, pE); @@ -219,7 +223,7 @@ public class HandleLog { public static class HandleCommonsLog extends EclipseAnnotationHandler { @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_COMMONS_FLAG_USAGE, "@apachecommons.CommonsLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.COMMONS, annotation, source, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.COMMONS, annotation, source, annotationNode); } } @@ -230,7 +234,7 @@ public class HandleLog { public static class HandleJulLog extends EclipseAnnotationHandler { @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JUL_FLAG_USAGE, "@java.Log", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.JUL, annotation, source, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.JUL, annotation, source, annotationNode); } } @@ -241,7 +245,7 @@ public class HandleLog { public static class HandleLog4jLog extends EclipseAnnotationHandler { @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J_FLAG_USAGE, "@Log4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.LOG4J, annotation, source, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.LOG4J, annotation, source, annotationNode); } } @@ -252,7 +256,7 @@ public class HandleLog { public static class HandleLog4j2Log extends EclipseAnnotationHandler { @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J2_FLAG_USAGE, "@Log4j2", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.LOG4J2, annotation, source, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.LOG4J2, annotation, source, annotationNode); } } @@ -263,7 +267,7 @@ public class HandleLog { public static class HandleSlf4jLog extends EclipseAnnotationHandler { @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_SLF4J_FLAG_USAGE, "@Slf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.SLF4J, annotation, source, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.SLF4J, annotation, source, annotationNode); } } @@ -274,7 +278,7 @@ public class HandleLog { public static class HandleXSlf4jLog extends EclipseAnnotationHandler { @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_XSLF4J_FLAG_USAGE, "@XSlf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.XSLF4J, annotation, source, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.XSLF4J, annotation, source, annotationNode); } } @@ -285,7 +289,7 @@ public class HandleLog { public static class HandleJBossLog extends EclipseAnnotationHandler { @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JBOSSLOG_FLAG_USAGE, "@JBossLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.JBOSSLOG, annotation, source, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.JBOSSLOG, annotation, source, annotationNode); } } @@ -296,7 +300,7 @@ public class HandleLog { public static class HandleFloggerLog extends EclipseAnnotationHandler { @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_FLOGGER_FLAG_USAGE, "@Flogger", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.FLOGGER, annotation, source, annotationNode, ""); + processAnnotation(LoggingFramework.FLOGGER, annotation, source, annotationNode); } } @@ -313,7 +317,7 @@ public class HandleLog { return; } LoggingFramework framework = new LoggingFramework(lombok.CustomLog.class, logDeclaration); - processAnnotation(framework, annotation, source, annotationNode, annotation.getInstance().topic()); + processAnnotation(framework, annotation, source, annotationNode); } } } diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 522f8576..3173b3ba 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -56,7 +56,7 @@ public class HandleLog { throw new UnsupportedOperationException(); } - public static void processAnnotation(LoggingFramework framework, AnnotationValues annotation, JavacNode annotationNode, String loggerTopic) { + public static void processAnnotation(LoggingFramework framework, AnnotationValues annotation, JavacNode annotationNode) { deleteAnnotationIfNeccessary(annotationNode, framework.getAnnotationClass()); JavacNode typeNode = annotationNode.up(); @@ -76,14 +76,17 @@ public class HandleLog { return; } - if (loggerTopic != null && loggerTopic.trim().isEmpty()) loggerTopic = null; + Object valueGuess = annotation.getValueGuess("topic"); + JCExpression loggerTopic = (JCExpression) annotation.getActualExpression("topic"); + + if (valueGuess instanceof String && ((String) valueGuess).trim().isEmpty()) loggerTopic = null; if (framework.getDeclaration().getParametersWithTopic() == null && loggerTopic != null) { annotationNode.addError(framework.getAnnotationAsString() + " does not allow a topic."); loggerTopic = null; } if (framework.getDeclaration().getParametersWithoutTopic() == null && loggerTopic == null) { annotationNode.addError(framework.getAnnotationAsString() + " requires a topic."); - loggerTopic = ""; + loggerTopic = typeNode.getTreeMaker().Literal(""); } JCFieldAccess loggingType = selfType(typeNode); @@ -101,7 +104,7 @@ public class HandleLog { return maker.Select(maker.Ident(name), typeNode.toName("class")); } - private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source, String logFieldName, boolean useStatic, String loggerTopic) { + private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source, String logFieldName, boolean useStatic, JCExpression loggerTopic) { JavacTreeMaker maker = typeNode.getTreeMaker(); LogDeclaration logDeclaration = framework.getDeclaration(); @@ -121,7 +124,7 @@ public class HandleLog { return true; } - private static JCExpression[] createFactoryParameters(JavacNode typeNode, JCFieldAccess loggingType, java.util.List parameters, String loggerTopic) { + private static JCExpression[] createFactoryParameters(JavacNode typeNode, JCFieldAccess loggingType, java.util.List parameters, JCExpression loggerTopic) { JCExpression[] expressions = new JCExpression[parameters.size()]; JavacTreeMaker maker = typeNode.getTreeMaker(); @@ -136,7 +139,7 @@ public class HandleLog { expressions[i] = maker.Apply(List.nil(), method, List.nil()); break; case TOPIC: - expressions[i] = maker.Literal(loggerTopic); + expressions[i] = (JCExpression) loggerTopic.clone(); break; case NULL: expressions[i] = maker.Literal(CTC_BOT, null); @@ -156,7 +159,7 @@ public class HandleLog { public static class HandleCommonsLog extends JavacAnnotationHandler { @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_COMMONS_FLAG_USAGE, "@apachecommons.CommonsLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.COMMONS, annotation, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.COMMONS, annotation, annotationNode); } } @@ -167,7 +170,7 @@ public class HandleLog { public static class HandleJulLog extends JavacAnnotationHandler { @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JUL_FLAG_USAGE, "@java.Log", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.JUL, annotation, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.JUL, annotation, annotationNode); } } @@ -178,7 +181,7 @@ public class HandleLog { public static class HandleLog4jLog extends JavacAnnotationHandler { @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J_FLAG_USAGE, "@Log4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.LOG4J, annotation, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.LOG4J, annotation, annotationNode); } } @@ -189,7 +192,7 @@ public class HandleLog { public static class HandleLog4j2Log extends JavacAnnotationHandler { @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_LOG4J2_FLAG_USAGE, "@Log4j2", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.LOG4J2, annotation, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.LOG4J2, annotation, annotationNode); } } @@ -200,7 +203,7 @@ public class HandleLog { public static class HandleSlf4jLog extends JavacAnnotationHandler { @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_SLF4J_FLAG_USAGE, "@Slf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.SLF4J, annotation, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.SLF4J, annotation, annotationNode); } } @@ -211,7 +214,7 @@ public class HandleLog { public static class HandleXSlf4jLog extends JavacAnnotationHandler { @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_XSLF4J_FLAG_USAGE, "@XSlf4j", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.XSLF4J, annotation, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.XSLF4J, annotation, annotationNode); } } @@ -222,7 +225,7 @@ public class HandleLog { public static class HandleJBossLog extends JavacAnnotationHandler { @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JBOSSLOG_FLAG_USAGE, "@JBossLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.JBOSSLOG, annotation, annotationNode, annotation.getInstance().topic()); + processAnnotation(LoggingFramework.JBOSSLOG, annotation, annotationNode); } } @@ -233,7 +236,7 @@ public class HandleLog { public static class HandleFloggerLog extends JavacAnnotationHandler { @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.LOG_FLOGGER_FLAG_USAGE, "@Flogger", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log"); - processAnnotation(LoggingFramework.FLOGGER, annotation, annotationNode, ""); + processAnnotation(LoggingFramework.FLOGGER, annotation, annotationNode); } } @@ -250,7 +253,7 @@ public class HandleLog { return; } LoggingFramework framework = new LoggingFramework(lombok.CustomLog.class, logDeclaration); - processAnnotation(framework, annotation, annotationNode, annotation.getInstance().topic()); + processAnnotation(framework, annotation, annotationNode); } } } diff --git a/test/transform/resource/after-delombok/LoggerCommons.java b/test/transform/resource/after-delombok/LoggerCommons.java index 954e730b..4b943da7 100644 --- a/test/transform/resource/after-delombok/LoggerCommons.java +++ b/test/transform/resource/after-delombok/LoggerCommons.java @@ -10,3 +10,8 @@ class LoggerCommonsWithDifferentName { @java.lang.SuppressWarnings("all") private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("DifferentName"); } +class LoggerCommonsWithStaticField { + @java.lang.SuppressWarnings("all") + private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LoggerCommonsWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/LoggerCustomWithTopicAndName.java b/test/transform/resource/after-delombok/LoggerCustomWithTopicAndName.java index abb785b9..4db02cc1 100644 --- a/test/transform/resource/after-delombok/LoggerCustomWithTopicAndName.java +++ b/test/transform/resource/after-delombok/LoggerCustomWithTopicAndName.java @@ -3,6 +3,12 @@ class LoggerCustomLog { private static final MyLoggerFactory log = MyLoggerFactory.create(LoggerCustomLog.class.getName(), "t", null, LoggerCustomLog.class, "t"); } +class LoggerCustomLogWithStaticField { + @java.lang.SuppressWarnings("all") + private static final MyLoggerFactory log = MyLoggerFactory.create(LoggerCustomLogWithStaticField.class.getName(), LoggerCustomLogWithStaticField.TOPIC, null, LoggerCustomLogWithStaticField.class, LoggerCustomLogWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; +} + class MyLoggerFactory { static MyLoggerFactory create(String name, String t1, Object o, Class clazz, String t2) { return null; diff --git a/test/transform/resource/after-delombok/LoggerJBossLog.java b/test/transform/resource/after-delombok/LoggerJBossLog.java index 41c18805..5fd98aa6 100644 --- a/test/transform/resource/after-delombok/LoggerJBossLog.java +++ b/test/transform/resource/after-delombok/LoggerJBossLog.java @@ -17,3 +17,9 @@ class LoggerJBossLogWithDifferentLoggerName { @java.lang.SuppressWarnings("all") private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger("DifferentLogger"); } + +class LoggerJBossLogWithStaticField { + @java.lang.SuppressWarnings("all") + private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LoggerJBossLogWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/LoggerJul.java b/test/transform/resource/after-delombok/LoggerJul.java index 63f96733..cfb44fde 100644 --- a/test/transform/resource/after-delombok/LoggerJul.java +++ b/test/transform/resource/after-delombok/LoggerJul.java @@ -10,3 +10,8 @@ class LoggerJulWithDifferentName { @java.lang.SuppressWarnings("all") private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger("DifferentName"); } +class LoggerJulWithStaticField { + @java.lang.SuppressWarnings("all") + private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggerJulWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/LoggerLog4j.java b/test/transform/resource/after-delombok/LoggerLog4j.java index 7d9d4409..cef83621 100644 --- a/test/transform/resource/after-delombok/LoggerLog4j.java +++ b/test/transform/resource/after-delombok/LoggerLog4j.java @@ -10,3 +10,8 @@ class LoggerLog4jWithDifferentName { @java.lang.SuppressWarnings("all") private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger("DifferentName"); } +class LoggerLog4jWithStaticField { + @java.lang.SuppressWarnings("all") + private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LoggerLog4jWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; +} diff --git a/test/transform/resource/after-delombok/LoggerLog4j2.java b/test/transform/resource/after-delombok/LoggerLog4j2.java index 3d8b7b5b..b32c7722 100644 --- a/test/transform/resource/after-delombok/LoggerLog4j2.java +++ b/test/transform/resource/after-delombok/LoggerLog4j2.java @@ -10,3 +10,8 @@ class LoggerLog4j2WithDifferentName { @java.lang.SuppressWarnings("all") private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger("DifferentName"); } +class LoggerLog4j2WithStaticField { + @java.lang.SuppressWarnings("all") + private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LoggerLog4j2WithStaticField.TOPIC); + static final String TOPIC = "StaticField"; +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/LoggerSlf4j.java b/test/transform/resource/after-delombok/LoggerSlf4j.java index 68d685f0..70f11ae4 100644 --- a/test/transform/resource/after-delombok/LoggerSlf4j.java +++ b/test/transform/resource/after-delombok/LoggerSlf4j.java @@ -17,3 +17,20 @@ class LoggerSlf4jWithDifferentLoggerName { @java.lang.SuppressWarnings("all") private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("DifferentLogger"); } + +class LoggerSlf4jWithStaticField { + @java.lang.SuppressWarnings("all") + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggerSlf4jWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; +} + +class LoggerSlf4jWithTwoStaticFields { + @java.lang.SuppressWarnings("all") + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggerSlf4jWithTwoStaticFields.TOPIC + LoggerSlf4jWithTwoStaticFields.TOPIC); + static final String TOPIC = "StaticField"; +} + +class LoggerSlf4jWithTwoLiterals { + @java.lang.SuppressWarnings("all") + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("A" + "B"); +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/LoggerSlf4jInvalidTopic.java b/test/transform/resource/after-delombok/LoggerSlf4jInvalidTopic.java new file mode 100644 index 00000000..86e6ae2c --- /dev/null +++ b/test/transform/resource/after-delombok/LoggerSlf4jInvalidTopic.java @@ -0,0 +1,5 @@ +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = 42) +class LoggerSlf4jWithIntegerTopic { +} \ No newline at end of file diff --git a/test/transform/resource/after-delombok/LoggerXSlf4j.java b/test/transform/resource/after-delombok/LoggerXSlf4j.java index 781733cf..ba0ec3f8 100644 --- a/test/transform/resource/after-delombok/LoggerXSlf4j.java +++ b/test/transform/resource/after-delombok/LoggerXSlf4j.java @@ -10,3 +10,8 @@ class LoggerXSlf4jWithDifferentName { @java.lang.SuppressWarnings("all") private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger("DifferentName"); } +class LoggerXSlf4jWithStaticField { + @java.lang.SuppressWarnings("all") + private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LoggerXSlf4jWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerCommons.java b/test/transform/resource/after-ecj/LoggerCommons.java index df102a12..b2ca055f 100644 --- a/test/transform/resource/after-ecj/LoggerCommons.java +++ b/test/transform/resource/after-ecj/LoggerCommons.java @@ -22,4 +22,13 @@ import lombok.extern.apachecommons.CommonsLog; LoggerCommonsWithDifferentName() { super(); } +} +@CommonsLog(topic = LoggerCommonsWithStaticField.TOPIC) class LoggerCommonsWithStaticField { + private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LoggerCommonsWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; + () { + } + LoggerCommonsWithStaticField() { + super(); + } } \ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerCustomWithTopicAndName.java b/test/transform/resource/after-ecj/LoggerCustomWithTopicAndName.java index 91cf6d8d..f6f85744 100644 --- a/test/transform/resource/after-ecj/LoggerCustomWithTopicAndName.java +++ b/test/transform/resource/after-ecj/LoggerCustomWithTopicAndName.java @@ -6,6 +6,15 @@ super(); } } +@lombok.CustomLog(topic = LoggerCustomLogWithStaticField.TOPIC) class LoggerCustomLogWithStaticField { + private static final MyLoggerFactory log = MyLoggerFactory.create(LoggerCustomLogWithStaticField.class.getName(), LoggerCustomLogWithStaticField.TOPIC, null, LoggerCustomLogWithStaticField.class, LoggerCustomLogWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; + () { + } + LoggerCustomLogWithStaticField() { + super(); + } +} class MyLoggerFactory { MyLoggerFactory() { super(); diff --git a/test/transform/resource/after-ecj/LoggerJBossLog.java b/test/transform/resource/after-ecj/LoggerJBossLog.java index e5c35708..c47f6c9e 100644 --- a/test/transform/resource/after-ecj/LoggerJBossLog.java +++ b/test/transform/resource/after-ecj/LoggerJBossLog.java @@ -35,4 +35,13 @@ class LoggerJBossLogOuter { LoggerJBossLogWithDifferentLoggerName() { super(); } +} +@JBossLog(topic = LoggerJBossLogWithStaticField.TOPIC) class LoggerJBossLogWithStaticField { + private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LoggerJBossLogWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; + () { + } + LoggerJBossLogWithStaticField() { + super(); + } } \ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerJul.java b/test/transform/resource/after-ecj/LoggerJul.java index 8aa4f59a..20cc5407 100644 --- a/test/transform/resource/after-ecj/LoggerJul.java +++ b/test/transform/resource/after-ecj/LoggerJul.java @@ -22,4 +22,13 @@ import lombok.extern.java.Log; LoggerJulWithDifferentName() { super(); } +} +@Log(topic = LoggerJulWithStaticField.TOPIC) class LoggerJulWithStaticField { + private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggerJulWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; + () { + } + LoggerJulWithStaticField() { + super(); + } } \ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerLog4j.java b/test/transform/resource/after-ecj/LoggerLog4j.java index 948412e2..e7d6c813 100644 --- a/test/transform/resource/after-ecj/LoggerLog4j.java +++ b/test/transform/resource/after-ecj/LoggerLog4j.java @@ -22,4 +22,13 @@ import lombok.extern.log4j.Log4j; LoggerLog4jWithDifferentName() { super(); } +} +@Log4j(topic = LoggerLog4jWithStaticField.TOPIC) class LoggerLog4jWithStaticField { + private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LoggerLog4jWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; + () { + } + LoggerLog4jWithStaticField() { + super(); + } } \ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerLog4j2.java b/test/transform/resource/after-ecj/LoggerLog4j2.java index c2fcd428..88def98d 100644 --- a/test/transform/resource/after-ecj/LoggerLog4j2.java +++ b/test/transform/resource/after-ecj/LoggerLog4j2.java @@ -22,4 +22,13 @@ import lombok.extern.log4j.Log4j2; LoggerLog4j2WithDifferentName() { super(); } +} +@Log4j2(topic = LoggerLog4j2WithStaticField.TOPIC) class LoggerLog4j2WithStaticField { + private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LoggerLog4j2WithStaticField.TOPIC); + static final String TOPIC = "StaticField"; + () { + } + LoggerLog4j2WithStaticField() { + super(); + } } \ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerSlf4j.java b/test/transform/resource/after-ecj/LoggerSlf4j.java index 9c5405cb..c303a895 100644 --- a/test/transform/resource/after-ecj/LoggerSlf4j.java +++ b/test/transform/resource/after-ecj/LoggerSlf4j.java @@ -36,4 +36,31 @@ class LoggerSlf4jOuter { LoggerSlf4jWithDifferentLoggerName() { super(); } +} + +@Slf4j(topic = LoggerSlf4jWithStaticField.TOPIC) class LoggerSlf4jWithStaticField { + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggerSlf4jWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; + () { + } + LoggerSlf4jWithStaticField() { + super(); + } +} +@Slf4j(topic = (LoggerSlf4jWithTwoStaticFields.TOPIC + LoggerSlf4jWithTwoStaticFields.TOPIC)) class LoggerSlf4jWithTwoStaticFields { + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger((LoggerSlf4jWithTwoStaticFields.TOPIC + LoggerSlf4jWithTwoStaticFields.TOPIC)); + static final String TOPIC = "StaticField"; + () { + } + LoggerSlf4jWithTwoStaticFields() { + super(); + } +} +@Slf4j(topic = ExtendedStringLiteral{AB}) class LoggerSlf4jWithTwoLiterals { + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("AB"); + () { + } + LoggerSlf4jWithTwoLiterals() { + super(); + } } \ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerSlf4jInvalidTopic.java b/test/transform/resource/after-ecj/LoggerSlf4jInvalidTopic.java new file mode 100644 index 00000000..33e212e3 --- /dev/null +++ b/test/transform/resource/after-ecj/LoggerSlf4jInvalidTopic.java @@ -0,0 +1,9 @@ +import lombok.extern.slf4j.Slf4j; +@Slf4j(topic = 42) class LoggerSlf4jWithIntegerTopic { + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(42); + () { + } + LoggerSlf4jWithIntegerTopic() { + super(); + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/LoggerXSlf4j.java b/test/transform/resource/after-ecj/LoggerXSlf4j.java index 916859a4..04acdd77 100644 --- a/test/transform/resource/after-ecj/LoggerXSlf4j.java +++ b/test/transform/resource/after-ecj/LoggerXSlf4j.java @@ -22,4 +22,13 @@ import lombok.extern.slf4j.XSlf4j; LoggerXSlf4jWithDifferentName() { super(); } -} \ No newline at end of file +} +@XSlf4j(topic = LoggerXSlf4jWithStaticField.TOPIC) class LoggerXSlf4jWithStaticField { + private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LoggerXSlf4jWithStaticField.TOPIC); + static final String TOPIC = "StaticField"; + () { + } + LoggerXSlf4jWithStaticField() { + super(); + } +} diff --git a/test/transform/resource/before/LoggerCommons.java b/test/transform/resource/before/LoggerCommons.java index 00419d00..e209c1d0 100644 --- a/test/transform/resource/before/LoggerCommons.java +++ b/test/transform/resource/before/LoggerCommons.java @@ -11,3 +11,8 @@ class LoggerCommonsWithImport { @CommonsLog(topic="DifferentName") class LoggerCommonsWithDifferentName { } + +@CommonsLog(topic=LoggerCommonsWithStaticField.TOPIC) +class LoggerCommonsWithStaticField { + static final String TOPIC = "StaticField"; +} \ No newline at end of file diff --git a/test/transform/resource/before/LoggerCustomWithTopicAndName.java b/test/transform/resource/before/LoggerCustomWithTopicAndName.java index b40ed86a..5b803217 100644 --- a/test/transform/resource/before/LoggerCustomWithTopicAndName.java +++ b/test/transform/resource/before/LoggerCustomWithTopicAndName.java @@ -3,6 +3,11 @@ class LoggerCustomLog { } +@lombok.CustomLog(topic=LoggerCustomLogWithStaticField.TOPIC) +class LoggerCustomLogWithStaticField { + static final String TOPIC = "StaticField"; +} + class MyLoggerFactory { static MyLoggerFactory create(String name, String t1, Object o, Class clazz, String t2) { return null; diff --git a/test/transform/resource/before/LoggerJBossLog.java b/test/transform/resource/before/LoggerJBossLog.java index fbd88177..f3480867 100644 --- a/test/transform/resource/before/LoggerJBossLog.java +++ b/test/transform/resource/before/LoggerJBossLog.java @@ -17,4 +17,9 @@ class LoggerJBossLogOuter { @JBossLog(topic="DifferentLogger") class LoggerJBossLogWithDifferentLoggerName { +} + +@JBossLog(topic=LoggerJBossLogWithStaticField.TOPIC) +class LoggerJBossLogWithStaticField { + static final String TOPIC = "StaticField"; } \ No newline at end of file diff --git a/test/transform/resource/before/LoggerJul.java b/test/transform/resource/before/LoggerJul.java index 006cc344..7b10d015 100644 --- a/test/transform/resource/before/LoggerJul.java +++ b/test/transform/resource/before/LoggerJul.java @@ -10,4 +10,9 @@ class LoggerJulWithImport { @Log(topic="DifferentName") class LoggerJulWithDifferentName { +} + +@Log(topic=LoggerJulWithStaticField.TOPIC) +class LoggerJulWithStaticField { + static final String TOPIC = "StaticField"; } \ No newline at end of file diff --git a/test/transform/resource/before/LoggerLog4j.java b/test/transform/resource/before/LoggerLog4j.java index 351049c5..b7086a05 100644 --- a/test/transform/resource/before/LoggerLog4j.java +++ b/test/transform/resource/before/LoggerLog4j.java @@ -10,4 +10,9 @@ class LoggerLog4jWithImport { @Log4j(topic="DifferentName") class LoggerLog4jWithDifferentName { +} + +@Log4j(topic=LoggerLog4jWithStaticField.TOPIC) +class LoggerLog4jWithStaticField { + static final String TOPIC = "StaticField"; } \ No newline at end of file diff --git a/test/transform/resource/before/LoggerLog4j2.java b/test/transform/resource/before/LoggerLog4j2.java index c9cf9412..10b3aae5 100644 --- a/test/transform/resource/before/LoggerLog4j2.java +++ b/test/transform/resource/before/LoggerLog4j2.java @@ -10,4 +10,9 @@ class LoggerLog4j2WithImport { @Log4j2(topic="DifferentName") class LoggerLog4j2WithDifferentName { +} + +@Log4j2(topic=LoggerLog4j2WithStaticField.TOPIC) +class LoggerLog4j2WithStaticField { + static final String TOPIC = "StaticField"; } \ No newline at end of file diff --git a/test/transform/resource/before/LoggerSlf4j.java b/test/transform/resource/before/LoggerSlf4j.java index 1113a63e..3f8284e8 100644 --- a/test/transform/resource/before/LoggerSlf4j.java +++ b/test/transform/resource/before/LoggerSlf4j.java @@ -17,4 +17,18 @@ class LoggerSlf4jOuter { @Slf4j(topic="DifferentLogger") class LoggerSlf4jWithDifferentLoggerName { +} + +@Slf4j(topic=LoggerSlf4jWithStaticField.TOPIC) +class LoggerSlf4jWithStaticField { + static final String TOPIC = "StaticField"; +} + +@Slf4j(topic=LoggerSlf4jWithTwoStaticFields.TOPIC + LoggerSlf4jWithTwoStaticFields.TOPIC) +class LoggerSlf4jWithTwoStaticFields { + static final String TOPIC = "StaticField"; +} + +@Slf4j(topic="A"+"B") +class LoggerSlf4jWithTwoLiterals { } \ No newline at end of file diff --git a/test/transform/resource/before/LoggerSlf4jInvalidTopic.java b/test/transform/resource/before/LoggerSlf4jInvalidTopic.java new file mode 100644 index 00000000..eed02f01 --- /dev/null +++ b/test/transform/resource/before/LoggerSlf4jInvalidTopic.java @@ -0,0 +1,5 @@ +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic=42) +class LoggerSlf4jWithIntegerTopic { +} \ No newline at end of file diff --git a/test/transform/resource/before/LoggerXSlf4j.java b/test/transform/resource/before/LoggerXSlf4j.java index a8bcb0c3..f70f2e2d 100644 --- a/test/transform/resource/before/LoggerXSlf4j.java +++ b/test/transform/resource/before/LoggerXSlf4j.java @@ -10,4 +10,9 @@ class LoggerXSlf4jWithImport { @XSlf4j(topic="DifferentName") class LoggerXSlf4jWithDifferentName { +} + +@XSlf4j(topic=LoggerXSlf4jWithStaticField.TOPIC) +class LoggerXSlf4jWithStaticField { + static final String TOPIC = "StaticField"; } \ No newline at end of file diff --git a/test/transform/resource/messages-delombok/LoggerSlf4jInvalidTopic.java.messages b/test/transform/resource/messages-delombok/LoggerSlf4jInvalidTopic.java.messages new file mode 100644 index 00000000..8de0a120 --- /dev/null +++ b/test/transform/resource/messages-delombok/LoggerSlf4jInvalidTopic.java.messages @@ -0,0 +1,2 @@ +3 incompatible types: int cannot be converted to java.lang.String +-1 not flagged modified \ No newline at end of file diff --git a/test/transform/resource/messages-ecj/LoggerSlf4jInvalidTopic.java.messages b/test/transform/resource/messages-ecj/LoggerSlf4jInvalidTopic.java.messages new file mode 100644 index 00000000..9bc2a82b --- /dev/null +++ b/test/transform/resource/messages-ecj/LoggerSlf4jInvalidTopic.java.messages @@ -0,0 +1 @@ +3 Type mismatch: cannot convert from int to String \ No newline at end of file diff --git a/test/transform/resource/messages-idempotent/LoggerSlf4jInvalidTopic.java.messages b/test/transform/resource/messages-idempotent/LoggerSlf4jInvalidTopic.java.messages new file mode 100644 index 00000000..d894fad1 --- /dev/null +++ b/test/transform/resource/messages-idempotent/LoggerSlf4jInvalidTopic.java.messages @@ -0,0 +1 @@ +3 incompatible types: int cannot be converted to java.lang.String \ No newline at end of file -- cgit From 84556ebb00af1817d521bc011333a0ed02162cc4 Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Tue, 30 Jun 2020 17:22:38 +0200 Subject: [fixes #2433] Add config key to turn off @SuppressWarnings("all") --- src/core/lombok/ConfigurationKeys.java | 7 ++++++ .../eclipse/handlers/EclipseHandlerUtil.java | 6 ++++- src/core/lombok/eclipse/handlers/HandleGetter.java | 9 +++++--- src/core/lombok/javac/handlers/HandleGetter.java | 7 +++++- .../lombok/javac/handlers/JavacHandlerUtil.java | 20 ++++++++-------- .../after-delombok/SkipSuppressWarnings.java | 24 +++++++++++++++++++ .../resource/after-ecj/SkipSuppressWarnings.java | 27 ++++++++++++++++++++++ .../resource/before/SkipSuppressWarnings.java | 9 ++++++++ .../SkipSuppressWarnings.java.messages | 1 + 9 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 test/transform/resource/after-delombok/SkipSuppressWarnings.java create mode 100644 test/transform/resource/after-ecj/SkipSuppressWarnings.java create mode 100644 test/transform/resource/before/SkipSuppressWarnings.java create mode 100644 test/transform/resource/messages-ecj/SkipSuppressWarnings.java.messages (limited to 'test/transform/resource') diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 46cf7412..60b98a94 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -89,6 +89,13 @@ public class ConfigurationKeys { */ public static final ConfigurationKey ADD_FINDBUGS_SUPPRESSWARNINGS_ANNOTATIONS = new ConfigurationKey("lombok.extern.findbugs.addSuppressFBWarnings", "Generate @edu.umd.cs.findbugs.annotations.SuppressFBWarnings on all generated code (default: false).") {}; + /** + * lombok configuration: {@code lombok.addSuppressWarnings} = {@code true} | {@code false}. + * + * If {@code true}, lombok generates {@code @java.lang.SuppressWarnings("all")} on all fields, methods, and types that are generated. + */ + public static final ConfigurationKey ADD_SUPPRESSWARNINGS_ANNOTATIONS = new ConfigurationKey("lombok.addSuppressWarnings", "Generate @java.lang.SuppressWarnings(\"all\") on all generated code (default: true).") {}; + /** * lombok configuration: {@code lombok.addNullAnnotations = }one of: [{@code none}, {@code javax}, {@code eclipse}, {@code jetbrains}, {@code netbeans}, {@code androidx}, {@code android.support}, {@code checkerframework}, {@code findbugs}, {@code spring}, {@code JML}, or a custom set of fully qualified annotation types]. * diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index e674409c..de76e32d 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -1962,7 +1962,11 @@ public class EclipseHandlerUtil { private static final char[][] EDU_UMD_CS_FINDBUGS_ANNOTATIONS_SUPPRESSFBWARNINGS = Eclipse.fromQualifiedName("edu.umd.cs.findbugs.annotations.SuppressFBWarnings"); public static Annotation[] addSuppressWarningsAll(EclipseNode node, ASTNode source, Annotation[] originalAnnotationArray) { - Annotation[] anns = addAnnotation(source, originalAnnotationArray, TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, new StringLiteral(ALL, 0, 0, 0)); + Annotation[] anns = originalAnnotationArray; + + if (!Boolean.FALSE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_SUPPRESSWARNINGS_ANNOTATIONS))) { + anns = addAnnotation(source, anns, TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, new StringLiteral(ALL, 0, 0, 0)); + } if (Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_FINDBUGS_SUPPRESSWARNINGS_ANNOTATIONS))) { MemberValuePair mvp = new MemberValuePair(JUSTIFICATION, 0, 0, new StringLiteral(GENERATED_CODE, 0, 0, 0)); diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java index 30b4a699..9cd1e2a1 100644 --- a/src/core/lombok/eclipse/handlers/HandleGetter.java +++ b/src/core/lombok/eclipse/handlers/HandleGetter.java @@ -285,10 +285,13 @@ public class HandleGetter extends EclipseAnnotationHandler { } if (addSuppressWarningsUnchecked) { + List suppressions = new ArrayList(2); + if (!Boolean.FALSE.equals(fieldNode.getAst().readConfiguration(ConfigurationKeys.ADD_SUPPRESSWARNINGS_ANNOTATIONS))) { + suppressions.add(new StringLiteral(ALL, 0, 0, 0)); + } + suppressions.add(new StringLiteral(UNCHECKED, 0, 0, 0)); ArrayInitializer arr = new ArrayInitializer(); - arr.expressions = new Expression[2]; - arr.expressions[0] = new StringLiteral(ALL, 0, 0, 0); - arr.expressions[1] = new StringLiteral(UNCHECKED, 0, 0, 0); + arr.expressions = suppressions.toArray(new Expression[0]); method.annotations = addAnnotation(source, method.annotations, TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, arr); } diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 985873c1..22f43d61 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -265,7 +265,12 @@ public class HandleGetter extends JavacAnnotationHandler { decl.mods.annotations = decl.mods.annotations.appendList(delegates); if (addSuppressWarningsUnchecked) { - addAnnotation(decl.mods, field, source.pos, source, field.getContext(), "java.lang.SuppressWarnings", treeMaker.NewArray(null, List.nil(), List.of(treeMaker.Literal("all"), treeMaker.Literal("unchecked")))); + ListBuffer suppressions = new ListBuffer(); + if (!Boolean.FALSE.equals(field.getAst().readConfiguration(ConfigurationKeys.ADD_SUPPRESSWARNINGS_ANNOTATIONS))) { + suppressions.add(treeMaker.Literal("all")); + } + suppressions.add(treeMaker.Literal("unchecked")); + addAnnotation(decl.mods, field, source.pos, source, field.getContext(), "java.lang.SuppressWarnings", treeMaker.NewArray(null, List.nil(), suppressions.toList())); } copyJavadoc(field, decl, CopyJavadoc.GETTER); diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index e0f6276f..3655e680 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1277,15 +1277,17 @@ public class JavacHandlerUtil { public static void addSuppressWarningsAll(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context) { if (!LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateSuppressWarnings()) return; - boolean addJLSuppress = true; - - for (JCAnnotation ann : mods.annotations) { - JCTree type = ann.getAnnotationType(); - Name n = null; - if (type instanceof JCIdent) n = ((JCIdent) type).name; - else if (type instanceof JCFieldAccess) n = ((JCFieldAccess) type).name; - if (n != null && n.contentEquals("SuppressWarnings")) { - addJLSuppress = false; + boolean addJLSuppress = !Boolean.FALSE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_SUPPRESSWARNINGS_ANNOTATIONS)); + + if (addJLSuppress) { + for (JCAnnotation ann : mods.annotations) { + JCTree type = ann.getAnnotationType(); + Name n = null; + if (type instanceof JCIdent) n = ((JCIdent) type).name; + else if (type instanceof JCFieldAccess) n = ((JCFieldAccess) type).name; + if (n != null && n.contentEquals("SuppressWarnings")) { + addJLSuppress = false; + } } } if (addJLSuppress) addAnnotation(mods, node, pos, source, context, "java.lang.SuppressWarnings", node.getTreeMaker().Literal("all")); diff --git a/test/transform/resource/after-delombok/SkipSuppressWarnings.java b/test/transform/resource/after-delombok/SkipSuppressWarnings.java new file mode 100644 index 00000000..151d4e17 --- /dev/null +++ b/test/transform/resource/after-delombok/SkipSuppressWarnings.java @@ -0,0 +1,24 @@ +class SkipSuppressWarnings { + private String field = ""; + private final java.util.concurrent.atomic.AtomicReference field2 = new java.util.concurrent.atomic.AtomicReference(); + + public String getField() { + return this.field; + } + + @java.lang.SuppressWarnings({"unchecked"}) + public String getField2() { + java.lang.Object value = this.field2.get(); + if (value == null) { + synchronized (this.field2) { + value = this.field2.get(); + if (value == null) { + final String actualValue = ""; + value = actualValue == null ? this.field2 : actualValue; + this.field2.set(value); + } + } + } + return (String) (value == this.field2 ? null : value); + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/SkipSuppressWarnings.java b/test/transform/resource/after-ecj/SkipSuppressWarnings.java new file mode 100644 index 00000000..53032519 --- /dev/null +++ b/test/transform/resource/after-ecj/SkipSuppressWarnings.java @@ -0,0 +1,27 @@ +class SkipSuppressWarnings { + private @lombok.Getter String field = ""; + private final @lombok.Getter(lazy = true) java.util.concurrent.atomic.AtomicReference field2 = new java.util.concurrent.atomic.AtomicReference(); + SkipSuppressWarnings() { + super(); + } + public String getField() { + return this.field; + } + public @java.lang.SuppressWarnings({"unchecked"}) String getField2() { + java.lang.Object value = this.field2.get(); + if ((value == null)) + { + synchronized (this.field2) + { + value = this.field2.get(); + if ((value == null)) + { + final String actualValue = ""; + value = ((actualValue == null) ? this.field2 : actualValue); + this.field2.set(value); + } + } + } + return (String) ((value == this.field2) ? null : value); + } +} \ No newline at end of file diff --git a/test/transform/resource/before/SkipSuppressWarnings.java b/test/transform/resource/before/SkipSuppressWarnings.java new file mode 100644 index 00000000..ed36eeb9 --- /dev/null +++ b/test/transform/resource/before/SkipSuppressWarnings.java @@ -0,0 +1,9 @@ +//CONF: lombok.addSuppressWarnings = false + +class SkipSuppressWarnings { + @lombok.Getter + private String field = ""; + + @lombok.Getter(lazy=true) + private final String field2 = ""; +} \ No newline at end of file diff --git a/test/transform/resource/messages-ecj/SkipSuppressWarnings.java.messages b/test/transform/resource/messages-ecj/SkipSuppressWarnings.java.messages new file mode 100644 index 00000000..5e7d759c --- /dev/null +++ b/test/transform/resource/messages-ecj/SkipSuppressWarnings.java.messages @@ -0,0 +1 @@ +7 Unnecessary @SuppressWarnings("unchecked") \ No newline at end of file -- cgit From 4fdcdd126a4b5ce365b97eb498536d04caee3b53 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Fri, 10 Jul 2020 02:51:00 +0200 Subject: [test] this covers more eclipse versions --- .../CheckerFrameworkSuperBuilder.java | 30 ++++++------ .../resource/after-delombok/ValLambda.java | 6 ++- .../after-ecj/CheckerFrameworkSuperBuilder.java | 32 ++++++------- .../after-ecj/EqualsAndHashCodeAnnotated.java | 53 ++++++++++++++++++++++ test/transform/resource/after-ecj/ValLambda.java | 6 ++- .../before/CheckerFrameworkSuperBuilder.java | 2 +- test/transform/resource/before/ValLambda.java | 6 ++- test/transform/resource/before/ValLub.java | 10 ++-- .../resource/messages-ecj/ValLambda.java.messages | 4 +- 9 files changed, 104 insertions(+), 45 deletions(-) create mode 100644 test/transform/resource/after-ecj/EqualsAndHashCodeAnnotated.java (limited to 'test/transform/resource') diff --git a/test/transform/resource/after-delombok/CheckerFrameworkSuperBuilder.java b/test/transform/resource/after-delombok/CheckerFrameworkSuperBuilder.java index 0f7f8997..e0daad32 100644 --- a/test/transform/resource/after-delombok/CheckerFrameworkSuperBuilder.java +++ b/test/transform/resource/after-delombok/CheckerFrameworkSuperBuilder.java @@ -124,7 +124,7 @@ class CheckerFrameworkSuperBuilder { return new CheckerFrameworkSuperBuilder.Parent.ParentBuilderImpl(); } } - public static class Child extends Parent { + public static class ZChild extends Parent { int a; int b; @java.lang.SuppressWarnings("all") @@ -132,7 +132,7 @@ class CheckerFrameworkSuperBuilder { return 1; } @java.lang.SuppressWarnings("all") - public static abstract class ChildBuilder> extends Parent.ParentBuilder { + public static abstract class ChildBuilder> extends Parent.ParentBuilder { @java.lang.SuppressWarnings("all") private boolean a$set; @java.lang.SuppressWarnings("all") @@ -147,17 +147,17 @@ class CheckerFrameworkSuperBuilder { @org.checkerframework.dataflow.qual.SideEffectFree @java.lang.Override @java.lang.SuppressWarnings("all") - public abstract C build(@org.checkerframework.checker.builder.qual.CalledMethods("b") CheckerFrameworkSuperBuilder.Child this); + public abstract C build(@org.checkerframework.checker.builder.qual.CalledMethods("b") CheckerFrameworkSuperBuilder.ZChild this); @org.checkerframework.checker.builder.qual.ReturnsReceiver @java.lang.SuppressWarnings("all") - public B a(@org.checkerframework.checker.builder.qual.NotCalledMethods("a") CheckerFrameworkSuperBuilder.Child.ChildBuilder this, final int a) { + public B a(@org.checkerframework.checker.builder.qual.NotCalledMethods("a") CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder this, final int a) { this.a$value = a; a$set = true; return self(); } @org.checkerframework.checker.builder.qual.ReturnsReceiver @java.lang.SuppressWarnings("all") - public B b(@org.checkerframework.checker.builder.qual.NotCalledMethods("b") CheckerFrameworkSuperBuilder.Child.ChildBuilder this, final int b) { + public B b(@org.checkerframework.checker.builder.qual.NotCalledMethods("b") CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder this, final int b) { this.b = b; return self(); } @@ -165,41 +165,41 @@ class CheckerFrameworkSuperBuilder { @java.lang.Override @java.lang.SuppressWarnings("all") public java.lang.String toString() { - return "CheckerFrameworkSuperBuilder.Child.ChildBuilder(super=" + super.toString() + ", a$value=" + this.a$value + ", b=" + this.b + ")"; + return "CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder(super=" + super.toString() + ", a$value=" + this.a$value + ", b=" + this.b + ")"; } } @java.lang.SuppressWarnings("all") - private static final class ChildBuilderImpl extends CheckerFrameworkSuperBuilder.Child.ChildBuilder { + private static final class ZChildBuilderImpl extends CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder { @org.checkerframework.common.aliasing.qual.Unique @java.lang.SuppressWarnings("all") - private ChildBuilderImpl() { + private ZChildBuilderImpl() { } @java.lang.Override @org.checkerframework.checker.builder.qual.ReturnsReceiver @org.checkerframework.dataflow.qual.Pure @java.lang.SuppressWarnings("all") - protected CheckerFrameworkSuperBuilder.Child.ChildBuilderImpl self() { + protected CheckerFrameworkSuperBuilder.ZChild.ZChildBuilderImpl self() { return this; } @org.checkerframework.dataflow.qual.SideEffectFree @java.lang.Override @java.lang.SuppressWarnings("all") - public CheckerFrameworkSuperBuilder.Child build(@org.checkerframework.checker.builder.qual.CalledMethods("b") CheckerFrameworkSuperBuilder.Child.ChildBuilderImpl this) { - return new CheckerFrameworkSuperBuilder.Child(this); + public CheckerFrameworkSuperBuilder.ZChild build(@org.checkerframework.checker.builder.qual.CalledMethods("b") CheckerFrameworkSuperBuilder.ZChild.ZChildBuilderImpl this) { + return new CheckerFrameworkSuperBuilder.ZChild(this); } } @org.checkerframework.dataflow.qual.SideEffectFree @java.lang.SuppressWarnings("all") - protected Child(final CheckerFrameworkSuperBuilder.Child.ChildBuilder b) { + protected ZChild(final CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder b) { super(b); if (b.a$set) this.a = b.a$value; - else this.a = CheckerFrameworkSuperBuilder.Child.$default$a(); + else this.a = CheckerFrameworkSuperBuilder.ZChild.$default$a(); this.b = b.b; } @org.checkerframework.dataflow.qual.SideEffectFree @java.lang.SuppressWarnings("all") - public static CheckerFrameworkSuperBuilder.Child.ChildBuilder builder() { - return new CheckerFrameworkSuperBuilder.Child.ChildBuilderImpl(); + public static CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder builder() { + return new CheckerFrameworkSuperBuilder.ZChild.ZChildBuilderImpl(); } } } \ No newline at end of file diff --git a/test/transform/resource/after-delombok/ValLambda.java b/test/transform/resource/after-delombok/ValLambda.java index 24ae3b5f..910e3506 100644 --- a/test/transform/resource/after-delombok/ValLambda.java +++ b/test/transform/resource/after-delombok/ValLambda.java @@ -1,4 +1,6 @@ // version 8: +import java.io.Serializable; + class ValLambda { static { final java.lang.Runnable foo = (System.currentTimeMillis() > 0) ? (Runnable) () -> { @@ -15,8 +17,8 @@ class ValLambda { }; } - public void easyIntersectionLambda() { - final java.lang.Runnable foo = (Runnable & java.io.Serializable) () -> { + public void intersectionLambda() { + final java.io.Serializable foo = (Runnable & Serializable) () -> { }; final java.io.Serializable bar = (java.io.Serializable & Runnable) () -> { }; diff --git a/test/transform/resource/after-ecj/CheckerFrameworkSuperBuilder.java b/test/transform/resource/after-ecj/CheckerFrameworkSuperBuilder.java index 43568236..7c8ff0ed 100644 --- a/test/transform/resource/after-ecj/CheckerFrameworkSuperBuilder.java +++ b/test/transform/resource/after-ecj/CheckerFrameworkSuperBuilder.java @@ -94,38 +94,38 @@ class CheckerFrameworkSuperBuilder { return new CheckerFrameworkSuperBuilder.Parent.ParentBuilderImpl(); } } - public static @lombok.experimental.SuperBuilder class Child extends Parent { - public static abstract @java.lang.SuppressWarnings("all") class ChildBuilder> extends Parent.ParentBuilder { + public static @lombok.experimental.SuperBuilder class ZChild extends Parent { + public static abstract @java.lang.SuppressWarnings("all") class ZChildBuilder> extends Parent.ParentBuilder { private @java.lang.SuppressWarnings("all") int a$value; private @java.lang.SuppressWarnings("all") boolean a$set; private @java.lang.SuppressWarnings("all") int b; - public ChildBuilder() { + public ZChildBuilder() { super(); } protected abstract @java.lang.Override @org.checkerframework.checker.builder.qual.ReturnsReceiver @org.checkerframework.dataflow.qual.Pure @java.lang.SuppressWarnings("all") B self(); - public abstract @java.lang.Override @org.checkerframework.dataflow.qual.SideEffectFree @java.lang.SuppressWarnings("all") C build(final @org.checkerframework.checker.builder.qual.CalledMethods("b") CheckerFrameworkSuperBuilder.Child.ChildBuilder this); - public @org.checkerframework.checker.builder.qual.ReturnsReceiver @java.lang.SuppressWarnings("all") B a(final @org.checkerframework.checker.builder.qual.NotCalledMethods("a") CheckerFrameworkSuperBuilder.Child.ChildBuilder this, final int a) { + public abstract @java.lang.Override @org.checkerframework.dataflow.qual.SideEffectFree @java.lang.SuppressWarnings("all") C build(final @org.checkerframework.checker.builder.qual.CalledMethods("b") CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder this); + public @org.checkerframework.checker.builder.qual.ReturnsReceiver @java.lang.SuppressWarnings("all") B a(final @org.checkerframework.checker.builder.qual.NotCalledMethods("a") CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder this, final int a) { this.a$value = a; a$set = true; return self(); } - public @org.checkerframework.checker.builder.qual.ReturnsReceiver @java.lang.SuppressWarnings("all") B b(final @org.checkerframework.checker.builder.qual.NotCalledMethods("b") CheckerFrameworkSuperBuilder.Child.ChildBuilder this, final int b) { + public @org.checkerframework.checker.builder.qual.ReturnsReceiver @java.lang.SuppressWarnings("all") B b(final @org.checkerframework.checker.builder.qual.NotCalledMethods("b") CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder this, final int b) { this.b = b; return self(); } public @java.lang.Override @org.checkerframework.dataflow.qual.SideEffectFree @java.lang.SuppressWarnings("all") java.lang.String toString() { - return (((((("CheckerFrameworkSuperBuilder.Child.ChildBuilder(super=" + super.toString()) + ", a$value=") + this.a$value) + ", b=") + this.b) + ")"); + return (((((("CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder(super=" + super.toString()) + ", a$value=") + this.a$value) + ", b=") + this.b) + ")"); } } - private static final @java.lang.SuppressWarnings("all") class ChildBuilderImpl extends CheckerFrameworkSuperBuilder.Child.ChildBuilder { - private ChildBuilderImpl() { + private static final @java.lang.SuppressWarnings("all") class ZChildBuilderImpl extends CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder { + private ZChildBuilderImpl() { super(); } - protected @java.lang.Override @org.checkerframework.checker.builder.qual.ReturnsReceiver @org.checkerframework.dataflow.qual.Pure @java.lang.SuppressWarnings("all") CheckerFrameworkSuperBuilder.Child.ChildBuilderImpl self() { + protected @java.lang.Override @org.checkerframework.checker.builder.qual.ReturnsReceiver @org.checkerframework.dataflow.qual.Pure @java.lang.SuppressWarnings("all") CheckerFrameworkSuperBuilder.ZChild.ZChildBuilderImpl self() { return this; } - public @java.lang.Override @org.checkerframework.dataflow.qual.SideEffectFree @java.lang.SuppressWarnings("all") CheckerFrameworkSuperBuilder.Child build(final @org.checkerframework.checker.builder.qual.CalledMethods("b") CheckerFrameworkSuperBuilder.Child.ChildBuilderImpl this) { - return new CheckerFrameworkSuperBuilder.Child(this); + public @java.lang.Override @org.checkerframework.dataflow.qual.SideEffectFree @java.lang.SuppressWarnings("all") CheckerFrameworkSuperBuilder.ZChild build(final @org.checkerframework.checker.builder.qual.CalledMethods("b") CheckerFrameworkSuperBuilder.ZChild.ZChildBuilderImpl this) { + return new CheckerFrameworkSuperBuilder.ZChild(this); } } @lombok.Builder.Default int a; @@ -133,16 +133,16 @@ class CheckerFrameworkSuperBuilder { private static @java.lang.SuppressWarnings("all") int $default$a() { return 1; } - protected @org.checkerframework.common.aliasing.qual.Unique @java.lang.SuppressWarnings("all") Child(final CheckerFrameworkSuperBuilder.Child.ChildBuilder b) { + protected @org.checkerframework.common.aliasing.qual.Unique @java.lang.SuppressWarnings("all") ZChild(final CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder b) { super(b); if (b.a$set) this.a = b.a$value; else - this.a = CheckerFrameworkSuperBuilder.Child.$default$a(); + this.a = CheckerFrameworkSuperBuilder.ZChild.$default$a(); this.b = b.b; } - public static @org.checkerframework.common.aliasing.qual.Unique @java.lang.SuppressWarnings("all") CheckerFrameworkSuperBuilder.Child.ChildBuilder builder() { - return new CheckerFrameworkSuperBuilder.Child.ChildBuilderImpl(); + public static @org.checkerframework.common.aliasing.qual.Unique @java.lang.SuppressWarnings("all") CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder builder() { + return new CheckerFrameworkSuperBuilder.ZChild.ZChildBuilderImpl(); } } CheckerFrameworkSuperBuilder() { diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeAnnotated.java b/test/transform/resource/after-ecj/EqualsAndHashCodeAnnotated.java new file mode 100644 index 00000000..4e377fb4 --- /dev/null +++ b/test/transform/resource/after-ecj/EqualsAndHashCodeAnnotated.java @@ -0,0 +1,53 @@ +import java.lang.annotation.*; +@lombok.EqualsAndHashCode class EqualsAndHashCodeAnnotated { + @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.SOURCE) @interface Annotated { + } + @Annotated int primitive; + @Annotated Object object; + int @Annotated [] primitiveValues; + int @Annotated [] @Annotated [] morePrimitiveValues; + Integer @Annotated [] objectValues; + Integer @Annotated [] @Annotated [] moreObjectValues; + EqualsAndHashCodeAnnotated() { + super(); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) { + if ((o == this)) + return true; + if ((! (o instanceof EqualsAndHashCodeAnnotated))) + return false; + final EqualsAndHashCodeAnnotated other = (EqualsAndHashCodeAnnotated) o; + if ((! other.canEqual((java.lang.Object) this))) + return false; + if ((this.primitive != other.primitive)) + return false; + final java.lang.Object this$object = this.object; + final java.lang.Object other$object = other.object; + if (((this$object == null) ? (other$object != null) : (! this$object.equals(other$object)))) + return false; + if ((! java.util.Arrays.equals(this.primitiveValues, other.primitiveValues))) + return false; + if ((! java.util.Arrays.deepEquals(this.morePrimitiveValues, other.morePrimitiveValues))) + return false; + if ((! java.util.Arrays.deepEquals(this.objectValues, other.objectValues))) + return false; + if ((! java.util.Arrays.deepEquals(this.moreObjectValues, other.moreObjectValues))) + return false; + return true; + } + protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) { + return (other instanceof EqualsAndHashCodeAnnotated); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() { + final int PRIME = 59; + int result = 1; + result = ((result * PRIME) + this.primitive); + final java.lang.Object $object = this.object; + result = ((result * PRIME) + (($object == null) ? 43 : $object.hashCode())); + result = ((result * PRIME) + java.util.Arrays.hashCode(this.primitiveValues)); + result = ((result * PRIME) + java.util.Arrays.deepHashCode(this.morePrimitiveValues)); + result = ((result * PRIME) + java.util.Arrays.deepHashCode(this.objectValues)); + result = ((result * PRIME) + java.util.Arrays.deepHashCode(this.moreObjectValues)); + return result; + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/ValLambda.java b/test/transform/resource/after-ecj/ValLambda.java index 5b52869f..6b59bdbd 100644 --- a/test/transform/resource/after-ecj/ValLambda.java +++ b/test/transform/resource/after-ecj/ValLambda.java @@ -1,3 +1,5 @@ +import java.io.Serializable; + class ValLambda { static { final @lombok.val java.lang.Runnable foo = ((System.currentTimeMillis() > 0) ? (Runnable) () -> { @@ -16,8 +18,8 @@ class ValLambda { final @lombok.val java.lang.Runnable foo = (Runnable) () -> { }; } - public void easyIntersectionLambda() { - final @lombok.val java.lang.Runnable foo = (Runnable & java.io.Serializable) () -> { + public void intersectionLambda() { + final @lombok.val java.io.Serializable foo = (Runnable & Serializable) () -> { }; final @lombok.val java.io.Serializable bar = (java.io.Serializable & Runnable) () -> { }; diff --git a/test/transform/resource/before/CheckerFrameworkSuperBuilder.java b/test/transform/resource/before/CheckerFrameworkSuperBuilder.java index 54aefb37..ed9e14cb 100644 --- a/test/transform/resource/before/CheckerFrameworkSuperBuilder.java +++ b/test/transform/resource/before/CheckerFrameworkSuperBuilder.java @@ -12,7 +12,7 @@ class CheckerFrameworkSuperBuilder { } @lombok.experimental.SuperBuilder - public static class Child extends Parent { + public static class ZChild extends Parent { @lombok.Builder.Default int a = 1; int b; } diff --git a/test/transform/resource/before/ValLambda.java b/test/transform/resource/before/ValLambda.java index 5c9c4a43..e956bcd3 100644 --- a/test/transform/resource/before/ValLambda.java +++ b/test/transform/resource/before/ValLambda.java @@ -1,4 +1,6 @@ // version 8: +import java.io.Serializable; + class ValLambda { static { @@ -12,8 +14,8 @@ class ValLambda { lombok.val foo = (Runnable)()-> {}; } - public void easyIntersectionLambda() { - lombok.val foo = (Runnable & java.io.Serializable)()-> {}; + public void intersectionLambda() { + lombok.val foo = (Runnable & Serializable)()-> {}; lombok.val bar = (java.io.Serializable & Runnable)()-> {}; } diff --git a/test/transform/resource/before/ValLub.java b/test/transform/resource/before/ValLub.java index c1b41c26..509a4f8b 100644 --- a/test/transform/resource/before/ValLub.java +++ b/test/transform/resource/before/ValLub.java @@ -1,21 +1,21 @@ class ValLub { public void easyLub() { java.util.Map m = java.util.Collections.emptyMap(); - + lombok.val foo = (System.currentTimeMillis() > 0) ? m : java.util.Collections.emptyMap(); } - + public void sillyLubWithUnboxingThatProducesErrorThatVarIsPrimitive() { Integer i = 20; Double d = 20.0; - + lombok.val thisShouldBePrimitiveDouble = (System.currentTimeMillis() > 0) ? i : d; } - + public void hardLub() { java.util.List list = new java.util.ArrayList(); java.util.Set set = new java.util.HashSet(); - + lombok.val thisShouldBeCollection = (System.currentTimeMillis() > 0) ? list : set; thisShouldBeCollection.add(""); String foo = thisShouldBeCollection.iterator().next(); diff --git a/test/transform/resource/messages-ecj/ValLambda.java.messages b/test/transform/resource/messages-ecj/ValLambda.java.messages index e6940434..fa7231ef 100644 --- a/test/transform/resource/messages-ecj/ValLambda.java.messages +++ b/test/transform/resource/messages-ecj/ValLambda.java.messages @@ -1,2 +1,2 @@ -23 Function is a raw type. References to generic type Function should be parameterized -24 Function is a raw type. References to generic type Function should be parameterized \ No newline at end of file +24 Function is a raw type. References to generic type Function should be parameterized +25 Function is a raw type. References to generic type Function should be parameterized \ No newline at end of file -- cgit From b1f6372b358119309b26016317a6dd709b9daa13 Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Sun, 12 Jul 2020 20:08:21 +0200 Subject: [fixes #2300] Keep method argument positions for lazy getter initializer --- src/core/lombok/javac/handlers/HandleGetter.java | 13 +++ .../after-delombok/GetterLazyArguments.java | 101 ++++++++++++++++++++ .../resource/after-ecj/GetterLazyArguments.java | 106 +++++++++++++++++++++ .../resource/before/GetterLazyArguments.java | 21 ++++ 4 files changed, 241 insertions(+) create mode 100644 test/transform/resource/after-delombok/GetterLazyArguments.java create mode 100644 test/transform/resource/after-ecj/GetterLazyArguments.java create mode 100644 test/transform/resource/before/GetterLazyArguments.java (limited to 'test/transform/resource') diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 22f43d61..110941d6 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -232,9 +232,17 @@ public class HandleGetter extends JavacAnnotationHandler { List statements; JCTree toClearOfMarkers = null; + int[] methodArgPos = null; boolean addSuppressWarningsUnchecked = false; if (lazy && !inNetbeansEditor(field)) { toClearOfMarkers = fieldNode.init; + if (toClearOfMarkers instanceof JCMethodInvocation) { + List args = ((JCMethodInvocation) toClearOfMarkers).args; + methodArgPos = new int[args.length()]; + for (int i = 0; i < methodArgPos.length; i++) { + methodArgPos[i] = args.get(i).pos; + } + } statements = createLazyGetterBody(treeMaker, field, source); addSuppressWarningsUnchecked = LombokOptionsFactory.getDelombokOptions(field.getContext()).getFormatPreferences().generateSuppressWarnings(); } else { @@ -262,6 +270,11 @@ public class HandleGetter extends JavacAnnotationHandler { methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source, field.getContext()); if (toClearOfMarkers != null) recursiveSetGeneratedBy(toClearOfMarkers, null, null); + if (methodArgPos != null) { + for (int i = 0; i < methodArgPos.length; i++) { + ((JCMethodInvocation) toClearOfMarkers).args.get(i).pos = methodArgPos[i]; + } + } decl.mods.annotations = decl.mods.annotations.appendList(delegates); if (addSuppressWarningsUnchecked) { diff --git a/test/transform/resource/after-delombok/GetterLazyArguments.java b/test/transform/resource/after-delombok/GetterLazyArguments.java new file mode 100644 index 00000000..a8a422c0 --- /dev/null +++ b/test/transform/resource/after-delombok/GetterLazyArguments.java @@ -0,0 +1,101 @@ +class GetterLazyArguments { + static String fun() { + return null; + } + + static String stringInt(String arg1, Integer arg2) { + return null; + } + + static String stringRunnable(String arg1, Runnable arg2) { + return null; + } + + private final java.util.concurrent.atomic.AtomicReference field1 = new java.util.concurrent.atomic.AtomicReference(); + private final java.util.concurrent.atomic.AtomicReference field2 = new java.util.concurrent.atomic.AtomicReference(); + private final java.util.concurrent.atomic.AtomicReference field3 = new java.util.concurrent.atomic.AtomicReference(); + private final java.util.concurrent.atomic.AtomicReference field4 = new java.util.concurrent.atomic.AtomicReference(); + private final java.util.concurrent.atomic.AtomicReference field5 = new java.util.concurrent.atomic.AtomicReference(); + + @java.lang.SuppressWarnings({"all", "unchecked"}) + public String getField1() { + java.lang.Object value = this.field1.get(); + if (value == null) { + synchronized (this.field1) { + value = this.field1.get(); + if (value == null) { + final String actualValue = stringInt(("a"), (1)); + value = actualValue == null ? this.field1 : actualValue; + this.field1.set(value); + } + } + } + return (String) (value == this.field1 ? null : value); + } + + @java.lang.SuppressWarnings({"all", "unchecked"}) + public String getField2() { + java.lang.Object value = this.field2.get(); + if (value == null) { + synchronized (this.field2) { + value = this.field2.get(); + if (value == null) { + final String actualValue = stringInt(true ? "a" : "b", true ? 1 : 0); + value = actualValue == null ? this.field2 : actualValue; + this.field2.set(value); + } + } + } + return (String) (value == this.field2 ? null : value); + } + + @java.lang.SuppressWarnings({"all", "unchecked"}) + public String getField3() { + java.lang.Object value = this.field3.get(); + if (value == null) { + synchronized (this.field3) { + value = this.field3.get(); + if (value == null) { + final String actualValue = stringInt(("a"), true ? 1 : 0); + value = actualValue == null ? this.field3 : actualValue; + this.field3.set(value); + } + } + } + return (String) (value == this.field3 ? null : value); + } + + @java.lang.SuppressWarnings({"all", "unchecked"}) + public String getField4() { + java.lang.Object value = this.field4.get(); + if (value == null) { + synchronized (this.field4) { + value = this.field4.get(); + if (value == null) { + final String actualValue = stringRunnable(fun(), () -> { + }); + value = actualValue == null ? this.field4 : actualValue; + this.field4.set(value); + } + } + } + return (String) (value == this.field4 ? null : value); + } + + @java.lang.SuppressWarnings({"all", "unchecked"}) + public String getField5() { + java.lang.Object value = this.field5.get(); + if (value == null) { + synchronized (this.field5) { + value = this.field5.get(); + if (value == null) { + final String actualValue = stringRunnable(("a"), () -> { + }); + value = actualValue == null ? this.field5 : actualValue; + this.field5.set(value); + } + } + } + return (String) (value == this.field5 ? null : value); + } +} \ No newline at end of file diff --git a/test/transform/resource/after-ecj/GetterLazyArguments.java b/test/transform/resource/after-ecj/GetterLazyArguments.java new file mode 100644 index 00000000..41f1771f --- /dev/null +++ b/test/transform/resource/after-ecj/GetterLazyArguments.java @@ -0,0 +1,106 @@ +class GetterLazyArguments { + private final @lombok.Getter(lazy = true) java.util.concurrent.atomic.AtomicReference field1 = new java.util.concurrent.atomic.AtomicReference(); + private final @lombok.Getter(lazy = true) java.util.concurrent.atomic.AtomicReference field2 = new java.util.concurrent.atomic.AtomicReference(); + private final @lombok.Getter(lazy = true) java.util.concurrent.atomic.AtomicReference field3 = new java.util.concurrent.atomic.AtomicReference(); + private final @lombok.Getter(lazy = true) java.util.concurrent.atomic.AtomicReference field4 = new java.util.concurrent.atomic.AtomicReference(); + private final @lombok.Getter(lazy = true) java.util.concurrent.atomic.AtomicReference field5 = new java.util.concurrent.atomic.AtomicReference(); + GetterLazyArguments() { + super(); + } + static String fun() { + return null; + } + static String stringInt(String arg1, Integer arg2) { + return null; + } + static String stringRunnable(String arg1, Runnable arg2) { + return null; + } + public @java.lang.SuppressWarnings({"all", "unchecked"}) String getField1() { + java.lang.Object value = this.field1.get(); + if ((value == null)) + { + synchronized (this.field1) + { + value = this.field1.get(); + if ((value == null)) + { + final String actualValue = stringInt("a", 1); + value = ((actualValue == null) ? this.field1 : actualValue); + this.field1.set(value); + } + } + } + return (String) ((value == this.field1) ? null : value); + } + public @java.lang.SuppressWarnings({"all", "unchecked"}) String getField2() { + java.lang.Object value = this.field2.get(); + if ((value == null)) + { + synchronized (this.field2) + { + value = this.field2.get(); + if ((value == null)) + { + final String actualValue = stringInt((true ? "a" : "b"), (true ? 1 : 0)); + value = ((actualValue == null) ? this.field2 : actualValue); + this.field2.set(value); + } + } + } + return (String) ((value == this.field2) ? null : value); + } + public @java.lang.SuppressWarnings({"all", "unchecked"}) String getField3() { + java.lang.Object value = this.field3.get(); + if ((value == null)) + { + synchronized (this.field3) + { + value = this.field3.get(); + if ((value == null)) + { + final String actualValue = stringInt("a", (true ? 1 : 0)); + value = ((actualValue == null) ? this.field3 : actualValue); + this.field3.set(value); + } + } + } + return (String) ((value == this.field3) ? null : value); + } + public @java.lang.SuppressWarnings({"all", "unchecked"}) String getField4() { + java.lang.Object value = this.field4.get(); + if ((value == null)) + { + synchronized (this.field4) + { + value = this.field4.get(); + if ((value == null)) + { + final String actualValue = stringRunnable(fun(), () -> { +}); + value = ((actualValue == null) ? this.field4 : actualValue); + this.field4.set(value); + } + } + } + return (String) ((value == this.field4) ? null : value); + } + public @java.lang.SuppressWarnings({"all", "unchecked"}) String getField5() { + java.lang.Object value = this.field5.get(); + if ((value == null)) + { + synchronized (this.field5) + { + value = this.field5.get(); + if ((value == null)) + { + final String actualValue = stringRunnable("a", () -> { +}); + value = ((actualValue == null) ? this.field5 : actualValue); + this.field5.set(value); + } + } + } + return (String) ((value == this.field5) ? null : value); + } +} \ No newline at end of file diff --git a/test/transform/resource/before/GetterLazyArguments.java b/test/transform/resource/before/GetterLazyArguments.java new file mode 100644 index 00000000..47dfae55 --- /dev/null +++ b/test/transform/resource/before/GetterLazyArguments.java @@ -0,0 +1,21 @@ +// version 8: +class GetterLazyArguments { + static String fun() { return null; } + static String stringInt(String arg1, Integer arg2) { return null; } + static String stringRunnable(String arg1, Runnable arg2) { return null; } + + @lombok.Getter(lazy=true) + private final String field1 = stringInt(("a"), (1)); + + @lombok.Getter(lazy=true) + private final String field2 = stringInt(true ? "a" : "b", true ? 1 : 0); + + @lombok.Getter(lazy=true) + private final String field3 = stringInt(("a"), true ? 1 : 0); + + @lombok.Getter(lazy=true) + private final String field4 = stringRunnable(fun(), () -> { }); + + @lombok.Getter(lazy=true) + private final String field5 = stringRunnable(("a"), () -> { }); +} -- cgit From 5175725eee22c842e3e41d2529be46f5621d047a Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Thu, 23 Jul 2020 22:49:30 +0200 Subject: [trivial] [tests] fixing a broken test --- .../resource/after-delombok/CheckerFrameworkSuperBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test/transform/resource') diff --git a/test/transform/resource/after-delombok/CheckerFrameworkSuperBuilder.java b/test/transform/resource/after-delombok/CheckerFrameworkSuperBuilder.java index e0daad32..30408c3b 100644 --- a/test/transform/resource/after-delombok/CheckerFrameworkSuperBuilder.java +++ b/test/transform/resource/after-delombok/CheckerFrameworkSuperBuilder.java @@ -132,7 +132,7 @@ class CheckerFrameworkSuperBuilder { return 1; } @java.lang.SuppressWarnings("all") - public static abstract class ChildBuilder> extends Parent.ParentBuilder { + public static abstract class ZChildBuilder> extends Parent.ParentBuilder { @java.lang.SuppressWarnings("all") private boolean a$set; @java.lang.SuppressWarnings("all") @@ -169,7 +169,7 @@ class CheckerFrameworkSuperBuilder { } } @java.lang.SuppressWarnings("all") - private static final class ZChildBuilderImpl extends CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder { + private static final class ZChildBuilderImpl extends CheckerFrameworkSuperBuilder.ZChild.ZChildBuilder { @org.checkerframework.common.aliasing.qual.Unique @java.lang.SuppressWarnings("all") private ZChildBuilderImpl() { -- cgit From d4bd359d21c223d6f8dc012c409f7262c4f51bb4 Mon Sep 17 00:00:00 2001 From: Rawi01 Date: Wed, 29 Jul 2020 09:42:07 +0200 Subject: [test] [bugfix] Compare full line instead of ignoring the last character --- test/core/src/lombok/AbstractRunTests.java | 2 +- test/transform/resource/after-delombok/GetterSetterJavadoc.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'test/transform/resource') diff --git a/test/core/src/lombok/AbstractRunTests.java b/test/core/src/lombok/AbstractRunTests.java index 8e73e122..448f77ab 100644 --- a/test/core/src/lombok/AbstractRunTests.java +++ b/test/core/src/lombok/AbstractRunTests.java @@ -285,7 +285,7 @@ public abstract class AbstractRunTests { endIdx--; } - return in.substring(0, endIdx); + return in.substring(0, endIdx + 1); } private static String[] removeBlanks(String[] in) { diff --git a/test/transform/resource/after-delombok/GetterSetterJavadoc.java b/test/transform/resource/after-delombok/GetterSetterJavadoc.java index ae662da7..78d120a4 100644 --- a/test/transform/resource/after-delombok/GetterSetterJavadoc.java +++ b/test/transform/resource/after-delombok/GetterSetterJavadoc.java @@ -115,7 +115,7 @@ class GetterSetterJavadoc4 { /** * Some text * - * @param fieldName Hello, World5 + * @param fieldName Hello, World4 * @return {@code this}. */ @java.lang.SuppressWarnings("all") -- cgit From 9148294f78a8e646ee131ca182a9b692bc028fdb Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Sat, 29 Aug 2020 04:14:10 +0200 Subject: [testing] [eclipse] [#2413] Eclipse tests now more expansive We now test generating a level2-DOM from our level1-AST (eclipse has 3 levels of ASTs, more or less), only if that is possible, i.e. only if the full eclipse is available. This requires using a test target named `eclipse-X`, and not one of the `ecjX` ones. This is the change that requires the massive update to the build system. About 6 tests, including a newly added one about @Delegate, now fail. These failures would usually not cause instant failure in eclipse, but can cause errors during save actions and will likely mess with other things in weird ways, such as messing up syntax highlighting. Yes, this commit now makes a bunch of cases fail the unit tests, but that is representative of actual errors in lombok, so I'm checking it in as is (without this commit, the problem is still there, the tests are just incapable of detecting it). --- buildScripts/ivy.xml | 1 + test/core/src/lombok/RunTestsViaEcj.java | 79 +++++++++++++++++++++- .../after-delombok/DelegateWithVarargs2.java | 12 ++++ .../resource/after-ecj/DelegateWithVarargs2.java | 17 +++++ .../resource/before/DelegateWithVarargs2.java | 9 +++ 5 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 test/transform/resource/after-delombok/DelegateWithVarargs2.java create mode 100644 test/transform/resource/after-ecj/DelegateWithVarargs2.java create mode 100644 test/transform/resource/before/DelegateWithVarargs2.java (limited to 'test/transform/resource') diff --git a/buildScripts/ivy.xml b/buildScripts/ivy.xml index 40bbad08..3dfbde7e 100644 --- a/buildScripts/ivy.xml +++ b/buildScripts/ivy.xml @@ -94,6 +94,7 @@ + diff --git a/test/core/src/lombok/RunTestsViaEcj.java b/test/core/src/lombok/RunTestsViaEcj.java index ab28cb0c..739d6316 100644 --- a/test/core/src/lombok/RunTestsViaEcj.java +++ b/test/core/src/lombok/RunTestsViaEcj.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2014 The Project Lombok Authors. + * Copyright (C) 2010-2020 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,25 +23,33 @@ package lombok; import java.io.File; import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; +import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; import lombok.eclipse.Eclipse; import lombok.javac.CapturingDiagnosticListener.CompilerMessage; +import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.CategorizedProblem; +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.Compiler; import org.eclipse.jdt.internal.compiler.ICompilerRequestor; import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; -import org.eclipse.jdt.internal.compiler.batch.CompilationUnit; import org.eclipse.jdt.internal.compiler.batch.FileSystem; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; @@ -103,7 +111,8 @@ public class RunTestsViaEcj extends AbstractRunTests { }; String source = readFile(file); - final CompilationUnit sourceUnit = new CompilationUnit(source.toCharArray(), file.getName(), encoding == null ? "UTF-8" : encoding); + char[] sourceArray = source.toCharArray(); + final org.eclipse.jdt.internal.compiler.batch.CompilationUnit sourceUnit = new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(sourceArray, file.getName(), encoding == null ? "UTF-8" : encoding); Compiler ecjCompiler = new Compiler(createFileSystem(file, minVersion), ecjErrorHandlingPolicy(), ecjCompilerOptions(), bitbucketRequestor, new DefaultProblemFactory(Locale.ENGLISH)) { @Override protected synchronized void addCompilationUnit(ICompilationUnit inUnit, CompilationUnitDeclaration parsedUnit) { @@ -126,11 +135,75 @@ public class RunTestsViaEcj extends AbstractRunTests { if (cud == null) result.append("---- No CompilationUnit provided by ecj ----"); else result.append(cud.toString()); + if (eclipseAvailable()) { + EclipseDomConversion.toDomAst(cud, sourceArray); + } + + return true; + } + + private boolean eclipseAvailable() { + try { + Class.forName("org.eclipse.jdt.core.dom.CompilationUnit"); + } catch (Throwable t) { + return false; + } + return true; } private static final String bootRuntimePath = System.getProperty("delombok.bootclasspath"); + private static class EclipseDomConversion { + static CompilationUnit toDomAst(CompilationUnitDeclaration cud, final char[] source) { + Map options = new HashMap(); + options.put(JavaCore.COMPILER_SOURCE, "11"); + options.put("org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures", "enabled"); + try { + org.eclipse.jdt.internal.core.CompilationUnit ccu = new org.eclipse.jdt.internal.core.CompilationUnit(null, null, null) { + @Override public char[] getContents() { + return source; + } + }; + return AST.convertCompilationUnit(4, cud, options, false, ccu, 0, null); + } catch (SecurityException e) { + try { + debugClasspathConflicts("org/eclipse/jdt/internal/compiler"); + } catch (Exception e2) { + throw Lombok.sneakyThrow(e2); + } + throw e; + } + } + } + + @SuppressWarnings({"all"}) + private static void debugClasspathConflicts(String prefixToLookFor) throws Exception { + String[] paths = System.getProperty("java.class.path").split(":"); + for (String p : paths) { + Path cp = Paths.get(p); + if (Files.isDirectory(cp)) { + if (Files.isDirectory(cp.resolve(prefixToLookFor))) System.out.println("** DIR-BASED: " + cp); + } else if (Files.isRegularFile(cp)) { + JarFile jf = new JarFile(cp.toFile()); + try { + Enumeration jes = jf.entries(); + while (jes.hasMoreElements()) { + JarEntry je = jes.nextElement(); + if (je.getName().startsWith(prefixToLookFor)) { + System.out.println("** JAR-BASED: " + cp); + break; + } + } + } finally { + jf.close(); + } + } else { + System.out.println("** MISSING: " + cp); + } + } + } + private FileSystem createFileSystem(File file, int minVersion) { List classpath = new ArrayList(); for (Iterator i = classpath.iterator(); i.hasNext();) { diff --git a/test/transform/resource/after-delombok/DelegateWithVarargs2.java b/test/transform/resource/after-delombok/DelegateWithVarargs2.java new file mode 100644 index 00000000..a8ff6e3b --- /dev/null +++ b/test/transform/resource/after-delombok/DelegateWithVarargs2.java @@ -0,0 +1,12 @@ +class DelegateWithVarargs2 { + private DelegateWithVarargs2.B bar; + public class B { + public void varargs(Object[]... keys) { + } + } + @java.lang.SuppressWarnings("all") + public void varargs(final java.lang.Object[]... keys) { + this.bar.varargs(keys); + } +} + diff --git a/test/transform/resource/after-ecj/DelegateWithVarargs2.java b/test/transform/resource/after-ecj/DelegateWithVarargs2.java new file mode 100644 index 00000000..ed0cddf5 --- /dev/null +++ b/test/transform/resource/after-ecj/DelegateWithVarargs2.java @@ -0,0 +1,17 @@ +import lombok.experimental.Delegate; +class DelegateWithVarargs2 { + public class B { + public B() { + super(); + } + public void varargs(Object[]... keys) { + } + } + private @Delegate DelegateWithVarargs2.B bar; + DelegateWithVarargs2() { + super(); + } + public @java.lang.SuppressWarnings("all") void varargs(final java.lang.Object[]... keys) { + this.bar.varargs(keys); + } +} diff --git a/test/transform/resource/before/DelegateWithVarargs2.java b/test/transform/resource/before/DelegateWithVarargs2.java new file mode 100644 index 00000000..8a3dbf14 --- /dev/null +++ b/test/transform/resource/before/DelegateWithVarargs2.java @@ -0,0 +1,9 @@ +import lombok.experimental.Delegate; + +class DelegateWithVarargs2 { + @Delegate private DelegateWithVarargs2.B bar; + + public class B { + public void varargs(Object[]... keys) {} + } +} -- cgit