RFR: 8225377: type annotations are not visible to javac plugins across compilation boundaries

Liam Miller-Cushon cushon at openjdk.org
Fri Oct 27 21:08:42 UTC 2023


Please consider this fix for [JDK-8225377: type annotations are not visible to javac plugins across compilation boundaries](https://bugs.openjdk.org/browse/JDK-8225377).


To provide some background context and motivation for the bug fix, consider an example like:

class B {
  @Nullable int f(int x) {
    return x;

If `@Nullable` is a `@Target(METHOD)` annotation, an annotation processor can retrieve the annotation by from the  `ExecutableElement` for `f` by calling `getAnnotationMirrors()`. This is true regardless of whether `B` is being compiled from source in the current compilation, or loaded from a class file.

If `@Nullable` is a `@Target(TYPE_USE)` annotation, an annotation processor should be able to retrieve the annotation by locating the `ExecutableElement` for `f`, and calling `getReturnType().getAnnotationMirrors()`. This works today if `B` is compiled from source, but (due to [JDK-8225377](https://bugs.openjdk.org/browse/JDK-8225377)) not if `B` is loaded from a class file.

This is a hurdle to migrating from existing declaration annotations to `@Target(TYPE_USE)` annotations for use-cases like `@Nullable`. For example: a dependency injection framework might use an annotation processor to generate code, and that code would want to know if a formal parameter type accepted `null` values, or if a method returned `null` values. That works today with declaration annotation definitions of `@Nullable`, and this fix will allow it work with `TYPE_USE` definitions of `@Nullable` in the future.


javac already reads type annotation information from `Runtime{Visible,Invisible}TypeAnnotations` attributes in class files, and `ClassReader` registers a completer that calls `Symbol#setTypeAttributes` to add the type annotations to the symbol's metadata. This change adds logic to associate those annotations with the corresponding type contained in the symbol.

Some notes on the approach:

* There are some similarities between the logic being added and existing logic in `TypeAnnotations`, but `TypeAnnotations` operates on the AST, and is solving different problems. In the AST annotations are already adjacent to the type they are annotating, and in bytecode they have been separated out and the implementation has to interpret the annotation target and type path information to match the annotations back up with their types.

* For initial test coverage, I have enabled test coverage for annotation processing of type annotations to also run the annotation processor on the pre-compiled class. There may be other type annotation tests that could be updated to exercise this change. Overall I think updating the existing extensive test coverage for type annotations avoids duplicating test inputs, and helps ensure both the type annotations for symbols compiled from source and loaded from bytecode match, and that they continue to match when there are changes in the future.


Commit messages:
 - 8225377: type annotations are not visible to javac plugins across compilation boundaries

Changes: https://git.openjdk.org/jdk/pull/16407/files
 Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=16407&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8225377
  Stats: 338 lines in 3 files changed: 337 ins; 0 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/16407.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/16407/head:pull/16407

PR: https://git.openjdk.org/jdk/pull/16407

More information about the compiler-dev mailing list