Skip to content

Commit

Permalink
Fix annotation string rendering on Java 19.
Browse files Browse the repository at this point in the history
  • Loading branch information
raphw committed Apr 7, 2022
1 parent 85a0943 commit 3a96680
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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());
}
};

/**
Expand All @@ -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;
Expand All @@ -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());
}
}

/**
Expand Down Expand Up @@ -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<Method, AnnotationValue.Loaded<?>> entry : values.entrySet()) {
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit 3a96680

Please sign in to comment.