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
30import java.util.*;
31import java.lang.annotation.*;
32import java.lang.reflect.*;
33import java.io.Serializable;
34
35public class TypeAnnotationReflection {
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
55    private static void check(boolean b) {
56        if (!b)
57            throw new RuntimeException();
58    }
59
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
574class Params {
575    public void noParams() {}
576    public void onlyAnnotated(@TypeAnno("1") String s1, @TypeAnno("2") String s2, @TypeAnno("3a") @TypeAnno2("3b") String s3) {}
577    public void mixed(@TypeAnno("1") String s1, String s2, @TypeAnno("3a") @TypeAnno2("3b") String s3) {}
578    public void unAnnotated(String s1, String s2, String s3) {}
579}
580
581abstract class TestWildcardType {
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
588abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> {
589    public ParameterizedOuter<String>.ParameterizedInner<Integer> foo() {return null;}
590    public @TypeAnno("O") ParameterizedOuter<@TypeAnno("S1") @TypeAnno2("S2") String>.
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
599class ParameterizedOuter <T> {
600    class ParameterizedInner <U> {}
601}
602
603abstract 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 {
607    public @TypeAnno("return4") Object @TypeAnno("return1") [][] @TypeAnno("return3")[] foo() { return null; }
608}
609
610abstract class TestClassNested {
611    public @TypeAnno("Outer") Outer.@TypeAnno("Inner")Inner @TypeAnno("array")[] foo() { return null; }
612}
613
614class Outer {
615    class Inner {
616    }
617}
618
619abstract class TestClassException {
620    public Object foo() throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException,
621                                                                 NullPointerException,
622                                             @TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException {
623        return null;
624    }
625}
626
627abstract 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
634    public @TypeAnno("t1") @TypeAnno2("t2") T foo(){ return null; }
635    public <M extends @TypeAnno("M Runnable") Runnable> M foo2() {return null;}
636    public <@TypeAnno("K") K extends Cloneable, L> K foo3() {return null;}
637    public <L> L foo4() {return null;}
638}
639
640@Target(ElementType.TYPE_USE)
641@Retention(RetentionPolicy.RUNTIME)
642@interface TypeAnno {
643    String value();
644}
645
646@Target(ElementType.TYPE_USE)
647@Retention(RetentionPolicy.RUNTIME)
648@interface TypeAnno2 {
649    String value();
650}
651