1 /*
2  * Copyright (c) 2009, 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 import java.io.*;
25 import com.sun.tools.classfile.*;
26 
27 /*
28  * @test Wildcards
29  * @bug 6843077
30  * @summary test that annotations target wildcards get emitted to classfile
31  * @modules jdk.jdeps/com.sun.tools.classfile
32  */
33 public class Wildcards {
main(String[] args)34     public static void main(String[] args) throws Exception {
35         new Wildcards().run();
36     }
37 
run()38     public void run() throws Exception {
39         File javaFile = writeTestFile();
40         File classFile = compileTestFile(javaFile);
41 
42         ClassFile cf = ClassFile.read(classFile);
43         test(cf);
44         for (Field f : cf.fields) {
45             test(cf, f);
46         }
47         for (Method m: cf.methods) {
48             test(cf, m);
49         }
50 
51         countAnnotations();
52 
53         if (errors > 0)
54             throw new Exception(errors + " errors found");
55         System.out.println("PASSED");
56     }
57 
test(ClassFile cf)58     void test(ClassFile cf) {
59         test(cf, Attribute.RuntimeVisibleTypeAnnotations, true);
60         test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false);
61     }
62 
test(ClassFile cf, Method m)63     void test(ClassFile cf, Method m) {
64         test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
65         test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
66     }
67 
test(ClassFile cf, Field m)68     void test(ClassFile cf, Field m) {
69         test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
70         test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
71     }
72 
73     // test the result of Attributes.getIndex according to expectations
74     // encoded in the method's name
test(ClassFile cf, String name, boolean visible)75     void test(ClassFile cf, String name, boolean visible) {
76         int index = cf.attributes.getIndex(cf.constant_pool, name);
77         if (index != -1) {
78             Attribute attr = cf.attributes.get(index);
79             assert attr instanceof RuntimeTypeAnnotations_attribute;
80             RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
81             all += tAttr.annotations.length;
82             if (visible)
83                 visibles += tAttr.annotations.length;
84             else
85                 invisibles += tAttr.annotations.length;
86         }
87     }
88 
89     // test the result of Attributes.getIndex according to expectations
90     // encoded in the method's name
test(ClassFile cf, Method m, String name, boolean visible)91     void test(ClassFile cf, Method m, String name, boolean visible) {
92         int index = m.attributes.getIndex(cf.constant_pool, name);
93         if (index != -1) {
94             Attribute attr = m.attributes.get(index);
95             assert attr instanceof RuntimeTypeAnnotations_attribute;
96             RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
97             all += tAttr.annotations.length;
98             if (visible)
99                 visibles += tAttr.annotations.length;
100             else
101                 invisibles += tAttr.annotations.length;
102         }
103     }
104 
105     // test the result of Attributes.getIndex according to expectations
106     // encoded in the method's name
test(ClassFile cf, Field m, String name, boolean visible)107     void test(ClassFile cf, Field m, String name, boolean visible) {
108         int index = m.attributes.getIndex(cf.constant_pool, name);
109         if (index != -1) {
110             Attribute attr = m.attributes.get(index);
111             assert attr instanceof RuntimeTypeAnnotations_attribute;
112             RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
113             all += tAttr.annotations.length;
114             if (visible)
115                 visibles += tAttr.annotations.length;
116             else
117                 invisibles += tAttr.annotations.length;
118         }
119     }
120 
writeTestFile()121     File writeTestFile() throws IOException {
122       File f = new File("Test.java");
123         PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
124         out.println("import java.lang.annotation.*;");
125         out.println("import java.util.*;");
126         out.println("class Test { ");
127         out.println("  @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})");
128         out.println("  @interface A { }");
129 
130         out.println("  List<? extends @A Number> f;");
131 
132         out.println("  List<? extends @A Object> test(List<? extends @A Number> p) {");
133         out.println("    List<? extends @A Object> l;");    // not counted... gets optimized away
134         out.println("    return null;");
135         out.println(" }");
136         out.println("}");
137 
138         out.close();
139         return f;
140     }
141 
compileTestFile(File f)142     File compileTestFile(File f) {
143         int rc = com.sun.tools.javac.Main.compile(new String[] {"-g", f.getPath() });
144         if (rc != 0)
145             throw new Error("compilation failed. rc=" + rc);
146         String path = f.getPath();
147         return new File(path.substring(0, path.length() - 5) + ".class");
148     }
149 
countAnnotations()150     void countAnnotations() {
151         int expected_visibles = 0, expected_invisibles = 3;
152         int expected_all = expected_visibles + expected_invisibles;
153 
154         if (expected_all != all) {
155             errors++;
156             System.err.println("expected " + expected_all
157                     + " annotations but found " + all);
158         }
159 
160         if (expected_visibles != visibles) {
161             errors++;
162             System.err.println("expected " + expected_visibles
163                     + " visibles annotations but found " + visibles);
164         }
165 
166         if (expected_invisibles != invisibles) {
167             errors++;
168             System.err.println("expected " + expected_invisibles
169                     + " invisibles annotations but found " + invisibles);
170         }
171 
172     }
173 
174     int errors;
175     int all;
176     int visibles;
177     int invisibles;
178 }
179