Mon, 22 Apr 2013 10:24:19 +0200
8011027: Type parameter annotations not passed through to javax.lang.model
Reviewed-by: jjg, darcy
1 /*
2 * Copyright (c) 2013, 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
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.lang.model.util.*;
37 import javax.tools.*;
39 public class TestTypeParameterAnnotations<@Foo @Bar @Baz T> extends JavacTestingAbstractProcessor {
40 int round = 0;
42 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
43 if (++round == 1) {
44 int found = (new Scanner()).scan(roundEnv.getRootElements(), null);
45 if (found == expect) {
46 ; //nop
47 } else {
48 error("unexpected number of results: expected " + expect
49 + ", found " + found);
50 }
52 }
53 return true;
54 }
56 class Scanner extends JavacTestingAbstractProcessor.ElementScanner<Integer,Void> {
57 @Override
58 public Integer visitExecutable(ExecutableElement e, Void p) {
59 super.visitExecutable(e, p);
60 found += check(e, e.getTypeParameters());
61 return found;
62 }
64 @Override
65 public Integer visitType(TypeElement e, Void p) {
66 super.visitType(e, p);
67 found += check(e, e.getTypeParameters());
68 return found;
69 }
71 int found;
72 }
74 int check(Element e, List<? extends TypeParameterElement> typarams) {
75 if (typarams.isEmpty())
76 return 0;
77 if (typarams.size() != 1)
78 return 0;
80 for (TypeParameterElement tpe: typarams) {
81 boolean b1 = checkAnnotationMirrors(tpe, tpe.getAnnotationMirrors());
82 boolean b2 = checkAnnotationMirrors(tpe, elements.getAllAnnotationMirrors(tpe));
83 boolean b3 = checkGetAnnotation(tpe);
84 boolean b4 = checkGetAnnotations(tpe);
85 return b1 && b2 && b3 && b4 ? 1 : 0;
86 }
87 return 0;
88 }
90 boolean checkAnnotationMirrors(TypeParameterElement tpe, List<? extends AnnotationMirror> l) {
91 if (l.size() != 3) {
92 error("To few annotations, got " + l.size() +
93 ", should be 3", tpe);
94 return false;
95 }
97 AnnotationMirror m = l.get(0);
98 if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Foo"))) {
99 error("Wrong type of annotation, was expecting @Foo", m.getAnnotationType().asElement());
100 return false;
101 }
102 m = l.get(1);
103 if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Bar"))) {
104 error("Wrong type of annotation, was expecting @Bar", m.getAnnotationType().asElement());
105 return false;
106 }
107 m = l.get(2);
108 if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Baz"))) {
109 error("Wrong type of annotation, was expecting @Baz", m.getAnnotationType().asElement());
110 return false;
111 }
112 return true;
113 }
115 boolean checkGetAnnotation(TypeParameterElement tpe) {
116 Foo f = tpe.getAnnotation(Foo.class);
117 if (f == null)
118 error("Expecting @Foo to be present in getAnnotation()", tpe);
120 Bar b = tpe.getAnnotation(Bar.class);
121 if (b == null)
122 error("Expecting @Bar to be present in getAnnotation()", tpe);
124 Baz z = tpe.getAnnotation(Baz.class);
125 if (z == null)
126 error("Expecting @Baz to be present in getAnnotation()", tpe);
128 return f != null &&
129 b != null &&
130 z != null;
131 }
133 boolean checkGetAnnotations(TypeParameterElement tpe) {
134 Foo[] f = tpe.getAnnotationsByType(Foo.class);
135 if (f.length != 1) {
136 error("Expecting 1 @Foo to be present in getAnnotationsByType()", tpe);
137 return false;
138 }
140 Bar[] b = tpe.getAnnotationsByType(Bar.class);
141 if (b.length != 1) {
142 error("Expecting 1 @Bar to be present in getAnnotationsByType()", tpe);
143 return false;
144 }
146 Baz[] z = tpe.getAnnotationsByType(Baz.class);
147 if (z.length != 1) {
148 error("Expecting 1 @Baz to be present in getAnnotationsByType()", tpe);
149 return false;
150 }
152 return true;
153 }
155 void note(String msg) {
156 messager.printMessage(Diagnostic.Kind.NOTE, msg);
157 }
159 void note(String msg, Element e) {
160 messager.printMessage(Diagnostic.Kind.NOTE, msg, e);
161 }
163 void error(String msg, Element e) {
164 messager.printMessage(Diagnostic.Kind.ERROR, msg, e);
165 }
167 void error(String msg) {
168 messager.printMessage(Diagnostic.Kind.ERROR, msg);
169 }
171 // additional generic elements to test
172 <@Foo @Bar @Baz X> X m(X x) { return x; }
174 interface Intf<@Foo @Bar @Baz X> { X m() ; }
176 class Class<@Foo @Bar @Baz X> {
177 <@Foo @Bar @Baz Y> Class() { }
178 }
180 final int expect = 5; // top level class, plus preceding examples
181 }
183 @Target(ElementType.TYPE_PARAMETER)
184 @interface Foo {}
186 @Target(ElementType.TYPE_PARAMETER)
187 @interface Bar {}
189 @Target(ElementType.TYPE_PARAMETER)
190 @interface Baz {}