8281462: Annotation toString output for enum not reusable for source input

Reviewed-by: mchung
This commit is contained in:
Joe Darcy 2022-02-11 23:24:08 +00:00
parent 4032fe76dc
commit c3179a8760
8 changed files with 74 additions and 55 deletions

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -145,7 +145,9 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable {
private String toStringImpl() {
StringBuilder result = new StringBuilder(128);
result.append('@');
result.append(type.getName());
// Guard against null canonical name; shouldn't happen
result.append(Objects.toString(type.getCanonicalName(),
"<no canonical name>"));
result.append('(');
boolean firstMember = true;
Set<Map.Entry<String, Object>> entries = memberValues.entrySet();
@ -189,6 +191,10 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable {
return toSourceString((long) value);
else if (type == Byte.class)
return toSourceString((byte) value);
else if (value instanceof Enum<?> v)
// Predicate above covers enum constants, including
// those with specialized class bodies.
return toSourceString(v);
else
return value.toString();
} else {
@ -219,6 +225,10 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable {
stringStream =
Arrays.stream((String[])value).
map(AnnotationInvocationHandler::toSourceString);
else if (type.getComponentType().isEnum())
stringStream =
Arrays.stream((Enum<?>[])value).
map(AnnotationInvocationHandler::toSourceString);
else
stringStream = Arrays.stream((Object[])value).map(Objects::toString);
@ -231,15 +241,9 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable {
* string representation of an annotation.
*/
private static String toSourceString(Class<?> clazz) {
Class<?> finalComponent = clazz;
StringBuilder arrayBrackets = new StringBuilder();
while(finalComponent.isArray()) {
finalComponent = finalComponent.getComponentType();
arrayBrackets.append("[]");
}
return finalComponent.getName() + arrayBrackets.toString() + ".class";
// Guard against null canonical name; shouldn't happen
return Objects.toString(clazz.getCanonicalName(),
"<no canonical name>") + ".class";
}
private static String toSourceString(float f) {
@ -307,6 +311,10 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable {
return String.valueOf(ell) + "L";
}
private static String toSourceString(Enum<?> enumConstant) {
return enumConstant.name();
}
/**
* Return a string suitable for use in the string representation
* of an annotation.

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,7 +31,8 @@
// test/langtools/tools/javac/processing/model/element/AnnotationToStringTest.java
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.lang.reflect.Field;
import javax.lang.model.element.Modifier;
import java.util.*;
/**
@ -160,6 +161,11 @@ public class AnnotationToStringTest {
}
static class ArrayAnnotationHost {
@ExpectedString(
"@EnumValue(NON_SEALED)") // toString and name differ
@EnumValue(Modifier.NON_SEALED)
public int f00;
@ExpectedString(
"@BooleanArray({true, false, true})")
@BooleanArray({true, false, true})
@ -213,8 +219,8 @@ public class AnnotationToStringTest {
public Class<?>[] f9;
@ExpectedString(
"@EnumArray({SOURCE})")
@EnumArray({RetentionPolicy.SOURCE})
"@EnumArray({SEALED, NON_SEALED, PUBLIC})")
@EnumArray({Modifier.SEALED, Modifier.NON_SEALED, Modifier.PUBLIC})
public RetentionPolicy[] f10;
}
}
@ -223,6 +229,11 @@ public class AnnotationToStringTest {
class Obj {}
@Retention(RetentionPolicy.RUNTIME)
@interface EnumValue {
Modifier value();
}
@Retention(RetentionPolicy.RUNTIME)
@interface ExpectedString {
String value();
@ -285,7 +296,7 @@ class Obj {}
@Retention(RetentionPolicy.RUNTIME)
@interface EnumArray {
RetentionPolicy[] value();
Modifier[] value();
}
@Retention(RetentionPolicy.RUNTIME)

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -61,7 +61,7 @@ public class EnumTypeMismatchTest {
} catch (AnnotationTypeMismatchException e) {
if (!e.element().getName().equals("value")) {
throw new IllegalStateException("Unexpected element: " + e.element());
} else if (!e.foundType().equals("@" + AnAnnotation.class.getName() + "(" + AnEnum.VALUE.name() + ")")) {
} else if (!e.foundType().equals("@" + AnAnnotation.class.getCanonicalName() + "(" + AnEnum.VALUE.name() + ")")) {
throw new IllegalStateException("Unexpected type: " + e.foundType());
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -129,21 +129,21 @@ public class TestConstructorParameterAnnotations {
@ExpectedGetParameterAnnotations(
"[[], " +
"[@TestConstructorParameterAnnotations$MarkerAnnotation(1)]]")
"[@TestConstructorParameterAnnotations.MarkerAnnotation(1)]]")
@ExpectedParameterAnnotations({
"null",
"@TestConstructorParameterAnnotations$MarkerAnnotation(1)"})
"@TestConstructorParameterAnnotations.MarkerAnnotation(1)"})
public class NestedClass1 {
public NestedClass1(@MarkerAnnotation(1) int parameter) {}
}
@ExpectedGetParameterAnnotations(
"[[], " +
"[@TestConstructorParameterAnnotations$MarkerAnnotation(2)], " +
"[@TestConstructorParameterAnnotations.MarkerAnnotation(2)], " +
"[]]")
@ExpectedParameterAnnotations({
"null",
"@TestConstructorParameterAnnotations$MarkerAnnotation(2)",
"@TestConstructorParameterAnnotations.MarkerAnnotation(2)",
"null"})
public class NestedClass2 {
public NestedClass2(@MarkerAnnotation(2) int parameter1,
@ -152,11 +152,11 @@ public class TestConstructorParameterAnnotations {
@ExpectedGetParameterAnnotations(
"[[], " +
"[@TestConstructorParameterAnnotations$MarkerAnnotation(3)], " +
"[@TestConstructorParameterAnnotations.MarkerAnnotation(3)], " +
"[]]")
@ExpectedParameterAnnotations({
"null",
"@TestConstructorParameterAnnotations$MarkerAnnotation(3)",
"@TestConstructorParameterAnnotations.MarkerAnnotation(3)",
"null"})
public class NestedClass3 {
public <P> NestedClass3(@MarkerAnnotation(3) P parameter1,
@ -165,11 +165,11 @@ public class TestConstructorParameterAnnotations {
@ExpectedGetParameterAnnotations(
"[[], " +
"[@TestConstructorParameterAnnotations$MarkerAnnotation(4)], " +
"[@TestConstructorParameterAnnotations.MarkerAnnotation(4)], " +
"[]]")
@ExpectedParameterAnnotations({
"null",
"@TestConstructorParameterAnnotations$MarkerAnnotation(4)",
"@TestConstructorParameterAnnotations.MarkerAnnotation(4)",
"null"})
public class NestedClass4 {
public <P, Q> NestedClass4(@MarkerAnnotation(4) P parameter1,
@ -183,18 +183,18 @@ public class TestConstructorParameterAnnotations {
}
@ExpectedGetParameterAnnotations(
"[[@TestConstructorParameterAnnotations$MarkerAnnotation(1)]]")
"[[@TestConstructorParameterAnnotations.MarkerAnnotation(1)]]")
@ExpectedParameterAnnotations({
"@TestConstructorParameterAnnotations$MarkerAnnotation(1)"})
"@TestConstructorParameterAnnotations.MarkerAnnotation(1)"})
public static class StaticNestedClass1 {
public StaticNestedClass1(@MarkerAnnotation(1) int parameter) {}
}
@ExpectedGetParameterAnnotations(
"[[@TestConstructorParameterAnnotations$MarkerAnnotation(2)], " +
"[[@TestConstructorParameterAnnotations.MarkerAnnotation(2)], " +
"[]]")
@ExpectedParameterAnnotations({
"@TestConstructorParameterAnnotations$MarkerAnnotation(2)",
"@TestConstructorParameterAnnotations.MarkerAnnotation(2)",
"null"})
public static class StaticNestedClass2 {
public StaticNestedClass2(@MarkerAnnotation(2) int parameter1,
@ -202,10 +202,10 @@ public class TestConstructorParameterAnnotations {
}
@ExpectedGetParameterAnnotations(
"[[@TestConstructorParameterAnnotations$MarkerAnnotation(3)], " +
"[[@TestConstructorParameterAnnotations.MarkerAnnotation(3)], " +
"[]]")
@ExpectedParameterAnnotations({
"@TestConstructorParameterAnnotations$MarkerAnnotation(3)",
"@TestConstructorParameterAnnotations.MarkerAnnotation(3)",
"null"})
public static class StaticNestedClass3 {
public <P> StaticNestedClass3(@MarkerAnnotation(3) P parameter1,
@ -213,10 +213,10 @@ public class TestConstructorParameterAnnotations {
}
@ExpectedGetParameterAnnotations(
"[[@TestConstructorParameterAnnotations$MarkerAnnotation(4)], " +
"[[@TestConstructorParameterAnnotations.MarkerAnnotation(4)], " +
"[]]")
@ExpectedParameterAnnotations({
"@TestConstructorParameterAnnotations$MarkerAnnotation(4)",
"@TestConstructorParameterAnnotations.MarkerAnnotation(4)",
"null"})
public static class StaticNestedClass4 {
public <P, Q> StaticNestedClass4(@MarkerAnnotation(4) P parameter1,

@ -64,31 +64,31 @@ public class GetAnnotatedNestedSuperclass {
public static void main(String[] args) throws Exception {
AnnotatedType x = Y.class.getAnnotatedSuperclass();
assertEquals(Arrays.toString(x.getAnnotations()), "[@GetAnnotatedNestedSuperclass$A()]");
assertEquals(Arrays.toString(x.getAnnotations()), "[@GetAnnotatedNestedSuperclass.A()]");
AnnotatedParameterizedType xpt = (AnnotatedParameterizedType) x;
{
AnnotatedType arg = xpt.getAnnotatedActualTypeArguments()[0];
assertEquals(
Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass$B()]");
Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass.B()]");
}
{
AnnotatedType arg = xpt.getAnnotatedActualTypeArguments()[1];
assertEquals(
Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass$C()]");
Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass.C()]");
}
{
AnnotatedType arg = xpt.getAnnotatedActualTypeArguments()[2];
assertEquals(
Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass$D()]");
Arrays.toString(arg.getAnnotations()), "[@GetAnnotatedNestedSuperclass.D()]");
AnnotatedType nestedArg =
((AnnotatedParameterizedType) arg).getAnnotatedActualTypeArguments()[0];
assertEquals(
Arrays.toString(nestedArg.getAnnotations()),
"[@GetAnnotatedNestedSuperclass$E()]");
"[@GetAnnotatedNestedSuperclass.E()]");
}
}
private static void assertEquals(Object expected, Object actual) {
private static void assertEquals(Object actual, Object expected) {
if (!Objects.equals(expected, actual)) {
throw new AssertionError("expected: " + expected + "; actual=" + actual);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -128,7 +128,7 @@ public class TestConstructorParameterTypeAnnotations {
@ExpectedGetParameterAnnotations("[[], []]")
@ExpectedParameterTypeAnnotations({
"null",
"@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(1)"})
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(1)"})
public class NestedClass1 {
public NestedClass1(@MarkerTypeAnnotation(1) int parameter) {}
}
@ -136,7 +136,7 @@ public class TestConstructorParameterTypeAnnotations {
@ExpectedGetParameterAnnotations("[[], [], []]")
@ExpectedParameterTypeAnnotations({
"null",
"@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(2)",
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(2)",
"null"})
public class NestedClass2 {
public NestedClass2(@MarkerTypeAnnotation(2) int parameter1,
@ -146,7 +146,7 @@ public class TestConstructorParameterTypeAnnotations {
@ExpectedGetParameterAnnotations("[[], [], []]")
@ExpectedParameterTypeAnnotations({
"null",
"@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(3)",
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(3)",
"null"})
public class NestedClass3 {
public <P> NestedClass3(@MarkerTypeAnnotation(3) P parameter1,
@ -156,7 +156,7 @@ public class TestConstructorParameterTypeAnnotations {
@ExpectedGetParameterAnnotations("[[], [], []]")
@ExpectedParameterTypeAnnotations({
"null",
"@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(4)",
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(4)",
"null"})
public class NestedClass4 {
public <P, Q> NestedClass4(@MarkerTypeAnnotation(4) P parameter1,
@ -171,14 +171,14 @@ public class TestConstructorParameterTypeAnnotations {
@ExpectedGetParameterAnnotations("[[]]")
@ExpectedParameterTypeAnnotations({
"@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(1)"})
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(1)"})
public static class StaticNestedClass1 {
public StaticNestedClass1(@MarkerTypeAnnotation(1) int parameter) {}
}
@ExpectedGetParameterAnnotations("[[], []]")
@ExpectedParameterTypeAnnotations({
"@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(2)",
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(2)",
"null"})
public static class StaticNestedClass2 {
public StaticNestedClass2(@MarkerTypeAnnotation(2) int parameter1,
@ -187,7 +187,7 @@ public class TestConstructorParameterTypeAnnotations {
@ExpectedGetParameterAnnotations("[[], []]")
@ExpectedParameterTypeAnnotations({
"@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(3)",
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(3)",
"null"})
public static class StaticNestedClass3 {
public <P> StaticNestedClass3(@MarkerTypeAnnotation(3) P parameter1,
@ -196,7 +196,7 @@ public class TestConstructorParameterTypeAnnotations {
@ExpectedGetParameterAnnotations("[[], []]")
@ExpectedParameterTypeAnnotations({
"@TestConstructorParameterTypeAnnotations$MarkerTypeAnnotation(4)",
"@TestConstructorParameterTypeAnnotations.MarkerTypeAnnotation(4)",
"null"})
public static class StaticNestedClass4 {
public <P, Q> StaticNestedClass4(@MarkerTypeAnnotation(4) P parameter1,

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -177,7 +177,7 @@ public class TestObjectMethods {
}
}
private static final Pattern annotationRegex = Pattern.compile("@TestObjectMethods\\$AnnotType\\((\\p{Digit})+\\)");
private static final Pattern annotationRegex = Pattern.compile("@TestObjectMethods\\.AnnotType\\((\\p{Digit})+\\)");
static void testGetAnnotations(Class<?> clazz, boolean annotationsExpectedOnMethods) {
System.err.println("Testing getAnnotations on methods of class " + clazz.getName());

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -162,7 +162,7 @@ public class RecordReflectionTest {
RecordComponent rc = recordClass.getRecordComponents()[0];
Annotation[] annos = rc.getAnnotations();
assertEquals(annos.length, 1);
assertEquals(annos[0].toString(), "@RecordReflectionTest$RCA()");
assertEquals(annos[0].toString(), "@RecordReflectionTest.RCA()");
Field f = recordClass.getDeclaredField("i");
assertEquals(f.getAnnotations().length, 1);
@ -181,7 +181,7 @@ public class RecordReflectionTest {
AnnotatedType at = rc.getAnnotatedType();
Annotation[] annos = at.getAnnotations();
assertEquals(annos.length, 1);
assertEquals(annos[0].toString(), "@RecordReflectionTest$TYPE_USE()");
assertEquals(annos[0].toString(), "@RecordReflectionTest.TYPE_USE()");
Field f = recordClass.getDeclaredField("i");
assertEquals(f.getAnnotatedType().getAnnotations().length, 1);