changeset 138:e4eaddca54b7

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
author mcimadamore
date Thu, 09 Oct 2008 16:19:13 +0100
parents 8eafba4f61be
children d766e40e49d6
files src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java src/share/classes/com/sun/tools/javac/util/Log.java src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java test/tools/javac/api/6731573/Erroneous.java test/tools/javac/api/6731573/T6731573.java
diffstat 6 files changed, 163 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Thu Oct 09 16:07:38 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Thu Oct 09 16:19:13 2008 +0100
@@ -33,6 +33,7 @@
 import com.sun.tools.javac.api.Formattable;
 import com.sun.tools.javac.api.DiagnosticFormatter.PositionKind;
 import com.sun.tools.javac.file.JavacFileManager;
+import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
 
 /**
  * This abstract class provides a basic implementation of the functionalities that should be provided
@@ -52,13 +53,21 @@
      * JavacMessages object used by this formatter for i18n
      */
     protected JavacMessages messages;
+    protected boolean showSource;
 
     /**
      * Initialize an AbstractDiagnosticFormatter by setting its JavacMessages object
      * @param messages
      */
-    protected AbstractDiagnosticFormatter(JavacMessages messages) {
+    protected AbstractDiagnosticFormatter(JavacMessages messages, Options options, boolean showSource) {
         this.messages = messages;
+        this.showSource = options.get("showSource") == null ? showSource :
+                          options.get("showSource").equals("true");
+    }
+
+    protected AbstractDiagnosticFormatter(JavacMessages messages, boolean showSource) {
+        this.messages = messages;
+        this.showSource = showSource;
     }
 
     public String formatMessage(JCDiagnostic d, Locale l) {
@@ -156,6 +165,27 @@
         return sbuf.toString();
     }
 
+    /** Format the faulty source code line and point to the error.
+     *  @param d The diagnostic for which the error line should be printed
+     */
+    protected String formatSourceLine(JCDiagnostic d) {
+        StringBuilder buf = new StringBuilder();
+        DiagnosticSource source = d.getDiagnosticSource();
+        int pos = d.getIntPosition();
+        if (d.getIntPosition() != Position.NOPOS) {
+            String line = (source == null ? null : source.getLine(pos));
+            if (line == null)
+                return "";
+            buf.append(line+"\n");
+            int col = source.getColumnNumber(pos, false);
+            for (int i = 0; i < col - 1; i++)  {
+                buf.append((line.charAt(i) == '\t') ? "\t" : " ");
+            }
+            buf.append("^");
+         }
+         return buf.toString();
+    }
+
     /**
      * Converts a String into a locale-dependent representation accordingly to a given locale
      *
@@ -167,4 +197,8 @@
     protected String localize(Locale l, String key, Object... args) {
         return messages.getLocalizedString(l, key, args);
     }
+
+    public boolean displaySource(JCDiagnostic d) {
+        return showSource && d.getType() != FRAGMENT;
+    }
 }
--- a/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java	Thu Oct 09 16:07:38 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java	Thu Oct 09 16:19:13 2008 +0100
@@ -62,7 +62,8 @@
      * @param msgs JavacMessages object used for i18n
      */
     BasicDiagnosticFormatter(Options opts, JavacMessages msgs) {
-        this(msgs); //common init
+        super(msgs, opts, true);
+        initAvailableFormats();
         String fmt = opts.get("diags");
         if (fmt != null) {
             String[] formats = fmt.split("\\|");
@@ -83,7 +84,11 @@
      * @param msgs JavacMessages object used for i18n
      */
     public BasicDiagnosticFormatter(JavacMessages msgs) {
-        super(msgs);
+        super(msgs, true);
+        initAvailableFormats();
+    }
+
+    public void initAvailableFormats() {
         availableFormats = new HashMap<BasicFormatKind, String>();
         availableFormats.put(DEFAULT_POS_FORMAT, "%f:%l:%_%t%m");
         availableFormats.put(DEFAULT_NO_POS_FORMAT, "%p%m");
@@ -104,6 +109,9 @@
             }
             buf.append(meta ? formatMeta(c, d, l) : String.valueOf(c));
         }
+        if (displaySource(d)) {
+            buf.append("\n" + formatSourceLine(d));
+        }
         return buf.toString();
     }
 
@@ -167,10 +175,6 @@
         return format;
     }
 
