8336754: Remodel TypeAnnotation to "has" instead of "be" an Annotation

Co-authored-by: Alex Buckley <abuckley@openjdk.org>
Reviewed-by: asotona
This commit is contained in:
Chen Liang 2024-08-16 15:48:54 +00:00
parent 07352c6744
commit 961e944fa7
20 changed files with 260 additions and 243 deletions

View File

@ -37,43 +37,60 @@ import java.util.List;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
/** /**
* Models an annotation on a declaration. * Models an {@code annotation} structure (JVMS {@jvms 4.7.16}) or part of a {@code
* type_annotation} structure (JVMS {@jvms 4.7.20}). This model indicates the
* interface of the annotation and a set of element-value pairs.
* <p>
* This model can reconstruct an annotation, given the location of the modeled structure
* in the class file and the definition of the annotation interface.
* <p>
* Two {@code Annotation} objects should be compared using the {@link
* Object#equals(Object) equals} method.
*
* @apiNote
* For Java programs, the location of the modeled structure indicates the source code
* element or type (JLS {@jls 9.7.4}) on which the reconstructed annotation appears,
* and the annotation interface definition determines whether the reconstructed annotation has
* elements with default values (JLS {@jls 9.6.2}), and whether the reconstructed annotation
* is a container annotation for multiple annotations (JLS {@jls 9.7.5}).
* *
* @see AnnotationElement * @see AnnotationElement
* @see AnnotationValue * @see AnnotationValue
* @see TypeAnnotation
* @see RuntimeVisibleAnnotationsAttribute * @see RuntimeVisibleAnnotationsAttribute
* @see RuntimeInvisibleAnnotationsAttribute * @see RuntimeInvisibleAnnotationsAttribute
* @see RuntimeVisibleParameterAnnotationsAttribute * @see RuntimeVisibleParameterAnnotationsAttribute
* @see RuntimeInvisibleParameterAnnotationsAttribute * @see RuntimeInvisibleParameterAnnotationsAttribute
* *
* @sealedGraph
* @since 22 * @since 22
*/ */
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public sealed interface Annotation public sealed interface Annotation
permits TypeAnnotation, AnnotationImpl { permits AnnotationImpl {
/** /**
* {@return the class of the annotation} * {@return the constant pool entry holding the {@linkplain Class#descriptorString
* descriptor string} of the annotation interface}
*/ */
Utf8Entry className(); Utf8Entry className();
/** /**
* {@return the class of the annotation, as a symbolic descriptor} * {@return the annotation interface, as a symbolic descriptor}
*/ */
default ClassDesc classSymbol() { default ClassDesc classSymbol() {
return ClassDesc.ofDescriptor(className().stringValue()); return ClassDesc.ofDescriptor(className().stringValue());
} }
/** /**
* {@return the elements of the annotation} * {@return the element-value pairs of the annotation}
*/ */
List<AnnotationElement> elements(); List<AnnotationElement> elements();
/** /**
* {@return an annotation} * {@return an annotation}
* @param annotationClass the class of the annotation * @param annotationClass the constant pool entry holding the descriptor string
* @param elements the elements of the annotation * of the annotation interface
* @param elements the element-value pairs of the annotation
*/ */
static Annotation of(Utf8Entry annotationClass, static Annotation of(Utf8Entry annotationClass,
List<AnnotationElement> elements) { List<AnnotationElement> elements) {
@ -82,8 +99,9 @@ public sealed interface Annotation
/** /**
* {@return an annotation} * {@return an annotation}
* @param annotationClass the class of the annotation * @param annotationClass the constant pool entry holding the descriptor string
* @param elements the elements of the annotation * of the annotation interface
* @param elements the element-value pairs of the annotation
*/ */
static Annotation of(Utf8Entry annotationClass, static Annotation of(Utf8Entry annotationClass,
AnnotationElement... elements) { AnnotationElement... elements) {
@ -92,8 +110,8 @@ public sealed interface Annotation
/** /**
* {@return an annotation} * {@return an annotation}
* @param annotationClass the class of the annotation * @param annotationClass the descriptor of the annotation interface
* @param elements the elements of the annotation * @param elements the element-value pairs of the annotation
*/ */
static Annotation of(ClassDesc annotationClass, static Annotation of(ClassDesc annotationClass,
List<AnnotationElement> elements) { List<AnnotationElement> elements) {
@ -102,8 +120,8 @@ public sealed interface Annotation
/** /**
* {@return an annotation} * {@return an annotation}
* @param annotationClass the class of the annotation * @param annotationClass the descriptor of the annotation interface
* @param elements the elements of the annotation * @param elements the element-value pairs of the annotation
*/ */
static Annotation of(ClassDesc annotationClass, static Annotation of(ClassDesc annotationClass,
AnnotationElement... elements) { AnnotationElement... elements) {

View File

@ -32,7 +32,13 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
/** /**
* Models a key-value pair of an annotation. * Models an element-value pair in the {@code element_value_pairs}
* table in the {@code annotation} structure defined in JVMS
* {@jvms 4.7.16} or the {@code type_annotation} structure defined
* in JVMS {@jvms 4.7.20}.
* <p>
* Two {@code AnnotationElement} objects should be compared using the
* {@link Object#equals(Object) equals} method.
* *
* @see Annotation * @see Annotation
* @see AnnotationValue * @see AnnotationValue
@ -45,6 +51,12 @@ public sealed interface AnnotationElement
/** /**
* {@return the element name} * {@return the element name}
*
* @apiNote
* In Java source code, by convention, the name of the sole element in a
* single-element annotation interface is {@code value}. (JLS {@jls 9.6.1})
* This is the case for single-element annotations (JLS {@jls 9.7.3}) and
* container annotations for multiple annotations (JLS {@jls 9.6.3}).
*/ */
Utf8Entry name(); Utf8Entry name();
@ -54,7 +66,7 @@ public sealed interface AnnotationElement
AnnotationValue value(); AnnotationValue value();
/** /**
* {@return an annotation key-value pair} * {@return an element-value pair}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
*/ */
@ -64,7 +76,7 @@ public sealed interface AnnotationElement
} }
/** /**
* {@return an annotation key-value pair} * {@return an element-value pair}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
*/ */
@ -74,9 +86,10 @@ public sealed interface AnnotationElement
} }
/** /**
* {@return an annotation key-value pair for a class-valued annotation} * {@return an element-value pair for a class-valued element}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
* @see AnnotationValue#ofClass(ClassDesc) AnnotationValue::ofClass
*/ */
static AnnotationElement ofClass(String name, static AnnotationElement ofClass(String name,
ClassDesc value) { ClassDesc value) {
@ -84,9 +97,10 @@ public sealed interface AnnotationElement
} }
/** /**
* {@return an annotation key-value pair for a string-valued annotation} * {@return an element-value pair for a string-valued element}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
* @see AnnotationValue#ofString(String) AnnotationValue::ofString
*/ */
static AnnotationElement ofString(String name, static AnnotationElement ofString(String name,
String value) { String value) {
@ -94,9 +108,10 @@ public sealed interface AnnotationElement
} }
/** /**
* {@return an annotation key-value pair for a long-valued annotation} * {@return an element-value pair for a long-valued element}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
* @see AnnotationValue#ofLong(long) AnnotationValue::ofLong
*/ */
static AnnotationElement ofLong(String name, static AnnotationElement ofLong(String name,
long value) { long value) {
@ -104,9 +119,10 @@ public sealed interface AnnotationElement
} }
/** /**
* {@return an annotation key-value pair for an int-valued annotation} * {@return an element-value pair for an int-valued element}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
* @see AnnotationValue#ofInt(int) AnnotationValue::ofInt
*/ */
static AnnotationElement ofInt(String name, static AnnotationElement ofInt(String name,
int value) { int value) {
@ -114,9 +130,10 @@ public sealed interface AnnotationElement
} }
/** /**
* {@return an annotation key-value pair for a char-valued annotation} * {@return an element-value pair for a char-valued element}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
* @see AnnotationValue#ofChar(char) AnnotationValue::ofChar
*/ */
static AnnotationElement ofChar(String name, static AnnotationElement ofChar(String name,
char value) { char value) {
@ -124,9 +141,10 @@ public sealed interface AnnotationElement
} }
/** /**
* {@return an annotation key-value pair for a short-valued annotation} * {@return an element-value pair for a short-valued element}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
* @see AnnotationValue#ofShort(short) AnnotationValue::ofShort
*/ */
static AnnotationElement ofShort(String name, static AnnotationElement ofShort(String name,
short value) { short value) {
@ -134,29 +152,32 @@ public sealed interface AnnotationElement
} }
/** /**
* {@return an annotation key-value pair for a byte-valued annotation} * {@return an element-value pair for a byte-valued element}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
* @see AnnotationValue#ofByte(byte) AnnotationValue::ofByte
*/ */
static AnnotationElement ofByte(String name, static AnnotationElement ofByte(String name,
byte value) { byte value) {
return of(name, AnnotationValue.ofByte(value)); return of(name, AnnotationValue.ofByte(value));
} }
/** /**
* {@return an annotation key-value pair for a boolean-valued annotation} * {@return an element-value pair for a boolean-valued element}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
* @see AnnotationValue#ofBoolean(boolean) AnnotationValue::ofBoolean
*/ */
static AnnotationElement ofBoolean(String name, static AnnotationElement ofBoolean(String name,
boolean value) { boolean value) {
return of(name, AnnotationValue.ofBoolean(value)); return of(name, AnnotationValue.ofBoolean(value));
} }
/** /**
* {@return an annotation key-value pair for a double-valued annotation} * {@return an element-value pair for a double-valued element}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
* @see AnnotationValue#ofDouble(double) AnnotationValue::ofDouble
*/ */
static AnnotationElement ofDouble(String name, static AnnotationElement ofDouble(String name,
double value) { double value) {
@ -164,9 +185,10 @@ public sealed interface AnnotationElement
} }
/** /**
* {@return an annotation key-value pair for a float-valued annotation} * {@return an element-value pair for a float-valued element}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
* @see AnnotationValue#ofFloat(float) AnnotationValue::ofFloat
*/ */
static AnnotationElement ofFloat(String name, static AnnotationElement ofFloat(String name,
float value) { float value) {
@ -174,9 +196,10 @@ public sealed interface AnnotationElement
} }
/** /**
* {@return an annotation key-value pair for an annotation-valued annotation} * {@return an element-value pair for an annotation-valued element}
* @param name the name of the key * @param name the name of the key
* @param value the associated value * @param value the associated value
* @see AnnotationValue#ofAnnotation AnnotationValue::ofAnnotation
*/ */
static AnnotationElement ofAnnotation(String name, static AnnotationElement ofAnnotation(String name,
Annotation value) { Annotation value) {
@ -184,9 +207,10 @@ public sealed interface AnnotationElement
} }
/** /**
* {@return an annotation key-value pair for an array-valued annotation} * {@return an element-value pair for an array-valued element}
* @param name the name of the key * @param name the name of the key
* @param values the associated values * @param values the associated values
* @see AnnotationValue#ofArray(AnnotationValue...) AnnotationValue::ofArray
*/ */
static AnnotationElement ofArray(String name, static AnnotationElement ofArray(String name,
AnnotationValue... values) { AnnotationValue... values) {

View File

@ -41,7 +41,11 @@ import java.util.List;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
/** /**
* Models the value of a key-value pair of an annotation. * Models an {@code element_value} structure, or a value of an element-value
* pair of an annotation, as defined in JVMS {@jvms 4.7.16.1}.
* <p>
* Two {@code AnnotationValue} objects should be compared using the {@link
* Object#equals(Object) equals} method.
* *
* @see Annotation * @see Annotation
* @see AnnotationElement * @see AnnotationElement
@ -53,8 +57,8 @@ import jdk.internal.javac.PreviewFeature;
public sealed interface AnnotationValue { public sealed interface AnnotationValue {
/** /**
* Models an annotation-valued element. * Models an annotation value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ANNOTATION}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ANNOTATION}.
* *
* @since 22 * @since 22
*/ */
@ -66,8 +70,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models an array-valued element. * Models an array value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ARRAY}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ARRAY}.
* *
* @since 22 * @since 22
*/ */
@ -79,13 +83,15 @@ public sealed interface AnnotationValue {
* *
* @apiNote * @apiNote
* All array elements derived from Java source code have the same type, * All array elements derived from Java source code have the same type,
* which must not be an array type. ({@jls 9.6.1}) * which must not be an array type. (JLS {@jls 9.6.1}) If such elements are
* annotations, they have the same annotation interface; if such elements
* are enum, they belong to the same enum class.
*/ */
List<AnnotationValue> values(); List<AnnotationValue> values();
} }
/** /**
* Models a constant-valued element. * Models a constant value of an element-value pair.
* *
* @sealedGraph * @sealedGraph
* @since 22 * @since 22
@ -123,8 +129,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models a string-valued element. * Models a string value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_STRING}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_STRING}.
* *
* @since 22 * @since 22
*/ */
@ -151,8 +157,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models a double-valued element. * Models a double value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_DOUBLE}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_DOUBLE}.
* *
* @since 22 * @since 22
*/ */
@ -179,8 +185,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models a float-valued element. * Models a float value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_FLOAT}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_FLOAT}.
* *
* @since 22 * @since 22
*/ */
@ -207,8 +213,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models a long-valued element. * Models a long value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_LONG}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_LONG}.
* *
* @since 22 * @since 22
*/ */
@ -235,8 +241,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models an int-valued element. * Models an int value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_INT}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_INT}.
* *
* @since 22 * @since 22
*/ */
@ -263,8 +269,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models a short-valued element. * Models a short value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_SHORT}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_SHORT}.
* *
* @since 22 * @since 22
*/ */
@ -294,8 +300,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models a char-valued element. * Models a char value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_CHAR}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_CHAR}.
* *
* @since 22 * @since 22
*/ */
@ -325,8 +331,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models a byte-valued element. * Models a byte value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_BYTE}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_BYTE}.
* *
* @since 22 * @since 22
*/ */
@ -356,8 +362,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models a boolean-valued element. * Models a boolean value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_BOOLEAN}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_BOOLEAN}.
* *
* @since 22 * @since 22
*/ */
@ -387,8 +393,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models a class-valued element. * Models a class value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_CLASS}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_CLASS}.
* *
* @since 22 * @since 22
*/ */
@ -405,8 +411,8 @@ public sealed interface AnnotationValue {
} }
/** /**
* Models an enum-valued element. * Models an enum value of an element-value pair.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ENUM}. * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ENUM}.
* *
* @since 22 * @since 22
*/ */
@ -426,12 +432,13 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return the tag character for this type as per JVMS {@jvms 4.7.16.1}} * {@return the tag character for this value as per JVMS {@jvms 4.7.16.1}}
* The tag characters have a one-to-one mapping to the types of annotation element values.
*/ */
char tag(); char tag();
/** /**
* {@return an annotation element for a enum-valued element} * {@return an enum value for an element-value pair}
* @param className the descriptor string of the enum class * @param className the descriptor string of the enum class
* @param constantName the name of the enum constant * @param constantName the name of the enum constant
*/ */
@ -441,7 +448,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a enum-valued element} * {@return an enum value for an element-value pair}
* @param className the descriptor of the enum class * @param className the descriptor of the enum class
* @param constantName the name of the enum constant * @param constantName the name of the enum constant
*/ */
@ -451,7 +458,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a class-valued element} * {@return a class value for an element-value pair}
* @param className the descriptor string of the class * @param className the descriptor string of the class
*/ */
static OfClass ofClass(Utf8Entry className) { static OfClass ofClass(Utf8Entry className) {
@ -459,7 +466,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a class-valued element} * {@return a class value for an element-value pair}
* @param className the descriptor of the class * @param className the descriptor of the class
*/ */
static OfClass ofClass(ClassDesc className) { static OfClass ofClass(ClassDesc className) {
@ -467,7 +474,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a string-valued element} * {@return a string value for an element-value pair}
* @param value the string * @param value the string
*/ */
static OfString ofString(Utf8Entry value) { static OfString ofString(Utf8Entry value) {
@ -475,7 +482,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a string-valued element} * {@return a string value for an element-value pair}
* @param value the string * @param value the string
*/ */
static OfString ofString(String value) { static OfString ofString(String value) {
@ -483,7 +490,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a double-valued element} * {@return a double value for an element-value pair}
* @param value the double value * @param value the double value
*/ */
static OfDouble ofDouble(DoubleEntry value) { static OfDouble ofDouble(DoubleEntry value) {
@ -491,7 +498,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a double-valued element} * {@return a double value for an element-value pair}
* @param value the double value * @param value the double value
*/ */
static OfDouble ofDouble(double value) { static OfDouble ofDouble(double value) {
@ -499,7 +506,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a float-valued element} * {@return a float value for an element-value pair}
* @param value the float value * @param value the float value
*/ */
static OfFloat ofFloat(FloatEntry value) { static OfFloat ofFloat(FloatEntry value) {
@ -507,7 +514,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a float-valued element} * {@return a float value for an element-value pair}
* @param value the float value * @param value the float value
*/ */
static OfFloat ofFloat(float value) { static OfFloat ofFloat(float value) {
@ -515,7 +522,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a long-valued element} * {@return a long value for an element-value pair}
* @param value the long value * @param value the long value
*/ */
static OfLong ofLong(LongEntry value) { static OfLong ofLong(LongEntry value) {
@ -523,7 +530,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a long-valued element} * {@return a long value for an element-value pair}
* @param value the long value * @param value the long value
*/ */
static OfLong ofLong(long value) { static OfLong ofLong(long value) {
@ -531,7 +538,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for an int-valued element} * {@return an int value for an element-value pair}
* @param value the int value * @param value the int value
*/ */
static OfInt ofInt(IntegerEntry value) { static OfInt ofInt(IntegerEntry value) {
@ -539,7 +546,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for an int-valued element} * {@return an int value for an element-value pair}
* @param value the int value * @param value the int value
*/ */
static OfInt ofInt(int value) { static OfInt ofInt(int value) {
@ -547,7 +554,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a short-valued element} * {@return a short value for an element-value pair}
* @param value the short value * @param value the short value
*/ */
static OfShort ofShort(IntegerEntry value) { static OfShort ofShort(IntegerEntry value) {
@ -555,7 +562,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a short-valued element} * {@return a short value for an element-value pair}
* @param value the short value * @param value the short value
*/ */
static OfShort ofShort(short value) { static OfShort ofShort(short value) {
@ -563,7 +570,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a char-valued element} * {@return a char value for an element-value pair}
* @param value the char value * @param value the char value
*/ */
static OfChar ofChar(IntegerEntry value) { static OfChar ofChar(IntegerEntry value) {
@ -571,7 +578,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a char-valued element} * {@return a char value for an element-value pair}
* @param value the char value * @param value the char value
*/ */
static OfChar ofChar(char value) { static OfChar ofChar(char value) {
@ -579,7 +586,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a byte-valued element} * {@return a byte value for an element-value pair}
* @param value the byte value * @param value the byte value
*/ */
static OfByte ofByte(IntegerEntry value) { static OfByte ofByte(IntegerEntry value) {
@ -587,7 +594,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a byte-valued element} * {@return a byte value for an element-value pair}
* @param value the byte value * @param value the byte value
*/ */
static OfByte ofByte(byte value) { static OfByte ofByte(byte value) {
@ -595,7 +602,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a boolean-valued element} * {@return a boolean value for an element-value pair}
* @param value the boolean value * @param value the boolean value
*/ */
static OfBoolean ofBoolean(IntegerEntry value) { static OfBoolean ofBoolean(IntegerEntry value) {
@ -603,7 +610,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for a boolean-valued element} * {@return a boolean value for an element-value pair}
* @param value the boolean value * @param value the boolean value
*/ */
static OfBoolean ofBoolean(boolean value) { static OfBoolean ofBoolean(boolean value) {
@ -612,7 +619,7 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for an annotation-valued element} * {@return an annotation value for an element-value pair}
* @param value the annotation * @param value the annotation
*/ */
static OfAnnotation ofAnnotation(Annotation value) { static OfAnnotation ofAnnotation(Annotation value) {
@ -620,7 +627,12 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for an array-valued element} * {@return an array value for an element-value pair}
*
* @apiNote
* See {@link AnnotationValue.OfArray#values() values()} for conventions
* on array values derived from Java source code.
*
* @param values the array elements * @param values the array elements
*/ */
static OfArray ofArray(List<AnnotationValue> values) { static OfArray ofArray(List<AnnotationValue> values) {
@ -628,7 +640,12 @@ public sealed interface AnnotationValue {
} }
/** /**
* {@return an annotation element for an array-valued element} * {@return an array value for an element-value pair}
*
* @apiNote
* See {@link AnnotationValue.OfArray#values() values()} for conventions
* on array values derived from Java source code.
*
* @param values the array elements * @param values the array elements
*/ */
static OfArray ofArray(AnnotationValue... values) { static OfArray ofArray(AnnotationValue... values) {

View File

@ -25,12 +25,10 @@
package java.lang.classfile; package java.lang.classfile;
import java.lang.constant.ClassDesc;
import java.util.List; import java.util.List;
import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute; import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute; import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import java.lang.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.TargetInfoImpl; import jdk.internal.classfile.impl.TargetInfoImpl;
import jdk.internal.classfile.impl.UnboundAttribute; import jdk.internal.classfile.impl.UnboundAttribute;
@ -56,12 +54,22 @@ import static java.lang.classfile.ClassFile.TAT_METHOD_TYPE_PARAMETER_BOUND;
import static java.lang.classfile.ClassFile.TAT_NEW; import static java.lang.classfile.ClassFile.TAT_NEW;
import static java.lang.classfile.ClassFile.TAT_RESOURCE_VARIABLE; import static java.lang.classfile.ClassFile.TAT_RESOURCE_VARIABLE;
import static java.lang.classfile.ClassFile.TAT_THROWS; import static java.lang.classfile.ClassFile.TAT_THROWS;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
/** /**
* Models an annotation on a type use, as defined in JVMS {@jvms 4.7.19} and {@jvms 4.7.20}. * Models a {@code type_annotation} structure (JVMS {@jvms 4.7.20}). This model
* indicates the annotated type within a declaration or expression and the part
* of the indicated type that is annotated, in addition to what is {@linkplain
* #annotation() available} in an {@code Annotation}.
* <p>
* This model can reconstruct an annotation on a type or a part of a type, given
* the location of the {@code type_annotation} structure in the class file and
* the definition of the annotation interface.
* <p>
* Two {@code TypeAnnotation} objects should be compared using the {@link
* Object#equals(Object) equals} method.
* *
* @see Annotation
* @see RuntimeVisibleTypeAnnotationsAttribute * @see RuntimeVisibleTypeAnnotationsAttribute
* @see RuntimeInvisibleTypeAnnotationsAttribute * @see RuntimeInvisibleTypeAnnotationsAttribute
* *
@ -69,7 +77,6 @@ import jdk.internal.javac.PreviewFeature;
*/ */
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public sealed interface TypeAnnotation public sealed interface TypeAnnotation
extends Annotation
permits UnboundAttribute.UnboundTypeAnnotation { permits UnboundAttribute.UnboundTypeAnnotation {
/** /**
@ -170,7 +177,7 @@ public sealed interface TypeAnnotation
/** /**
* {@return information describing precisely which type in a declaration or expression * {@return information describing precisely which type in a declaration or expression
* is annotated} * is annotated} This models the {@code target_type} and {@code target_info} items.
*/ */
TargetInfo targetInfo(); TargetInfo targetInfo();
@ -180,57 +187,22 @@ public sealed interface TypeAnnotation
List<TypePathComponent> targetPath(); List<TypePathComponent> targetPath();
/** /**
* {@return a type annotation} * {@return the annotation applied to the part indicated by {@link #targetPath()}}
* @param targetInfo which type in a declaration or expression is annotated * This models the interface of the annotation and the set of element-value pairs,
* @param targetPath which part of the type is annotated * the subset of the {@code type_annotation} structure that is identical to the
* @param annotationClassUtf8Entry the annotation class * {@code annotation} structure.
* @param annotationElements the annotation elements
*/ */
static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath, Annotation annotation();
Utf8Entry annotationClassUtf8Entry,
List<AnnotationElement> annotationElements) {
return new UnboundAttribute.UnboundTypeAnnotation(targetInfo, targetPath,
annotationClassUtf8Entry, annotationElements);
}
/** /**
* {@return a type annotation} * {@return a {@code type_annotation} structure}
* @param targetInfo which type in a declaration or expression is annotated * @param targetInfo which type in a declaration or expression is annotated
* @param targetPath which part of the type is annotated * @param targetPath which part of the type is annotated
* @param annotationClass the annotation class * @param annotation the annotation
* @param annotationElements the annotation elements
*/ */
static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath, static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
ClassDesc annotationClass, Annotation annotation) {
AnnotationElement... annotationElements) { return new UnboundAttribute.UnboundTypeAnnotation(targetInfo, targetPath, annotation);
return of(targetInfo, targetPath, annotationClass, List.of(annotationElements));
}
/**
* {@return a type annotation}
* @param targetInfo which type in a declaration or expression is annotated
* @param targetPath which part of the type is annotated
* @param annotationClass the annotation class
* @param annotationElements the annotation elements
*/
static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
ClassDesc annotationClass,
List<AnnotationElement> annotationElements) {
return of(targetInfo, targetPath,
TemporaryConstantPool.INSTANCE.utf8Entry(annotationClass.descriptorString()), annotationElements);
}
/**
* {@return a type annotation}
* @param targetInfo which type in a declaration or expression is annotated
* @param targetPath which part of the type is annotated
* @param annotationClassUtf8Entry the annotation class
* @param annotationElements the annotation elements
*/
static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
Utf8Entry annotationClassUtf8Entry,
AnnotationElement... annotationElements) {
return of(targetInfo, targetPath, annotationClassUtf8Entry, List.of(annotationElements));
} }
/** /**

View File

@ -657,7 +657,7 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
@Override @Override
protected void writeBody(BufWriter buf, RuntimeInvisibleTypeAnnotationsAttribute attr) { protected void writeBody(BufWriter buf, RuntimeInvisibleTypeAnnotationsAttribute attr) {
AnnotationReader.writeAnnotations(buf, attr.annotations()); AnnotationReader.writeTypeAnnotations(buf, attr.annotations());
} }
} }
@ -714,7 +714,7 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
@Override @Override
protected void writeBody(BufWriter buf, RuntimeVisibleTypeAnnotationsAttribute attr) { protected void writeBody(BufWriter buf, RuntimeVisibleTypeAnnotationsAttribute attr) {
AnnotationReader.writeAnnotations(buf, attr.annotations()); AnnotationReader.writeTypeAnnotations(buf, attr.annotations());
} }
} }

View File

@ -241,10 +241,8 @@ public final class AnnotationReader {
}; };
} }
// the annotation info for this annotation // the annotation info for this annotation
Utf8Entry type = classReader.readEntry(p, Utf8Entry.class); var anno = readAnnotation(classReader, p);
p += 2; return TypeAnnotation.of(targetInfo, List.of(typePath), anno);
return TypeAnnotation.of(targetInfo, List.of(typePath), type,
readAnnotationElementValuePairs(classReader, p));
} }
private static List<TypeAnnotation.LocalVarTargetInfo> readLocalVarEntries(ClassReader classReader, int p, LabelContext lc, int targetType) { private static List<TypeAnnotation.LocalVarTargetInfo> readLocalVarEntries(ClassReader classReader, int p, LabelContext lc, int targetType) {
@ -283,13 +281,11 @@ public final class AnnotationReader {
} }
public static void writeAnnotation(BufWriterImpl buf, Annotation annotation) { public static void writeAnnotation(BufWriterImpl buf, Annotation annotation) {
// handles annotations and type annotations
// TODO annotation cleanup later // TODO annotation cleanup later
((Util.Writable) annotation).writeTo(buf); ((Util.Writable) annotation).writeTo(buf);
} }
public static void writeAnnotations(BufWriter buf, List<? extends Annotation> list) { public static void writeAnnotations(BufWriter buf, List<Annotation> list) {
// handles annotations and type annotations
var internalBuf = (BufWriterImpl) buf; var internalBuf = (BufWriterImpl) buf;
internalBuf.writeU2(list.size()); internalBuf.writeU2(list.size());
for (var e : list) { for (var e : list) {
@ -297,6 +293,66 @@ public final class AnnotationReader {
} }
} }
private static int labelToBci(LabelContext lr, Label label, TypeAnnotation ta) {
//helper method to avoid NPE
if (lr == null) throw new IllegalArgumentException("Illegal targetType '%s' in TypeAnnotation outside of Code attribute".formatted(ta.targetInfo().targetType()));
return lr.labelToBci(label);
}
public static void writeTypeAnnotation(BufWriterImpl buf, TypeAnnotation ta) {
LabelContext lr = buf.labelContext();
// target_type
buf.writeU1(ta.targetInfo().targetType().targetTypeValue());
// target_info
switch (ta.targetInfo()) {
case TypeAnnotation.TypeParameterTarget tpt -> buf.writeU1(tpt.typeParameterIndex());
case TypeAnnotation.SupertypeTarget st -> buf.writeU2(st.supertypeIndex());
case TypeAnnotation.TypeParameterBoundTarget tpbt -> {
buf.writeU1(tpbt.typeParameterIndex());
buf.writeU1(tpbt.boundIndex());
}
case TypeAnnotation.EmptyTarget _ -> {
// nothing to write
}
case TypeAnnotation.FormalParameterTarget fpt -> buf.writeU1(fpt.formalParameterIndex());
case TypeAnnotation.ThrowsTarget tt -> buf.writeU2(tt.throwsTargetIndex());
case TypeAnnotation.LocalVarTarget lvt -> {
buf.writeU2(lvt.table().size());
for (var e : lvt.table()) {
int startPc = labelToBci(lr, e.startLabel(), ta);
buf.writeU2(startPc);
buf.writeU2(labelToBci(lr, e.endLabel(), ta) - startPc);
buf.writeU2(e.index());
}
}
case TypeAnnotation.CatchTarget ct -> buf.writeU2(ct.exceptionTableIndex());
case TypeAnnotation.OffsetTarget ot -> buf.writeU2(labelToBci(lr, ot.target(), ta));
case TypeAnnotation.TypeArgumentTarget tat -> {
buf.writeU2(labelToBci(lr, tat.target(), ta));
buf.writeU1(tat.typeArgumentIndex());
}
}
// target_path
buf.writeU1(ta.targetPath().size());
for (TypeAnnotation.TypePathComponent component : ta.targetPath()) {
buf.writeU1(component.typePathKind().tag());
buf.writeU1(component.typeArgumentIndex());
}
// annotation data
writeAnnotation(buf, ta.annotation());
}
public static void writeTypeAnnotations(BufWriter buf, List<TypeAnnotation> list) {
var internalBuf = (BufWriterImpl) buf;
internalBuf.writeU2(list.size());
for (var e : list) {
writeTypeAnnotation(internalBuf, e);
}
}
public static void writeAnnotationValue(BufWriterImpl buf, AnnotationValue value) { public static void writeAnnotationValue(BufWriterImpl buf, AnnotationValue value) {
// TODO annotation cleanup later // TODO annotation cleanup later
((Util.Writable) value).writeTo(buf); ((Util.Writable) value).writeTo(buf);

View File

@ -1038,9 +1038,9 @@ public final class ClassPrinterImpl {
private static Node typeAnnotationsToTree(Style style, String name, List<TypeAnnotation> annos) { private static Node typeAnnotationsToTree(Style style, String name, List<TypeAnnotation> annos) {
return new ListNodeImpl(style, name, annos.stream().map(a -> return new ListNodeImpl(style, name, annos.stream().map(a ->
new MapNodeImpl(FLOW, "anno") new MapNodeImpl(FLOW, "anno")
.with(leaf("annotation class", a.className().stringValue()), .with(leaf("annotation class", a.annotation().className().stringValue()),
leaf("target info", a.targetInfo().targetType().name())) leaf("target info", a.targetInfo().targetType().name()))
.with(elementValuePairsToTree(a.elements())))); .with(elementValuePairsToTree(a.annotation().elements()))));
} }

View File

@ -401,9 +401,7 @@ public record ClassRemapperImpl(Function<ClassDesc, ClassDesc> mapFunction) impl
List<TypeAnnotation> mapTypeAnnotations(List<TypeAnnotation> typeAnnotations) { List<TypeAnnotation> mapTypeAnnotations(List<TypeAnnotation> typeAnnotations) {
return typeAnnotations.stream().map(a -> TypeAnnotation.of(a.targetInfo(), return typeAnnotations.stream().map(a -> TypeAnnotation.of(a.targetInfo(),
a.targetPath(), map(a.classSymbol()), a.targetPath(), mapAnnotation(a.annotation()))).toList();
a.elements().stream().map(el -> AnnotationElement.of(el.name(),
mapAnnotationValue(el.value()))).toList())).toList();
} }
List<Signature.TypeParam> mapTypeParams(List<Signature.TypeParam> typeParams) { List<Signature.TypeParam> mapTypeParams(List<Signature.TypeParam> typeParams) {

View File

@ -29,14 +29,12 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.lang.classfile.Annotation; import java.lang.classfile.Annotation;
import java.lang.classfile.AnnotationElement;
import java.lang.classfile.AnnotationValue; import java.lang.classfile.AnnotationValue;
import java.lang.classfile.Attribute; import java.lang.classfile.Attribute;
import java.lang.classfile.AttributeMapper; import java.lang.classfile.AttributeMapper;
import java.lang.classfile.Attributes; import java.lang.classfile.Attributes;
import java.lang.classfile.BootstrapMethodEntry; import java.lang.classfile.BootstrapMethodEntry;
import java.lang.classfile.constantpool.ClassEntry; import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.Label;
import java.lang.classfile.TypeAnnotation; import java.lang.classfile.TypeAnnotation;
import java.lang.classfile.attribute.AnnotationDefaultAttribute; import java.lang.classfile.attribute.AnnotationDefaultAttribute;
import java.lang.classfile.attribute.BootstrapMethodsAttribute; import java.lang.classfile.attribute.BootstrapMethodsAttribute;
@ -758,75 +756,10 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public record UnboundTypeAnnotation(TargetInfo targetInfo, public record UnboundTypeAnnotation(TargetInfo targetInfo,
List<TypePathComponent> targetPath, List<TypePathComponent> targetPath,
Utf8Entry className, Annotation annotation) implements TypeAnnotation {
List<AnnotationElement> elements) implements TypeAnnotation, Util.Writable {
public UnboundTypeAnnotation(TargetInfo targetInfo, List<TypePathComponent> targetPath, public UnboundTypeAnnotation {
Utf8Entry className, List<AnnotationElement> elements) { targetPath = List.copyOf(targetPath);
this.targetInfo = targetInfo;
this.targetPath = List.copyOf(targetPath);
this.className = className;
this.elements = List.copyOf(elements);
}
private int labelToBci(LabelContext lr, Label label) {
//helper method to avoid NPE
if (lr == null) throw new IllegalArgumentException("Illegal targetType '%s' in TypeAnnotation outside of Code attribute".formatted(targetInfo.targetType()));
return lr.labelToBci(label);
}
@Override
public void writeTo(BufWriterImpl buf) {
LabelContext lr = buf.labelContext();
// target_type
buf.writeU1(targetInfo.targetType().targetTypeValue());
// target_info
switch (targetInfo) {
case TypeParameterTarget tpt -> buf.writeU1(tpt.typeParameterIndex());
case SupertypeTarget st -> buf.writeU2(st.supertypeIndex());
case TypeParameterBoundTarget tpbt -> {
buf.writeU1(tpbt.typeParameterIndex());
buf.writeU1(tpbt.boundIndex());
}
case EmptyTarget et -> {
// nothing to write
}
case FormalParameterTarget fpt -> buf.writeU1(fpt.formalParameterIndex());
case ThrowsTarget tt -> buf.writeU2(tt.throwsTargetIndex());
case LocalVarTarget lvt -> {
buf.writeU2(lvt.table().size());
for (var e : lvt.table()) {
int startPc = labelToBci(lr, e.startLabel());
buf.writeU2(startPc);
buf.writeU2(labelToBci(lr, e.endLabel()) - startPc);
buf.writeU2(e.index());
}
}
case CatchTarget ct -> buf.writeU2(ct.exceptionTableIndex());
case OffsetTarget ot -> buf.writeU2(labelToBci(lr, ot.target()));
case TypeArgumentTarget tat -> {
buf.writeU2(labelToBci(lr, tat.target()));
buf.writeU1(tat.typeArgumentIndex());
}
}
// target_path
buf.writeU1(targetPath().size());
for (TypePathComponent component : targetPath()) {
buf.writeU1(component.typePathKind().tag());
buf.writeU1(component.typeArgumentIndex());
}
// type_index
buf.writeIndex(className);
// element_value_pairs
buf.writeU2(elements.size());
for (AnnotationElement pair : elements()) {
buf.writeIndex(pair.name());
AnnotationReader.writeAnnotationValue(buf, pair.value());
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -393,7 +393,7 @@ public record ParserVerifier(ClassModel classModel) {
private static int typeAnnotationsSize(List<TypeAnnotation> ans) { private static int typeAnnotationsSize(List<TypeAnnotation> ans) {
int l = 2; int l = 2;
for (var an : ans) { for (var an : ans) {
l += 2 + an.targetInfo().size() + 2 * an.targetPath().size() + annotationSize(an); l += 2 + an.targetInfo().size() + 2 * an.targetPath().size() + annotationSize(an.annotation());
} }
return l; return l;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -95,13 +95,13 @@ public class AnnotationWriter extends BasicWriter {
write(annot, true, false, lr); write(annot, true, false, lr);
println(); println();
indent(+1); indent(+1);
write(annot, true); write(annot.annotation(), true);
indent(-1); indent(-1);
} }
public void write(TypeAnnotation annot, boolean showOffsets, public void write(TypeAnnotation annot, boolean showOffsets,
boolean resolveIndices, CodeAttribute lr) { boolean resolveIndices, CodeAttribute lr) {
write(annot, resolveIndices); write(annot.annotation(), resolveIndices);
print(": "); print(": ");
write(annot.targetInfo(), annot.targetPath(), showOffsets, lr); write(annot.targetInfo(), annot.targetPath(), showOffsets, lr);
} }

View File

@ -66,7 +66,7 @@ class ClassPrinterTest {
RuntimeInvisibleTypeAnnotationsAttribute.of( RuntimeInvisibleTypeAnnotationsAttribute.of(
TypeAnnotation.of(TypeAnnotation.TargetInfo.ofField(), TypeAnnotation.of(TypeAnnotation.TargetInfo.ofField(),
List.of(TypeAnnotation.TypePathComponent.WILDCARD), List.of(TypeAnnotation.TypePathComponent.WILDCARD),
ClassDesc.of("Boo"), List.of())))))) Annotation.of(ClassDesc.of("Boo"), List.of())))))))
.with(RuntimeInvisibleAnnotationsAttribute.of(Annotation.of(ClassDesc.of("Phoo"), AnnotationElement.ofFloat("flfl", 2), AnnotationElement.ofFloat("frfl", 3)))) .with(RuntimeInvisibleAnnotationsAttribute.of(Annotation.of(ClassDesc.of("Phoo"), AnnotationElement.ofFloat("flfl", 2), AnnotationElement.ofFloat("frfl", 3))))
.with(PermittedSubclassesAttribute.ofSymbols(ClassDesc.of("Boo"), ClassDesc.of("Phoo"))) .with(PermittedSubclassesAttribute.ofSymbols(ClassDesc.of("Boo"), ClassDesc.of("Phoo")))
.withField("f", ConstantDescs.CD_String, fb -> fb .withField("f", ConstantDescs.CD_String, fb -> fb
@ -101,7 +101,7 @@ class ClassPrinterTest {
tryb.with(RuntimeInvisibleTypeAnnotationsAttribute.of( tryb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(
TypeAnnotation.of(TypeAnnotation.TargetInfo.ofField(), TypeAnnotation.of(TypeAnnotation.TargetInfo.ofField(),
List.of(TypeAnnotation.TypePathComponent.WILDCARD), List.of(TypeAnnotation.TypePathComponent.WILDCARD),
ClassDesc.of("Boo"), List.of()))); Annotation.of(ClassDesc.of("Boo"), List.of()))));
tryb.invokedynamic(DynamicCallSiteDesc.of( tryb.invokedynamic(DynamicCallSiteDesc.of(
MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, ClassDesc.of("Phoo"), "phee", MethodTypeDesc.of(ClassDesc.of("Boo"))), MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, ClassDesc.of("Phoo"), "phee", MethodTypeDesc.of(ClassDesc.of("Boo"))),
"intfMethod", "intfMethod",
@ -116,7 +116,7 @@ class ClassPrinterTest {
.with(RuntimeVisibleTypeAnnotationsAttribute.of( .with(RuntimeVisibleTypeAnnotationsAttribute.of(
TypeAnnotation.of(TypeAnnotation.TargetInfo.ofField(), TypeAnnotation.of(TypeAnnotation.TargetInfo.ofField(),
List.of(TypeAnnotation.TypePathComponent.ARRAY), List.of(TypeAnnotation.TypePathComponent.ARRAY),
ClassDesc.of("Fee"), List.of(AnnotationElement.ofBoolean("yes", false))))) Annotation.of(ClassDesc.of("Fee"), List.of(AnnotationElement.ofBoolean("yes", false))))))
)))); ))));
} }

View File

@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 8336010 8336588 * @bug 8335935 8336588
* @summary Testing ClassFile transformations. * @summary Testing ClassFile transformations.
* @run junit TransformTests * @run junit TransformTests
*/ */

View File

@ -828,7 +828,7 @@ public record ClassRecord(
ann.targetInfo().targetType().targetTypeValue(), ann.targetInfo().targetType().targetTypeValue(),
TargetInfoRecord.ofTargetInfo(ann.targetInfo(), lr, code), TargetInfoRecord.ofTargetInfo(ann.targetInfo(), lr, code),
ann.targetPath().stream().map(tpc -> TypePathRecord.ofTypePathComponent(tpc)).collect(toSet()), ann.targetPath().stream().map(tpc -> TypePathRecord.ofTypePathComponent(tpc)).collect(toSet()),
AnnotationRecord.ofAnnotation(ann)); AnnotationRecord.ofAnnotation(ann.annotation()));
} }
public interface TargetInfoRecord { public interface TargetInfoRecord {

View File

@ -179,8 +179,7 @@ class RebuildingTransformation {
return annotations.stream().map(ta -> TypeAnnotation.of( return annotations.stream().map(ta -> TypeAnnotation.of(
transformTargetInfo(ta.targetInfo(), cob, labels), transformTargetInfo(ta.targetInfo(), cob, labels),
ta.targetPath().stream().map(tpc -> TypeAnnotation.TypePathComponent.of(tpc.typePathKind(), tpc.typeArgumentIndex())).toList(), ta.targetPath().stream().map(tpc -> TypeAnnotation.TypePathComponent.of(tpc.typePathKind(), tpc.typeArgumentIndex())).toList(),
ta.classSymbol(), transformAnnotation(ta.annotation()))).toArray(TypeAnnotation[]::new);
ta.elements().stream().map(ae -> AnnotationElement.of(ae.name().stringValue(), transformAnnotationValue(ae.value()))).toList())).toArray(TypeAnnotation[]::new);
} }
static TypeAnnotation.TargetInfo transformTargetInfo(TypeAnnotation.TargetInfo ti, CodeBuilder cob, HashMap<Label, Label> labels) { static TypeAnnotation.TargetInfo transformTargetInfo(TypeAnnotation.TargetInfo ti, CodeBuilder cob, HashMap<Label, Label> labels) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -603,7 +603,7 @@ public class ClassfileInspector {
} }
public boolean checkMatch(TypeAnnotation anno) { public boolean checkMatch(TypeAnnotation anno) {
boolean matches = checkMatch((Annotation) anno); boolean matches = checkMatch(anno.annotation());
int boundIdx = Integer.MIN_VALUE, paraIdx = Integer.MIN_VALUE, tIdx = Integer.MIN_VALUE, exIdx = Integer.MIN_VALUE; int boundIdx = Integer.MIN_VALUE, paraIdx = Integer.MIN_VALUE, tIdx = Integer.MIN_VALUE, exIdx = Integer.MIN_VALUE;
switch (anno.targetInfo()) { switch (anno.targetInfo()) {
case TypeAnnotation.TypeParameterBoundTarget binfo -> { case TypeAnnotation.TypeParameterBoundTarget binfo -> {
@ -1197,8 +1197,8 @@ public class ClassfileInspector {
switch (attr) { switch (attr) {
case RuntimeVisibleTypeAnnotationsAttribute rvattr -> { case RuntimeVisibleTypeAnnotationsAttribute rvattr -> {
if (expected.matchVisibility(true)) { if (expected.matchVisibility(true)) {
for(Annotation anno : rvattr.annotations()) { for(var anno : rvattr.annotations()) {
expected.matchAnnotation(anno); expected.matchAnnotation(anno.annotation());
} }
} }
} }

View File

@ -215,7 +215,7 @@ public class AnonymousClassTest {
int offset = info instanceof TypeAnnotation.OffsetTarget offsetInfo? cAttr.labelToBci(offsetInfo.target()): -1; int offset = info instanceof TypeAnnotation.OffsetTarget offsetInfo? cAttr.labelToBci(offsetInfo.target()): -1;
String name; String name;
try { try {
name = annotation.classSymbol().descriptorString(); name = annotation.annotation().classSymbol().descriptorString();
} catch (Exception e) { } catch (Exception e) {
throw new AssertionError(e); throw new AssertionError(e);
} }
@ -227,7 +227,7 @@ public class AnonymousClassTest {
return String.format( return String.format(
"@%s(%s) %s, offset=%d, location=%s", "@%s(%s) %s, offset=%d, location=%s",
name, name,
annotationValueDebugString(cm, annotation), annotationValueDebugString(cm, annotation.annotation()),
info.targetType(), info.targetType(),
offset, offset,
location); location);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -97,7 +97,7 @@ public class ReferenceInfoUtil {
List<TAD> result = new ArrayList<>(); List<TAD> result = new ArrayList<>();
for (TypeAnnotation anno: annos) { for (TypeAnnotation anno: annos) {
TAD tad = new TAD(); TAD tad = new TAD();
tad.annotation = anno.className().stringValue(); tad.annotation = anno.annotation().className().stringValue();
tad.type = anno.targetInfo().targetType(); tad.type = anno.targetInfo().targetType();
switch (anno.targetInfo().targetType()) { switch (anno.targetInfo().targetType()) {
case CAST, CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT, METHOD_INVOCATION_TYPE_ARGUMENT -> { case CAST, CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT, METHOD_INVOCATION_TYPE_ARGUMENT -> {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -74,7 +74,7 @@ public class Annotations extends JavacTestingAbstractProcessor {
StringBuilder actual = new StringBuilder(); StringBuilder actual = new StringBuilder();
for (TypeAnnotation ta: annotations.annotations()) { for (TypeAnnotation ta: annotations.annotations()) {
TypeAnnotation.LocalVarTargetInfo info = ((TypeAnnotation.LocalVarTarget) ta.targetInfo()).table().getFirst(); TypeAnnotation.LocalVarTargetInfo info = ((TypeAnnotation.LocalVarTarget) ta.targetInfo()).table().getFirst();
actual.append(ta.className().stringValue() + " pos: [" + ta.targetInfo().targetType()); actual.append(ta.annotation().className().stringValue() + " pos: [" + ta.targetInfo().targetType());
actual.append(", {start_pc=" + codeAttr.labelToBci(info.startLabel()) + ", end_pc=" + codeAttr.labelToBci(info.endLabel())); actual.append(", {start_pc=" + codeAttr.labelToBci(info.startLabel()) + ", end_pc=" + codeAttr.labelToBci(info.endLabel()));
actual.append(", index=" + info.index()+ "}], "); actual.append(", index=" + info.index()+ "}], ");
} }

View File

@ -1615,7 +1615,7 @@ class RecordCompilationTests extends CompilationTestCase {
} }
assert tAnno != null; assert tAnno != null;
Assert.check(tAnno.targetInfo().targetType().name().equals(positionType)); Assert.check(tAnno.targetInfo().targetType().name().equals(positionType));
String annotationName = tAnno.classSymbol().displayName(); String annotationName = tAnno.annotation().classSymbol().displayName();
Assert.check(annotationName.startsWith(annoName)); Assert.check(annotationName.startsWith(annoName));
} }
private void checkAnno(Attribute<?> rAnnos, private void checkAnno(Attribute<?> rAnnos,