test/tools/javac/processing/model/element/TestTypeParameterAnnotations.java

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

author
jlahoda
date
Wed, 18 Jun 2014 10:44:16 +0200
changeset 2427
a3ad6e2ede44
parent 1709
bae8387d16aa
child 2525
2eb010b6cb22
permissions
-rw-r--r--

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

     1 /*
     2  * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 /*
    25  * @test
    26  * @bug 8011027 8046916
    27  * @library /tools/javac/lib
    28  * @build JavacTestingAbstractProcessor TestTypeParameterAnnotations
    29  * @compile -processor TestTypeParameterAnnotations -proc:only TestTypeParameterAnnotations.java
    30  */
    32 import java.util.*;
    33 import java.lang.annotation.*;
    34 import javax.annotation.processing.*;
    35 import javax.lang.model.element.*;
    36 import javax.tools.*;
    38 @ExpectedTypeParameterAnnotations(typeParameterName="T1",
    39                                   annotations={"Foo1", "Bar1", "Baz1"})
    40 @ExpectedTypeParameterAnnotations(typeParameterName="T2", annotations={})
    41 @ExpectedTypeParameterAnnotations(typeParameterName="T3",
    42                                   annotations={"Foo2", "Bar2", "Baz2"})
    43 @ExpectedTypeParameterAnnotations(typeParameterName="T4", annotations={})
    44 public class TestTypeParameterAnnotations<@Foo1 @Bar1 @Baz1 T1, T2, @Foo2 @Bar2 @Baz2 T3, T4> extends
    45         JavacTestingAbstractProcessor {
    46     int round = 0;
    48     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    49         if (++round == 1) {
    50             int found = (new Scanner()).scan(roundEnv.getRootElements(), null);
    51             if (found == expect) {
    52                 ; //nop
    53             } else {
    54                 error("unexpected number of results: expected " + expect
    55                         + ", found " + found);
    56             }
    58         }
    59         return true;
    60     }
    62     class Scanner extends JavacTestingAbstractProcessor.ElementScanner<Integer,Void> {
    63         @Override
    64         public Integer visitExecutable(ExecutableElement e, Void p) {
    65             super.visitExecutable(e, p);
    66             found += check(e, e.getTypeParameters());
    67             return found;
    68         }
    70         @Override
    71         public Integer visitType(TypeElement e, Void p) {
    72             super.visitType(e, p);
    73             found += check(e, e.getTypeParameters());
    74             return found;
    75         }
    77         int found;
    78     }
    80     int check(Element e, List<? extends TypeParameterElement> typarams) {
    81         if (typarams.isEmpty())
    82             return 0;
    84         for (TypeParameterElement tpe : typarams) {
    85             ExpectedTypeParameterAnnotations expected = null;
    86             for (ExpectedTypeParameterAnnotations a : e.getAnnotationsByType(ExpectedTypeParameterAnnotations.class)) {
    87                 if (tpe.getSimpleName().contentEquals(a.typeParameterName())) {
    88                     expected = a;
    89                     break;
    90                 }
    91             }
    92             if (expected == null) {
    93                 throw new IllegalStateException("Does not have expected values annotation.");
    94             }
    95             checkAnnotationMirrors(tpe, tpe.getAnnotationMirrors(), expected);
    96             checkAnnotationMirrors(tpe, elements.getAllAnnotationMirrors(tpe), expected);
    97             checkGetAnnotation(tpe, expected);
    98             checkGetAnnotations(tpe, expected);
    99         }
   101         return typarams.size();
   102     }
   104     void checkAnnotationMirrors(TypeParameterElement tpe, List<? extends AnnotationMirror> l, ExpectedTypeParameterAnnotations expected) {
   105         String[] expectedAnnotations = expected.annotations();
   107         if (l.size() != expectedAnnotations.length) {
   108             error("Incorrect number of annotations, got " + l.size() +
   109                     ", should be " + expectedAnnotations.length, tpe);
   110             return ;
   111         }
   113         for (int i = 0; i < expectedAnnotations.length; i++) {
   114             AnnotationMirror m = l.get(i);
   115             if (!m.getAnnotationType().asElement().equals(elements.getTypeElement(expectedAnnotations[i]))) {
   116                 error("Wrong type of annotation, was expecting @Foo", m.getAnnotationType().asElement());
   117                 return ;
   118             }
   119         }
   120     }
   122     void checkGetAnnotation(TypeParameterElement tpe, ExpectedTypeParameterAnnotations expected) {
   123         List<String> expectedAnnotations = Arrays.asList(expected.annotations());
   125         for (Class<? extends Annotation> c : ALL_ANNOTATIONS) {
   126             Object a = tpe.getAnnotation(c);
   128             if (a != null ^ expectedAnnotations.indexOf(c.getName()) != (-1)) {
   129                 error("Unexpected behavior for " + c.getName(), tpe);
   130                 return ;
   131             }
   132         }
   133     }
   135     void checkGetAnnotations(TypeParameterElement tpe, ExpectedTypeParameterAnnotations expected) {
   136         List<String> expectedAnnotations = Arrays.asList(expected.annotations());
   138         for (Class<? extends Annotation> c : ALL_ANNOTATIONS) {
   139             Object[] a = tpe.getAnnotationsByType(c);
   141             if (a.length > 0 ^ expectedAnnotations.indexOf(c.getName()) != (-1)) {
   142                 error("Unexpected behavior for " + c.getName(), tpe);
   143                 return ;
   144             }
   145         }
   146     }
   148     void note(String msg) {
   149         messager.printMessage(Diagnostic.Kind.NOTE, msg);
   150     }
   152     void note(String msg, Element e) {
   153         messager.printMessage(Diagnostic.Kind.NOTE, msg, e);
   154     }
   156     void error(String msg, Element e) {
   157         messager.printMessage(Diagnostic.Kind.ERROR, msg, e);
   158     }
   160     void error(String msg) {
   161         messager.printMessage(Diagnostic.Kind.ERROR, msg);
   162     }
   164     Class<? extends Annotation>[] ALL_ANNOTATIONS = new Class[] {
   165         Foo1.class, Bar1.class, Baz1.class,
   166         Foo2.class, Bar2.class, Baz2.class,
   167     };
   169     // additional generic elements to test
   170     @ExpectedTypeParameterAnnotations(typeParameterName="W",
   171                                       annotations={"Foo1", "Bar1", "Baz1"})
   172     @ExpectedTypeParameterAnnotations(typeParameterName="X", annotations={})
   173     @ExpectedTypeParameterAnnotations(typeParameterName="Y",
   174                                       annotations={"Foo2", "Bar2", "Baz2"})
   175     @ExpectedTypeParameterAnnotations(typeParameterName="Z", annotations={})
   176     <@Foo1 @Bar1 @Baz1 W, X, @Foo2 @Bar2 @Baz2 Y, Z> X m(X x) { return x; }
   178     @ExpectedTypeParameterAnnotations(typeParameterName="W",
   179                                       annotations={"Foo1", "Bar1", "Baz1"})
   180     @ExpectedTypeParameterAnnotations(typeParameterName="X", annotations={})
   181     @ExpectedTypeParameterAnnotations(typeParameterName="Y",
   182                                       annotations={"Foo2", "Bar2", "Baz2"})
   183     @ExpectedTypeParameterAnnotations(typeParameterName="Z", annotations={})
   184     interface Intf<@Foo1 @Bar1 @Baz1 W, X, @Foo2 @Bar2 @Baz2 Y, Z> { X m() ; }
   186     @ExpectedTypeParameterAnnotations(typeParameterName="W",
   187                                       annotations={"Foo1", "Bar1", "Baz1"})
   188     @ExpectedTypeParameterAnnotations(typeParameterName="X", annotations={})
   189     @ExpectedTypeParameterAnnotations(typeParameterName="Y",
   190                                       annotations={"Foo2", "Bar2", "Baz2"})
   191     @ExpectedTypeParameterAnnotations(typeParameterName="Z", annotations={})
   192     class Clazz<@Foo1 @Bar1 @Baz1 W, X, @Foo2 @Bar2 @Baz2 Y, Z> {
   193         @ExpectedTypeParameterAnnotations(typeParameterName="W",
   194                                           annotations={"Foo1", "Bar1", "Baz1"})
   195         @ExpectedTypeParameterAnnotations(typeParameterName="X", annotations={})
   196         @ExpectedTypeParameterAnnotations(typeParameterName="Y",
   197                                           annotations={"Foo2", "Bar2", "Baz2"})
   198         @ExpectedTypeParameterAnnotations(typeParameterName="Z", annotations={})
   199         <@Foo1 @Bar1 @Baz1 W, X, @Foo2 @Bar2 @Baz2 Y, Z> Clazz() { }
   200     }
   202     final int expect = 5 * 4;  // top level class, plus preceding examples, 4 type variables each
   203 }
   205 @Target(ElementType.TYPE_PARAMETER)
   206 @interface Foo1 {}
   208 @Target(ElementType.TYPE_PARAMETER)
   209 @interface Bar1 {}
   211 @Target(ElementType.TYPE_PARAMETER)
   212 @interface Baz1 {}
   214 @Target(ElementType.TYPE_PARAMETER)
   215 @interface Foo2 {}
   217 @Target(ElementType.TYPE_PARAMETER)
   218 @interface Bar2 {}
   220 @Target(ElementType.TYPE_PARAMETER)
   221 @interface Baz2 {}
   223 @Repeatable(ExpectedTypeParameterAnnotationsCollection.class)
   224 @interface ExpectedTypeParameterAnnotations {
   225     public String typeParameterName();
   226     public String[] annotations();
   227 }
   229 @interface ExpectedTypeParameterAnnotationsCollection {
   230     public ExpectedTypeParameterAnnotations[] value();
   231 }

mercurial