Class ClassFileParameterAnnotations
The Scala compiler reads a Java class from its class file into the same symbols a
Scala class has, and that reading is what the rest of the model is built from. It leaves
one thing out: dotty's class-file parser does not read RuntimeVisibleParameterAnnotations
or its invisible counterpart at all -- a documented TODO -- and parameter annotations are
where Micronaut looks most. @Nullable decides whether an argument may be absent,
@Body and @QueryValue decide where it comes from, and @Id on a
repository method's parameter decides what it means.
This reads exactly that, from the bytes the compiler already has for the class, with the JDK's own class-file API. Nothing is loaded: reading bytes has no static initialiser to run and no classloader to choose, which is what the reflective reading it replaces got wrong whenever the plugin's classloader and the application's disagreed.
Type annotations are read as well, where they sit on a parameter's own type, a return
type or a field's type. Nullability in Java has moved there: jspecify's @Nullable is
TYPE_USE only, so body(@Nullable T body) records nothing in the parameter
annotations and everything in the type annotations, and javac's model reports it on the
parameter regardless. Annotations deeper in a type -- on a type argument -- are left where
they are.
The values come out as plain data -- constants, names, and the records below -- and are turned into the model's own annotation data by the extractor, which is where the annotation types are resolved.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordAn annotation as written in the class file.static final recordA class literal used as an annotation value.static final recordAn enum constant used as an annotation value.static final recordWhat a method's class file says about its annotations beyond what the compiler read.static final recordA private field the compiler did not enter.static final recordA private method the compiler did not enter. -
Method Summary
Modifier and TypeMethodDescriptionThe default value of each member of an annotation type, from itsAnnotationDefaultattributes.The type annotations on a field's type, which the compiler does not read.The annotations of a method the compiler did not read: on its parameters, and on its return type and parameter types.parse(byte[] bytes) Reads a class file.The private fields of the class, which the compiler does not enter at all.The private methods of the class, which the compiler does not enter at all; seeprivateFields().
-
Method Details
-
parse
Reads a class file.- Parameters:
bytes- The class file- Returns:
- Its parameter annotations
-
forMethod
public ClassFileParameterAnnotations.MethodAnnotations forMethod(String name, List<String> erasedParameterTypes) The annotations of a method the compiler did not read: on its parameters, and on its return type and parameter types.The method is found by name and by the erased types of its parameters, which is what a JVM descriptor holds. An overload set is disambiguated that way; a single method of the name and arity is taken as is, so a mismatch in how an erasure is spelled cannot lose the annotations of an unambiguous method.
A constructor of an inner class takes the enclosing instance as a leading parameter the language does not show, and the compiler's model of it does not either. When no constructor matches as declared, one whose descriptor has exactly that one extra leading parameter is accepted. Whether its annotation attributes count that parameter is the compiler's choice -- the JVM specification leaves it open, javac counts the parameters written in the source and other compilers have counted the descriptor's -- so each attribute is read by what it holds: one entry per written parameter is aligned as it is, and one that runs past the written parameters is aligned from the descriptor.
- Parameters:
name- The method name,<init>for a constructorerasedParameterTypes- The erased parameter types, as binary names- Returns:
- The annotations,
ClassFileParameterAnnotations.MethodAnnotations.NONEwhen the method is not found
-
privateFields
The private fields of the class, which the compiler does not enter at all.dotty's class-file parser skips every private member of a Java class -- a Scala program cannot refer to one, so the compiler has no use for it. Micronaut does: an
@Injectfield or a@PostConstructmethod in a library's base class may well be private, and the Java model shows both. They are read from the class file instead, with their generic signatures, so the model can build the same types for them it builds for everything else.- Returns:
- The private fields, in class-file order
-
privateMethods
The private methods of the class, which the compiler does not enter at all; seeprivateFields(). Constructors, bridges and synthetics are not included.- Returns:
- The private methods, in class-file order
-
annotationDefaults
The default value of each member of an annotation type, from itsAnnotationDefaultattributes. The compiler records that a member has a default and discards the value; the value is what a use of the annotation that omits the member means.- Returns:
- The defaults by member name, as
ClassFileParameterAnnotations.Annotationvalues are represented
-
forField
The type annotations on a field's type, which the compiler does not read.- Parameters:
name- The field name- Returns:
- The annotations, empty when there are none or the field is not found
-