Thu, 21 Feb 2013 15:27:05 +0000
8008444: Inherited generic functional descriptors are merged incorrectly
Summary: Missing call to Types.createMethodWithThrownTypes
Reviewed-by: jjg
1 /*
2 * Copyright (c) 2011, 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 */
24 /**
25 * @test
26 * @bug 7021650
27 * @summary Fix Context issues
28 * @library /tools/javac/lib
29 * @build JavacTestingAbstractProcessor T7021650
30 * @run main T7021650
31 */
33 import java.io.*;
34 import java.net.*;
35 import java.util.*;
36 import javax.annotation.processing.*;
37 import javax.lang.model.element.*;
38 import javax.tools.*;
40 import com.sun.tools.javac.comp.Attr;
41 import com.sun.tools.javac.file.JavacFileManager;
42 import com.sun.tools.javac.main.Main;
43 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
44 import com.sun.tools.javac.util.Context;
46 public class T7021650 extends JavacTestingAbstractProcessor {
47 public static void main(String... args) throws Exception {
48 new T7021650().run();
49 }
51 static File testSrc = new File(System.getProperty("test.src"));
52 static final int MAX_ROUNDS = 3;
54 /**
55 * Perform a compilation with custom factories registered in the context,
56 * and verify that corresponding objects are created in each round.
57 */
58 void run() throws Exception {
59 Counter demoCounter = new Counter();
60 Counter myAttrCounter = new Counter();
62 Context context = new Context();
63 // Use a custom file manager which creates classloaders for annotation
64 // processors with a sensible delegation parent, so that all instances
65 // of test classes come from the same class loader. This is important
66 // because the test performs class checks on the instances of classes
67 // found in the context for each round or processing.
68 context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
69 public JavaFileManager make(Context c) {
70 return new JavacFileManager(c, true, null) {
71 @Override
72 protected ClassLoader getClassLoader(URL[] urls) {
73 return new URLClassLoader(urls, T7021650.class.getClassLoader());
74 }
75 };
76 }
77 });
79 Demo.preRegister(context, demoCounter);
80 MyAttr.preRegister(context, myAttrCounter);
82 String[] args = {
83 "-d", ".",
84 "-processor", T7021650.class.getName(),
85 "-XprintRounds",
86 new File(testSrc, T7021650.class.getName() + ".java").getPath()
87 };
89 compile(context, args);
91 // Expect to create Demo for initial round, then MAX_ROUNDS in which
92 // GenX files are generated, then standard final round of processing.
93 checkEqual("demoCounter", demoCounter.count, MAX_ROUNDS + 2);
95 // Expect to create MyAttr for same processing rounds as for Demo,
96 // plus additional context for final compilation.
97 checkEqual("myAttrCounter", myAttrCounter.count, MAX_ROUNDS + 3);
98 }
100 void compile(Context context, String... args) throws Exception {
101 StringWriter sw = new StringWriter();
102 PrintWriter pw = new PrintWriter(sw);
103 Main m = new Main("javac", pw);
104 Main.Result res = m.compile(args, context);
105 pw.close();
106 String out = sw.toString();
107 if (!out.isEmpty())
108 System.err.println(out);
109 if (!res.isOK())
110 throw new Exception("compilation failed unexpectedly: result=" + res);
111 }
113 void checkEqual(String label, int found, int expect) throws Exception {
114 if (found != expect)
115 throw new Exception("unexpected value for " + label
116 + ": expected " + expect
117 + ": found " + found);
118 }
120 //---------------
122 /*
123 * A custom class unknown to javac but nonetheless registered in the context.
124 */
125 static class Demo {
126 static void preRegister(Context context, final Counter counter) {
127 context.put(Demo.class, new Context.Factory<Demo>() {
128 public Demo make(Context c) {
129 counter.count++;
130 return new Demo(c);
131 }
132 });
133 }
135 Demo(Context c) {
136 c.put(Demo.class, this);
137 }
139 static Demo instance(Context context) {
140 return context.get(Demo.class);
141 }
142 }
144 /**
145 * A custom version of a standard javac component.
146 */
147 static class MyAttr extends Attr {
148 static void preRegister(Context context, final Counter counter) {
149 context.put(attrKey, new Context.Factory<Attr>() {
150 public Attr make(Context c) {
151 counter.count++;
152 return new MyAttr(c);
153 }
154 });
155 }
157 MyAttr(Context c) {
158 super(c);
159 }
160 }
162 static class Counter {
163 int count;
164 }
166 //---------------
168 int round = 0;
170 @Override
171 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
172 round++;
174 Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
176 // verify items in context as expected
177 check("Demo", Demo.instance(context), Demo.class);
178 check("Attr", Attr.instance(context), MyAttr.class);
180 // For a few rounds, generate new source files, so that we can check whether
181 // values in the context are correctly handled in subsequent processing rounds
182 if (round <= MAX_ROUNDS) {
183 String pkg = "p";
184 String currClass = "Gen" + round;
185 String curr = pkg + "." + currClass;
186 String next = (pkg + ".Gen" + (round + 1));
187 StringBuilder text = new StringBuilder();
188 text.append("package ").append(pkg).append(";\n");
189 text.append("public class ").append(currClass).append(" {\n");
190 if (round < MAX_ROUNDS)
191 text.append(" ").append(next).append(" x;\n");
192 text.append("}\n");
194 try {
195 JavaFileObject fo = filer.createSourceFile(curr);
196 Writer out = fo.openWriter();
197 try {
198 out.write(text.toString());
199 } finally {
200 out.close();
201 }
202 } catch (IOException e) {
203 throw new Error(e);
204 }
205 }
207 return true;
208 }
210 void check(String label, Object o, Class<?> clazz) {
211 if (o == null)
212 throw new IllegalStateException(label + ": no item found");
213 if (!clazz.isAssignableFrom(o.getClass()))
214 throw new IllegalStateException(label + ": unexpected class: " + o.getClass());
215 }
216 }