Thu, 09 Oct 2008 16:19:13 +0100
6731573: diagnostic output should optionally include source line
Summary: Added an -XD option to optionally prints out source lines in error messages
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Thu Oct 09 16:07:38 2008 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Thu Oct 09 16:19:13 2008 +0100 1.3 @@ -33,6 +33,7 @@ 1.4 import com.sun.tools.javac.api.Formattable; 1.5 import com.sun.tools.javac.api.DiagnosticFormatter.PositionKind; 1.6 import com.sun.tools.javac.file.JavacFileManager; 1.7 +import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*; 1.8 1.9 /** 1.10 * This abstract class provides a basic implementation of the functionalities that should be provided 1.11 @@ -52,13 +53,21 @@ 1.12 * JavacMessages object used by this formatter for i18n 1.13 */ 1.14 protected JavacMessages messages; 1.15 + protected boolean showSource; 1.16 1.17 /** 1.18 * Initialize an AbstractDiagnosticFormatter by setting its JavacMessages object 1.19 * @param messages 1.20 */ 1.21 - protected AbstractDiagnosticFormatter(JavacMessages messages) { 1.22 + protected AbstractDiagnosticFormatter(JavacMessages messages, Options options, boolean showSource) { 1.23 this.messages = messages; 1.24 + this.showSource = options.get("showSource") == null ? showSource : 1.25 + options.get("showSource").equals("true"); 1.26 + } 1.27 + 1.28 + protected AbstractDiagnosticFormatter(JavacMessages messages, boolean showSource) { 1.29 + this.messages = messages; 1.30 + this.showSource = showSource; 1.31 } 1.32 1.33 public String formatMessage(JCDiagnostic d, Locale l) { 1.34 @@ -156,6 +165,27 @@ 1.35 return sbuf.toString(); 1.36 } 1.37 1.38 + /** Format the faulty source code line and point to the error. 1.39 + * @param d The diagnostic for which the error line should be printed 1.40 + */ 1.41 + protected String formatSourceLine(JCDiagnostic d) { 1.42 + StringBuilder buf = new StringBuilder(); 1.43 + DiagnosticSource source = d.getDiagnosticSource(); 1.44 + int pos = d.getIntPosition(); 1.45 + if (d.getIntPosition() != Position.NOPOS) { 1.46 + String line = (source == null ? null : source.getLine(pos)); 1.47 + if (line == null) 1.48 + return ""; 1.49 + buf.append(line+"\n"); 1.50 + int col = source.getColumnNumber(pos, false); 1.51 + for (int i = 0; i < col - 1; i++) { 1.52 + buf.append((line.charAt(i) == '\t') ? "\t" : " "); 1.53 + } 1.54 + buf.append("^"); 1.55 + } 1.56 + return buf.toString(); 1.57 + } 1.58 + 1.59 /** 1.60 * Converts a String into a locale-dependent representation accordingly to a given locale 1.61 * 1.62 @@ -167,4 +197,8 @@ 1.63 protected String localize(Locale l, String key, Object... args) { 1.64 return messages.getLocalizedString(l, key, args); 1.65 } 1.66 + 1.67 + public boolean displaySource(JCDiagnostic d) { 1.68 + return showSource && d.getType() != FRAGMENT; 1.69 + } 1.70 }
2.1 --- a/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java Thu Oct 09 16:07:38 2008 +0100 2.2 +++ b/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java Thu Oct 09 16:19:13 2008 +0100 2.3 @@ -62,7 +62,8 @@ 2.4 * @param msgs JavacMessages object used for i18n 2.5 */ 2.6 BasicDiagnosticFormatter(Options opts, JavacMessages msgs) { 2.7 - this(msgs); //common init 2.8 + super(msgs, opts, true); 2.9 + initAvailableFormats(); 2.10 String fmt = opts.get("diags"); 2.11 if (fmt != null) { 2.12 String[] formats = fmt.split("\\|"); 2.13 @@ -83,7 +84,11 @@ 2.14 * @param msgs JavacMessages object used for i18n 2.15 */ 2.16 public BasicDiagnosticFormatter(JavacMessages msgs) { 2.17 - super(msgs); 2.18 + super(msgs, true); 2.19 + initAvailableFormats(); 2.20 + } 2.21 + 2.22 + public void initAvailableFormats() { 2.23 availableFormats = new HashMap<BasicFormatKind, String>(); 2.24 availableFormats.put(DEFAULT_POS_FORMAT, "%f:%l:%_%t%m"); 2.25 availableFormats.put(DEFAULT_NO_POS_FORMAT, "%p%m"); 2.26 @@ -104,6 +109,9 @@ 2.27 } 2.28 buf.append(meta ? formatMeta(c, d, l) : String.valueOf(c)); 2.29 } 2.30 + if (displaySource(d)) { 2.31 + buf.append("\n" + formatSourceLine(d)); 2.32 + } 2.33 return buf.toString(); 2.34 } 2.35 2.36 @@ -167,10 +175,6 @@ 2.37 return format; 2.38 } 2.39 2.40 - public boolean displaySource(JCDiagnostic d) { 2.41 - return true; 2.42 - } 2.43 - 2.44 /** 2.45 * This enum contains all the kinds of formatting patterns supported 2.46 * by a basic diagnostic formatter.
3.1 --- a/src/share/classes/com/sun/tools/javac/util/Log.java Thu Oct 09 16:07:38 2008 +0100 3.2 +++ b/src/share/classes/com/sun/tools/javac/util/Log.java Thu Oct 09 16:19:13 2008 +0100 3.3 @@ -120,7 +120,7 @@ 3.4 3.5 boolean rawDiagnostics = options.get("rawDiagnostics") != null; 3.6 messages = JavacMessages.instance(context); 3.7 - this.diagFormatter = rawDiagnostics ? new RawDiagnosticFormatter(messages) : 3.8 + this.diagFormatter = rawDiagnostics ? new RawDiagnosticFormatter(options) : 3.9 new BasicDiagnosticFormatter(options, messages); 3.10 @SuppressWarnings("unchecked") // FIXME 3.11 DiagnosticListener<? super JavaFileObject> diagListener = 3.12 @@ -340,14 +340,6 @@ 3.13 PrintWriter writer = getWriterForDiagnosticType(diag.getType()); 3.14 3.15 printLines(writer, diagFormatter.format(diag, messages.getCurrentLocale())); 3.16 - if (diagFormatter.displaySource(diag)) { 3.17 - int pos = diag.getIntPosition(); 3.18 - if (pos != Position.NOPOS) { 3.19 - JavaFileObject prev = useSource(diag.getSource()); 3.20 - printErrLine(pos, writer); 3.21 - useSource(prev); 3.22 - } 3.23 - } 3.24 3.25 if (promptOnError) { 3.26 switch (diag.getType()) {
4.1 --- a/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java Thu Oct 09 16:07:38 2008 +0100 4.2 +++ b/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java Thu Oct 09 16:19:13 2008 +0100 4.3 @@ -41,8 +41,8 @@ 4.4 * Create a formatter based on the supplied options. 4.5 * @param msgs 4.6 */ 4.7 - public RawDiagnosticFormatter(JavacMessages msgs) { 4.8 - super(null); 4.9 + public RawDiagnosticFormatter(Options opts) { 4.10 + super(null, opts, false); 4.11 } 4.12 4.13 //provide common default formats 4.14 @@ -61,6 +61,8 @@ 4.15 buf.append('-'); 4.16 buf.append(' '); 4.17 buf.append(formatMessage(d, null)); 4.18 + if (displaySource(d)) 4.19 + buf.append("\n" + formatSourceLine(d)); 4.20 return buf.toString(); 4.21 } 4.22 catch (Exception e) { 4.23 @@ -94,8 +96,4 @@ 4.24 } 4.25 return buf.toString(); 4.26 } 4.27 - 4.28 - public boolean displaySource(JCDiagnostic d) { 4.29 - return false; 4.30 - } 4.31 }
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/tools/javac/api/6731573/Erroneous.java Thu Oct 09 16:19:13 2008 +0100 5.3 @@ -0,0 +1,4 @@ 5.4 +class A { 5.5 + boolean b; 5.6 + boolean b; 5.7 +} 5.8 \ No newline at end of file
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/tools/javac/api/6731573/T6731573.java Thu Oct 09 16:19:13 2008 +0100 6.3 @@ -0,0 +1,109 @@ 6.4 +/* 6.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 6.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 6.24 + * have any questions. 6.25 + */ 6.26 + 6.27 +/* 6.28 + * @test 6.29 + * @bug 6731573 6.30 + * @summary diagnostic output should optionally include source line 6.31 + * @author Maurizio Cimadamore 6.32 + * @library ../lib 6.33 + */ 6.34 + 6.35 +import java.io.*; 6.36 +import java.util.*; 6.37 +import javax.tools.*; 6.38 + 6.39 +public class T6731573 extends ToolTester { 6.40 + 6.41 + enum DiagnosticType { 6.42 + BASIC(null) { 6.43 + boolean shouldDisplaySource(SourceLine sourceLine) { 6.44 + return sourceLine != SourceLine.DISABLED; 6.45 + } 6.46 + }, 6.47 + RAW("-XDrawDiagnostics") { 6.48 + boolean shouldDisplaySource(SourceLine sourceLine) { 6.49 + return sourceLine == SourceLine.ENABLED; 6.50 + } 6.51 + }; 6.52 + 6.53 + String optValue; 6.54 + 6.55 + DiagnosticType(String optValue) { 6.56 + this.optValue = optValue; 6.57 + } 6.58 + 6.59 + abstract boolean shouldDisplaySource(SourceLine sourceLine); 6.60 + } 6.61 + 6.62 + enum SourceLine { 6.63 + STANDARD(null), 6.64 + ENABLED("-XDshowSource=true"), 6.65 + DISABLED("-XDshowSource=false"); 6.66 + 6.67 + String optValue; 6.68 + 6.69 + SourceLine(String optValue) { 6.70 + this.optValue = optValue; 6.71 + } 6.72 + } 6.73 + 6.74 + void checkErrorLine(String output, boolean expected, List<String> options) { 6.75 + System.err.println("\noptions = "+options); 6.76 + System.err.println(output); 6.77 + boolean errLinePresent = output.contains("^"); 6.78 + if (errLinePresent != expected) { 6.79 + throw new AssertionError("Error in diagnostic: error line" + 6.80 + (expected ? "" : " not") + " expected but" + 6.81 + (errLinePresent ? "" : " not") + " found"); 6.82 + } 6.83 + } 6.84 + 6.85 + void exec(DiagnosticType diagType, SourceLine sourceLine) { 6.86 + final Iterable<? extends JavaFileObject> compilationUnits = 6.87 + fm.getJavaFileObjects(new File(test_src, "Erroneous.java")); 6.88 + StringWriter pw = new StringWriter(); 6.89 + ArrayList<String> options = new ArrayList<String>(); 6.90 + if (diagType.optValue != null) 6.91 + options.add(diagType.optValue); 6.92 + if (sourceLine.optValue != null) 6.93 + options.add(sourceLine.optValue); 6.94 + task = tool.getTask(pw, fm, null, options, null, compilationUnits); 6.95 + task.call(); 6.96 + checkErrorLine(pw.toString(), 6.97 + diagType.shouldDisplaySource(sourceLine), 6.98 + options); 6.99 + } 6.100 + 6.101 + void test() { 6.102 + for (DiagnosticType dt : DiagnosticType.values()) { 6.103 + for (SourceLine sl : SourceLine.values()) { 6.104 + exec(dt, sl); 6.105 + } 6.106 + } 6.107 + } 6.108 + 6.109 + public static void main(String... args) throws Exception { 6.110 + new T6731573().test(); 6.111 + } 6.112 +} 6.113 \ No newline at end of file