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