|
1 /* |
|
2 * Copyright (c) 2009, 2013, 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 6769027 8006694 |
|
27 * @summary Source line should be displayed immediately after the first diagnostic line |
|
28 * temporarily workaround combo tests are causing time out in several platforms |
|
29 * @author Maurizio Cimadamore |
|
30 * @library ../../lib |
|
31 * @build JavacTestingAbstractThreadedTest |
|
32 * @run main/othervm T6769027 |
|
33 */ |
|
34 |
|
35 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) |
|
36 // see JDK-8006746 |
|
37 |
|
38 import java.net.URI; |
|
39 import java.util.regex.Matcher; |
|
40 import javax.tools.*; |
|
41 import com.sun.tools.javac.util.*; |
|
42 |
|
43 public class T6769027 |
|
44 extends JavacTestingAbstractThreadedTest |
|
45 implements Runnable { |
|
46 |
|
47 enum OutputKind { |
|
48 RAW("rawDiagnostics","rawDiagnostics"), |
|
49 BASIC("",""); |
|
50 |
|
51 String key; |
|
52 String value; |
|
53 |
|
54 void init(Options opts) { |
|
55 opts.put(key, value); |
|
56 } |
|
57 |
|
58 OutputKind(String key, String value) { |
|
59 this.key = key; |
|
60 this.value = value; |
|
61 } |
|
62 } |
|
63 |
|
64 enum CaretKind { |
|
65 DEFAULT("", ""), |
|
66 SHOW("showCaret","true"), |
|
67 HIDE("showCaret","false"); |
|
68 |
|
69 String key; |
|
70 String value; |
|
71 |
|
72 void init(Options opts) { |
|
73 opts.put(key, value); |
|
74 } |
|
75 |
|
76 CaretKind(String key, String value) { |
|
77 this.key = key; |
|
78 this.value = value; |
|
79 } |
|
80 |
|
81 boolean isEnabled() { |
|
82 return this == DEFAULT || this == SHOW; |
|
83 } |
|
84 } |
|
85 |
|
86 enum SourceLineKind { |
|
87 DEFAULT("", ""), |
|
88 AFTER_SUMMARY("sourcePosition", "top"), |
|
89 BOTTOM("sourcePosition", "bottom"); |
|
90 |
|
91 String key; |
|
92 String value; |
|
93 |
|
94 void init(Options opts) { |
|
95 opts.put(key, value); |
|
96 } |
|
97 |
|
98 SourceLineKind(String key, String value) { |
|
99 this.key = key; |
|
100 this.value = value; |
|
101 } |
|
102 |
|
103 boolean isAfterSummary() { |
|
104 return this == DEFAULT || this == AFTER_SUMMARY; |
|
105 } |
|
106 } |
|
107 |
|
108 enum XDiagsSource { |
|
109 DEFAULT(""), |
|
110 SOURCE("source"), |
|
111 NO_SOURCE("-source"); |
|
112 |
|
113 String flag; |
|
114 |
|
115 void init(Options opts) { |
|
116 if (this != DEFAULT) { |
|
117 String flags = opts.get("diags"); |
|
118 flags = flags == null ? flag : flags + "," + flag; |
|
119 opts.put("diags", flags); |
|
120 } |
|
121 } |
|
122 |
|
123 XDiagsSource(String flag) { |
|
124 this.flag = flag; |
|
125 } |
|
126 |
|
127 String getOutput(CaretKind caretKind, IndentKind indent, OutputKind outKind) { |
|
128 String spaces = (outKind == OutputKind.BASIC) ? indent.string : ""; |
|
129 return "\n" + spaces + "This is a source line" + |
|
130 (caretKind.isEnabled() ? "\n" + spaces + " ^" : ""); |
|
131 } |
|
132 } |
|
133 |
|
134 enum XDiagsCompact { |
|
135 DEFAULT(""), |
|
136 COMPACT("short"), |
|
137 NO_COMPACT("-short"); |
|
138 |
|
139 String flag; |
|
140 |
|
141 void init(Options opts) { |
|
142 if (this != DEFAULT) { |
|
143 String flags = opts.get("diags"); |
|
144 flags = flags == null ? flag : flags + "," + flag; |
|
145 opts.put("diags", flags); |
|
146 } |
|
147 } |
|
148 |
|
149 XDiagsCompact(String flag) { |
|
150 this.flag = flag; |
|
151 } |
|
152 } |
|
153 |
|
154 enum ErrorKind { |
|
155 SINGLE("single", |
|
156 "compiler.err.single: Hello!", |
|
157 "KXThis is a test error message Hello!"), |
|
158 DOUBLE("double", |
|
159 "compiler.err.double: Hello!", |
|
160 "KXThis is a test error message.\n" + |
|
161 "KXYThis is another line of the above error message Hello!"); |
|
162 |
|
163 String key; |
|
164 String rawOutput; |
|
165 String nonRawOutput; |
|
166 |
|
167 String key() { |
|
168 return key; |
|
169 } |
|
170 |
|
171 ErrorKind(String key, String rawOutput, String nonRawOutput) { |
|
172 this.key = key; |
|
173 this.rawOutput = rawOutput; |
|
174 this.nonRawOutput = nonRawOutput; |
|
175 } |
|
176 |
|
177 String getOutput(OutputKind outKind, IndentKind summaryIndent, IndentKind detailsIndent) { |
|
178 return outKind == OutputKind.RAW ? |
|
179 rawOutput : |
|
180 nonRawOutput.replace("X", summaryIndent.string).replace("Y", detailsIndent.string).replace("K", ""); |
|
181 } |
|
182 |
|
183 String getOutput(OutputKind outKind, IndentKind summaryIndent, IndentKind detailsIndent, String indent) { |
|
184 return outKind == OutputKind.RAW ? |
|
185 rawOutput : |
|
186 nonRawOutput.replace("X", summaryIndent.string).replace("Y", detailsIndent.string).replace("K", indent); |
|
187 } |
|
188 } |
|
189 |
|
190 enum MultilineKind { |
|
191 NONE(0), |
|
192 DOUBLE(1), |
|
193 NESTED(2), |
|
194 DOUBLE_NESTED(3); |
|
195 |
|
196 static String[][] rawTemplates = { |
|
197 {"", ",{(E),(E)}", ",{(E,{(E)})}", ",{(E,{(E)}),(E,{(E)})}"}, //ENABLED |
|
198 {"", "", "", "",""}, //DISABLED |
|
199 {"", ",{(E)}", ",{(E,{(E)})}", ",{(E,{(E)})}"}, //LIMIT_LENGTH |
|
200 {"", ",{(E),(E)}", ",{(E)}", ",{(E),(E)}"}, //LIMIT_DEPTH |
|
201 {"", ",{(E)}", ",{(E)}", ",{(E)}"}}; //LIMIT_BOTH |
|
202 |
|
203 static String[][] basicTemplates = { |
|
204 {"", "\nE\nE", "\nE\nQ", "\nE\nQ\nE\nQ"}, //ENABLED |
|
205 {"", "", "", "",""}, //DISABLED |
|
206 {"", "\nE", "\nE\nQ", "\nE\nQ"}, //LIMIT_LENGTH |
|
207 {"", "\nE\nE", "\nE", "\nE\nE"}, //LIMIT_DEPTH |
|
208 {"", "\nE", "\nE", "\nE"}}; //LIMIT_BOTH |
|
209 |
|
210 |
|
211 int index; |
|
212 |
|
213 MultilineKind (int index) { |
|
214 this.index = index; |
|
215 } |
|
216 |
|
217 boolean isDouble() { |
|
218 return this == DOUBLE || this == DOUBLE_NESTED; |
|
219 } |
|
220 |
|
221 boolean isNested() { |
|
222 return this == NESTED || this == DOUBLE_NESTED; |
|
223 } |
|
224 |
|
225 String getOutput(OutputKind outKind, ErrorKind errKind, MultilinePolicy policy, |
|
226 IndentKind summaryIndent, IndentKind detailsIndent, IndentKind multiIndent) { |
|
227 String constIndent = (errKind == ErrorKind.DOUBLE) ? |
|
228 summaryIndent.string + detailsIndent.string : |
|
229 summaryIndent.string; |
|
230 constIndent += multiIndent.string; |
|
231 |
|
232 String errMsg1 = errKind.getOutput(outKind, summaryIndent, detailsIndent, constIndent); |
|
233 String errMsg2 = errKind.getOutput(outKind, summaryIndent, detailsIndent, constIndent + constIndent); |
|
234 |
|
235 errMsg1 = errMsg1.replaceAll("compiler.err", "compiler.misc"); |
|
236 errMsg1 = errMsg1.replaceAll("error message", "subdiagnostic"); |
|
237 errMsg2 = errMsg2.replaceAll("compiler.err", "compiler.misc"); |
|
238 errMsg2 = errMsg2.replaceAll("error message", "subdiagnostic"); |
|
239 |
|
240 String template = outKind == OutputKind.RAW ? |
|
241 rawTemplates[policy.index][index] : |
|
242 basicTemplates[policy.index][index]; |
|
243 |
|
244 template = template.replaceAll("E", errMsg1); |
|
245 return template.replaceAll("Q", errMsg2); |
|
246 } |
|
247 } |
|
248 |
|
249 enum MultilinePolicy { |
|
250 ENABLED(0, "multilinePolicy", "enabled"), |
|
251 DISABLED(1, "multilinePolicy", "disabled"), |
|
252 LIMIT_LENGTH(2, "multilinePolicy", "limit:1:*"), |
|
253 LIMIT_DEPTH(3, "multilinePolicy", "limit:*:1"), |
|
254 LIMIT_BOTH(4, "multilinePolicy", "limit:1:1"); |
|
255 |
|
256 String name; |
|
257 String value; |
|
258 int index; |
|
259 |
|
260 MultilinePolicy(int index, String name, String value) { |
|
261 this.name = name; |
|
262 this.value = value; |
|
263 this.index = index; |
|
264 } |
|
265 |
|
266 void init(Options options) { |
|
267 options.put(name, value); |
|
268 } |
|
269 } |
|
270 |
|
271 enum PositionKind { |
|
272 NOPOS(Position.NOPOS, "- ", "error: "), |
|
273 POS(5, "Test.java:1:6: ", "/Test.java:1: error: "); |
|
274 |
|
275 int pos; |
|
276 String rawOutput; |
|
277 String nonRawOutput; |
|
278 |
|
279 PositionKind(int pos, String rawOutput, String nonRawOutput) { |
|
280 this.pos = pos; |
|
281 this.rawOutput = rawOutput; |
|
282 this.nonRawOutput = nonRawOutput; |
|
283 } |
|
284 |
|
285 JCDiagnostic.DiagnosticPosition pos() { |
|
286 return new JCDiagnostic.SimpleDiagnosticPosition(pos); |
|
287 } |
|
288 |
|
289 String getOutput(OutputKind outputKind) { |
|
290 return outputKind == OutputKind.RAW ? |
|
291 rawOutput : |
|
292 nonRawOutput; |
|
293 } |
|
294 } |
|
295 |
|
296 static class MyFileObject extends SimpleJavaFileObject { |
|
297 private String text; |
|
298 public MyFileObject(String text) { |
|
299 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); |
|
300 this.text = text; |
|
301 } |
|
302 @Override |
|
303 public CharSequence getCharContent(boolean ignoreEncodingErrors) { |
|
304 return text; |
|
305 } |
|
306 } |
|
307 |
|
308 enum IndentKind { |
|
309 NONE(""), |
|
310 CUSTOM(" "); |
|
311 |
|
312 String string; |
|
313 |
|
314 IndentKind(String indent) { |
|
315 string = indent; |
|
316 } |
|
317 } |
|
318 |
|
319 class MyLog extends Log { |
|
320 MyLog(Context ctx) { |
|
321 super(ctx); |
|
322 } |
|
323 |
|
324 @Override |
|
325 protected java.io.PrintWriter getWriterForDiagnosticType(JCDiagnostic.DiagnosticType dt) { |
|
326 return outWriter; |
|
327 } |
|
328 |
|
329 @Override |
|
330 protected boolean shouldReport(JavaFileObject jfo, int pos) { |
|
331 return true; |
|
332 } |
|
333 } |
|
334 |
|
335 OutputKind outputKind; |
|
336 ErrorKind errorKind; |
|
337 MultilineKind multiKind; |
|
338 MultilinePolicy multiPolicy; |
|
339 PositionKind posKind; |
|
340 XDiagsSource xdiagsSource; |
|
341 XDiagsCompact xdiagsCompact; |
|
342 CaretKind caretKind; |
|
343 SourceLineKind sourceLineKind; |
|
344 IndentKind summaryIndent; |
|
345 IndentKind detailsIndent; |
|
346 IndentKind sourceIndent; |
|
347 IndentKind subdiagsIndent; |
|
348 |
|
349 T6769027(OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind, |
|
350 MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource, |
|
351 XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind, |
|
352 IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent, |
|
353 IndentKind subdiagsIndent) { |
|
354 this.outputKind = outputKind; |
|
355 this.errorKind = errorKind; |
|
356 this.multiKind = multiKind; |
|
357 this.multiPolicy = multiPolicy; |
|
358 this.posKind = posKind; |
|
359 this.xdiagsSource = xdiagsSource; |
|
360 this.xdiagsCompact = xdiagsCompact; |
|
361 this.caretKind = caretKind; |
|
362 this.sourceLineKind = sourceLineKind; |
|
363 this.summaryIndent = summaryIndent; |
|
364 this.detailsIndent = detailsIndent; |
|
365 this.sourceIndent = sourceIndent; |
|
366 this.subdiagsIndent = subdiagsIndent; |
|
367 } |
|
368 |
|
369 @Override |
|
370 public void run() { |
|
371 Context ctx = new Context(); |
|
372 Options options = Options.instance(ctx); |
|
373 outputKind.init(options); |
|
374 multiPolicy.init(options); |
|
375 xdiagsSource.init(options); |
|
376 xdiagsCompact.init(options); |
|
377 caretKind.init(options); |
|
378 sourceLineKind.init(options); |
|
379 String indentString = ""; |
|
380 indentString = (summaryIndent == IndentKind.CUSTOM) ? "3" : "0"; |
|
381 indentString += (detailsIndent == IndentKind.CUSTOM) ? "|3" : "|0"; |
|
382 indentString += (sourceIndent == IndentKind.CUSTOM) ? "|3" : "|0"; |
|
383 indentString += (subdiagsIndent == IndentKind.CUSTOM) ? "|3" : "|0"; |
|
384 options.put("diagsIndentation", indentString); |
|
385 MyLog log = new MyLog(ctx); |
|
386 JavacMessages messages = JavacMessages.instance(ctx); |
|
387 messages.add("tester"); |
|
388 JCDiagnostic.Factory diags = JCDiagnostic.Factory.instance(ctx); |
|
389 log.useSource(new MyFileObject("This is a source line")); |
|
390 JCDiagnostic d = diags.error(log.currentSource(), |
|
391 posKind.pos(), |
|
392 errorKind.key(), "Hello!"); |
|
393 if (multiKind != MultilineKind.NONE) { |
|
394 JCDiagnostic sub = diags.fragment(errorKind.key(), "Hello!"); |
|
395 if (multiKind.isNested()) |
|
396 sub = new JCDiagnostic.MultilineDiagnostic(sub, List.of(sub)); |
|
397 List<JCDiagnostic> subdiags = multiKind.isDouble() ? |
|
398 List.of(sub, sub) : |
|
399 List.of(sub); |
|
400 d = new JCDiagnostic.MultilineDiagnostic(d, subdiags); |
|
401 } |
|
402 String diag = log.getDiagnosticFormatter().format(d, messages.getCurrentLocale()); |
|
403 checkOutput(diag); |
|
404 } |
|
405 |
|
406 public static void main(String[] args) throws Exception { |
|
407 for (OutputKind outputKind : OutputKind.values()) { |
|
408 for (ErrorKind errKind : ErrorKind.values()) { |
|
409 for (MultilineKind multiKind : MultilineKind.values()) { |
|
410 for (MultilinePolicy multiPolicy : MultilinePolicy.values()) { |
|
411 for (PositionKind posKind : PositionKind.values()) { |
|
412 for (XDiagsSource xdiagsSource : XDiagsSource.values()) { |
|
413 for (XDiagsCompact xdiagsCompact : XDiagsCompact.values()) { |
|
414 for (CaretKind caretKind : CaretKind.values()) { |
|
415 for (SourceLineKind sourceLineKind : SourceLineKind.values()) { |
|
416 for (IndentKind summaryIndent : IndentKind.values()) { |
|
417 for (IndentKind detailsIndent : IndentKind.values()) { |
|
418 for (IndentKind sourceIndent : IndentKind.values()) { |
|
419 for (IndentKind subdiagsIndent : IndentKind.values()) { |
|
420 pool.execute(new T6769027(outputKind, |
|
421 errKind, |
|
422 multiKind, |
|
423 multiPolicy, |
|
424 posKind, |
|
425 xdiagsSource, |
|
426 xdiagsCompact, |
|
427 caretKind, |
|
428 sourceLineKind, |
|
429 summaryIndent, |
|
430 detailsIndent, |
|
431 sourceIndent, |
|
432 subdiagsIndent)); |
|
433 } |
|
434 } |
|
435 } |
|
436 } |
|
437 } |
|
438 } |
|
439 } |
|
440 } |
|
441 } |
|
442 } |
|
443 } |
|
444 } |
|
445 } |
|
446 |
|
447 checkAfterExec(false); |
|
448 } |
|
449 |
|
450 void printInfo(String msg, String errorLine) { |
|
451 String sep = "*********************************************************"; |
|
452 String desc = "raw=" + outputKind + " pos=" + posKind + " key=" + errorKind.key() + |
|
453 " multiline=" + multiKind +" multiPolicy=" + multiPolicy.value + |
|
454 " diags= " + java.util.Arrays.asList(xdiagsSource.flag, xdiagsCompact.flag) + |
|
455 " caret=" + caretKind + " sourcePosition=" + sourceLineKind + |
|
456 " summaryIndent=" + summaryIndent + " detailsIndent=" + detailsIndent + |
|
457 " sourceIndent=" + sourceIndent + " subdiagsIndent=" + subdiagsIndent; |
|
458 errWriter.println(sep); |
|
459 errWriter.println(desc); |
|
460 errWriter.println(sep); |
|
461 errWriter.println(msg); |
|
462 errWriter.println("Diagnostic formatting problem - expected diagnostic...\n" + errorLine); |
|
463 } |
|
464 |
|
465 void checkOutput(String msg) { |
|
466 boolean shouldPrintSource = posKind == PositionKind.POS && |
|
467 xdiagsSource != XDiagsSource.NO_SOURCE && |
|
468 (xdiagsSource == XDiagsSource.SOURCE || |
|
469 outputKind == OutputKind.BASIC); |
|
470 String errorLine = posKind.getOutput(outputKind) + |
|
471 errorKind.getOutput(outputKind, summaryIndent, detailsIndent); |
|
472 if (xdiagsCompact != XDiagsCompact.COMPACT) |
|
473 errorLine += multiKind.getOutput(outputKind, errorKind, multiPolicy, |
|
474 summaryIndent, detailsIndent, subdiagsIndent); |
|
475 String[] lines = errorLine.split("\n"); |
|
476 if (xdiagsCompact == XDiagsCompact.COMPACT) { |
|
477 errorLine = lines[0]; |
|
478 lines = new String[] {errorLine}; |
|
479 } |
|
480 if (shouldPrintSource) { |
|
481 if (sourceLineKind.isAfterSummary()) { |
|
482 String sep = "\n"; |
|
483 if (lines.length == 1) { |
|
484 errorLine += "\n"; |
|
485 sep = ""; |
|
486 } |
|
487 errorLine = errorLine.replaceFirst("\n", |
|
488 Matcher.quoteReplacement(xdiagsSource.getOutput(caretKind, sourceIndent, outputKind) + sep)); |
|
489 } |
|
490 else |
|
491 errorLine += xdiagsSource.getOutput(caretKind, sourceIndent, outputKind); |
|
492 } |
|
493 |
|
494 if (!msg.equals(errorLine)) { |
|
495 // printInfo(msg, errorLine); |
|
496 errCount.incrementAndGet(); |
|
497 } |
|
498 } |
|
499 |
|
500 } |