diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index 3b408145..259880fa 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -25,7 +25,6 @@ import static lombok.core.handlers.HandlerUtil.handleFlagUsage; import static lombok.javac.Javac.*; import static lombok.javac.handlers.JavacHandlerUtil.*; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -269,7 +268,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler member : members) { JavacNode memberNode = member.getNode(); - JCExpression fType = unnotate(getFieldType(memberNode, fieldAccess)); + JCExpression fType = removeTypeUseAnnotations(getFieldType(memberNode, fieldAccess)); boolean isMethod = memberNode.getKind() == Kind.METHOD; JCExpression fieldAccessor = isMethod ? createMethodAccessor(maker, memberNode) : createFieldAccessor(maker, memberNode, fieldAccess); @@ -316,8 +315,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler jcAnnotatedTypeClass = null; - private Field jcAnnotatedTypeUnderlyingTypeField = null; - - private JCExpression unnotate(JCExpression type) { - if (!isJcAnnotatedType(type)) return type; - if (jcAnnotatedTypeUnderlyingTypeField == null) return type; - try { - return (JCExpression) jcAnnotatedTypeUnderlyingTypeField.get(type); - } catch (Exception ignore) {} - return type; - } - - private boolean isJcAnnotatedType(JCExpression o) { - if (o == null) return false; - if (!jcAnnotatedTypeInit) { - try { - jcAnnotatedTypeClass = Class.forName("com.sun.tools.javac.tree.JCTree$JCAnnotatedType", false, o.getClass().getClassLoader()); - jcAnnotatedTypeUnderlyingTypeField = jcAnnotatedTypeClass.getDeclaredField("underlyingType"); - } - catch (Exception ignore) {} - jcAnnotatedTypeInit = true; - } - return jcAnnotatedTypeClass == o.getClass(); - } } diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index 8a0bc686..8eccf079 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -206,7 +206,7 @@ public class HandleToString extends JavacAnnotationHandler { memberAccessor = createFieldAccessor(maker, memberNode, fieldAccess); } - JCExpression memberType = getFieldType(memberNode, fieldAccess); + JCExpression memberType = removeTypeUseAnnotations(getFieldType(memberNode, fieldAccess)); // The distinction between primitive and object will be useful if we ever add a 'hideNulls' option. @SuppressWarnings("unused") diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index d093e890..6993a6ba 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -586,29 +586,40 @@ public class JavacHandlerUtil { static class RecordComponentReflect { private static final Field astField; + private static final Field originalAnnos; private static final Method findRecordComponentToRemove; static { Field a = null; + Field o = null; Method m = null; try { Class forName = Class.forName("com.sun.tools.javac.code.Symbol$RecordComponent"); a = Permit.permissiveGetField(forName, "ast"); + o = Permit.permissiveGetField(forName, "originalAnnos"); m = Permit.permissiveGetMethod(ClassSymbol.class, "findRecordComponentToRemove", JCVariableDecl.class); } catch (Throwable e) { // Ignore } astField = a; + originalAnnos = o; findRecordComponentToRemove = m; } static void deleteAnnotation(JCClassDecl record, JCVariableDecl component, JCTree annotation) { - if (astField == null || findRecordComponentToRemove == null) return; + if ((astField == null && originalAnnos == null) || findRecordComponentToRemove == null) return; try { Object toRemove = Permit.invokeSneaky(findRecordComponentToRemove, record.sym, component); - JCVariableDecl variable = (JCVariableDecl) Permit.get(astField, toRemove); - variable.mods.annotations = filterListByPos(variable.mods.annotations, annotation); + if (astField != null) { + // OpenJDK + JCVariableDecl variable = Permit.get(astField, toRemove); + variable.mods.annotations = filterListByPos(variable.mods.annotations, annotation); + } else { + // Zulu JDK 17 + List annotations = Permit.get(originalAnnos, toRemove); + Permit.set(originalAnnos, toRemove, filterListByPos(annotations, annotation)); + } } catch (Throwable e) { // Ignore } @@ -1212,41 +1223,39 @@ public class JavacHandlerUtil { } static class JCAnnotatedTypeReflect { - private static Class TYPE; - private static Constructor CONSTRUCTOR; - private static Field ANNOTATIONS, UNDERLYING_TYPE; + private static final Class TYPE; + private static final Constructor CONSTRUCTOR; + private static final Field ANNOTATIONS, UNDERLYING_TYPE; - private static void initByLoader(ClassLoader classLoader) { - if (TYPE != null) return; - Class c; + static { + Class t = null; + Constructor c = null; + Field a = null; + Field u = null; + try { - c = classLoader.loadClass("com.sun.tools.javac.tree.JCTree$JCAnnotatedType"); + t = Class.forName("com.sun.tools.javac.tree.JCTree$JCAnnotatedType"); + c = Permit.getConstructor(t, List.class, JCExpression.class); + a = Permit.permissiveGetField(t, "annotations"); + u = Permit.permissiveGetField(t, "underlyingType"); } catch (Exception e) { - return; + // Ignore } - init(c); - } - - private static void init(Class in) { - if (TYPE != null) return; - if (!in.getName().equals("com.sun.tools.javac.tree.JCTree$JCAnnotatedType")) return; - try { - CONSTRUCTOR = Permit.getConstructor(in, List.class, JCExpression.class); - ANNOTATIONS = Permit.getField(in, "annotations"); - UNDERLYING_TYPE = Permit.getField(in, "underlyingType"); - TYPE = in; - } catch (Exception ignore) {} + + TYPE = t; + CONSTRUCTOR = c; + ANNOTATIONS = a; + UNDERLYING_TYPE = u; } static boolean is(JCTree obj) { if (obj == null) return false; - init(obj.getClass()); return obj.getClass() == TYPE; } @SuppressWarnings("unchecked") static List getAnnotations(JCTree obj) { - init(obj.getClass()); + if (ANNOTATIONS == null) return List.nil(); try { return (List) ANNOTATIONS.get(obj); } catch (Exception e) { @@ -1255,14 +1264,16 @@ public class JavacHandlerUtil { } static void setAnnotations(JCTree obj, List anns) { - init(obj.getClass()); + if (ANNOTATIONS == null) return; try { ANNOTATIONS.set(obj, anns); - } catch (Exception e) {} + } catch (Exception e) { + // Ignore + } } static JCExpression getUnderlyingType(JCTree obj) { - init(obj.getClass()); + if (UNDERLYING_TYPE == null) return null; try { return (JCExpression) UNDERLYING_TYPE.get(obj); } catch (Exception e) { @@ -1271,7 +1282,7 @@ public class JavacHandlerUtil { } static JCExpression create(List annotations, JCExpression underlyingType) { - initByLoader(underlyingType.getClass().getClassLoader()); + if (CONSTRUCTOR == null) return underlyingType; try { return (JCExpression) CONSTRUCTOR.newInstance(annotations, underlyingType); } catch (Exception e) { diff --git a/src/utils/lombok/permit/Permit.java b/src/utils/lombok/permit/Permit.java index af97a807..477f06c1 100644 --- a/src/utils/lombok/permit/Permit.java +++ b/src/utils/lombok/permit/Permit.java @@ -297,9 +297,9 @@ public class Permit { } } - public static Object get(Field f, Object receiver) throws IllegalAccessException { + public static T get(Field f, Object receiver) throws IllegalAccessException { try { - return f.get(receiver); + return (T) f.get(receiver); } catch (IllegalAccessException e) { handleReflectionDebug(e, null); throw e; diff --git a/test/transform/resource/after-delombok/ToStringArray.java b/test/transform/resource/after-delombok/ToStringArray.java new file mode 100644 index 00000000..ffd614ad --- /dev/null +++ b/test/transform/resource/after-delombok/ToStringArray.java @@ -0,0 +1,13 @@ +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +public class ToStringArray { + int[] primitiveArray; + Object[] objectArray; + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "ToStringArray(primitiveArray=" + java.util.Arrays.toString(this.primitiveArray) + ", objectArray=" + java.util.Arrays.deepToString(this.objectArray) + ")"; + } +} diff --git a/test/transform/resource/after-delombok/ToStringArrayTypeAnnotations.java b/test/transform/resource/after-delombok/ToStringArrayTypeAnnotations.java new file mode 100644 index 00000000..b2104ffd --- /dev/null +++ b/test/transform/resource/after-delombok/ToStringArrayTypeAnnotations.java @@ -0,0 +1,23 @@ +//version 8: +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +public class ToStringArrayTypeAnnotations { + @TA + int[] primitiveArray1; + int @TA [] primitiveArray2; + @TA + Object[] objectArray1; + Object @TA [] objectArray2; + + + @Target({ElementType.TYPE_USE}) + @interface TA { + } + + @java.lang.Override + @java.lang.SuppressWarnings("all") + public java.lang.String toString() { + return "ToStringArrayTypeAnnotations(primitiveArray1=" + java.util.Arrays.toString(this.primitiveArray1) + ", primitiveArray2=" + java.util.Arrays.toString(this.primitiveArray2) + ", objectArray1=" + java.util.Arrays.deepToString(this.objectArray1) + ", objectArray2=" + java.util.Arrays.deepToString(this.objectArray2) + ")"; + } +} diff --git a/test/transform/resource/after-ecj/ToStringArray.java b/test/transform/resource/after-ecj/ToStringArray.java new file mode 100644 index 00000000..e6e69c85 --- /dev/null +++ b/test/transform/resource/after-ecj/ToStringArray.java @@ -0,0 +1,12 @@ +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; +public @lombok.ToString class ToStringArray { + int[] primitiveArray; + Object[] objectArray; + public ToStringArray() { + super(); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (((("ToStringArray(primitiveArray=" + java.util.Arrays.toString(this.primitiveArray)) + ", objectArray=") + java.util.Arrays.deepToString(this.objectArray)) + ")"); + } +} diff --git a/test/transform/resource/after-ecj/ToStringArrayTypeAnnotations.java b/test/transform/resource/after-ecj/ToStringArrayTypeAnnotations.java new file mode 100644 index 00000000..ef3ed4c1 --- /dev/null +++ b/test/transform/resource/after-ecj/ToStringArrayTypeAnnotations.java @@ -0,0 +1,16 @@ +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; +public @lombok.ToString class ToStringArrayTypeAnnotations { + @Target({ElementType.TYPE_USE}) @interface TA { + } + @TA int[] primitiveArray1; + int @TA [] primitiveArray2; + @TA Object[] objectArray1; + Object @TA [] objectArray2; + public ToStringArrayTypeAnnotations() { + super(); + } + public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { + return (((((((("ToStringArrayTypeAnnotations(primitiveArray1=" + java.util.Arrays.toString(this.primitiveArray1)) + ", primitiveArray2=") + java.util.Arrays.toString(this.primitiveArray2)) + ", objectArray1=") + java.util.Arrays.deepToString(this.objectArray1)) + ", objectArray2=") + java.util.Arrays.deepToString(this.objectArray2)) + ")"); + } +} diff --git a/test/transform/resource/before/ToStringArray.java b/test/transform/resource/before/ToStringArray.java new file mode 100644 index 00000000..1d8f930f --- /dev/null +++ b/test/transform/resource/before/ToStringArray.java @@ -0,0 +1,9 @@ +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@lombok.ToString +public class ToStringArray { + int[] primitiveArray; + + Object[] objectArray; +} \ No newline at end of file diff --git a/test/transform/resource/before/ToStringArrayTypeAnnotations.java b/test/transform/resource/before/ToStringArrayTypeAnnotations.java new file mode 100644 index 00000000..1bdf9971 --- /dev/null +++ b/test/transform/resource/before/ToStringArrayTypeAnnotations.java @@ -0,0 +1,16 @@ +//version 8: +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@lombok.ToString +public class ToStringArrayTypeAnnotations { + @TA int[] primitiveArray1; + int @TA [] primitiveArray2; + + @TA Object[] objectArray1; + Object @TA [] objectArray2; + + @Target({ElementType.TYPE_USE}) + @interface TA { + } +} \ No newline at end of file