nbauma109 opened a new pull request, #539: URL: https://github.com/apache/commons-bcel/pull/539
Parses and writes the `RuntimeVisibleTypeAnnotations` and `RuntimeInvisibleTypeAnnotations` attributes ([JVMS 4.7.20](https://docs.oracle.com/javase/specs/jvms/se21/html/jvms-4.html#jvms-4.7.20)), which `Attribute.readAttribute` returns as `Unknown` today. ## Why Annotations written on types (JSR 308) are stored apart from the declaration annotations: JSpecify's `@Nullable` in `void put(@Nullable Object key)`, `List<@Nullable String>`, `<K extends @Nullable Object>`. A user of BCEL can only get them by parsing the bytes of an `Unknown` attribute itself: target type, variable-size target info, type path, then the annotation with its element values. For example, a decompiler built on BCEL loses every `@Nullable` of a library such as Guava, whose packages are `@NullMarked`, and the recompiled sources are rejected by Error Prone. ## Changes - `Const`: `ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = 29`, `ATTR_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = 30`, `KNOWN_ATTRIBUTES = 31`, and the two attribute names. - `TypeAnnotations` (abstract, `Iterable<TypeAnnotationEntry>`, like `Annotations`), `RuntimeVisibleTypeAnnotations`, `RuntimeInvisibleTypeAnnotations`. - `TypeAnnotationEntry`: the target type (`TARGET_*` constants for the table 4.7.20-A), the target info as stored in the class file (its size depends on the target type; the `localvar_target` table has a variable size), the type path (`getTypePathLength`, `getTypePathKind`, `getTypePathArgumentIndex`), and the `AnnotationEntry` read by the existing code. An undefined target type throws `ClassFormatException`. `dump` writes what `read` read. - `Attribute.readAttribute`, `Visitor.visitTypeAnnotations` (a default method: existing `Visitor` implementations are unaffected), `DescendingVisitor`, `EmptyVisitor`, `StringRepresentation`, and an entry in `changes.xml`. The target info is exposed as bytes, not as one class per kind of target, to keep the API small. The meaning of its bytes is documented on `getTargetInfo()`: index of the type parameter, of the bound, or of the formal parameter. ## Tests `TypeAnnotationsTest` reads `src/test/resources/typeannotations/TypeAnnotated.class`, compiled with `javac --release 8` from the `.java` file next to it. It covers a field, the type path of a type argument, an invisible annotation, a method return and a parameter, the bound of a class type parameter, dump then re-read, `copy`, the visitor and `StringRepresentation`. Two more tests cover the `localvar_target` table (read then dump gives the same bytes) and an undefined target type. The default `mvn` goal (tests, rat, japicmp, checkstyle, pmd, spotbugs, javadoc) passes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
