Wed, 12 Nov 2008 14:17:03 +0000
6768932: Add support for multiline diagnostics
Summary: Added basic support for multiline/tabular diagnostics
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Fri Nov 07 11:45:49 2008 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Wed Nov 12 14:17:03 2008 +0000 1.3 @@ -27,13 +27,13 @@ 1.4 import java.util.Collection; 1.5 import java.util.Locale; 1.6 import javax.tools.JavaFileObject; 1.7 -import java.util.ResourceBundle; 1.8 1.9 import com.sun.tools.javac.api.DiagnosticFormatter; 1.10 import com.sun.tools.javac.api.Formattable; 1.11 import com.sun.tools.javac.api.DiagnosticFormatter.PositionKind; 1.12 import com.sun.tools.javac.file.JavacFileManager; 1.13 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*; 1.14 +import static com.sun.tools.javac.util.LayoutCharacters.*; 1.15 1.16 /** 1.17 * This abstract class provides a basic implementation of the functionalities that should be provided 1.18 @@ -72,8 +72,13 @@ 1.19 1.20 public String formatMessage(JCDiagnostic d, Locale l) { 1.21 //this code should rely on the locale settings but it's not! See RFE 6443132 1.22 + StringBuilder buf = new StringBuilder(); 1.23 Collection<String> args = formatArguments(d, l); 1.24 - return localize(l, d.getCode(), args.toArray()); 1.25 + buf.append(localize(l, d.getCode(), args.toArray())); 1.26 + if (d.isMultiline()) { 1.27 + buf.append(formatSubdiagnostics(d, l)); 1.28 + } 1.29 + return buf.toString(); 1.30 } 1.31 1.32 public String formatKind(JCDiagnostic d, Locale l) { 1.33 @@ -165,6 +170,23 @@ 1.34 return sbuf.toString(); 1.35 } 1.36 1.37 + /** 1.38 + * Format all the subdiagnostics attached to a given diagnostic 1.39 + * 1.40 + * @param d diagnostic whose subdiagnostics are to be formatted 1.41 + * @param l locale object to be used for i18n 1.42 + * @return string representation of the subdiagnostics 1.43 + */ 1.44 + protected String formatSubdiagnostics(JCDiagnostic d, Locale l) { 1.45 + StringBuilder buf = new StringBuilder(); 1.46 + for (JCDiagnostic d2 : d.getSubdiagnostics()) { 1.47 + buf.append('\n'); 1.48 + String subdiagMsg = format(d2, l); 1.49 + buf.append(indent(subdiagMsg, DiagInc)); 1.50 + } 1.51 + return buf.toString(); 1.52 + } 1.53 + 1.54 /** Format the faulty source code line and point to the error. 1.55 * @param d The diagnostic for which the error line should be printed 1.56 */ 1.57 @@ -201,4 +223,44 @@ 1.58 public boolean displaySource(JCDiagnostic d) { 1.59 return showSource && d.getType() != FRAGMENT; 1.60 } 1.61 + 1.62 + /** 1.63 + * Creates a string with a given amount of empty spaces. Useful for 1.64 + * indenting the text of a diagnostic message. 1.65 + * 1.66 + * @param nSpaces the amount of spaces to be added to the result string 1.67 + * @return the indentation string 1.68 + */ 1.69 + protected String indentString(int nSpaces) { 1.70 + String spaces = " "; 1.71 + if (nSpaces <= spaces.length()) 1.72 + return spaces.substring(0, nSpaces); 1.73 + else { 1.74 + StringBuilder buf = new StringBuilder(); 1.75 + for (int i = 0 ; i < nSpaces ; i++) 1.76 + buf.append(" "); 1.77 + return buf.toString(); 1.78 + } 1.79 + } 1.80 + 1.81 + /** 1.82 + * Indent a string by prepending a given amount of empty spaces to each line 1.83 + * of the string 1.84 + * 1.85 + * @param s the string to be indented 1.86 + * @param nSpaces the amount of spaces that should be prepended to each line 1.87 + * of the string 1.88 + * @return an indented string 1.89 + */ 1.90 + protected String indent(String s, int nSpaces) { 1.91 + String indent = indentString(nSpaces); 1.92 + StringBuilder buf = new StringBuilder(); 1.93 + String nl = ""; 1.94 + for (String line : s.split("\n")) { 1.95 + buf.append(nl); 1.96 + buf.append(indent + line); 1.97 + nl = "\n"; 1.98 + } 1.99 + return buf.toString(); 1.100 + } 1.101 }
2.1 --- a/src/share/classes/com/sun/tools/javac/util/AbstractLog.java Fri Nov 07 11:45:49 2008 -0800 2.2 +++ b/src/share/classes/com/sun/tools/javac/util/AbstractLog.java Wed Nov 12 14:17:03 2008 +0000 2.3 @@ -67,6 +67,12 @@ 2.4 return s; 2.5 } 2.6 2.7 + /** Return the underlying diagnostic source 2.8 + */ 2.9 + public DiagnosticSource currentSource() { 2.10 + return source; 2.11 + } 2.12 + 2.13 /** Report an error, unless another error was already reported at same 2.14 * source position. 2.15 * @param key The key for the localized error message.
3.1 --- a/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Fri Nov 07 11:45:49 2008 -0800 3.2 +++ b/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Wed Nov 12 14:17:03 2008 +0000 3.3 @@ -289,7 +289,7 @@ 3.4 this.source = source; 3.5 this.position = pos; 3.6 this.key = key; 3.7 - this.args = args; 3.8 + this.args = args; 3.9 3.10 int n = (pos == null ? Position.NOPOS : pos.getPreferredPosition()); 3.11 if (n == Position.NOPOS || source == null) 3.12 @@ -309,6 +309,18 @@ 3.13 } 3.14 3.15 /** 3.16 + * Get the subdiagnostic list 3.17 + * @return subdiagnostic list 3.18 + */ 3.19 + public List<JCDiagnostic> getSubdiagnostics() { 3.20 + return List.nil(); 3.21 + } 3.22 + 3.23 + public boolean isMultiline() { 3.24 + return false; 3.25 + } 3.26 + 3.27 + /** 3.28 * Check whether or not this diagnostic is required to be shown. 3.29 * @return true if this diagnostic is required to be shown. 3.30 */ 3.31 @@ -440,7 +452,32 @@ 3.32 } 3.33 3.34 public String getMessage(Locale locale) { 3.35 - // RFE 6406133: JCDiagnostic.getMessage ignores locale argument 3.36 return defaultFormatter.formatMessage(this, locale); 3.37 } 3.38 + 3.39 + public static class MultilineDiagnostic extends JCDiagnostic { 3.40 + 3.41 + private final List<JCDiagnostic> subdiagnostics; 3.42 + 3.43 + public MultilineDiagnostic(JCDiagnostic other, List<JCDiagnostic> subdiagnostics) { 3.44 + super(other.defaultFormatter, 3.45 + other.getType(), 3.46 + other.isMandatory(), 3.47 + other.getDiagnosticSource(), 3.48 + other.position, 3.49 + other.getCode(), 3.50 + other.getArgs()); 3.51 + this.subdiagnostics = subdiagnostics; 3.52 + } 3.53 + 3.54 + @Override 3.55 + public List<JCDiagnostic> getSubdiagnostics() { 3.56 + return subdiagnostics; 3.57 + } 3.58 + 3.59 + @Override 3.60 + public boolean isMultiline() { 3.61 + return true; 3.62 + } 3.63 + } 3.64 }
4.1 --- a/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java Fri Nov 07 11:45:49 2008 -0800 4.2 +++ b/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java Wed Nov 12 14:17:03 2008 +0000 4.3 @@ -39,6 +39,10 @@ 4.4 */ 4.5 final static int TabInc = 8; 4.6 4.7 + /** Diagnostic standard indentation 4.8 + */ 4.9 + final static int DiagInc = 2; 4.10 + 4.11 /** Tabulator character. 4.12 */ 4.13 final static byte TAB = 0x8;
5.1 --- a/src/share/classes/com/sun/tools/javac/util/Log.java Fri Nov 07 11:45:49 2008 -0800 5.2 +++ b/src/share/classes/com/sun/tools/javac/util/Log.java Wed Nov 12 14:17:03 2008 +0000 5.3 @@ -190,9 +190,9 @@ 5.4 getSource(name).setEndPosTable(table); 5.5 } 5.6 5.7 - /** Return current source name. 5.8 + /** Return current sourcefile. 5.9 */ 5.10 - public JavaFileObject currentSource() { 5.11 + public JavaFileObject currentSourceFile() { 5.12 return source == null ? null : source.getFile(); 5.13 } 5.14 5.15 @@ -395,7 +395,7 @@ 5.16 printLines(errWriter, "error: " + msg); 5.17 } else { 5.18 int line = source.getLineNumber(pos); 5.19 - JavaFileObject file = currentSource(); 5.20 + JavaFileObject file = source.getFile(); 5.21 if (file != null) 5.22 printLines(errWriter, 5.23 JavacFileManager.getJavacFileName(file) + ":" + 5.24 @@ -408,7 +408,7 @@ 5.25 /** report an error: 5.26 */ 5.27 public void rawError(int pos, String msg) { 5.28 - if (nerrors < MaxErrors && shouldReport(currentSource(), pos)) { 5.29 + if (nerrors < MaxErrors && shouldReport(currentSourceFile(), pos)) { 5.30 printRawError(pos, msg); 5.31 prompt(); 5.32 nerrors++;
6.1 --- a/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java Fri Nov 07 11:45:49 2008 -0800 6.2 +++ b/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java Wed Nov 12 14:17:03 2008 +0000 6.3 @@ -118,7 +118,7 @@ 6.4 * Report a mandatory warning. 6.5 */ 6.6 public void report(DiagnosticPosition pos, String msg, Object... args) { 6.7 - JavaFileObject currentSource = log.currentSource(); 6.8 + JavaFileObject currentSource = log.currentSourceFile(); 6.9 6.10 if (verbose) { 6.11 if (sourcesWithReportedWarnings == null)
7.1 --- a/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java Fri Nov 07 11:45:49 2008 -0800 7.2 +++ b/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java Wed Nov 12 14:17:03 2008 +0000 7.3 @@ -85,6 +85,20 @@ 7.4 } 7.5 7.6 @Override 7.7 + protected String formatSubdiagnostics(JCDiagnostic d, Locale l) { 7.8 + StringBuilder buf = new StringBuilder(); 7.9 + String sep = ""; 7.10 + buf.append(",{"); 7.11 + for (JCDiagnostic d2 : d.getSubdiagnostics()) { 7.12 + buf.append(sep); 7.13 + buf.append("(" + format(d2, l) + ")"); 7.14 + sep = ","; 7.15 + } 7.16 + buf.append('}'); 7.17 + return buf.toString(); 7.18 + } 7.19 + 7.20 + @Override 7.21 protected String localize(Locale l, String s, Object... args) { 7.22 StringBuffer buf = new StringBuffer(); 7.23 buf.append(s);