RFR JDK-8208470: Type annotations on inner type that is an array component

B. Blaser bsrbnd at gmail.com
Sat Sep 22 16:59:34 UTC 2018


Hi,

I tried the initial example at processing and at runtime:

$ cat ArrayOfInner.java ArrayOfInnerProc.java
import java.lang.annotation.*;
import java.lang.reflect.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@interface TA {
    int value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@interface TB {}

@TB
class ArrayOfInner {
    @TB
    class Inner {}

    @TA(1) ArrayOfInner. @TA(2) Inner oi;
    @TA(3) ArrayOfInner. @TA(4) Inner [] oia;
    @TA(5) Inner i;
    @TA(6) Inner [] ia;

    public static void main(String... args) throws Exception {
        printField(ArrayOfInner.class.getDeclaredField("oi"));
        printArray(ArrayOfInner.class.getDeclaredField("oia"));
        printField(ArrayOfInner.class.getDeclaredField("i"));
        printArray(ArrayOfInner.class.getDeclaredField("ia"));
    }

    private static void printField(Field f) {
        AnnotatedType typeUse = f.getAnnotatedType();

        System.out.println(f + ":");
        for (Annotation a: typeUse.getAnnotations())
            System.out.println(" " + a + " // type use");
        if (typeUse.getAnnotatedOwnerType() != null)
            for (Annotation a: typeUse.getAnnotatedOwnerType().getAnnotations())
                System.out.println(" " + a + " // outer type use");
        for (Annotation a: f.getType().getAnnotations())
            System.out.println(" " + a + " // declared type");
    }

    private static void printArray(Field f) {
        AnnotatedArrayType array = (AnnotatedArrayType)f.getAnnotatedType();
        AnnotatedType typeUse = array.getAnnotatedGenericComponentType();

        System.out.println(f + ":");
        for (Annotation a: typeUse.getAnnotations())
            System.out.println(" " + a + " // type use");
        if (typeUse.getAnnotatedOwnerType() != null)
            for (Annotation a: typeUse.getAnnotatedOwnerType().getAnnotations())
                System.out.println(" " + a + " // outer type use");
        for (Annotation a: f.getType().getComponentType().getAnnotations())
            System.out.println(" " + a + " // declared type");
    }
}
import java.util.*;

import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.lang.model.type.*;

@SupportedSourceVersion(SourceVersion.RELEASE_12)
@SupportedAnnotationTypes({"*"})
public class ArrayOfInnerProc extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
        for (Element c: roundEnv.getRootElements()) {
            if (!c.toString().equals("ArrayOfInner")) continue;

            for(Element f: ((TypeElement)c).getEnclosedElements()) {
                if (f.getKind() != ElementKind.FIELD) continue;

                System.out.println(f + ":");

                TypeMirror t = f.asType();
                if (t.getKind() == TypeKind.ARRAY)
                    t = ((ArrayType)f.asType()).getComponentType();

                for (AnnotationMirror a: t.getAnnotationMirrors())
                    System.out.println(" " + a + " // type use");

                for (AnnotationMirror a:
((DeclaredType)t).getEnclosingType().getAnnotationMirrors())
                    System.out.println(" " + a + " // outer type use");

                Element e = processingEnv.getTypeUtils().asElement(t);
                for (AnnotationMirror a: e.getAnnotationMirrors())
                    System.out.println(" " + a + " // declared type");
            }
        }
        return false;
    }
}

Without fix, note the wrong location for @TA(3) at processing:

$ javac ArrayOfInnerProc.java
$ javac -processor ArrayOfInnerProc ArrayOfInner.java
oi:
 @TA(2) // type use
 @TA(1) // outer type use
 @TB // declared type
oia:
 @TA(3) // type use
 @TA(4) // type use
 @TB // declared type
i:
 @TA(5) // type use
 @TB // declared type
ia:
 @TA(6) // type use
 @TB // declared type

And note the wrong location for @TA(6) at runtime:

$ java ArrayOfInner
ArrayOfInner$Inner ArrayOfInner.oi:
 @TA(value=2) // type use
 @TA(value=1) // outer type use
 @TB() // declared type
ArrayOfInner$Inner[] ArrayOfInner.oia:
 @TA(value=4) // type use
 @TA(value=3) // outer type use
 @TB() // declared type
ArrayOfInner$Inner ArrayOfInner.i:
 @TA(value=5) // type use
 @TB() // declared type
ArrayOfInner$Inner[] ArrayOfInner.ia:
 @TA(value=6) // outer type use
 @TB() // declared type

All seems to be fine with the fix:

$ javac -processor ArrayOfInnerProc ArrayOfInner.java
oi:
 @TA(2) // type use
 @TA(1) // outer type use
 @TB // declared type
oia:
 @TA(4) // type use
 @TA(3) // outer type use
 @TB // declared type
i:
 @TA(5) // type use
 @TB // declared type
ia:
 @TA(6) // type use
 @TB // declared type

$ java ArrayOfInner
ArrayOfInner$Inner ArrayOfInner.oi:
 @TA(value=2) // type use
 @TA(value=1) // outer type use
 @TB() // declared type
ArrayOfInner$Inner[] ArrayOfInner.oia:
 @TA(value=4) // type use
 @TA(value=3) // outer type use
 @TB() // declared type
ArrayOfInner$Inner ArrayOfInner.i:
 @TA(value=5) // type use
 @TB() // declared type
ArrayOfInner$Inner[] ArrayOfInner.ia:
 @TA(value=6) // type use
 @TB() // declared type

Thoughts?

Thanks,
Bernard

On Tue, 18 Sep 2018 at 15:41, B. Blaser <bsrbnd at gmail.com> wrote:
>
> Hi,
>
> Please review the following fix for [1]:
>
> http://cr.openjdk.java.net/~bsrbnd/jdk8208470/webrev.00/
>
> We've seen in thread [2] that [3] has probably caused the regression.
> Among the variants we explored, Werner's one enhanced as discussed in
> [2] seems quite good to me.
> It has a small side-effect as the array element type would then carry
> the annotation which is revealed by test [4], but I'm of Werner's
> opinion that this would be correct.
> I've made other attempts [5] to avoid this side-effect but I'm not
> sure this is really the right approach.
>
> Any feedback is welcome (langtools:tier1 is OK),
> Bernard
>
> [1] https://bugs.openjdk.java.net/browse/JDK-8208470
> [2] http://mail.openjdk.java.net/pipermail/compiler-dev/2018-July/012199.html
> [3] http://hg.openjdk.java.net/jdk9/dev/langtools/rev/62e285806e83#l6.440
> [4] http://cr.openjdk.java.net/~bsrbnd/jdk8208470/webrev.00/test/langtools/tools/javac/warnings/6747671/T6747671.out.frames.html
> [5] http://mail.openjdk.java.net/pipermail/compiler-dev/2018-July/012266.html


More information about the compiler-dev mailing list