diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationDescription.java b/byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationDescription.java index 55ff3212d42..8dd5954425d 100644 --- a/byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationDescription.java +++ b/byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationDescription.java @@ -170,7 +170,7 @@ enum RenderingDispatcher { LEGACY_VM, /** - * A rendering dispatcher for Java 14 onward. + * A rendering dispatcher for Java 14 until Java 18. */ JAVA_14_CAPABLE_VM { @Override @@ -179,6 +179,23 @@ public void appendPrefix(StringBuilder toString, String key, int count) { super.appendPrefix(toString, key, count); } } + }, + + /** + * A rendering dispatcher for Java 19 onward. + */ + JAVA_19_CAPABLE_VM { + @Override + public void appendPrefix(StringBuilder toString, String key, int count) { + if (count > 1 || !key.equals("value")) { + super.appendPrefix(toString, key, count); + } + } + + @Override + public void appendType(StringBuilder toString, TypeDescription typeDescription) { + toString.append(typeDescription.getCanonicalName()); + } }; /** @@ -190,7 +207,10 @@ public void appendPrefix(StringBuilder toString, String key, int count) { * Initializes the rendering dispatcher. */ static { - if (ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V5).isAtLeast(ClassFileVersion.JAVA_V14)) { + ClassFileVersion classFileVersion = ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V5); + if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V19)) { + CURRENT = RenderingDispatcher.JAVA_19_CAPABLE_VM; + } else if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V14)) { CURRENT = RenderingDispatcher.JAVA_14_CAPABLE_VM; } else { CURRENT = RenderingDispatcher.LEGACY_VM; @@ -200,13 +220,23 @@ public void appendPrefix(StringBuilder toString, String key, int count) { /** * Appends the key property prefix to a string builder representing an annotation's string representation. * - * @param toString The {@link Object#toString()} representation of the annotation being handled. + * @param toString The string builder that creates the string representation. * @param key The key's name. * @param count The property count. */ public void appendPrefix(StringBuilder toString, String key, int count) { toString.append(key).append('='); } + + /** + * Appends the type name of the annotation being rendered. + * + * @param toString The string builder that creates the string representation. + * @param typeDescription The annotation type being rendered. + */ + public void appendType(StringBuilder toString, TypeDescription typeDescription) { + toString.append(typeDescription.getName()); + } } /** @@ -318,7 +348,7 @@ public Object invoke(Object proxy, Method method, @MaybeNull Object[] argument) protected String toStringRepresentation() { StringBuilder toString = new StringBuilder(); toString.append('@'); - toString.append(annotationType.getName()); + RenderingDispatcher.CURRENT.appendType(toString, TypeDescription.ForLoadedType.of(annotationType)); toString.append('('); boolean firstMember = true; for (Map.Entry> entry : values.entrySet()) { @@ -574,7 +604,9 @@ public boolean equals(@MaybeNull Object other) { @Override public String toString() { TypeDescription annotationType = getAnnotationType(); - StringBuilder toString = new StringBuilder().append('@').append(annotationType.getName()).append('('); + StringBuilder toString = new StringBuilder().append('@'); + RenderingDispatcher.CURRENT.appendType(toString, annotationType); + toString.append('('); boolean firstMember = true; for (MethodDescription.InDefinedShape methodDescription : annotationType.getDeclaredMethods()) { AnnotationValue value = getValue(methodDescription); diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationValue.java b/byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationValue.java index 468cad145a0..9d9b155ea62 100644 --- a/byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationValue.java +++ b/byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationValue.java @@ -201,7 +201,7 @@ public String toSourceString(TypeDescription value) { /** * A rendering dispatcher for Java 14 onward. */ - JAVA_14_CAPABLE_VM('{', '}', ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V5).isLessThan(ClassFileVersion.JAVA_V17)) { + JAVA_14_CAPABLE_VM('{', '}', true) { @Override public String toSourceString(byte value) { return "(byte)0x" + Integer.toHexString(value & 0xFF); @@ -253,7 +253,7 @@ public String toSourceString(TypeDescription value) { /** * A rendering dispatcher for Java 17 onward. */ - JAVA_17_CAPABLE_VM('{', '}', ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V5).isLessThan(ClassFileVersion.JAVA_V17)) { + JAVA_17_CAPABLE_VM('{', '}', false) { @Override public String toSourceString(byte value) { return "(byte)0x" + Integer.toHexString(value & 0xFF); @@ -301,6 +301,63 @@ public String toSourceString(TypeDescription value) { return value.getActualName() + ".class"; } + @Override + public String toTypeErrorString(Class type) { + return type.getName(); + } + }, + + /** + * A rendering dispatcher for Java 19 onward. + */ + JAVA_19_CAPABLE_VM('{', '}', ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V5).isLessThan(ClassFileVersion.JAVA_V17)) { + @Override + public String toSourceString(byte value) { + return "(byte)0x" + Integer.toHexString(value & 0xFF); + } + + @Override + public String toSourceString(char value) { + StringBuilder stringBuilder = new StringBuilder().append('\''); + if (value == '\'') { + stringBuilder.append("\\'"); + } else { + stringBuilder.append(value); + } + return stringBuilder.append('\'').toString(); + } + + @Override + public String toSourceString(long value) { + return value + "L"; + } + + @Override + public String toSourceString(float value) { + return Math.abs(value) <= Float.MAX_VALUE // Float.isFinite(value) + ? value + "f" + : (Float.isInfinite(value) ? (value < 0.0f ? "-1.0f/0.0f" : "1.0f/0.0f") : "0.0f/0.0f"); + } + + @Override + public String toSourceString(double value) { + return Math.abs(value) <= Double.MAX_VALUE // Double.isFinite(value) + ? Double.toString(value) + : (Double.isInfinite(value) ? (value < 0.0d ? "-1.0/0.0" : "1.0/0.0") : "0.0/0.0"); + } + + @Override + public String toSourceString(String value) { + return "\"" + (value.indexOf('"') == -1 + ? value + : value.replace("\"", "\\\"")) + "\""; + } + + @Override + public String toSourceString(TypeDescription value) { + return value.getCanonicalName() + ".class"; + } + @Override public String toTypeErrorString(Class type) { return type.getName(); @@ -317,9 +374,14 @@ public String toTypeErrorString(Class type) { */ public static final RenderingDispatcher CURRENT; + /* + * Resolves the rendering dispatcher to use. + */ static { ClassFileVersion classFileVersion = ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V5); - if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V17)) { + if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V19)) { + CURRENT = RenderingDispatcher.JAVA_19_CAPABLE_VM; + } else if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V17)) { CURRENT = RenderingDispatcher.JAVA_17_CAPABLE_VM; } else if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V14)) { CURRENT = RenderingDispatcher.JAVA_14_CAPABLE_VM; diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/description/annotation/AbstractAnnotationDescriptionTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/description/annotation/AbstractAnnotationDescriptionTest.java index a4edcb54d5a..c6b9bc4915d 100644 --- a/byte-buddy-dep/src/test/java/net/bytebuddy/description/annotation/AbstractAnnotationDescriptionTest.java +++ b/byte-buddy-dep/src/test/java/net/bytebuddy/description/annotation/AbstractAnnotationDescriptionTest.java @@ -223,7 +223,9 @@ public void assertToString() throws Exception { } private void assertToString(String toString, Annotation actual) throws Exception { - String prefix = "@" + actual.annotationType().getName() + "("; + String prefix = "@" + (ClassFileVersion.ofThisVm().isAtLeast(ClassFileVersion.JAVA_V19) + ? actual.annotationType().getCanonicalName() + : actual.annotationType().getName()) + "("; assertThat(toString, startsWith(prefix)); assertThat(toString, endsWith(")")); String actualString = actual.toString();