8046916: Type parameter annotations don't work with multiple type parameters

Wed, 18 Jun 2014 10:44:16 +0200

author
jlahoda
date
Wed, 18 Jun 2014 10:44:16 +0200
changeset 2427
a3ad6e2ede44
parent 2426
829f01e7f732
child 2428
ce1d9dd2e9eb

8046916: Type parameter annotations don't work with multiple type parameters
Summary: When reading type variable's annotations out of the owner's type annotations, use the type variable's index in owner to exclude annotations belonging to other type variables.
Reviewed-by: jfranck, emc

src/share/classes/com/sun/tools/javac/code/Symbol.java file | annotate | diff | comparison | revisions
test/tools/javac/processing/model/element/TestTypeParameterAnnotations.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Jun 19 12:22:39 2014 +0100
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java	Wed Jun 18 10:44:16 2014 +0200
     1.3 @@ -779,42 +779,41 @@
     1.4  
     1.5          @Override
     1.6          public List<Attribute.Compound> getAnnotationMirrors() {
     1.7 -            return onlyTypeVariableAnnotations(owner.getRawTypeAttributes());
     1.8 -        }
     1.9 -
    1.10 -        private List<Attribute.Compound> onlyTypeVariableAnnotations(
    1.11 -                List<Attribute.TypeCompound> candidates) {
    1.12 -            // Declaration annotations on TypeParameters are stored in type attributes
    1.13 +            // Declaration annotations on type variables are stored in type attributes
    1.14 +            // on the owner of the TypeVariableSymbol
    1.15 +            List<Attribute.TypeCompound> candidates = owner.getRawTypeAttributes();
    1.16 +            int index = owner.getTypeParameters().indexOf(this);
    1.17              List<Attribute.Compound> res = List.nil();
    1.18              for (Attribute.TypeCompound a : candidates) {
    1.19 -                if (a.position.type == TargetType.CLASS_TYPE_PARAMETER ||
    1.20 -                    a.position.type == TargetType.METHOD_TYPE_PARAMETER)
    1.21 +                if (isCurrentSymbolsAnnotation(a, index))
    1.22                      res = res.prepend(a);
    1.23              }
    1.24  
    1.25 -            return res = res.reverse();
    1.26 +            return res.reverse();
    1.27          }
    1.28  
    1.29 -
    1.30 -
    1.31          // Helper to getAnnotation[s]
    1.32          @Override
    1.33          public <A extends Annotation> Attribute.Compound getAttribute(Class<A> annoType) {
    1.34 -
    1.35              String name = annoType.getName();
    1.36  
    1.37              // Declaration annotations on type variables are stored in type attributes
    1.38              // on the owner of the TypeVariableSymbol
    1.39              List<Attribute.TypeCompound> candidates = owner.getRawTypeAttributes();
    1.40 +            int index = owner.getTypeParameters().indexOf(this);
    1.41              for (Attribute.TypeCompound anno : candidates)
    1.42 -                if (anno.position.type == TargetType.CLASS_TYPE_PARAMETER ||
    1.43 -                        anno.position.type == TargetType.METHOD_TYPE_PARAMETER)
    1.44 -                    if (name.contentEquals(anno.type.tsym.flatName()))
    1.45 -                        return anno;
    1.46 +                if (isCurrentSymbolsAnnotation(anno, index) &&
    1.47 +                    name.contentEquals(anno.type.tsym.flatName()))
    1.48 +                    return anno;
    1.49  
    1.50              return null;
    1.51          }
    1.52 -
    1.53 +            //where:
    1.54 +            boolean isCurrentSymbolsAnnotation(Attribute.TypeCompound anno, int index) {
    1.55 +                return (anno.position.type == TargetType.CLASS_TYPE_PARAMETER ||
    1.56 +                        anno.position.type == TargetType.METHOD_TYPE_PARAMETER) &&
    1.57 +                       anno.position.parameter_index == index;
    1.58 +            }
    1.59  
    1.60  
    1.61          @Override
     2.1 --- a/test/tools/javac/processing/model/element/TestTypeParameterAnnotations.java	Thu Jun 19 12:22:39 2014 +0100
     2.2 +++ b/test/tools/javac/processing/model/element/TestTypeParameterAnnotations.java	Wed Jun 18 10:44:16 2014 +0200
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -23,7 +23,7 @@
    2.11  
    2.12  /*
    2.13   * @test
    2.14 - * @bug 8011027
    2.15 + * @bug 8011027 8046916
    2.16   * @library /tools/javac/lib
    2.17   * @build JavacTestingAbstractProcessor TestTypeParameterAnnotations
    2.18   * @compile -processor TestTypeParameterAnnotations -proc:only TestTypeParameterAnnotations.java
    2.19 @@ -33,10 +33,16 @@
    2.20  import java.lang.annotation.*;
    2.21  import javax.annotation.processing.*;
    2.22  import javax.lang.model.element.*;
    2.23 -import javax.lang.model.util.*;
    2.24  import javax.tools.*;
    2.25  
    2.26 -public class TestTypeParameterAnnotations<@Foo @Bar @Baz T> extends JavacTestingAbstractProcessor {
    2.27 +@ExpectedTypeParameterAnnotations(typeParameterName="T1",
    2.28 +                                  annotations={"Foo1", "Bar1", "Baz1"})
    2.29 +@ExpectedTypeParameterAnnotations(typeParameterName="T2", annotations={})
    2.30 +@ExpectedTypeParameterAnnotations(typeParameterName="T3",
    2.31 +                                  annotations={"Foo2", "Bar2", "Baz2"})
    2.32 +@ExpectedTypeParameterAnnotations(typeParameterName="T4", annotations={})
    2.33 +public class TestTypeParameterAnnotations<@Foo1 @Bar1 @Baz1 T1, T2, @Foo2 @Bar2 @Baz2 T3, T4> extends
    2.34 +        JavacTestingAbstractProcessor {
    2.35      int round = 0;
    2.36  
    2.37      public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    2.38 @@ -74,82 +80,69 @@
    2.39      int check(Element e, List<? extends TypeParameterElement> typarams) {
    2.40          if (typarams.isEmpty())
    2.41              return 0;
    2.42 -        if (typarams.size() != 1)
    2.43 -            return 0;
    2.44  
    2.45 -        for (TypeParameterElement tpe: typarams) {
    2.46 -            boolean b1 = checkAnnotationMirrors(tpe, tpe.getAnnotationMirrors());
    2.47 -            boolean b2 = checkAnnotationMirrors(tpe, elements.getAllAnnotationMirrors(tpe));
    2.48 -            boolean b3 = checkGetAnnotation(tpe);
    2.49 -            boolean b4 = checkGetAnnotations(tpe);
    2.50 -            return b1 && b2 && b3 && b4 ? 1 : 0;
    2.51 +        for (TypeParameterElement tpe : typarams) {
    2.52 +            ExpectedTypeParameterAnnotations expected = null;
    2.53 +            for (ExpectedTypeParameterAnnotations a : e.getAnnotationsByType(ExpectedTypeParameterAnnotations.class)) {
    2.54 +                if (tpe.getSimpleName().contentEquals(a.typeParameterName())) {
    2.55 +                    expected = a;
    2.56 +                    break;
    2.57 +                }
    2.58 +            }
    2.59 +            if (expected == null) {
    2.60 +                throw new IllegalStateException("Does not have expected values annotation.");
    2.61 +            }
    2.62 +            checkAnnotationMirrors(tpe, tpe.getAnnotationMirrors(), expected);
    2.63 +            checkAnnotationMirrors(tpe, elements.getAllAnnotationMirrors(tpe), expected);
    2.64 +            checkGetAnnotation(tpe, expected);
    2.65 +            checkGetAnnotations(tpe, expected);
    2.66          }
    2.67 -        return 0;
    2.68 +
    2.69 +        return typarams.size();
    2.70      }
    2.71  
    2.72 -    boolean checkAnnotationMirrors(TypeParameterElement tpe, List<? extends AnnotationMirror> l) {
    2.73 -        if (l.size() != 3) {
    2.74 -            error("To few annotations, got " + l.size() +
    2.75 -                    ", should be 3", tpe);
    2.76 -            return false;
    2.77 +    void checkAnnotationMirrors(TypeParameterElement tpe, List<? extends AnnotationMirror> l, ExpectedTypeParameterAnnotations expected) {
    2.78 +        String[] expectedAnnotations = expected.annotations();
    2.79 +
    2.80 +        if (l.size() != expectedAnnotations.length) {
    2.81 +            error("Incorrect number of annotations, got " + l.size() +
    2.82 +                    ", should be " + expectedAnnotations.length, tpe);
    2.83 +            return ;
    2.84          }
    2.85  
    2.86 -        AnnotationMirror m = l.get(0);
    2.87 -        if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Foo"))) {
    2.88 -            error("Wrong type of annotation, was expecting @Foo", m.getAnnotationType().asElement());
    2.89 -            return false;
    2.90 +        for (int i = 0; i < expectedAnnotations.length; i++) {
    2.91 +            AnnotationMirror m = l.get(i);
    2.92 +            if (!m.getAnnotationType().asElement().equals(elements.getTypeElement(expectedAnnotations[i]))) {
    2.93 +                error("Wrong type of annotation, was expecting @Foo", m.getAnnotationType().asElement());
    2.94 +                return ;
    2.95 +            }
    2.96          }
    2.97 -        m = l.get(1);
    2.98 -        if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Bar"))) {
    2.99 -            error("Wrong type of annotation, was expecting @Bar", m.getAnnotationType().asElement());
   2.100 -            return false;
   2.101 -        }
   2.102 -        m = l.get(2);
   2.103 -        if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Baz"))) {
   2.104 -            error("Wrong type of annotation, was expecting @Baz", m.getAnnotationType().asElement());
   2.105 -            return false;
   2.106 -        }
   2.107 -        return true;
   2.108      }
   2.109  
   2.110 -    boolean checkGetAnnotation(TypeParameterElement tpe) {
   2.111 -        Foo f = tpe.getAnnotation(Foo.class);
   2.112 -        if (f == null)
   2.113 -            error("Expecting @Foo to be present in getAnnotation()", tpe);
   2.114 +    void checkGetAnnotation(TypeParameterElement tpe, ExpectedTypeParameterAnnotations expected) {
   2.115 +        List<String> expectedAnnotations = Arrays.asList(expected.annotations());
   2.116  
   2.117 -        Bar b = tpe.getAnnotation(Bar.class);
   2.118 -        if (b == null)
   2.119 -            error("Expecting @Bar to be present in getAnnotation()", tpe);
   2.120 +        for (Class<? extends Annotation> c : ALL_ANNOTATIONS) {
   2.121 +            Object a = tpe.getAnnotation(c);
   2.122  
   2.123 -        Baz z = tpe.getAnnotation(Baz.class);
   2.124 -        if (z == null)
   2.125 -            error("Expecting @Baz to be present in getAnnotation()", tpe);
   2.126 -
   2.127 -        return f != null &&
   2.128 -            b != null &&
   2.129 -            z != null;
   2.130 +            if (a != null ^ expectedAnnotations.indexOf(c.getName()) != (-1)) {
   2.131 +                error("Unexpected behavior for " + c.getName(), tpe);
   2.132 +                return ;
   2.133 +            }
   2.134 +        }
   2.135      }
   2.136  
   2.137 -    boolean checkGetAnnotations(TypeParameterElement tpe) {
   2.138 -        Foo[] f = tpe.getAnnotationsByType(Foo.class);
   2.139 -        if (f.length != 1) {
   2.140 -            error("Expecting 1 @Foo to be present in getAnnotationsByType()", tpe);
   2.141 -            return false;
   2.142 +    void checkGetAnnotations(TypeParameterElement tpe, ExpectedTypeParameterAnnotations expected) {
   2.143 +        List<String> expectedAnnotations = Arrays.asList(expected.annotations());
   2.144 +
   2.145 +        for (Class<? extends Annotation> c : ALL_ANNOTATIONS) {
   2.146 +            Object[] a = tpe.getAnnotationsByType(c);
   2.147 +
   2.148 +            if (a.length > 0 ^ expectedAnnotations.indexOf(c.getName()) != (-1)) {
   2.149 +                error("Unexpected behavior for " + c.getName(), tpe);
   2.150 +                return ;
   2.151 +            }
   2.152          }
   2.153 -
   2.154 -        Bar[] b = tpe.getAnnotationsByType(Bar.class);
   2.155 -        if (b.length != 1) {
   2.156 -            error("Expecting 1 @Bar to be present in getAnnotationsByType()", tpe);
   2.157 -            return false;
   2.158 -        }
   2.159 -
   2.160 -        Baz[] z = tpe.getAnnotationsByType(Baz.class);
   2.161 -        if (z.length != 1) {
   2.162 -            error("Expecting 1 @Baz to be present in getAnnotationsByType()", tpe);
   2.163 -            return false;
   2.164 -        }
   2.165 -
   2.166 -        return true;
   2.167      }
   2.168  
   2.169      void note(String msg) {
   2.170 @@ -168,23 +161,71 @@
   2.171          messager.printMessage(Diagnostic.Kind.ERROR, msg);
   2.172      }
   2.173  
   2.174 +    Class<? extends Annotation>[] ALL_ANNOTATIONS = new Class[] {
   2.175 +        Foo1.class, Bar1.class, Baz1.class,
   2.176 +        Foo2.class, Bar2.class, Baz2.class,
   2.177 +    };
   2.178 +
   2.179      // additional generic elements to test
   2.180 -    <@Foo @Bar @Baz X> X m(X x) { return x; }
   2.181 +    @ExpectedTypeParameterAnnotations(typeParameterName="W",
   2.182 +                                      annotations={"Foo1", "Bar1", "Baz1"})
   2.183 +    @ExpectedTypeParameterAnnotations(typeParameterName="X", annotations={})
   2.184 +    @ExpectedTypeParameterAnnotations(typeParameterName="Y",
   2.185 +                                      annotations={"Foo2", "Bar2", "Baz2"})
   2.186 +    @ExpectedTypeParameterAnnotations(typeParameterName="Z", annotations={})
   2.187 +    <@Foo1 @Bar1 @Baz1 W, X, @Foo2 @Bar2 @Baz2 Y, Z> X m(X x) { return x; }
   2.188  
   2.189 -    interface Intf<@Foo @Bar @Baz X> { X m() ; }
   2.190 +    @ExpectedTypeParameterAnnotations(typeParameterName="W",
   2.191 +                                      annotations={"Foo1", "Bar1", "Baz1"})
   2.192 +    @ExpectedTypeParameterAnnotations(typeParameterName="X", annotations={})
   2.193 +    @ExpectedTypeParameterAnnotations(typeParameterName="Y",
   2.194 +                                      annotations={"Foo2", "Bar2", "Baz2"})
   2.195 +    @ExpectedTypeParameterAnnotations(typeParameterName="Z", annotations={})
   2.196 +    interface Intf<@Foo1 @Bar1 @Baz1 W, X, @Foo2 @Bar2 @Baz2 Y, Z> { X m() ; }
   2.197  
   2.198 -    class Class<@Foo @Bar @Baz X> {
   2.199 -        <@Foo @Bar @Baz Y> Class() { }
   2.200 +    @ExpectedTypeParameterAnnotations(typeParameterName="W",
   2.201 +                                      annotations={"Foo1", "Bar1", "Baz1"})
   2.202 +    @ExpectedTypeParameterAnnotations(typeParameterName="X", annotations={})
   2.203 +    @ExpectedTypeParameterAnnotations(typeParameterName="Y",
   2.204 +                                      annotations={"Foo2", "Bar2", "Baz2"})
   2.205 +    @ExpectedTypeParameterAnnotations(typeParameterName="Z", annotations={})
   2.206 +    class Clazz<@Foo1 @Bar1 @Baz1 W, X, @Foo2 @Bar2 @Baz2 Y, Z> {
   2.207 +        @ExpectedTypeParameterAnnotations(typeParameterName="W",
   2.208 +                                          annotations={"Foo1", "Bar1", "Baz1"})
   2.209 +        @ExpectedTypeParameterAnnotations(typeParameterName="X", annotations={})
   2.210 +        @ExpectedTypeParameterAnnotations(typeParameterName="Y",
   2.211 +                                          annotations={"Foo2", "Bar2", "Baz2"})
   2.212 +        @ExpectedTypeParameterAnnotations(typeParameterName="Z", annotations={})
   2.213 +        <@Foo1 @Bar1 @Baz1 W, X, @Foo2 @Bar2 @Baz2 Y, Z> Clazz() { }
   2.214      }
   2.215  
   2.216 -    final int expect = 5;  // top level class, plus preceding examples
   2.217 +    final int expect = 5 * 4;  // top level class, plus preceding examples, 4 type variables each
   2.218  }
   2.219  
   2.220  @Target(ElementType.TYPE_PARAMETER)
   2.221 -@interface Foo {}
   2.222 +@interface Foo1 {}
   2.223  
   2.224  @Target(ElementType.TYPE_PARAMETER)
   2.225 -@interface Bar {}
   2.226 +@interface Bar1 {}
   2.227  
   2.228  @Target(ElementType.TYPE_PARAMETER)
   2.229 -@interface Baz {}
   2.230 +@interface Baz1 {}
   2.231 +
   2.232 +@Target(ElementType.TYPE_PARAMETER)
   2.233 +@interface Foo2 {}
   2.234 +
   2.235 +@Target(ElementType.TYPE_PARAMETER)
   2.236 +@interface Bar2 {}
   2.237 +
   2.238 +@Target(ElementType.TYPE_PARAMETER)
   2.239 +@interface Baz2 {}
   2.240 +
   2.241 +@Repeatable(ExpectedTypeParameterAnnotationsCollection.class)
   2.242 +@interface ExpectedTypeParameterAnnotations {
   2.243 +    public String typeParameterName();
   2.244 +    public String[] annotations();
   2.245 +}
   2.246 +
   2.247 +@interface ExpectedTypeParameterAnnotationsCollection {
   2.248 +    public ExpectedTypeParameterAnnotations[] value();
   2.249 +}

mercurial