1 /*
2  * Copyright (c) 2013, 2015, 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  */
23 
24 /*
25  * @test
26  * @bug 8004698 8007073 8022343 8054304 8057804 8058595
27  * @summary Unit test for type annotations
28  */
29 
30 import java.util.*;
31 import java.lang.annotation.*;
32 import java.lang.reflect.*;
33 import java.io.Serializable;
34 
35 public class TypeAnnotationReflection {
main(String[] args)36     public static void main(String[] args) throws Exception {
37         testSuper();
38         testInterfaces();
39         testReturnType();
40         testNested();
41         testArray();
42         testRunException();
43         testClassTypeVarBounds();
44         testMethodTypeVarBounds();
45         testFields();
46         testClassTypeVar();
47         testMethodTypeVar();
48         testParameterizedType();
49         testNestedParameterizedType();
50         testWildcardType();
51         testParameterTypes();
52         testParameterType();
53     }
54 
check(boolean b)55     private static void check(boolean b) {
56         if (!b)
57             throw new RuntimeException();
58     }
59 
testSuper()60     private static void testSuper() throws Exception {
61         check(Object.class.getAnnotatedSuperclass() == null);
62         check(Class.class.getAnnotatedSuperclass().getAnnotations().length == 0);
63 
64         AnnotatedType a;
65         a = TestClassArray.class.getAnnotatedSuperclass();
66         Annotation[] annos = a.getAnnotations();
67         check(annos.length == 2);
68         check(annos[0].annotationType().equals(TypeAnno.class));
69         check(annos[1].annotationType().equals(TypeAnno2.class));
70         check(((TypeAnno)annos[0]).value().equals("extends"));
71         check(((TypeAnno2)annos[1]).value().equals("extends2"));
72     }
73 
testInterfaces()74     private static void testInterfaces() throws Exception {
75         AnnotatedType[] as;
76         as = TestClassArray.class.getAnnotatedInterfaces();
77         check(as.length == 3);
78         check(as[1].getAnnotations().length == 0);
79 
80         Annotation[] annos;
81         annos = as[0].getAnnotations();
82         check(annos.length == 2);
83         check(annos[0].annotationType().equals(TypeAnno.class));
84         check(annos[1].annotationType().equals(TypeAnno2.class));
85         check(((TypeAnno)annos[0]).value().equals("implements serializable"));
86         check(((TypeAnno2)annos[1]).value().equals("implements2 serializable"));
87 
88         annos = as[2].getAnnotations();
89         check(annos.length == 2);
90         check(annos[0].annotationType().equals(TypeAnno.class));
91         check(annos[1].annotationType().equals(TypeAnno2.class));
92         check(((TypeAnno)annos[0]).value().equals("implements cloneable"));
93         check(((TypeAnno2)annos[1]).value().equals("implements2 cloneable"));
94     }
95 
testReturnType()96     private static void testReturnType() throws Exception {
97         Method m = TestClassArray.class.getDeclaredMethod("foo", (Class<?>[])null);
98         Annotation[] annos = m.getAnnotatedReturnType().getAnnotations();
99         check(annos.length == 1);
100         check(annos[0].annotationType().equals(TypeAnno.class));
101         check(((TypeAnno)annos[0]).value().equals("return1"));
102     }
103 
testNested()104     private static void testNested() throws Exception {
105         Method m = TestClassNested.class.getDeclaredMethod("foo", (Class<?>[])null);
106         Annotation[] annos = m.getAnnotatedReturnType().getAnnotations();
107         check(annos.length == 1);
108         check(annos[0].annotationType().equals(TypeAnno.class));
109         check(((TypeAnno)annos[0]).value().equals("array"));
110 
111         AnnotatedType t = m.getAnnotatedReturnType();
112         t = ((AnnotatedArrayType)t).getAnnotatedGenericComponentType();
113         annos = t.getAnnotations();
114         check(annos.length == 1);
115         check(annos[0].annotationType().equals(TypeAnno.class));
116         check(((TypeAnno)annos[0]).value().equals("Inner"));
117     }
118 
testArray()119     private static void testArray() throws Exception {
120         Method m = TestClassArray.class.getDeclaredMethod("foo", (Class<?>[])null);
121         AnnotatedArrayType t = (AnnotatedArrayType) m.getAnnotatedReturnType();
122         Annotation[] annos = t.getAnnotations();
123         check(annos.length == 1);
124         check(annos[0].annotationType().equals(TypeAnno.class));
125         check(((TypeAnno)annos[0]).value().equals("return1"));
126 
127         t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType();
128         annos = t.getAnnotations();
129         check(annos.length == 0);
130 
131         t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType();
132         annos = t.getAnnotations();
133         check(annos.length == 1);
134         check(annos[0].annotationType().equals(TypeAnno.class));
135         check(((TypeAnno)annos[0]).value().equals("return3"));
136 
137         AnnotatedType tt = t.getAnnotatedGenericComponentType();
138         check(!(tt instanceof AnnotatedArrayType));
139         annos = tt.getAnnotations();
140         check(annos.length == 1);
141         check(annos[0].annotationType().equals(TypeAnno.class));
142         check(((TypeAnno)annos[0]).value().equals("return4"));
143     }
144 
testRunException()145     private static void testRunException() throws Exception {
146         Method m = TestClassException.class.getDeclaredMethod("foo", (Class<?>[])null);
147         AnnotatedType[] ts = m.getAnnotatedExceptionTypes();
148         check(ts.length == 3);
149 
150         AnnotatedType t;
151         Annotation[] annos;
152         t = ts[0];
153         annos = t.getAnnotations();
154         check(annos.length == 2);
155         check(annos[0].annotationType().equals(TypeAnno.class));
156         check(annos[1].annotationType().equals(TypeAnno2.class));
157         check(((TypeAnno)annos[0]).value().equals("RE"));
158         check(((TypeAnno2)annos[1]).value().equals("RE2"));
159 
160         t = ts[1];
161         annos = t.getAnnotations();
162         check(annos.length == 0);
163 
164         t = ts[2];
165         annos = t.getAnnotations();
166         check(annos.length == 1);
167         check(annos[0].annotationType().equals(TypeAnno.class));
168         check(((TypeAnno)annos[0]).value().equals("AIOOBE"));
169     }
170 
testClassTypeVarBounds()171     private static void testClassTypeVarBounds() throws Exception {
172         Method m = TestClassTypeVarAndField.class.getDeclaredMethod("foo", (Class<?>[])null);
173         AnnotatedType ret = m.getAnnotatedReturnType();
174         Annotation[] annos = ret.getAnnotations();
175         check(annos.length == 2);
176 
177         AnnotatedType[] annotatedBounds = ((AnnotatedTypeVariable)ret).getAnnotatedBounds();
178         check(annotatedBounds.length == 2);
179 
180         annos = annotatedBounds[0].getAnnotations();
181         check(annos.length == 1);
182         check(annos[0].annotationType().equals(TypeAnno.class));
183         check(((TypeAnno)annos[0]).value().equals("Object1"));
184 
185         annos = annotatedBounds[1].getAnnotations();
186         check(annos.length == 2);
187         check(annos[0].annotationType().equals(TypeAnno.class));
188         check(annos[1].annotationType().equals(TypeAnno2.class));
189         check(((TypeAnno)annos[0]).value().equals("Runnable1"));
190         check(((TypeAnno2)annos[1]).value().equals("Runnable2"));
191     }
192 
testMethodTypeVarBounds()193     private static void testMethodTypeVarBounds() throws Exception {
194         Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class<?>[])null);
195         AnnotatedType ret2 = m2.getAnnotatedReturnType();
196         AnnotatedType[] annotatedBounds2 = ((AnnotatedTypeVariable)ret2).getAnnotatedBounds();
197         check(annotatedBounds2.length == 1);
198 
199         Annotation[] annos = annotatedBounds2[0].getAnnotations();
200         check(annos.length == 1);
201         check(annos[0].annotationType().equals(TypeAnno.class));
202         check(((TypeAnno)annos[0]).value().equals("M Runnable"));
203 
204         // Check that AnnotatedTypeVariable.getAnnotatedBounds() returns jlO for a naked
205         // type variable (i.e no bounds, no annotations)
206         Method m4 = TestClassTypeVarAndField.class.getDeclaredMethod("foo4", (Class<?>[])null);
207         AnnotatedType ret4 = m4.getAnnotatedReturnType();
208         AnnotatedType[] annotatedBounds4 = ((AnnotatedTypeVariable)ret4).getAnnotatedBounds();
209         check(annotatedBounds4.length == 1);
210 
211         annos = annotatedBounds4[0].getAnnotations();
212         check(annos.length == 0);
213         check(annotatedBounds4[0].getType().equals(Object.class));
214     }
215 
testFields()216     private static void testFields() throws Exception {
217         Field f1 = TestClassTypeVarAndField.class.getDeclaredField("field1");
218         AnnotatedType at;
219         Annotation[] annos;
220 
221         at = f1.getAnnotatedType();
222         annos = at.getAnnotations();
223         check(annos.length == 2);
224         check(annos[0].annotationType().equals(TypeAnno.class));
225         check(annos[1].annotationType().equals(TypeAnno2.class));
226         check(((TypeAnno)annos[0]).value().equals("T1 field"));
227         check(((TypeAnno2)annos[1]).value().equals("T2 field"));
228 
229         Field f2 = TestClassTypeVarAndField.class.getDeclaredField("field2");
230         at = f2.getAnnotatedType();
231         annos = at.getAnnotations();
232         check(annos.length == 0);
233 
234         Field f3 = TestClassTypeVarAndField.class.getDeclaredField("field3");
235         at = f3.getAnnotatedType();
236         annos = at.getAnnotations();
237         check(annos.length == 1);
238         check(annos[0].annotationType().equals(TypeAnno.class));
239         check(((TypeAnno)annos[0]).value().equals("Object field"));
240     }
241 
testClassTypeVar()242     private static void testClassTypeVar() throws Exception {
243         TypeVariable[] typeVars = TestClassTypeVarAndField.class.getTypeParameters();
244         Annotation[] annos;
245         check(typeVars.length == 3);
246 
247         // First TypeVar
248         AnnotatedType[] annotatedBounds = typeVars[0].getAnnotatedBounds();
249         check(annotatedBounds.length == 2);
250 
251         annos = annotatedBounds[0].getAnnotations();
252         check(annos.length == 1);
253         check(annos[0].annotationType().equals(TypeAnno.class));
254         check(((TypeAnno)annos[0]).value().equals("Object1"));
255 
256         annos = annotatedBounds[1].getAnnotations();
257         check(annos.length == 2);
258         check(annos[0].annotationType().equals(TypeAnno.class));
259         check(annos[1].annotationType().equals(TypeAnno2.class));
260         check(((TypeAnno)annos[0]).value().equals("Runnable1"));
261         check(((TypeAnno2)annos[1]).value().equals("Runnable2"));
262 
263         // second TypeVar regular anno
264         Annotation[] regularAnnos = typeVars[1].getAnnotations();
265         check(regularAnnos.length == 1);
266         check(typeVars[1].getAnnotation(TypeAnno.class).value().equals("EE"));
267 
268         // second TypeVar
269         annotatedBounds = typeVars[1].getAnnotatedBounds();
270         check(annotatedBounds.length == 1);
271 
272         annos = annotatedBounds[0].getAnnotations();
273         check(annos.length == 1);
274         check(annos[0].annotationType().equals(TypeAnno2.class));
275         check(((TypeAnno2)annos[0]).value().equals("EEBound"));
276 
277         // third Typevar V declared without explicit bounds should see jlO as its bound.
278         annotatedBounds = typeVars[2].getAnnotatedBounds();
279         check(annotatedBounds.length == 1);
280 
281         annos = annotatedBounds[0].getAnnotations();
282         check(annos.length == 0);
283         check(annotatedBounds[0].getType().equals(Object.class));
284     }
285 
testMethodTypeVar()286     private static void testMethodTypeVar() throws Exception {
287         Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class<?>[])null);
288         TypeVariable[] t = m2.getTypeParameters();
289         check(t.length == 1);
290         Annotation[] annos = t[0].getAnnotations();
291         check(annos.length == 0);
292 
293         AnnotatedType[] annotatedBounds2 = t[0].getAnnotatedBounds();
294         check(annotatedBounds2.length == 1);
295 
296         annos = annotatedBounds2[0].getAnnotations();
297         check(annos.length == 1);
298         check(annos[0].annotationType().equals(TypeAnno.class));
299         check(((TypeAnno)annos[0]).value().equals("M Runnable"));
300 
301         // Second method
302         m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo3", (Class<?>[])null);
303         t = m2.getTypeParameters();
304         check(t.length == 2);
305         annos = t[0].getAnnotations();
306         check(annos.length == 1);
307         check(annos[0].annotationType().equals(TypeAnno.class));
308         check(((TypeAnno)annos[0]).value().equals("K"));
309 
310         annotatedBounds2 = t[0].getAnnotatedBounds();
311         check(annotatedBounds2.length == 1);
312 
313         annos = annotatedBounds2[0].getAnnotations();
314         check(annos.length == 0);
315 
316         // for the naked type variable L of foo3, we should see jlO as its bound.
317         annotatedBounds2 = t[1].getAnnotatedBounds();
318         check(annotatedBounds2.length == 1);
319         check(annotatedBounds2[0].getType().equals(Object.class));
320 
321         annos = annotatedBounds2[0].getAnnotations();
322         check(annos.length == 0);
323     }
324 
testParameterizedType()325     private static void testParameterizedType() {
326         // Base
327         AnnotatedType[] as;
328         as = TestParameterizedType.class.getAnnotatedInterfaces();
329         check(as.length == 1);
330         check(as[0].getAnnotations().length == 1);
331         check(as[0].getAnnotation(TypeAnno.class).value().equals("M"));
332 
333         Annotation[] annos;
334         as = ((AnnotatedParameterizedType)as[0]).getAnnotatedActualTypeArguments();
335         check(as.length == 2);
336         annos = as[0].getAnnotations();
337         check(annos.length == 1);
338         check(as[0].getAnnotation(TypeAnno.class).value().equals("S"));
339         check(as[0].getAnnotation(TypeAnno2.class) == null);
340 
341         annos = as[1].getAnnotations();
342         check(annos.length == 2);
343         check(((TypeAnno)annos[0]).value().equals("I"));
344         check(as[1].getAnnotation(TypeAnno2.class).value().equals("I2"));
345     }
346 
testNestedParameterizedType()347     private static void testNestedParameterizedType() throws Exception {
348         Method m = TestParameterizedType.class.getDeclaredMethod("foo2", (Class<?>[])null);
349         AnnotatedType ret = m.getAnnotatedReturnType();
350         Annotation[] annos;
351         annos = ret.getAnnotations();
352         check(annos.length == 1);
353         check(((TypeAnno)annos[0]).value().equals("I"));
354 
355         AnnotatedType[] args = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments();
356         check(args.length == 1);
357         annos = args[0].getAnnotations();
358         check(annos.length == 2);
359         check(((TypeAnno)annos[0]).value().equals("I1"));
360         check(args[0].getAnnotation(TypeAnno2.class).value().equals("I2"));
361 
362         // check type args
363         Field f = TestParameterizedType.class.getDeclaredField("theField");
364         AnnotatedParameterizedType fType = (AnnotatedParameterizedType)f.getAnnotatedType();
365         args = fType.getAnnotatedActualTypeArguments();
366         check(args.length == 1);
367         annos = args[0].getAnnotations();
368         check(annos.length == 1);
369         check(((TypeAnno2)annos[0]).value().equals("Map Arg"));
370         check(args[0].getAnnotation(TypeAnno2.class).value().equals("Map Arg"));
371 
372         // check outer type type args
373         fType = (AnnotatedParameterizedType)fType.getAnnotatedOwnerType();
374         args = fType.getAnnotatedActualTypeArguments();
375         check(args.length == 1);
376         annos = args[0].getAnnotations();
377         check(annos.length == 1);
378         check(((TypeAnno2)annos[0]).value().equals("String Arg"));
379         check(args[0].getAnnotation(TypeAnno2.class).value().equals("String Arg"));
380 
381         // check outer type normal type annotations
382         annos = fType.getAnnotations();
383         check(annos.length == 1);
384         check(((TypeAnno)annos[0]).value().equals("FieldOuter"));
385         check(fType.getAnnotation(TypeAnno.class).value().equals("FieldOuter"));
386     }
387 
testWildcardType()388     private static void testWildcardType() throws Exception {
389         Method m = TestWildcardType.class.getDeclaredMethod("foo", (Class<?>[])null);
390         AnnotatedType ret = m.getAnnotatedReturnType();
391         AnnotatedType[] t;
392         t = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments();
393         check(t.length == 1);
394         ret = t[0];
395 
396         Field f = TestWildcardType.class.getDeclaredField("f1");
397         AnnotatedWildcardType w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
398             .getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
399         t = w.getAnnotatedLowerBounds();
400         check(t.length == 0);
401         t = w.getAnnotatedUpperBounds();
402         check(t.length == 1);
403         Annotation[] annos;
404         annos = t[0].getAnnotations();
405         check(annos.length == 1);
406         check(((TypeAnno)annos[0]).value().equals("2"));
407 
408         f = TestWildcardType.class.getDeclaredField("f2");
409         w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
410             .getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
411         t = w.getAnnotatedUpperBounds();
412         check(t.length == 1);
413         check(t[0].getType().equals(Object.class));
414         annos = t[0].getAnnotations();
415         check(annos.length == 0);
416         t = w.getAnnotatedLowerBounds();
417         check(t.length == 1);
418 
419         // for an unbounded wildcard, we should see jlO as its upperbound and null type as its lower bound.
420         f = TestWildcardType.class.getDeclaredField("f3");
421         w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
422             .getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
423         t = w.getAnnotatedUpperBounds();
424         check(t.length == 1);
425         check(t[0].getType().equals(Object.class));
426         annos = t[0].getAnnotations();
427         check(annos.length == 0);
428         t = w.getAnnotatedLowerBounds();
429         check(t.length == 0);
430     }
431 
testParameterTypes()432     private static void testParameterTypes() throws Exception {
433         // NO PARAMS
434         Method m = Params.class.getDeclaredMethod("noParams", (Class<?>[])null);
435         AnnotatedType[] t = m.getAnnotatedParameterTypes();
436         check(t.length == 0);
437 
438         // ONLY ANNOTATED PARAM TYPES
439         Class[] argsArr = {String.class, String.class, String.class};
440         m = Params.class.getDeclaredMethod("onlyAnnotated", (Class<?>[])argsArr);
441         t = m.getAnnotatedParameterTypes();
442         check(t.length == 3);
443 
444         check(t[0].getAnnotations().length == 1);
445         check(t[0].getAnnotation(TypeAnno.class) != null);
446         check(t[0].getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
447 
448         check(t[1].getAnnotations().length == 1);
449         check(t[1].getAnnotation(TypeAnno.class) != null);
450         check(t[1].getAnnotationsByType(TypeAnno.class)[0].value().equals("2"));
451 
452         check(t[2].getAnnotations().length == 2);
453         check(t[2].getAnnotations()[0].annotationType().equals(TypeAnno.class));
454         check(t[2].getAnnotation(TypeAnno.class) != null);
455         check(t[2].getAnnotation(TypeAnno2.class) != null);
456         check(t[2].getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
457         check(t[2].getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
458 
459         // MIXED ANNOTATED PARAM TYPES
460         m = Params.class.getDeclaredMethod("mixed", (Class<?>[])argsArr);
461         t = m.getAnnotatedParameterTypes();
462         check(t.length == 3);
463 
464         check(t[0].getAnnotations().length == 1);
465         check(t[0].getAnnotation(TypeAnno.class) != null);
466         check(t[0].getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
467 
468         check(t[1].getAnnotations().length == 0);
469         check(t[1].getAnnotation(TypeAnno.class) == null);
470         check(t[1].getAnnotation(TypeAnno2.class) == null);
471 
472         check(t[2].getAnnotations().length == 2);
473         check(t[2].getAnnotations()[0].annotationType().equals(TypeAnno.class));
474         check(t[2].getAnnotation(TypeAnno.class) != null);
475         check(t[2].getAnnotation(TypeAnno2.class) != null);
476         check(t[2].getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
477         check(t[2].getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
478 
479         // NO ANNOTATED PARAM TYPES
480         m = Params.class.getDeclaredMethod("unAnnotated", (Class<?>[])argsArr);
481         t = m.getAnnotatedParameterTypes();
482         check(t.length == 3);
483 
484         check(t[0].getAnnotations().length == 0);
485         check(t[0].getAnnotation(TypeAnno.class) == null);
486         check(t[0].getAnnotation(TypeAnno2.class) == null);
487 
488         check(t[1].getAnnotations().length == 0);
489         check(t[1].getAnnotation(TypeAnno.class) == null);
490         check(t[1].getAnnotation(TypeAnno2.class) == null);
491 
492         check(t[2].getAnnotations().length == 0);
493         check(t[2].getAnnotation(TypeAnno.class) == null);
494         check(t[2].getAnnotation(TypeAnno2.class) == null);
495     }
496 
testParameterType()497     private static void testParameterType() throws Exception {
498         // NO PARAMS
499         Method m = Params.class.getDeclaredMethod("noParams", (Class<?>[])null);
500         Parameter[] p = m.getParameters();
501         check(p.length == 0);
502 
503         // ONLY ANNOTATED PARAM TYPES
504         Class[] argsArr = {String.class, String.class, String.class};
505         m = Params.class.getDeclaredMethod("onlyAnnotated", (Class<?>[])argsArr);
506         p = m.getParameters();
507         check(p.length == 3);
508         AnnotatedType t0 = p[0].getAnnotatedType();
509         AnnotatedType t1 = p[1].getAnnotatedType();
510         AnnotatedType t2 = p[2].getAnnotatedType();
511 
512         check(t0.getAnnotations().length == 1);
513         check(t0.getAnnotation(TypeAnno.class) != null);
514         check(t0.getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
515 
516         check(t1.getAnnotations().length == 1);
517         check(t1.getAnnotation(TypeAnno.class) != null);
518         check(t1.getAnnotationsByType(TypeAnno.class)[0].value().equals("2"));
519 
520         check(t2.getAnnotations().length == 2);
521         check(t2.getAnnotations()[0].annotationType().equals(TypeAnno.class));
522         check(t2.getAnnotation(TypeAnno.class) != null);
523         check(t2.getAnnotation(TypeAnno2.class) != null);
524         check(t2.getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
525         check(t2.getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
526 
527         // MIXED ANNOTATED PARAM TYPES
528         m = Params.class.getDeclaredMethod("mixed", (Class<?>[])argsArr);
529         p = m.getParameters();
530         check(p.length == 3);
531 
532         t0 = p[0].getAnnotatedType();
533         t1 = p[1].getAnnotatedType();
534         t2 = p[2].getAnnotatedType();
535 
536         check(t0.getAnnotations().length == 1);
537         check(t0.getAnnotation(TypeAnno.class) != null);
538         check(t0.getAnnotationsByType(TypeAnno.class)[0].value().equals("1"));
539 
540         check(t1.getAnnotations().length == 0);
541         check(t1.getAnnotation(TypeAnno.class) == null);
542         check(t1.getAnnotation(TypeAnno2.class) == null);
543 
544         check(t2.getAnnotations().length == 2);
545         check(t2.getAnnotations()[0].annotationType().equals(TypeAnno.class));
546         check(t2.getAnnotation(TypeAnno.class) != null);
547         check(t2.getAnnotation(TypeAnno2.class) != null);
548         check(t2.getAnnotationsByType(TypeAnno.class)[0].value().equals("3a"));
549         check(t2.getAnnotationsByType(TypeAnno2.class)[0].value().equals("3b"));
550 
551         // NO ANNOTATED PARAM TYPES
552         m = Params.class.getDeclaredMethod("unAnnotated", (Class<?>[])argsArr);
553         p = m.getParameters();
554         check(p.length == 3);
555 
556         t0 = p[0].getAnnotatedType();
557         t1 = p[1].getAnnotatedType();
558         t2 = p[2].getAnnotatedType();
559 
560         check(t0.getAnnotations().length == 0);
561         check(t0.getAnnotation(TypeAnno.class) == null);
562         check(t0.getAnnotation(TypeAnno2.class) == null);
563 
564         check(t1.getAnnotations().length == 0);
565         check(t1.getAnnotation(TypeAnno.class) == null);
566         check(t1.getAnnotation(TypeAnno2.class) == null);
567 
568         check(t2.getAnnotations().length == 0);
569         check(t2.getAnnotation(TypeAnno.class) == null);
570         check(t2.getAnnotation(TypeAnno2.class) == null);
571     }
572 }
573 
574 class Params {
noParams()575     public void noParams() {}
onlyAnnotated(@ypeAnnoR) String s1, @TypeAnno(R) String s2, @TypeAnno(R) @TypeAnno2(R) String s3)576     public void onlyAnnotated(@TypeAnno("1") String s1, @TypeAnno("2") String s2, @TypeAnno("3a") @TypeAnno2("3b") String s3) {}
mixed(@ypeAnnoR) String s1, String s2, @TypeAnno(R) @TypeAnno2(R) String s3)577     public void mixed(@TypeAnno("1") String s1, String s2, @TypeAnno("3a") @TypeAnno2("3b") String s3) {}
unAnnotated(String s1, String s2, String s3)578     public void unAnnotated(String s1, String s2, String s3) {}
579 }
580 
581 abstract class TestWildcardType {
foo()582     public <T> List<? super T> foo() { return null;}
583     public Class<@TypeAnno("1") ? extends @TypeAnno("2") Annotation> f1;
584     public Class<@TypeAnno("3") ? super @TypeAnno("4") Annotation> f2;
585     public Class<@TypeAnno("5") ?> f3;
586 }
587 
588 abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> {
foo()589     public ParameterizedOuter<String>.ParameterizedInner<Integer> foo() {return null;}
590     public @TypeAnno("O") ParameterizedOuter<@TypeAnno("S1") @TypeAnno2("S2") String>.
foo2()591             @TypeAnno("I") ParameterizedInner<@TypeAnno("I1") @TypeAnno2("I2")Integer> foo2() {
592         return null;
593     }
594 
595     public @TypeAnno("FieldOuter") ParameterizedOuter<@TypeAnno2("String Arg") String>.
596             @TypeAnno("FieldInner")ParameterizedInner<@TypeAnno2("Map Arg")Map> theField;
597 }
598 
599 class ParameterizedOuter <T> {
600     class ParameterizedInner <U> {}
601 }
602 
603 abstract class TestClassArray extends @TypeAnno("extends") @TypeAnno2("extends2") Object
604     implements @TypeAnno("implements serializable") @TypeAnno2("implements2 serializable") Serializable,
605     Readable,
606     @TypeAnno("implements cloneable") @TypeAnno2("implements2 cloneable") Cloneable {
foo()607     public @TypeAnno("return4") Object @TypeAnno("return1") [][] @TypeAnno("return3")[] foo() { return null; }
608 }
609 
610 abstract class TestClassNested {
foo()611     public @TypeAnno("Outer") Outer.@TypeAnno("Inner")Inner @TypeAnno("array")[] foo() { return null; }
612 }
613 
614 class Outer {
615     class Inner {
616     }
617 }
618 
619 abstract class TestClassException {
620     public Object foo() throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException,
621                                                                  NullPointerException,
622                                              @TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException {
623         return null;
624     }
625 }
626 
627 abstract class TestClassTypeVarAndField <T extends @TypeAnno("Object1") Object
628                                           & @TypeAnno("Runnable1") @TypeAnno2("Runnable2") Runnable,
629                                         @TypeAnno("EE")EE extends @TypeAnno2("EEBound") Runnable, V > {
630     @TypeAnno("T1 field") @TypeAnno2("T2 field") T field1;
631     T field2;
632     @TypeAnno("Object field") Object field3;
633 
foo()634     public @TypeAnno("t1") @TypeAnno2("t2") T foo(){ return null; }
foo2()635     public <M extends @TypeAnno("M Runnable") Runnable> M foo2() {return null;}
foo3()636     public <@TypeAnno("K") K extends Cloneable, L> K foo3() {return null;}
foo4()637     public <L> L foo4() {return null;}
638 }
639 
640 @Target(ElementType.TYPE_USE)
641 @Retention(RetentionPolicy.RUNTIME)
642 @interface TypeAnno {
value()643     String value();
644 }
645 
646 @Target(ElementType.TYPE_USE)
647 @Retention(RetentionPolicy.RUNTIME)
648 @interface TypeAnno2 {
value()649     String value();
650 }
651