21 * questions. |
21 * questions. |
22 */ |
22 */ |
23 |
23 |
24 /* |
24 /* |
25 * @test |
25 * @test |
26 * @bug 8011027 |
26 * @bug 8011027 8046916 |
27 * @library /tools/javac/lib |
27 * @library /tools/javac/lib |
28 * @build JavacTestingAbstractProcessor TestTypeParameterAnnotations |
28 * @build JavacTestingAbstractProcessor TestTypeParameterAnnotations |
29 * @compile -processor TestTypeParameterAnnotations -proc:only TestTypeParameterAnnotations.java |
29 * @compile -processor TestTypeParameterAnnotations -proc:only TestTypeParameterAnnotations.java |
30 */ |
30 */ |
31 |
31 |
32 import java.util.*; |
32 import java.util.*; |
33 import java.lang.annotation.*; |
33 import java.lang.annotation.*; |
34 import javax.annotation.processing.*; |
34 import javax.annotation.processing.*; |
35 import javax.lang.model.element.*; |
35 import javax.lang.model.element.*; |
36 import javax.lang.model.util.*; |
|
37 import javax.tools.*; |
36 import javax.tools.*; |
38 |
37 |
39 public class TestTypeParameterAnnotations<@Foo @Bar @Baz T> extends JavacTestingAbstractProcessor { |
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 { |
40 int round = 0; |
46 int round = 0; |
41 |
47 |
42 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
48 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
43 if (++round == 1) { |
49 if (++round == 1) { |
44 int found = (new Scanner()).scan(roundEnv.getRootElements(), null); |
50 int found = (new Scanner()).scan(roundEnv.getRootElements(), null); |
72 } |
78 } |
73 |
79 |
74 int check(Element e, List<? extends TypeParameterElement> typarams) { |
80 int check(Element e, List<? extends TypeParameterElement> typarams) { |
75 if (typarams.isEmpty()) |
81 if (typarams.isEmpty()) |
76 return 0; |
82 return 0; |
77 if (typarams.size() != 1) |
83 |
78 return 0; |
84 for (TypeParameterElement tpe : typarams) { |
79 |
85 ExpectedTypeParameterAnnotations expected = null; |
80 for (TypeParameterElement tpe: typarams) { |
86 for (ExpectedTypeParameterAnnotations a : e.getAnnotationsByType(ExpectedTypeParameterAnnotations.class)) { |
81 boolean b1 = checkAnnotationMirrors(tpe, tpe.getAnnotationMirrors()); |
87 if (tpe.getSimpleName().contentEquals(a.typeParameterName())) { |
82 boolean b2 = checkAnnotationMirrors(tpe, elements.getAllAnnotationMirrors(tpe)); |
88 expected = a; |
83 boolean b3 = checkGetAnnotation(tpe); |
89 break; |
84 boolean b4 = checkGetAnnotations(tpe); |
90 } |
85 return b1 && b2 && b3 && b4 ? 1 : 0; |
91 } |
86 } |
92 if (expected == null) { |
87 return 0; |
93 throw new IllegalStateException("Does not have expected values annotation."); |
88 } |
94 } |
89 |
95 checkAnnotationMirrors(tpe, tpe.getAnnotationMirrors(), expected); |
90 boolean checkAnnotationMirrors(TypeParameterElement tpe, List<? extends AnnotationMirror> l) { |
96 checkAnnotationMirrors(tpe, elements.getAllAnnotationMirrors(tpe), expected); |
91 if (l.size() != 3) { |
97 checkGetAnnotation(tpe, expected); |
92 error("To few annotations, got " + l.size() + |
98 checkGetAnnotations(tpe, expected); |
93 ", should be 3", tpe); |
99 } |
94 return false; |
100 |
95 } |
101 return typarams.size(); |
96 |
102 } |
97 AnnotationMirror m = l.get(0); |
103 |
98 if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Foo"))) { |
104 void checkAnnotationMirrors(TypeParameterElement tpe, List<? extends AnnotationMirror> l, ExpectedTypeParameterAnnotations expected) { |
99 error("Wrong type of annotation, was expecting @Foo", m.getAnnotationType().asElement()); |
105 String[] expectedAnnotations = expected.annotations(); |
100 return false; |
106 |
101 } |
107 if (l.size() != expectedAnnotations.length) { |
102 m = l.get(1); |
108 error("Incorrect number of annotations, got " + l.size() + |
103 if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Bar"))) { |
109 ", should be " + expectedAnnotations.length, tpe); |
104 error("Wrong type of annotation, was expecting @Bar", m.getAnnotationType().asElement()); |
110 return ; |
105 return false; |
111 } |
106 } |
112 |
107 m = l.get(2); |
113 for (int i = 0; i < expectedAnnotations.length; i++) { |
108 if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Baz"))) { |
114 AnnotationMirror m = l.get(i); |
109 error("Wrong type of annotation, was expecting @Baz", m.getAnnotationType().asElement()); |
115 if (!m.getAnnotationType().asElement().equals(elements.getTypeElement(expectedAnnotations[i]))) { |
110 return false; |
116 error("Wrong type of annotation, was expecting @Foo", m.getAnnotationType().asElement()); |
111 } |
117 return ; |
112 return true; |
118 } |
113 } |
119 } |
114 |
120 } |
115 boolean checkGetAnnotation(TypeParameterElement tpe) { |
121 |
116 Foo f = tpe.getAnnotation(Foo.class); |
122 void checkGetAnnotation(TypeParameterElement tpe, ExpectedTypeParameterAnnotations expected) { |
117 if (f == null) |
123 List<String> expectedAnnotations = Arrays.asList(expected.annotations()); |
118 error("Expecting @Foo to be present in getAnnotation()", tpe); |
124 |
119 |
125 for (Class<? extends Annotation> c : ALL_ANNOTATIONS) { |
120 Bar b = tpe.getAnnotation(Bar.class); |
126 Object a = tpe.getAnnotation(c); |
121 if (b == null) |
127 |
122 error("Expecting @Bar to be present in getAnnotation()", tpe); |
128 if (a != null ^ expectedAnnotations.indexOf(c.getName()) != (-1)) { |
123 |
129 error("Unexpected behavior for " + c.getName(), tpe); |
124 Baz z = tpe.getAnnotation(Baz.class); |
130 return ; |
125 if (z == null) |
131 } |
126 error("Expecting @Baz to be present in getAnnotation()", tpe); |
132 } |
127 |
133 } |
128 return f != null && |
134 |
129 b != null && |
135 void checkGetAnnotations(TypeParameterElement tpe, ExpectedTypeParameterAnnotations expected) { |
130 z != null; |
136 List<String> expectedAnnotations = Arrays.asList(expected.annotations()); |
131 } |
137 |
132 |
138 for (Class<? extends Annotation> c : ALL_ANNOTATIONS) { |
133 boolean checkGetAnnotations(TypeParameterElement tpe) { |
139 Object[] a = tpe.getAnnotationsByType(c); |
134 Foo[] f = tpe.getAnnotationsByType(Foo.class); |
140 |
135 if (f.length != 1) { |
141 if (a.length > 0 ^ expectedAnnotations.indexOf(c.getName()) != (-1)) { |
136 error("Expecting 1 @Foo to be present in getAnnotationsByType()", tpe); |
142 error("Unexpected behavior for " + c.getName(), tpe); |
137 return false; |
143 return ; |
138 } |
144 } |
139 |
145 } |
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 } |
|
145 |
|
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 } |
|
151 |
|
152 return true; |
|
153 } |
146 } |
154 |
147 |
155 void note(String msg) { |
148 void note(String msg) { |
156 messager.printMessage(Diagnostic.Kind.NOTE, msg); |
149 messager.printMessage(Diagnostic.Kind.NOTE, msg); |
157 } |
150 } |
166 |
159 |
167 void error(String msg) { |
160 void error(String msg) { |
168 messager.printMessage(Diagnostic.Kind.ERROR, msg); |
161 messager.printMessage(Diagnostic.Kind.ERROR, msg); |
169 } |
162 } |
170 |
163 |
|
164 Class<? extends Annotation>[] ALL_ANNOTATIONS = new Class[] { |
|
165 Foo1.class, Bar1.class, Baz1.class, |
|
166 Foo2.class, Bar2.class, Baz2.class, |
|
167 }; |
|
168 |
171 // additional generic elements to test |
169 // additional generic elements to test |
172 <@Foo @Bar @Baz X> X m(X x) { return x; } |
170 @ExpectedTypeParameterAnnotations(typeParameterName="W", |
173 |
171 annotations={"Foo1", "Bar1", "Baz1"}) |
174 interface Intf<@Foo @Bar @Baz X> { X m() ; } |
172 @ExpectedTypeParameterAnnotations(typeParameterName="X", annotations={}) |
175 |
173 @ExpectedTypeParameterAnnotations(typeParameterName="Y", |
176 class Class<@Foo @Bar @Baz X> { |
174 annotations={"Foo2", "Bar2", "Baz2"}) |
177 <@Foo @Bar @Baz Y> Class() { } |
175 @ExpectedTypeParameterAnnotations(typeParameterName="Z", annotations={}) |
178 } |
176 <@Foo1 @Bar1 @Baz1 W, X, @Foo2 @Bar2 @Baz2 Y, Z> X m(X x) { return x; } |
179 |
177 |
180 final int expect = 5; // top level class, plus preceding examples |
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() ; } |
|
185 |
|
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 } |
|
201 |
|
202 final int expect = 5 * 4; // top level class, plus preceding examples, 4 type variables each |
181 } |
203 } |
182 |
204 |
183 @Target(ElementType.TYPE_PARAMETER) |
205 @Target(ElementType.TYPE_PARAMETER) |
184 @interface Foo {} |
206 @interface Foo1 {} |
185 |
207 |
186 @Target(ElementType.TYPE_PARAMETER) |
208 @Target(ElementType.TYPE_PARAMETER) |
187 @interface Bar {} |
209 @interface Bar1 {} |
188 |
210 |
189 @Target(ElementType.TYPE_PARAMETER) |
211 @Target(ElementType.TYPE_PARAMETER) |
190 @interface Baz {} |
212 @interface Baz1 {} |
|
213 |
|
214 @Target(ElementType.TYPE_PARAMETER) |
|
215 @interface Foo2 {} |
|
216 |
|
217 @Target(ElementType.TYPE_PARAMETER) |
|
218 @interface Bar2 {} |
|
219 |
|
220 @Target(ElementType.TYPE_PARAMETER) |
|
221 @interface Baz2 {} |
|
222 |
|
223 @Repeatable(ExpectedTypeParameterAnnotationsCollection.class) |
|
224 @interface ExpectedTypeParameterAnnotations { |
|
225 public String typeParameterName(); |
|
226 public String[] annotations(); |
|
227 } |
|
228 |
|
229 @interface ExpectedTypeParameterAnnotationsCollection { |
|
230 public ExpectedTypeParameterAnnotations[] value(); |
|
231 } |