Fri, 21 Dec 2012 08:45:43 -0800
8005282: Use @library tag with non-relative path for javac tests
Reviewed-by: jjg
1 /*
2 * Copyright (c) 2010, 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 6877202 6986246
27 * @summary Elements.getDocComment() is not getting JavaDocComments
28 */
30 import com.sun.source.tree.*;
31 import com.sun.source.util.*;
32 import java.io.*;
33 import java.util.*;
34 import javax.annotation.processing.*;
35 import javax.lang.model.*;
36 import javax.lang.model.element.*;
37 import javax.lang.model.util.*;
38 import javax.tools.*;
40 /*
41 * For a mixture of pre-existing and generated source files, ensure that we can
42 * get the doc comments.
43 * The test uses both a standard ElementScanner to find all the elements being
44 * processed, and a TreeScanner to find all the local and anonymous inner classes
45 * as well.
46 * And, because the relevant code paths in the compiler are different for
47 * command line and JSR 199 invocation, the test covers both ways of invoking the
48 * compiler.
49 */
51 @SupportedOptions("scan")
52 @SupportedAnnotationTypes("*")
53 public class TestDocComments extends AbstractProcessor {
54 enum CompileKind { API, CMD };
55 enum ScanKind { TREE, ELEMENT };
57 // ----- Main test driver: invoke compiler for the various test cases ------
59 public static void main(String... args) throws Exception {
60 for (CompileKind ck: CompileKind.values()) {
61 for (ScanKind sk: ScanKind.values()) {
62 try {
63 test(ck, sk);
64 } catch (IOException e) {
65 error(e.toString());
66 }
67 }
68 }
70 if (errors > 0)
71 throw new Exception(errors + " errors occurred");
72 }
74 static void test(CompileKind ck, ScanKind sk) throws IOException {
75 String testClasses = System.getProperty("test.classes");
76 String testSrc = System.getProperty("test.src");
77 File testDir = new File("test." + ck + "." + sk);
78 testDir.mkdirs();
79 String[] opts = {
80 "-d", testDir.getPath(),
81 "-implicit:none",
82 "-processor", TestDocComments.class.getName(),
83 "-processorpath", testClasses,
84 //"-XprintRounds",
85 "-Ascan=" + sk
86 };
87 File[] files = {
88 new File(testSrc, "a/First.java")
89 };
91 if (ck == CompileKind.API)
92 test_javac_api(opts, files);
93 else
94 test_javac_cmd(opts, files);
95 }
97 static void test_javac_api(String[] opts, File[] files) throws IOException {
98 System.err.println("test javac api: " + Arrays.asList(opts) + " " + Arrays.asList(files));
99 DiagnosticListener<JavaFileObject> dl = new DiagnosticListener<JavaFileObject>() {
100 public void report(Diagnostic diagnostic) {
101 error(diagnostic.toString());
102 }
103 };
104 JavaCompiler c = ToolProvider.getSystemJavaCompiler();
105 StandardJavaFileManager fm = c.getStandardFileManager(null, null, null);
106 Iterable<? extends JavaFileObject> units = fm.getJavaFileObjects(files);
107 JavacTask t = (JavacTask) c.getTask(null, fm, dl, Arrays.asList(opts), null, units);
108 t.parse();
109 t.analyze();
110 }
112 static void test_javac_cmd(String[] opts, File[] files) {
113 System.err.println("test javac cmd: " + Arrays.asList(opts) + " " + Arrays.asList(files));
114 StringWriter sw = new StringWriter();
115 PrintWriter pw = new PrintWriter(sw);
116 List<String> args = new ArrayList<String>(Arrays.asList(opts));
117 for (File f: files)
118 args.add(f.getPath());
119 int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw);
120 pw.close();
121 String out = sw.toString();
122 if (out.length() > 0)
123 System.err.println(out);
124 if (rc > 0)
125 error("Compilation failed: rc=" + rc);
126 }
128 static void error(String msg) {
129 System.err.println(msg);
130 errors++;
131 //throw new Error(msg);
132 }
134 static int errors;
136 // ----- Annotation processor: scan for elements and check doc comments ----
138 Map<String,String> options;
139 Filer filer;
140 Messager messager;
141 Elements elements;
142 Trees trees;
143 ScanKind skind;
145 int round = 0;
147 @Override
148 public SourceVersion getSupportedSourceVersion() {
149 return SourceVersion.latest();
150 }
152 @Override
153 public void init(ProcessingEnvironment pEnv) {
154 super.init(pEnv);
155 options = pEnv.getOptions();
156 filer = pEnv.getFiler();
157 messager = pEnv.getMessager();
158 elements = pEnv.getElementUtils();
159 trees = Trees.instance(processingEnv);
160 skind = ScanKind.valueOf(options.get("scan"));
161 }
163 @Override
164 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
165 round++;
167 // Scan elements using an appropriate scanner, and for each element found,
168 // call check(Element e) to verify the doc comment on that element
169 for (Element e: roundEnv.getRootElements()) {
170 System.err.println("scan " + skind + " " + e.getKind() + " " + e.getSimpleName());
171 if (skind == ScanKind.TREE) {
172 new TestTreeScanner().scan(trees.getPath(e), trees);
173 } else
174 new TestElementScanner().scan(e);
175 }
177 // For a few rounds, generate new source files, so that we can check whether
178 // doc comments are correctly handled in subsequent processing rounds
179 final int MAX_ROUNDS = 3;
180 if (round <= MAX_ROUNDS) {
181 String pkg = "p";
182 String currClass = "Gen" + round;
183 String curr = pkg + "." + currClass;
184 String next = (round < MAX_ROUNDS) ? (pkg + ".Gen" + (round + 1)) : "z.Last";
185 StringBuilder text = new StringBuilder();
186 text.append("package ").append(pkg).append(";\n");
187 text.append("/** CLASS ").append(currClass).append(" */\n");
188 text.append("public class ").append(currClass).append(" {\n");
189 text.append(" /** CONSTRUCTOR <init> **/\n");
190 text.append(" ").append(currClass).append("() { }\n");
191 text.append(" /** FIELD x */\n");
192 text.append(" ").append(next).append(" x;\n");
193 text.append(" /** METHOD m */\n");
194 text.append(" void m() { }\n");
195 text.append("}\n");
197 try {
198 JavaFileObject fo = filer.createSourceFile(curr);
199 Writer out = fo.openWriter();
200 try {
201 out.write(text.toString());
202 } finally {
203 out.close();
204 }
205 } catch (IOException e) {
206 throw new Error(e);
207 }
208 }
210 return true;
211 }
213 /*
214 * Check that the doc comment on an element is as expected.
215 * This method is invoked for each element found by the scanners run by process.
216 */
217 void check(Element e) {
218 System.err.println("Checking " + e);
220 String dc = elements.getDocComment(e);
221 System.err.println(" found " + dc);
223 String expect = (e.getKind() + " " + e.getSimpleName()); // default
225 Name name = e.getSimpleName();
226 Element encl = e.getEnclosingElement();
227 Name enclName = encl.getSimpleName();
228 ElementKind enclKind = encl.getKind();
229 switch (e.getKind()) {
230 case PARAMETER:
231 case LOCAL_VARIABLE:
232 // doc comments not retained for these elements
233 expect = null;
234 break;
236 case CONSTRUCTOR:
237 if (enclName.length() == 0 || enclKind == ElementKind.ENUM) {
238 // Enum constructor is synthetic
239 expect = null;
240 }
241 break;
243 case METHOD:
244 if (enclKind == ElementKind.ENUM
245 && (name.contentEquals("values") || name.contentEquals("valueOf"))) {
246 // synthetic enum methods
247 expect = null;
248 }
249 break;
251 case CLASS:
252 if (e.getSimpleName().length() == 0) {
253 // anon inner class
254 expect = null;
255 }
256 break;
257 }
259 System.err.println(" expect " + expect);
261 if (dc == null ? expect == null : dc.trim().equals(expect))
262 return;
264 if (dc == null)
265 messager.printMessage(Diagnostic.Kind.ERROR, "doc comment is null", e);
266 else {
267 messager.printMessage(Diagnostic.Kind.ERROR,
268 "unexpected comment: \"" + dc + "\", expected \"" + expect + "\"", e);
269 }
270 }
272 // ----- Scanners to find elements -----------------------------------------
274 class TestElementScanner extends ElementScanner7<Void, Void> {
275 @Override
276 public Void visitExecutable(ExecutableElement e, Void _) {
277 check(e);
278 return super.visitExecutable(e, _);
279 }
280 @Override
281 public Void visitType(TypeElement e, Void _) {
282 check(e);
283 return super.visitType(e, _);
284 }
285 @Override
286 public Void visitVariable(VariableElement e, Void _) {
287 check(e);
288 return super.visitVariable(e, _);
289 }
290 }
292 class TestTreeScanner extends TreePathScanner<Void,Trees> {
293 @Override
294 public Void visitClass(ClassTree tree, Trees trees) {
295 check(trees.getElement(getCurrentPath()));
296 return super.visitClass(tree, trees);
297 }
298 @Override
299 public Void visitMethod(MethodTree tree, Trees trees) {
300 check(trees.getElement(getCurrentPath()));
301 return super.visitMethod(tree, trees);
302 }
303 @Override
304 public Void visitVariable(VariableTree tree, Trees trees) {
305 check(trees.getElement(getCurrentPath()));
306 return super.visitVariable(tree, trees);
307 }
308 }
310 }