-    public boolean displaySource(JCDiagnostic d) {
-        return true;
-    }
-
     /**
      * This enum contains all the kinds of formatting patterns supported
      * by a basic diagnostic formatter.
--- a/src/share/classes/com/sun/tools/javac/util/Log.java	Thu Oct 09 16:07:38 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/util/Log.java	Thu Oct 09 16:19:13 2008 +0100
@@ -120,7 +120,7 @@
 
         boolean rawDiagnostics = options.get("rawDiagnostics") != null;
         messages = JavacMessages.instance(context);
-        this.diagFormatter = rawDiagnostics ? new RawDiagnosticFormatter(messages) :
+        this.diagFormatter = rawDiagnostics ? new RawDiagnosticFormatter(options) :
                                               new BasicDiagnosticFormatter(options, messages);
         @SuppressWarnings("unchecked") // FIXME
         DiagnosticListener<? super JavaFileObject> diagListener =
@@ -340,14 +340,6 @@
         PrintWriter writer = getWriterForDiagnosticType(diag.getType());
 
         printLines(writer, diagFormatter.format(diag, messages.getCurrentLocale()));
-        if (diagFormatter.displaySource(diag)) {
-            int pos = diag.getIntPosition();
-            if (pos != Position.NOPOS) {
-                JavaFileObject prev = useSource(diag.getSource());
-                printErrLine(pos, writer);
-                useSource(prev);
-            }
-        }
 
         if (promptOnError) {
             switch (diag.getType()) {
--- a/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java	Thu Oct 09 16:07:38 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java	Thu Oct 09 16:19:13 2008 +0100
@@ -41,8 +41,8 @@
      * Create a formatter based on the supplied options.
      * @param msgs
      */
-    public RawDiagnosticFormatter(JavacMessages msgs) {
-        super(null);
+    public RawDiagnosticFormatter(Options opts) {
+        super(null, opts, false);
     }
 
     //provide common default formats
@@ -61,6 +61,8 @@
                 buf.append('-');
             buf.append(' ');
             buf.append(formatMessage(d, null));
+            if (displaySource(d))
+                buf.append("\n" + formatSourceLine(d));
             return buf.toString();
         }
         catch (Exception e) {
@@ -94,8 +96,4 @@
         }
         return buf.toString();
     }
-
-    public boolean displaySource(JCDiagnostic d) {
-        return false;
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/api/6731573/Erroneous.java	Thu Oct 09 16:19:13 2008 +0100
@@ -0,0 +1,4 @@
+class A {
+    boolean b;
+    boolean b;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/api/6731573/T6731573.java	Thu Oct 09 16:19:13 2008 +0100
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug     6731573
+ * @summary diagnostic output should optionally include source line
+ * @author  Maurizio Cimadamore
+ * @library ../lib
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.tools.*;
+
+public class T6731573 extends ToolTester {
+
+    enum DiagnosticType {
+        BASIC(null) {
+            boolean shouldDisplaySource(SourceLine sourceLine) {
+                return sourceLine != SourceLine.DISABLED;
+            }
+        },
+        RAW("-XDrawDiagnostics") {
+            boolean shouldDisplaySource(SourceLine sourceLine) {
+                return sourceLine == SourceLine.ENABLED;
+            }
+        };
+
+        String optValue;
+
+        DiagnosticType(String optValue) {
+            this.optValue = optValue;
+        }
+
+        abstract boolean shouldDisplaySource(SourceLine sourceLine);
+    }
+
+    enum SourceLine {
+        STANDARD(null),
+        ENABLED("-XDshowSource=true"),
+        DISABLED("-XDshowSource=false");
+
+        String optValue;
+
+        SourceLine(String optValue) {
+            this.optValue = optValue;
+        }
+    }
+
+    void checkErrorLine(String output, boolean expected, List<String> options) {
+        System.err.println("\noptions = "+options);
+        System.err.println(output);
+        boolean errLinePresent = output.contains("^");
+        if (errLinePresent != expected) {
+            throw new AssertionError("Error in diagnostic: error line" +
+                    (expected ? "" : " not") + " expected but" +
+                    (errLinePresent ? "" : " not") + " found");
+        }
+    }
+
+    void exec(DiagnosticType diagType, SourceLine sourceLine) {
+        final Iterable<? extends JavaFileObject> compilationUnits =
+            fm.getJavaFileObjects(new File(test_src, "Erroneous.java"));
+        StringWriter pw = new StringWriter();
+        ArrayList<String> options = new ArrayList<String>();
+        if (diagType.optValue != null)
+            options.add(diagType.optValue);
+        if (sourceLine.optValue != null)
+            options.add(sourceLine.optValue);
+        task = tool.getTask(pw, fm, null, options, null, compilationUnits);
+        task.call();
+        checkErrorLine(pw.toString(),
+                diagType.shouldDisplaySource(sourceLine),
+                options);
+    }
+
+    void test() {
+        for (DiagnosticType dt : DiagnosticType.values()) {
+            for (SourceLine sl : SourceLine.values()) {
+                exec(dt, sl);
+            }
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        new T6731573().test();
+    }
+}
\ No newline at end of file