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 8013852 8031744
27 * @summary Annotations on types
28 * @library /tools/javac/lib
29 * @modules jdk.compiler/com.sun.tools.javac.api
30 *          jdk.compiler/com.sun.tools.javac.code
31 *          jdk.compiler/com.sun.tools.javac.processing
32 *          jdk.compiler/com.sun.tools.javac.tree
33 *          jdk.compiler/com.sun.tools.javac.util
34 * @build JavacTestingAbstractProcessor DPrinter BasicAnnoTests
35 * @compile/process -XDaccessInternalAPI -processor BasicAnnoTests -proc:only BasicAnnoTests.java
36 */
37
38import java.io.PrintWriter;
39import java.io.Serializable;
40import java.lang.annotation.Annotation;
41import java.lang.annotation.ElementType;
42import java.lang.annotation.Repeatable;
43import java.lang.annotation.Target;
44import java.util.ArrayList;
45
46import java.util.HashSet;
47import java.util.List;
48import java.util.Map;
49import java.util.NavigableMap;
50import java.util.Set;
51import java.util.TreeMap;
52
53import javax.annotation.processing.ProcessingEnvironment;
54import javax.annotation.processing.RoundEnvironment;
55import javax.lang.model.AnnotatedConstruct;
56import javax.lang.model.element.AnnotationMirror;
57import javax.lang.model.element.AnnotationValue;
58import javax.lang.model.element.Element;
59import javax.lang.model.element.ExecutableElement;
60import javax.lang.model.element.TypeElement;
61import javax.lang.model.type.ArrayType;
62import javax.lang.model.type.DeclaredType;
63import javax.lang.model.type.ExecutableType;
64import javax.lang.model.type.IntersectionType;
65import javax.lang.model.type.TypeMirror;
66import javax.lang.model.type.TypeVariable;
67import javax.lang.model.type.WildcardType;
68import javax.lang.model.util.Types;
69import javax.tools.Diagnostic.Kind;
70
71import com.sun.tools.javac.code.Attribute;
72import com.sun.tools.javac.code.Symbol;
73import com.sun.tools.javac.processing.JavacProcessingEnvironment;
74import com.sun.tools.javac.util.Name;
75
76import static com.sun.tools.javac.code.Attribute.Array;
77import static com.sun.tools.javac.code.Attribute.Constant;
78import static com.sun.tools.javac.code.Attribute.Compound;
79
80/**
81 * The test scans this file looking for test cases annotated with @Test.
82 */
83public class BasicAnnoTests extends JavacTestingAbstractProcessor {
84    DPrinter dprinter;
85    PrintWriter out;
86    boolean verbose = true;
87
88    @Override
89    public void init(ProcessingEnvironment pEnv) {
90        super.init(pEnv);
91        dprinter = new DPrinter(((JavacProcessingEnvironment) pEnv).getContext());
92        out = dprinter.out;
93    }
94
95    @Override
96    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
97        TestElementScanner s = new TestElementScanner();
98        for (Element e: roundEnv.getRootElements()) {
99            s.scan(e, null);
100        }
101        return true;
102    }
103
104    void error(Element e, String msg) {
105        messager.printMessage(Kind.ERROR, msg, e);
106        errors++;
107    }
108
109    int errors;
110
111    /**
112     * Scan an element looking for declarations annotated with @Test.
113     * Run a TestTypeScanner on the annotations that are found.
114     */
115    class TestElementScanner extends ElementScanner<Void,Void> {
116        public Void scan(Element elem, Void ignore) {
117            List<AnnotationMirror> tests = new ArrayList<>();
118            AnnotationMirror test = getAnnotation(elem, Test.class.getName().replace('$', '.'));
119            if (test != null) {
120                tests.add(test);
121            }
122            tests.addAll(getAnnotations(elem, Tests.class.getName().replace('$', '.')));
123
124            if (tests.size() > 0) {
125                out.println("Test: " + elem + " " + test);
126                TestTypeScanner s = new TestTypeScanner(elem, tests, types);
127                s.test(elem.asType());
128                out.println();
129            }
130            return super.scan(elem, ignore);
131        }
132    }
133
134    /**
135     * Scan the type of an element, looking for an annotation
136     * to match the expected annotation specified in the @Test annotation.
137     */
138    class TestTypeScanner extends TypeScanner<Void, Void> {
139        Element elem;
140        NavigableMap<Integer, AnnotationMirror> toBeFound;
141        int count = 0;
142        Set<TypeMirror> seen = new HashSet<>();
143
144        TestTypeScanner(Element elem, List<AnnotationMirror> tests, Types types) {
145            super(types);
146            this.elem = elem;
147
148            NavigableMap<Integer, AnnotationMirror> testByPos = new TreeMap<>();
149            for (AnnotationMirror test : tests) {
150                for (int pos : getPosn(test)) {
151                    testByPos.put(pos, test);
152                }
153            }
154            this.toBeFound = testByPos;
155        }
156
157        public void test(TypeMirror t) {
158            scan(t, null);
159        }
160
161        @Override
162        Void scan(TypeMirror t, Void ignore) {
163            if (t == null)
164                return DEFAULT_VALUE;
165
166            if (!seen.contains(t)) {
167                try {
168                    seen.add(t);
169                    if (verbose)
170                        out.println("scan " + count + ": " + t);
171                    if (toBeFound.size() > 0) {
172                        if (toBeFound.firstKey().equals(count)) {
173                            AnnotationMirror test = toBeFound.pollFirstEntry().getValue();
174                            String annoType = getAnnoType(test);
175                            AnnotationMirror anno = getAnnotation(t, annoType);
176                            if (anno == null) {
177                                error(elem, "annotation not found on " + count + ": " + t);
178                            } else {
179                                String v = getValue(anno, "value").toString();
180                                if (v.equals(getExpect(test))) {
181                                    out.println("found " + anno + " as expected");
182                                } else {
183                                    error(elem, "Unexpected value: " + v + ", expected: " + getExpect(test));
184                                }
185                            }
186                        } else if (count > toBeFound.firstKey()) {
187                            rescue();
188                        } else {
189                            List<? extends AnnotationMirror> annos = t.getAnnotationMirrors();
190                            if (annos.size() > 0) {
191                                for (AnnotationMirror a : annos)
192                                    error(elem, "annotation " + a + " found on " + count + ": " + t);
193                            }
194                        }
195                    } else {
196                        List<? extends AnnotationMirror> annos = t.getAnnotationMirrors();
197                        if (annos.size() > 0) {
198                            for (AnnotationMirror a : annos)
199                                error(elem, "annotation " + a + " found on " + count + ": " + t);
200                        }
201                    }
202                    count++;
203                    return super.scan(t, ignore);
204
205                } finally {
206                    seen.remove(t);
207                }
208            }
209
210            return DEFAULT_VALUE;
211
212        }
213
214        private void rescue() {
215            while (toBeFound.size() > 0 && toBeFound.firstKey() >= count)
216                toBeFound.pollFirstEntry();
217        }
218    }
219
220    /** Get the position value from an element annotated with a @Test annotation mirror. */
221    static int[] getPosn(Element elem) {
222        return elem.getAnnotation(Test.class).posn();
223    }
224
225    /** Get the position value from a @Test annotation mirror. */
226    static Integer[] getPosn(AnnotationMirror test) {
227        AnnotationValue v = getValue(test, "posn");
228        Object value = v.getValue();
229        Integer i = 0;
230        if (value instanceof Constant) {
231            i = (Integer)((Constant)value).getValue();
232            Integer[] res = new Integer[1];
233            res[0] = i;
234            return res;
235        } else if (value instanceof List) {
236            List<Constant> l = (List<Constant>)value;
237            Integer[] res = new Integer[l.size()];
238            for (int c = 0; c < l.size(); c++) {
239                res[c] = (Integer)l.get(c).getValue();
240            }
241            return res;
242        }
243        return null;
244    }
245
246    /** Get the expect value from an @Test annotation mirror. */
247    static String getExpect(AnnotationMirror test) {
248        AnnotationValue v = getValue(test, "expect");
249        return (String) v.getValue();
250    }
251
252    /** Get the annoType value from an @Test annotation mirror. */
253    static String getAnnoType(AnnotationMirror test) {
254        AnnotationValue v = getValue(test, "annoType");
255        TypeMirror m = (TypeMirror) v.getValue();
256        return m.toString();
257    }
258
259    /**
260     * Get a specific annotation mirror from an annotated construct.
261     */
262    static AnnotationMirror getAnnotation(AnnotatedConstruct e, String name) {
263        for (AnnotationMirror m: e.getAnnotationMirrors()) {
264            TypeElement te = (TypeElement) m.getAnnotationType().asElement();
265            if (te.getQualifiedName().contentEquals(name)) {
266                return m;
267            }
268        }
269        return null;
270    }
271
272    static List<AnnotationMirror> getAnnotations(Element e, String name) {
273        Name valueName = ((Symbol)e).getSimpleName().table.names.value;
274        List<AnnotationMirror> res = new ArrayList<>();
275
276        for (AnnotationMirror m : e.getAnnotationMirrors()) {
277            TypeElement te = (TypeElement) m.getAnnotationType().asElement();
278            if (te.getQualifiedName().contentEquals(name)) {
279                Compound theAnno = (Compound)m;
280                Array valueArray = (Array)theAnno.member(valueName);
281                for (Attribute a : valueArray.getValue()) {
282                    AnnotationMirror theMirror = (AnnotationMirror) a;
283
284                    res.add(theMirror);
285                }
286            }
287        }
288        return res;
289    }
290
291    /**
292     * Get a specific value from an annotation mirror.
293     */
294    static AnnotationValue getValue(AnnotationMirror anno, String name) {
295        Map<? extends ExecutableElement, ? extends AnnotationValue> map = anno.getElementValues();
296        for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e: map.entrySet()) {
297            if (e.getKey().getSimpleName().contentEquals(name)) {
298                return e.getValue();
299            }
300        }
301        return null;
302    }
303
304    /**
305     * The Language Model API does not provide a type scanner, so provide
306     * one sufficient for our needs.
307     */
308    static class TypeScanner<R, P> extends SimpleTypeVisitor<R, P> {
309        private Types types;
310
311        public TypeScanner(Types types) {
312            super();
313            this.types = types;
314        }
315
316        @Override
317        public R visitArray(ArrayType t, P p) {
318            scan(t.getComponentType(), p);
319            return super.visitArray(t, p);
320        }
321
322        @Override
323        public R visitExecutable(ExecutableType t, P p) {
324            //out.println("  type parameters: " + t.getTypeVariables());
325            scan(t.getTypeVariables(), p);
326            //out.println("  return: " + t.getReturnType());
327            scan(t.getReturnType(), p);
328            //out.println("  receiver: " + t.getReceiverTypes());
329            scan(t.getReceiverType());
330            //out.println("  params: " + t.getParameterTypes());
331            scan(t.getParameterTypes(), p);
332            //out.println("  throws: " + t.getThrownTypes());
333            scan(t.getThrownTypes(), p);
334            return super.visitExecutable(t, p);
335        }
336
337        @Override
338        public R visitDeclared(DeclaredType t, P p) {
339            scan(t.getTypeArguments(), p);
340            // don't scan enclosing
341            scan(types.directSupertypes(t), p);
342            return super.visitDeclared(t, p);
343        }
344
345        @Override
346        public R visitIntersection(IntersectionType t, P p) {
347            scan(t.getBounds(), p);
348            return super.visitIntersection(t, p);
349        }
350
351        @Override
352        public R visitTypeVariable(TypeVariable t, P p) {
353            scan(t.getLowerBound(), p);
354            scan(t.getUpperBound(), p);
355            return super.visitTypeVariable(t, p);
356        }
357
358        @Override
359        public R visitWildcard(WildcardType t, P p) {
360            scan(t.getExtendsBound(), p);
361            scan(t.getSuperBound(), p);
362            return super.visitWildcard(t, p);
363        }
364
365        R scan(TypeMirror t) {
366            return scan(t, null);
367        }
368
369        R scan(TypeMirror t, P p) {
370            return (t == null) ? DEFAULT_VALUE : t.accept(this, p);
371        }
372
373        R scan(Iterable<? extends TypeMirror> iter, P p) {
374            if (iter == null)
375                return DEFAULT_VALUE;
376            R result = DEFAULT_VALUE;
377            for (TypeMirror t: iter)
378                result = scan(t, p);
379            return result;
380        }
381    }
382
383    /** Annotation to identify test cases. */
384    @Repeatable(Tests.class)
385    @interface Test {
386        /** Where to look for the annotation, expressed as a scan index. */
387        int[] posn();
388        /** The annotation to look for. */
389        Class<? extends Annotation> annoType();
390        /** The string representation of the annotation's value. */
391        String expect();
392    }
393
394    @interface Tests {
395        Test[] value();
396    }
397
398    /** Type annotation to use in test cases. */
399    @Target(ElementType.TYPE_USE)
400    public @interface TA {
401        int value();
402    }
403    @Target(ElementType.TYPE_USE)
404    public @interface TB {
405        int value();
406    }
407
408    // Test cases
409
410    // TODO: add more cases for arrays
411    //       all annotated
412    //       all but one annotated
413    //             vary position of one not annotated
414    //       only one annotated
415    //             vary position of one annotated
416    //       the three above with the corner case of the ambiguos decl + type anno added
417
418    @Test(posn=0, annoType=TA.class, expect="1")
419    public @TA(1) int f1;
420
421    @Test(posn=0, annoType=TA.class, expect="11")
422    @TA(11) public int f11;
423
424    @Test(posn=1, annoType=TA.class, expect="111")
425    @TA(111) public int [] f111;
426
427    @Test(posn=1, annoType=TA.class, expect="1120")
428    @Test(posn=0, annoType=TB.class, expect="1121")
429    @TA(1120) public int @TB(1121) [] f112;
430
431    @Test(posn=0, annoType=TB.class, expect="11211")
432    @Test(posn=1, annoType=TA.class, expect="11200")
433    public @TA(11200) int @TB(11211) [] f112b;
434
435    @Test(posn=1, annoType=TB.class, expect="1131")
436    @Test(posn=2, annoType=TA.class, expect="1130")
437    @TA(1130) public int [] @TB(1131) [] f113;
438
439    @Test(posn=5, annoType=TA.class, expect="12")
440    public @TA(12) int [] [] [] [] [] f12;
441
442    @Test(posn=6, annoType=TA.class, expect="13")
443    public @TA(13) int [] [] [] [] [] [] f13;
444
445    @Test(posn=7, annoType=TA.class, expect="14")
446    @TA(14) public int [] [] [] [] [] [] [] f14;
447
448    @Test(posn=6, annoType=TA.class, expect="150")
449    @Test(posn=7, annoType=TB.class, expect="151")
450    @TB(151) public int [] [] [] [] [] [] @TA(150) [] f15;
451
452    @Test(posn=0, annoType=TB.class, expect="1511")
453    @Test(posn=3, annoType=TA.class, expect="1512")
454    @Test(posn=6, annoType=TA.class, expect="150")
455    @Test(posn=7, annoType=TB.class, expect="151")
456    @TB(151) public int @TB(1511) [] [] [] @TA(1512) [] [] [] @TA(150) [] f15b;
457
458    @Test(posn=0, annoType=TB.class, expect="1521")
459    @Test(posn=3, annoType=TA.class, expect="1522")
460    @Test(posn=6, annoType=TA.class, expect="152")
461    public int @TB(1521) [] [] [] @TA(1522) [] [] [] @TA(152) [] f15c;
462
463    @Test(posn=5, annoType=TA.class, expect="160")
464    @Test(posn=6, annoType=TB.class, expect="161")
465    public int [] [] [] [] [] @TA(160) [] @TB(161) [] f16;
466
467    @Test(posn=0, annoType=TA.class, expect="2")
468    public int @TA(2) [] f2;
469
470    @Test(posn=0, annoType=TB.class, expect="33")
471    @Test(posn=1, annoType=TA.class, expect="3")
472    public @TA(3) int @TB(33) [] f3;
473
474    @Test(posn=2, annoType=TA.class, expect="4")
475    public int m1(@TA(4) float a) throws Exception { return 0; }
476
477    @Test(posn=1, annoType=TA.class, expect="5")
478    public @TA(5) int m2(float a) throws Exception { return 0; }
479
480    @Test(posn=3, annoType=TA.class, expect="6")
481    public int m3(float a) throws @TA(6) Exception { return 0; }
482
483    // Also tests that a decl anno on a typevar doesn't show up on the Type
484    @Test(posn=7, annoType=TA.class, expect="8")
485    public <@TA(7) M> M m4(@TA(8) float a) throws Exception { return null; }
486
487    // Also tests that a decl anno on a typevar doesn't show up on the Type
488    @Test(posn=4, annoType=TA.class, expect="10")
489    public class Inner1<@TA(9) S> extends @TA(10) Object implements Cloneable {}
490
491    // Also tests that a decl anno on a typevar doesn't show up on the Type
492    @Test(posn=5, annoType=TA.class, expect="12")
493    public class Inner2<@TA(11) S> extends Object implements @TA(12) Cloneable {}
494
495    @Test(posn={3,6}, annoType=TA.class, expect="13")
496    public <M extends @TA(13) Object> M m5(float a) { return null; }
497
498    @Test(posn=3, annoType=TA.class, expect="14")
499    public class Inner3<QQQ extends @TA(14) Map> {}
500
501    @Test(posn=4, annoType=TA.class, expect="15")
502    public class Inner4<T extends @TA(15) Object & Cloneable & Serializable> {}
503
504    @Test(posn=5, annoType=TA.class, expect="16")
505    public class Inner5<T extends Object & @TA(16) Cloneable & Serializable> {}
506
507    @Test(posn=7, annoType=TA.class, expect="17")
508    public class Inner6<T extends Object & Cloneable & @TA(17) Serializable> {}
509
510    // Test annotated bounds
511
512    @Test(posn=1, annoType=TA.class, expect="18")
513    public Set<@TA(18) ? extends Object> f4;
514
515    @Test(posn=2, annoType=TA.class, expect="19")
516    public Set<? extends @TA(19) Object> f5;
517
518    @Test(posn=3, annoType=TA.class, expect="20")
519    public Set<? extends Set<@TA(20) ? extends Object>> f6;
520
521    @Test(posn=4, annoType=TA.class, expect="21")
522    public Set<? extends Set<? extends @TA(21) Object>> f7;
523
524    @Test(posn=1, annoType=TA.class, expect="22")
525    public Set<@TA(22) ?> f8;
526
527    @Test(posn=1, annoType=TA.class, expect="23")
528    public Set<@TA(23) ? super Object> f9;
529
530    // Test type use annotations on uses of type variables
531    @Test(posn=5, annoType = TA.class, expect = "25")
532    @Test(posn=5, annoType = TB.class, expect = "26")
533    <T> void m6(@TA(25) @TB(26) T t) { }
534
535    class Inner7<T> {
536        @Test(posn=0, annoType = TA.class, expect = "30")
537        @Test(posn=0, annoType = TB.class, expect = "31")
538        @TA(30) @TB(31) T f;
539    }
540
541    // Test type use annotations on uses of type variables
542    @Test(posn=5, annoType = TB.class, expect = "41")
543    <@TA(40) T> void m7(@TB(41) T t) { }
544
545    class Inner8<@TA(50) T> {
546        @Test(posn=0, annoType = TB.class, expect = "51")
547        @TB(51) T f;
548    }
549
550    // Test type use annotations on uses of Class types
551    @Test(posn=5, annoType = TA.class, expect = "60")
552    @Test(posn=5, annoType = TB.class, expect = "61")
553    <T> void m60(@TA(60) @TB(61) String t) { }
554
555    class Inner70<T> {
556        @Test(posn=0, annoType = TA.class, expect = "70")
557        @Test(posn=0, annoType = TB.class, expect = "71")
558        @TA(70) @TB(71) String f;
559    }
560
561    // Test type use annotations on uses of type variables
562    @Test(posn=5, annoType = TB.class, expect = "81")
563    <@TA(80) T> void m80(@TB(81) String t) { }
564
565    class Inner90<@TA(90) T> {
566        @Test(posn=0, annoType = TB.class, expect = "91")
567        @TB(91) String f;
568    }
569
570    // Recursive bound
571    @Test(posn=4, annoType = TB.class, expect = "100")
572    class Inner100<T extends Inner100<@TB(100) T>> {
573    }
574}
575