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;
/**
* 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 AnnotationValue
* @see TypeAnnotation
* @see RuntimeVisibleAnnotationsAttribute
* @see RuntimeInvisibleAnnotationsAttribute
* @see RuntimeVisibleParameterAnnotationsAttribute
* @see RuntimeInvisibleParameterAnnotationsAttribute
*
* @sealedGraph
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
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();
/**
* {@return the class of the annotation, as a symbolic descriptor}
* {@return the annotation interface, as a symbolic descriptor}
*/
default ClassDesc classSymbol() {
return ClassDesc.ofDescriptor(className().stringValue());
}
/**
* {@return the elements of the annotation}
* {@return the element-value pairs of the annotation}
*/
List<AnnotationElement> elements();
/**
* {@return an annotation}
* @param annotationClass the class of the annotation
* @param elements the elements of the annotation
* @param annotationClass the constant pool entry holding the descriptor string
* of the annotation interface
* @param elements the element-value pairs of the annotation
*/
static Annotation of(Utf8Entry annotationClass,
List<AnnotationElement> elements) {
@ -82,8 +99,9 @@ public sealed interface Annotation
/**
* {@return an annotation}
* @param annotationClass the class of the annotation
* @param elements the elements of the annotation
* @param annotationClass the constant pool entry holding the descriptor string
* of the annotation interface
* @param elements the element-value pairs of the annotation
*/
static Annotation of(Utf8Entry annotationClass,
AnnotationElement... elements) {
@ -92,8 +110,8 @@ public sealed interface Annotation
/**
* {@return an annotation}
* @param annotationClass the class of the annotation
* @param elements the elements of the annotation
* @param annotationClass the descriptor of the annotation interface
* @param elements the element-value pairs of the annotation
*/
static Annotation of(ClassDesc annotationClass,
List<AnnotationElement> elements) {
@ -102,8 +120,8 @@ public sealed interface Annotation
/**
* {@return an annotation}
* @param annotationClass the class of the annotation
* @param elements the elements of the annotation
* @param annotationClass the descriptor of the annotation interface
* @param elements the element-value pairs of the annotation
*/
static Annotation of(ClassDesc annotationClass,
AnnotationElement... elements) {

View File

@ -32,7 +32,13 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
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 AnnotationValue
@ -45,6 +51,12 @@ public sealed interface AnnotationElement
/**
* {@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();
@ -54,7 +66,7 @@ public sealed interface AnnotationElement
AnnotationValue value();
/**
* {@return an annotation key-value pair}
* {@return an element-value pair}
* @param name the name of the key
* @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 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 value the associated value
* @see AnnotationValue#ofClass(ClassDesc) AnnotationValue::ofClass
*/
static AnnotationElement ofClass(String name,
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 value the associated value
* @see AnnotationValue#ofString(String) AnnotationValue::ofString
*/
static AnnotationElement ofString(String name,
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 value the associated value
* @see AnnotationValue#ofLong(long) AnnotationValue::ofLong
*/
static AnnotationElement ofLong(String name,
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 value the associated value
* @see AnnotationValue#ofInt(int) AnnotationValue::ofInt
*/
static AnnotationElement ofInt(String name,
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 value the associated value
* @see AnnotationValue#ofChar(char) AnnotationValue::ofChar
*/
static AnnotationElement ofChar(String name,
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 value the associated value
* @see AnnotationValue#ofShort(short) AnnotationValue::ofShort
*/
static AnnotationElement ofShort(String name,
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 value the associated value
* @see AnnotationValue#ofByte(byte) AnnotationValue::ofByte
*/
static AnnotationElement ofByte(String name,
byte value) {
byte 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 value the associated value
* @see AnnotationValue#ofBoolean(boolean) AnnotationValue::ofBoolean
*/
static AnnotationElement ofBoolean(String name,
boolean value) {
boolean 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 value the associated value
* @see AnnotationValue#ofDouble(double) AnnotationValue::ofDouble
*/
static AnnotationElement ofDouble(String name,
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 value the associated value
* @see AnnotationValue#ofFloat(float) AnnotationValue::ofFloat
*/
static AnnotationElement ofFloat(String name,
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 value the associated value
* @see AnnotationValue#ofAnnotation AnnotationValue::ofAnnotation
*/
static AnnotationElement ofAnnotation(String name,
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 values the associated values
* @see AnnotationValue#ofArray(AnnotationValue...) AnnotationValue::ofArray
*/
static AnnotationElement ofArray(String name,
AnnotationValue... values) {

View File

@ -41,7 +41,11 @@ import java.util.List;
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 AnnotationElement
@ -53,8 +57,8 @@ import jdk.internal.javac.PreviewFeature;
public sealed interface AnnotationValue {
/**
* Models an annotation-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ANNOTATION}.
* Models an annotation value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ANNOTATION}.
*
* @since 22
*/
@ -66,8 +70,8 @@ public sealed interface AnnotationValue {
}
/**
* Models an array-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ARRAY}.
* Models an array value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ARRAY}.
*
* @since 22
*/
@ -79,13 +83,15 @@ public sealed interface AnnotationValue {
*
* @apiNote
* 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();
}
/**
* Models a constant-valued element.
* Models a constant value of an element-value pair.
*
* @sealedGraph
* @since 22
@ -123,8 +129,8 @@ public sealed interface AnnotationValue {
}
/**
* Models a string-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_STRING}.
* Models a string value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_STRING}.
*
* @since 22
*/
@ -151,8 +157,8 @@ public sealed interface AnnotationValue {
}
/**
* Models a double-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_DOUBLE}.
* Models a double value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_DOUBLE}.
*
* @since 22
*/
@ -179,8 +185,8 @@ public sealed interface AnnotationValue {
}
/**
* Models a float-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_FLOAT}.
* Models a float value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_FLOAT}.
*
* @since 22
*/
@ -207,8 +213,8 @@ public sealed interface AnnotationValue {
}
/**
* Models a long-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_LONG}.
* Models a long value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_LONG}.
*
* @since 22
*/
@ -235,8 +241,8 @@ public sealed interface AnnotationValue {
}
/**
* Models an int-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_INT}.
* Models an int value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_INT}.
*
* @since 22
*/
@ -263,8 +269,8 @@ public sealed interface AnnotationValue {
}
/**
* Models a short-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_SHORT}.
* Models a short value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_SHORT}.
*
* @since 22
*/
@ -294,8 +300,8 @@ public sealed interface AnnotationValue {
}
/**
* Models a char-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_CHAR}.
* Models a char value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_CHAR}.
*
* @since 22
*/
@ -325,8 +331,8 @@ public sealed interface AnnotationValue {
}
/**
* Models a byte-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_BYTE}.
* Models a byte value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_BYTE}.
*
* @since 22
*/
@ -356,8 +362,8 @@ public sealed interface AnnotationValue {
}
/**
* Models a boolean-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_BOOLEAN}.
* Models a boolean value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_BOOLEAN}.
*
* @since 22
*/
@ -387,8 +393,8 @@ public sealed interface AnnotationValue {
}
/**
* Models a class-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_CLASS}.
* Models a class value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_CLASS}.
*
* @since 22
*/
@ -405,8 +411,8 @@ public sealed interface AnnotationValue {
}
/**
* Models an enum-valued element.
* The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ENUM}.
* Models an enum value of an element-value pair.
* The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ENUM}.
*
* @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();
/**
* {@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 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 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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
static OfArray ofArray(AnnotationValue... values) {

View File

@ -25,12 +25,10 @@
package java.lang.classfile;
import java.lang.constant.ClassDesc;
import java.util.List;
import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import java.lang.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.TargetInfoImpl;
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_RESOURCE_VARIABLE;
import static java.lang.classfile.ClassFile.TAT_THROWS;
import jdk.internal.classfile.impl.TemporaryConstantPool;
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 RuntimeInvisibleTypeAnnotationsAttribute
*
@ -69,7 +77,6 @@ import jdk.internal.javac.PreviewFeature;
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public sealed interface TypeAnnotation
extends Annotation
permits UnboundAttribute.UnboundTypeAnnotation {
/**
@ -170,7 +177,7 @@ public sealed interface TypeAnnotation
/**
* {@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();
@ -180,57 +187,22 @@ public sealed interface TypeAnnotation
List<TypePathComponent> targetPath();
/**
* {@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
* {@return the annotation applied to the part indicated by {@link #targetPath()}}
* This models the interface of the annotation and the set of element-value pairs,
* the subset of the {@code type_annotation} structure that is identical to the
* {@code annotation} structure.
*/
static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
Utf8Entry annotationClassUtf8Entry,
List<AnnotationElement> annotationElements) {
return new UnboundAttribute.UnboundTypeAnnotation(targetInfo, targetPath,
annotationClassUtf8Entry, annotationElements);
}
Annotation annotation();
/**
* {@return a type annotation}
* {@return a {@code type_annotation} structure}
* @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
* @param annotation the annotation
*/
static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
ClassDesc annotationClass,
AnnotationElement... annotationElements) {
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));
Annotation annotation) {
return new UnboundAttribute.UnboundTypeAnnotation(targetInfo, targetPath, annotation);
}
/**

View File

@ -657,7 +657,7 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
@Override
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
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
Utf8Entry type = classReader.readEntry(p, Utf8Entry.class);
p += 2;
return TypeAnnotation.of(targetInfo, List.of(typePath), type,
readAnnotationElementValuePairs(classReader, p));
var anno = readAnnotation(classReader, p);
return TypeAnnotation.of(targetInfo, List.of(typePath), anno);
}
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) {
// handles annotations and type annotations
// TODO annotation cleanup later
((Util.Writable) annotation).writeTo(buf);
}
public static void writeAnnotations(BufWriter buf, List<? extends Annotation> list) {
// handles annotations and type annotations
public static void writeAnnotations(BufWriter buf, List<Annotation> list) {
var internalBuf = (BufWriterImpl) buf;
internalBuf.writeU2(list.size());
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) {
// TODO annotation cleanup later
((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) {
return new ListNodeImpl(style, name, annos.stream().map(a ->
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()))
.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) {
return typeAnnotations.stream().map(a -> TypeAnnotation.of(a.targetInfo(),
a.targetPath(), map(a.classSymbol()),
a.elements().stream().map(el -> AnnotationElement.of(el.name(),
mapAnnotationValue(el.value()))).toList())).toList();
a.targetPath(), mapAnnotation(a.annotation()))).toList();
}
List<Signature.TypeParam> mapTypeParams(List<Signature.TypeParam> typeParams) {

View File

@ -29,14 +29,12 @@ import java.util.List;
import java.util.Optional;
import java.lang.classfile.Annotation;
import java.lang.classfile.AnnotationElement;
import java.lang.classfile.AnnotationValue;
import java.lang.classfile.Attribute;
import java.lang.classfile.AttributeMapper;
import java.lang.classfile.Attributes;
import java.lang.classfile.BootstrapMethodEntry;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.Label;
import java.lang.classfile.TypeAnnotation;
import java.lang.classfile.attribute.AnnotationDefaultAttribute;
import java.lang.classfile.attribute.BootstrapMethodsAttribute;
@ -758,75 +756,10 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public record UnboundTypeAnnotation(TargetInfo targetInfo,
List<TypePathComponent> targetPath,
Utf8Entry className,
List<AnnotationElement> elements) implements TypeAnnotation, Util.Writable {
Annotation annotation) implements TypeAnnotation {
public UnboundTypeAnnotation(TargetInfo targetInfo, List<TypePathComponent> targetPath,
Utf8Entry className, List<AnnotationElement> elements) {
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());
}
public UnboundTypeAnnotation {
targetPath = List.copyOf(targetPath);
}
}

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.
*
* 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) {
int l = 2;
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;
}

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.
*
* 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);
println();
indent(+1);
write(annot, true);
write(annot.annotation(), true);
indent(-1);
}
public void write(TypeAnnotation annot, boolean showOffsets,
boolean resolveIndices, CodeAttribute lr) {
write(annot, resolveIndices);
write(annot.annotation(), resolveIndices);
print(": ");
write(annot.targetInfo(), annot.targetPath(), showOffsets, lr);
}

View File

@ -66,7 +66,7 @@ class ClassPrinterTest {
RuntimeInvisibleTypeAnnotationsAttribute.of(
TypeAnnotation.of(TypeAnnotation.TargetInfo.ofField(),
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(PermittedSubclassesAttribute.ofSymbols(ClassDesc.of("Boo"), ClassDesc.of("Phoo")))
.withField("f", ConstantDescs.CD_String, fb -> fb
@ -101,7 +101,7 @@ class ClassPrinterTest {
tryb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(
TypeAnnotation.of(TypeAnnotation.TargetInfo.ofField(),
List.of(TypeAnnotation.TypePathComponent.WILDCARD),
ClassDesc.of("Boo"), List.of())));
Annotation.of(ClassDesc.of("Boo"), List.of()))));
tryb.invokedynamic(DynamicCallSiteDesc.of(
MethodHandleDesc.ofMethod(DirectMethodHandleDesc.Kind.STATIC, ClassDesc.of("Phoo"), "phee", MethodTypeDesc.of(ClassDesc.of("Boo"))),
"intfMethod",
@ -116,7 +116,7 @@ class ClassPrinterTest {
.with(RuntimeVisibleTypeAnnotationsAttribute.of(
TypeAnnotation.of(TypeAnnotation.TargetInfo.ofField(),
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
* @bug 8336010 8336588
* @bug 8335935 8336588
* @summary Testing ClassFile transformations.
* @run junit TransformTests
*/

View File

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

View File

@ -179,8 +179,7 @@ class RebuildingTransformation {
return annotations.stream().map(ta -> TypeAnnotation.of(
transformTargetInfo(ta.targetInfo(), cob, labels),
ta.targetPath().stream().map(tpc -> TypeAnnotation.TypePathComponent.of(tpc.typePathKind(), tpc.typeArgumentIndex())).toList(),
ta.classSymbol(),
ta.elements().stream().map(ae -> AnnotationElement.of(ae.name().stringValue(), transformAnnotationValue(ae.value()))).toList())).toArray(TypeAnnotation[]::new);
transformAnnotation(ta.annotation()))).toArray(TypeAnnotation[]::new);
}
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.
*
* 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) {
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;
switch (anno.targetInfo()) {
case TypeAnnotation.TypeParameterBoundTarget binfo -> {
@ -1197,8 +1197,8 @@ public class ClassfileInspector {
switch (attr) {
case RuntimeVisibleTypeAnnotationsAttribute rvattr -> {
if (expected.matchVisibility(true)) {
for(Annotation anno : rvattr.annotations()) {
expected.matchAnnotation(anno);
for(var anno : rvattr.annotations()) {
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;
String name;
try {
name = annotation.classSymbol().descriptorString();
name = annotation.annotation().classSymbol().descriptorString();
} catch (Exception e) {
throw new AssertionError(e);
}
@ -227,7 +227,7 @@ public class AnonymousClassTest {
return String.format(
"@%s(%s) %s, offset=%d, location=%s",
name,
annotationValueDebugString(cm, annotation),
annotationValueDebugString(cm, annotation.annotation()),
info.targetType(),
offset,
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.
*
* 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<>();
for (TypeAnnotation anno: annos) {
TAD tad = new TAD();
tad.annotation = anno.className().stringValue();
tad.annotation = anno.annotation().className().stringValue();
tad.type = anno.targetInfo().targetType();
switch (anno.targetInfo().targetType()) {
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.
*
* 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();
for (TypeAnnotation ta: annotations.annotations()) {
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(", index=" + info.index()+ "}], ");
}

View File

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