6720185: DiagnosticFormatter refactoring
Summary: Brand new hierarchy of diagnostic formatters for achieving better reusability
Reviewed-by: jjg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java Mon Jul 28 10:22:10 2008 +0100
@@ -0,0 +1,117 @@
+/*
+ * 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package com.sun.tools.javac.api;
+
+import java.util.Locale;
+import javax.tools.Diagnostic;
+
+/**
+ * Provides simple functionalities for javac diagnostic formatting
+ * @param <D> type of diagnostic handled by this formatter
+ */
+public interface DiagnosticFormatter<D extends Diagnostic<?>> {
+
+ /**
+ * Whether the source code output for this diagnostic is to be displayed
+ *
+ * @param diag diagnostic to be formatted
+ * @return true if the source line this diagnostic refers to is to be displayed
+ */
+ boolean displaySource(D diag);
+
+ /**
+ * Format the contents of a diagnostics
+ *
+ * @param diag the diagnostic to be formatted
+ * @param l locale object to be used for i18n
+ * @return a string representing the diagnostic
+ */
+ public String format(D diag, Locale l);
+
+ /**
+ * Controls the way in which a diagnostic message is displayed.
+ *
+ * @param diag diagnostic to be formatted
+ * @param l locale object to be used for i18n
+ * @return string representation of the diagnostic message
+ */
+ public String formatMessage(D diag,Locale l);
+
+ /**
+ * Controls the way in which a diagnostic kind is displayed.
+ *
+ * @param diag diagnostic to be formatted
+ * @param l locale object to be used for i18n
+ * @return string representation of the diagnostic prefix
+ */
+ public String formatKind(D diag, Locale l);
+
+ /**
+ * Controls the way in which a diagnostic source is displayed.
+ *
+ * @param diag diagnostic to be formatted
+ * @param l locale object to be used for i18n
+ * @return string representation of the diagnostic source
+ */
+ public String formatSource(D diag, Locale l);
+
+ /**
+ * Controls the way in which a diagnostic position is displayed.
+ *
+ * @param diag diagnostic to be formatted
+ * @param pk enum constant representing the position kind
+ * @param l locale object to be used for i18n
+ * @return string representation of the diagnostic position
+ */
+ public String formatPosition(D diag, PositionKind pk, Locale l);
+ //where
+ /**
+ * This enum defines a set of constants for all the kinds of position
+ * that a diagnostic can be asked for. All positions are intended to be
+ * relative to a given diagnostic source.
+ */
+ public enum PositionKind {
+ /**
+ * Start position
+ */
+ START,
+ /**
+ * End position
+ */
+ END,
+ /**
+ * Line number
+ */
+ LINE,
+ /**
+ * Column number
+ */
+ COLUMN,
+ /**
+ * Offset position
+ */
+ OFFSET
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Mon Jul 28 10:22:10 2008 +0100
@@ -0,0 +1,169 @@
+/*
+ * 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package com.sun.tools.javac.util;
+
+import java.util.Collection;
+import java.util.Locale;
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.api.DiagnosticFormatter;
+import com.sun.tools.javac.api.Formattable;
+import com.sun.tools.javac.api.DiagnosticFormatter.PositionKind;
+import com.sun.tools.javac.file.JavacFileManager;
+
+/**
+ * This abstract class provides a basic implementation of the functionalities that should be provided
+ * by any formatter used by javac. Among the main features provided by AbstractDiagnosticFormatter are:
+ *
+ * <ul>
+ * <li> Provides a standard implementation of the visitor-like methods defined in the interface DiagnisticFormatter.
+ * Those implementations are specifically targeting JCDiagnostic objects.
+ * <li> Provides basic support for i18n and a method for executing all locale-dependent conversions
+ * <li> Provides the formatting logic for rendering the arguments of a JCDiagnostic object.
+ * <ul>
+ *
+ */
+public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter<JCDiagnostic> {
+
+ /**
+ * Messages object used by this formatter for i18n
+ */
+ protected Messages messages;
+
+ /**
+ * Initialize an AbstractDiagnosticFormatter by setting its Messages object
+ * @param messages
+ */
+ protected AbstractDiagnosticFormatter(Messages messages) {
+ this.messages = messages;
+ }
+
+ public String formatMessage(JCDiagnostic d, Locale l) {
+ //this code should rely on the locale settings but it's not! See RFE 6443132
+ Collection<String> args = formatArguments(d, l);
+ return localize(l, d.getCode(), args.toArray());
+ }
+
+ public String formatKind(JCDiagnostic d, Locale l) {
+ switch (d.getType()) {
+ case FRAGMENT: return "";
+ case NOTE: return localize(l, "compiler.note.note");
+ case WARNING: return localize(l, "compiler.warn.warning");
+ case ERROR: return localize(l, "compiler.err.error");
+ default:
+ throw new AssertionError("Unknown diagnostic type: " + d.getType());
+ }
+ }
+
+ public String formatPosition(JCDiagnostic d, PositionKind pk,Locale l) {
+ assert (d.getPosition() != Position.NOPOS);
+ return String.valueOf(getPosition(d, pk));
+ }
+ //WHERE
+ public long getPosition(JCDiagnostic d, PositionKind pk) {
+ switch (pk) {
+ case START: return d.getIntStartPosition();
+ case END: return d.getIntEndPosition();
+ case LINE: return d.getLineNumber();
+ case COLUMN: return d.getColumnNumber();
+ case OFFSET: return d.getIntPosition();
+ default:
+ throw new AssertionError("Unknown diagnostic position: " + pk);
+ }
+ }
+
+ public String formatSource(JCDiagnostic d,Locale l) {
+ assert (d.getSource() != null);
+ return d.getSource().getName();
+ }
+
+ /**
+ * Format the arguments of a given diagnostic.
+ *
+ * @param d diagnostic whose arguments are to be formatted
+ * @param l locale object to be used for i18n
+ * @return a Collection whose elements are the formatted arguments of the diagnostic
+ */
+ protected Collection<String> formatArguments(JCDiagnostic d, Locale l) {
+ ListBuffer<String> buf = new ListBuffer<String>();
+ for (Object o : d.getArgs()) {
+ buf.append(formatArgument(d, o, l));
+ }
+ return buf.toList();
+ }
+
+ /**
+ * Format a single argument of a given diagnostic.
+ *
+ * @param d diagnostic whose argument is to be formatted
+ * @param arg argument to be formatted
+ * @param l locale object to be used for i18n
+ * @return string representation of the diagnostic argument
+ */
+ protected String formatArgument(JCDiagnostic d, Object arg, Locale l) {
+ if (arg instanceof JCDiagnostic)
+ return format((JCDiagnostic)arg, l);
+ else if (arg instanceof Iterable<?>) {
+ return formatIterable(d, (Iterable<?>)arg, l);
+ }
+ else if (arg instanceof JavaFileObject)
+ return JavacFileManager.getJavacBaseFileName((JavaFileObject)arg);
+ else if (arg instanceof Formattable)
+ return ((Formattable)arg).toString(Messages.getDefaultBundle());
+ else
+ return String.valueOf(arg);
+ }
+
+ /**
+ * Format an iterable argument of a given diagnostic.
+ *
+ * @param d diagnostic whose argument is to be formatted
+ * @param it iterable argument to be formatted
+ * @param l locale object to be used for i18n
+ * @return string representation of the diagnostic iterable argument
+ */
+ protected String formatIterable(JCDiagnostic d, Iterable<?> it, Locale l) {
+ StringBuilder sbuf = new StringBuilder();
+ String sep = "";
+ for (Object o : it) {
+ sbuf.append(sep);
+ sbuf.append(formatArgument(d, o, l));
+ sep = ",";
+ }
+ return sbuf.toString();
+ }
+
+ /**
+ * Converts a String into a locale-dependent representation accordingly to a given locale
+ *
+ * @param l locale object to be used for i18n
+ * @param key locale-independent key used for looking up in a resource file
+ * @param args localization arguments
+ * @return a locale-dependent string
+ */
+ protected String localize(Locale l, String key, Object... args) {
+ return messages.getLocalizedString(key, args);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java Mon Jul 28 10:22:10 2008 +0100
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2005-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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.tools.javac.util;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import javax.tools.JavaFileObject;
+
+import static com.sun.tools.javac.util.BasicDiagnosticFormatter.BasicFormatKind.*;
+import static com.sun.tools.javac.api.DiagnosticFormatter.PositionKind.*;
+
+/**
+ * A basic formatter for diagnostic messages.
+ * The basic formatter will format a diagnostic according to one of three format patterns, depending on whether
+ * or not the source name and position are set. The formatter supports a printf-like string for patterns
+ * with the following special characters:
+ * <ul>
+ * <li>%b: the base of the source name
+ * <li>%f: the source name (full absolute path)
+ * <li>%l: the line number of the diagnostic, derived from the character offset
+ * <li>%c: the column number of the diagnostic, derived from the character offset
+ * <li>%o: the character offset of the diagnostic if set
+ * <li>%p: the prefix for the diagnostic, derived from the diagnostic type
+ * <li>%t: the prefix as it normally appears in standard diagnostics. In this case, no prefix is
+ * shown if the type is ERROR and if a source name is set
+ * <li>%m: the text or the diagnostic, including any appropriate arguments
+ * <li>%_: space delimiter, useful for formatting purposes
+ * </ul>
+ */
+public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter {
+
+ protected Map<BasicFormatKind, String> availableFormats;
+
+ /**
+ * Create a basic formatter based on the supplied options.
+ *
+ * @param opts list of command-line options
+ * @param msgs Messages object used for i18n
+ */
+ BasicDiagnosticFormatter(Options opts, Messages msgs) {
+ this(msgs); //common init
+ String fmt = opts.get("diags");
+ if (fmt != null) {
+ String[] formats = fmt.split("\\|");
+ switch (formats.length) {
+ case 3:
+ availableFormats.put(DEFAULT_CLASS_FORMAT, formats[2]);
+ case 2:
+ availableFormats.put(DEFAULT_NO_POS_FORMAT, formats[1]);
+ default:
+ availableFormats.put(DEFAULT_POS_FORMAT, formats[0]);
+ }
+ }
+ }
+
+ /**
+ * Create a standard basic formatter
+ *
+ * @param msgs Messages object used for i18n
+ */
+ public BasicDiagnosticFormatter(Messages msgs) {
+ super(msgs);
+ availableFormats = new HashMap<BasicFormatKind, String>();
+ availableFormats.put(DEFAULT_POS_FORMAT, "%f:%l:%_%t%m");
+ availableFormats.put(DEFAULT_NO_POS_FORMAT, "%p%m");
+ availableFormats.put(DEFAULT_CLASS_FORMAT, "%f:%_%t%m");
+ }
+
+ public String format(JCDiagnostic d, Locale l) {
+ String format = selectFormat(d);
+ StringBuilder buf = new StringBuilder();
+ for (int i = 0; i < format.length(); i++) {
+ char c = format.charAt(i);
+ boolean meta = false;
+ if (c == '%' && i < format.length() - 1) {
+ meta = true;
+ c = format.charAt(++i);
+ }
+ buf.append(meta ? formatMeta(c, d, l) : String.valueOf(c));
+ }
+ return buf.toString();
+ }
+
+ protected String formatMeta(char c, JCDiagnostic d, Locale l) {
+ switch (c) {
+ case 'b':
+ return formatSource(d, l);
+ case 'e':
+ return formatPosition(d, END, l);
+ case 'f':
+ return formatSource(d, l);
+ case 'l':
+ return formatPosition(d, LINE, l);
+ case 'c':
+ return formatPosition(d, COLUMN, l);
+ case 'o':
+ return formatPosition(d, OFFSET, l);
+ case 'p':
+ return formatKind(d, l);
+ case 's':
+ return formatPosition(d, START, l);
+ case 't': {
+ boolean usePrefix;
+ switch (d.getType()) {
+ case FRAGMENT:
+ usePrefix = false;
+ break;
+ case ERROR:
+ usePrefix = (d.getIntPosition() == Position.NOPOS);
+ break;
+ default:
+ usePrefix = true;
+ }
+ if (usePrefix)
+ return formatKind(d, l);
+ else
+ return "";
+ }
+ case 'm':
+ return formatMessage(d, l);
+ case '_':
+ return " ";
+ case '%':
+ return "%";
+ default:
+ return String.valueOf(c);
+ }
+ }
+
+ private String selectFormat(JCDiagnostic d) {
+ DiagnosticSource source = d.getDiagnosticSource();
+ String format = availableFormats.get(DEFAULT_NO_POS_FORMAT);
+ if (source != null) {
+ if (d.getIntPosition() != Position.NOPOS) {
+ format = availableFormats.get(DEFAULT_POS_FORMAT);
+ } else if (source.getFile() != null &&
+ source.getFile().getKind() == JavaFileObject.Kind.CLASS) {
+ format = availableFormats.get(DEFAULT_CLASS_FORMAT);
+ }
+ }
+ return format;
+ }
+
+ public boolean displaySource(JCDiagnostic d) {
+ return true;
+ }
+
+ /**
+ * This enum contains all the kinds of formatting patterns supported
+ * by a basic diagnostic formatter.
+ */
+ public enum BasicFormatKind {
+ /**
+ * A format string to be used for diagnostics with a given position.
+ */
+ DEFAULT_POS_FORMAT,
+ /**
+ * A format string to be used for diagnostics without a given position.
+ */
+ DEFAULT_NO_POS_FORMAT,
+ /**
+ * A format string to be used for diagnostics regarding classfiles
+ */
+ DEFAULT_CLASS_FORMAT;
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java Fri Jul 25 12:22:09 2008 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,267 +0,0 @@
-/*
- * Copyright 2005-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. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package com.sun.tools.javac.util;
-
-import java.util.Collection;
-import javax.tools.JavaFileObject;
-
-import com.sun.tools.javac.file.JavacFileManager;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
-
-/**
- * A formatter for diagnostic messages.
- * The formatter will format a diagnostic according to one of two format strings, depending on whether
- * or not the source name and position are set. The format is a printf-like string,
- * with the following special characters:
- * <ul>
- * <li>%b: the base of the source name, or "-" if not set
- * <li>%f: the source name, or "-" if not set
- * <li>%l: the line number of the diagnostic, derived from the character offset if set, or "-" otherwise
- * <li>%c: the column number of the diagnostic, derived from the character offset if set, or "-" otherwise
- * <li>%o: the character offset of the diagnostic if set, or "-" otherwise
- * <li>%p: the prefix for the diagnostic, derived from the diagnostic type
- * <li>%t: the prefix as it normally appears in standard diagnostics. In this case, no prefix is
- * shown if the type is ERROR and if a source name is set
- * <li>%m: the text or the diagnostic, including any appropriate arguments
- * </ul>
- */
-public class DiagnosticFormatter {
- /**
- * A format string to be used for diagnostics with a given position.
- */
- protected String posFormat;
-
- /**
- * A format string to be used for diagnostics regarding classfiles
- */
- protected String classFormat = DEFAULT_CLASS_FORMAT;
-
- /**
- * A format string to be used for diagnostics without a given position.
- */
- protected String noPosFormat;
-
- /**
- * A value to indicate whether to output the i18n key and args, instead of
- * the derived l10n message.
- */
- protected boolean raw;
-
- /** The context key for the formatter. */
- protected static final Context.Key<DiagnosticFormatter> formatterKey =
- new Context.Key<DiagnosticFormatter>();
-
- /** Get the DiagnosticFormatter instance for this context. */
- public static DiagnosticFormatter instance(Context context) {
- DiagnosticFormatter instance = context.get(formatterKey);
- if (instance == null)
- instance = new DiagnosticFormatter(context);
- return instance;
- }
-
- /**
- * Create a formatter based on the supplied options.
- */
- protected DiagnosticFormatter(Context context) {
- Options options = Options.instance(context);
- raw = options.get("rawDiagnostics") != null;
- String fmt = options.get("diags");
- if (fmt != null) {
- int sep = fmt.indexOf('|');
- if (sep == -1)
- posFormat = noPosFormat = fmt;
- else {
- posFormat = fmt.substring(0, sep);
- noPosFormat = fmt.substring(sep + 1);
- }
- }
- else {
- posFormat = DEFAULT_POS_FORMAT;
- noPosFormat = DEFAULT_NO_POS_FORMAT;
- }
- }
-
- public static final String DEFAULT_POS_FORMAT = "%f:%l: %t%m";
- public static final String DEFAULT_CLASS_FORMAT = "%f: %t%m";
- public static final String DEFAULT_NO_POS_FORMAT = "%p%m";
-
- public DiagnosticFormatter() {
- posFormat = DEFAULT_POS_FORMAT;
- noPosFormat = DEFAULT_NO_POS_FORMAT;
- raw = false;
- }
-
- public DiagnosticFormatter(String pos, String noPos) {
- posFormat = pos;
- noPosFormat = noPos;
- raw = false;
- }
-
- String format(JCDiagnostic d) {
- return (raw ? format_raw(d) : format_std(d));
- }
-
- private String format_raw(JCDiagnostic d) {
- DiagnosticSource source = d.getDiagnosticSource();
- int position = d.getIntPosition();
-
- StringBuilder sb = new StringBuilder();
- if (position == Position.NOPOS)
- sb.append("-");
- else {
- sb.append(source.getName() + ":" + source.getLineNumber(position) + ":" + source.getColumnNumber(position) + ":");
- }
- sb.append(" ");
- sb.append(d.getCode());
- String sep = ": ";
- for (Object arg: d.getArgs()) {
- sb.append(sep);
- if (arg instanceof JCDiagnostic) {
- sb.append('(');
- sb.append(format_raw((JCDiagnostic) arg));
- sb.append(')');
- }
- else if (arg instanceof JavaFileObject)
- sb.append(JavacFileManager.getJavacBaseFileName((JavaFileObject) arg));
- else if (arg instanceof Collection<?>)
- sb.append(convert((Collection<?>)arg));
- else
- sb.append(arg);
- sep = ", ";
- }
- return sb.toString();
- }
-
- static <T> List<T> convert(Collection<T> c) {
- if (c instanceof List<?>)
- return (List<T>)c;
- else {
- List<T> l = List.<T>nil();
- for (T t : c) {
- l = l.prepend(t);
- }
- return l.reverse();
- }
- }
-
- private String format_std(JCDiagnostic d) {
- DiagnosticSource source = d.getDiagnosticSource();
- DiagnosticType type = d.getType();
- int position = d.getIntPosition();
-
-
- String format = noPosFormat;
- if (source != null) {
- if (position != Position.NOPOS) {
- format = posFormat;
- } else if (source.getFile() != null &&
- source.getFile().getKind() == JavaFileObject.Kind.CLASS) {
- format = classFormat;
- }
- }
-
- StringBuilder sb = new StringBuilder();
-
- for (int i = 0; i < format.length(); i++) {
- char c = format.charAt(i);
- if (c == '%' && i < format.length() - 1) {
- c = format.charAt(++i);
- switch (c) {
- case 'b':
- sb.append(source == null ? "-" : source.getName());
- break;
-
- case 'e':
- sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getEndPosition()));
- break;
-
- case 'f':
- sb.append(source == null ? "-" : d.getSourceName());
- break;
-
- case 'l':
- sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getLineNumber()));
- break;
-
- case 'c':
- sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getColumnNumber()));
- break;
-
- case 'o':
- sb.append(position == Position.NOPOS ? "-" : String.valueOf(position));
- break;
-
- case 'p':
- sb.append(d.getPrefix());
- break;
-
- case 's':
- sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getStartPosition()));
- break;
-
- case 't': {
- boolean usePrefix;
- switch (type) {
- case FRAGMENT:
- usePrefix = false;
- break;
-
- case ERROR:
- usePrefix = (position == Position.NOPOS);
- break;
-
- default:
- usePrefix = true;
- }
-
- if (usePrefix)
- sb.append(d.getPrefix());
- break;
- }
-
- case 'm':
- sb.append(d.getMessage(null));
- break;
-
- case '_':
- sb.append(' ');
- break;
-
- case '%':
- sb.append('%');
- break;
-
- default:
- sb.append(c);
- break;
- }
- }
- else
- sb.append(c);
- }
- return sb.toString();
- }
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Fri Jul 25 12:22:09 2008 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Mon Jul 28 10:22:10 2008 +0100
@@ -25,15 +25,13 @@
package com.sun.tools.javac.util;
-import java.util.ResourceBundle;
-import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
-import com.sun.tools.javac.api.Formattable;
+import com.sun.tools.javac.api.DiagnosticFormatter;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.tree.JCTree;
@@ -256,7 +254,7 @@
private final int line;
private final int column;
private final String key;
- private final Object[] args;
+ protected Object[] args;
private boolean mandatory;
/**
@@ -400,52 +398,25 @@
* @return the prefix string associated with a particular type of diagnostic
*/
public String getPrefix(DiagnosticType dt) {
- switch (dt) {
- case FRAGMENT: return "";
- case NOTE: return getLocalizedString("compiler.note.note");
- case WARNING: return getLocalizedString("compiler.warn.warning");
- case ERROR: return getLocalizedString("compiler.err.error");
- default:
- throw new AssertionError("Unknown diagnostic type: " + dt);
+ return getFormatter().formatKind(this, Locale.getDefault());
+ }
+
+ private DiagnosticFormatter<JCDiagnostic> getFormatter() {
+ if (defaultFormatter == null) {
+ defaultFormatter = new BasicDiagnosticFormatter(messages);
}
+ return defaultFormatter;
}
+
/**
* Return the standard presentation of this diagnostic.
*/
public String toString() {
- if (defaultFormatter == null) {
- defaultFormatter =
- new DiagnosticFormatter();
- }
- return defaultFormatter.format(this);
+ return getFormatter().format(this,Locale.getDefault());
}
- private static DiagnosticFormatter defaultFormatter;
-
- private static final String messageBundleName =
- "com.sun.tools.javac.resources.compiler";
-
- private String getLocalizedString(String key, Object... args) {
- String[] strings = new String[args.length];
- for (int i = 0; i < strings.length; i++) {
- Object arg = args[i];
- if (arg == null)
- strings[i] = null;
- else if (arg instanceof JCDiagnostic)
- strings[i] = ((JCDiagnostic) arg).getMessage(null);
- else if (arg instanceof Collection<?>)
- strings[i] = DiagnosticFormatter.convert((Collection<?>)arg).toString();
- else if (arg instanceof Formattable) {
- ResourceBundle rb = ResourceBundle.getBundle(messageBundleName);
- strings[i] = ((Formattable)arg).toString(rb);
- }
- else
- strings[i] = arg.toString();
- }
-
- return messages.getLocalizedString(key, (Object[]) strings);
- }
+ private static DiagnosticFormatter<JCDiagnostic> defaultFormatter;
// Methods for javax.tools.Diagnostic
@@ -469,7 +440,6 @@
public String getMessage(Locale locale) {
// RFE 6406133: JCDiagnostic.getMessage ignores locale argument
- return getLocalizedString(key, args);
+ return getFormatter().formatMessage(this, locale);
}
-
}
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java Fri Jul 25 12:22:09 2008 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java Mon Jul 28 10:22:10 2008 +0100
@@ -29,11 +29,13 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.Locale;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.api.DiagnosticFormatter;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
@@ -68,10 +70,6 @@
public final int MaxErrors;
public final int MaxWarnings;
- /** Whether or not to display the line of source containing a diagnostic.
- */
- private final boolean showSourceLine;
-
/** Switch: prompt user on each error.
*/
public boolean promptOnError;
@@ -97,7 +95,7 @@
/**
* Formatter for diagnostics
*/
- private DiagnosticFormatter diagFormatter;
+ private DiagnosticFormatter<JCDiagnostic> diagFormatter;
/** Construct a log with given I/O redirections.
*/
@@ -115,9 +113,11 @@
this.emitWarnings = options.get("-Xlint:none") == null;
this.MaxErrors = getIntOption(options, "-Xmaxerrs", 100);
this.MaxWarnings = getIntOption(options, "-Xmaxwarns", 100);
- this.showSourceLine = options.get("rawDiagnostics") == null;
- this.diagFormatter = DiagnosticFormatter.instance(context);
+ boolean rawDiagnostics = options.get("rawDiagnostics") != null;
+ Messages msgs = Messages.instance(context);
+ this.diagFormatter = rawDiagnostics ? new RawDiagnosticFormatter(msgs) :
+ new BasicDiagnosticFormatter(options, msgs);
@SuppressWarnings("unchecked") // FIXME
DiagnosticListener<? super JavaFileObject> diagListener =
context.get(DiagnosticListener.class);
@@ -335,8 +335,8 @@
PrintWriter writer = getWriterForDiagnosticType(diag.getType());
- printLines(writer, diagFormatter.format(diag));
- if (showSourceLine) {
+ printLines(writer, diagFormatter.format(diag, Locale.getDefault()));
+ if (diagFormatter.displaySource(diag)) {
int pos = diag.getIntPosition();
if (pos != Position.NOPOS) {
JavaFileObject prev = useSource(diag.getSource());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java Mon Jul 28 10:22:10 2008 +0100
@@ -0,0 +1,107 @@
+/*
+ * 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package com.sun.tools.javac.util;
+
+import java.util.Locale;
+
+import com.sun.tools.javac.api.Formattable;
+import static com.sun.tools.javac.api.DiagnosticFormatter.PositionKind.*;
+
+/**
+ * A raw formatter for diagnostic messages.
+ * The raw formatter will format a diagnostic according to one of two format patterns, depending on whether
+ * or not the source name and position are set. This formatter provides a standardized, localize-independent
+ * implementation of a diagnostic formatter; as such, this formatter is best suited for testing purposes.
+ */
+public class RawDiagnosticFormatter extends AbstractDiagnosticFormatter {
+
+ /**
+ * Create a formatter based on the supplied options.
+ * @param msgs
+ */
+ public RawDiagnosticFormatter(Messages msgs) {
+ super(null);
+ }
+
+ //provide common default formats
+ public String format(JCDiagnostic d, Locale l) {
+ try {
+ StringBuffer buf = new StringBuffer();
+ if (d.getPosition() != Position.NOPOS) {
+ buf.append(formatSource(d, null));
+ buf.append(':');
+ buf.append(formatPosition(d, LINE, null));
+ buf.append(':');
+ buf.append(formatPosition(d, COLUMN, null));
+ buf.append(':');
+ }
+ else
+ buf.append('-');
+ buf.append(' ');
+ buf.append(formatMessage(d, null));
+ return buf.toString();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ public String formatSource(JCDiagnostic d,Locale l) {
+ assert(d.getSource() != null);
+ return d.getSource().getName();
+ }
+
+ @Override
+ protected String formatArgument(JCDiagnostic diag, Object arg, Locale l) {
+ String s;
+ if (arg instanceof Formattable)
+ s = arg.toString();
+ else
+ s = super.formatArgument(diag, arg, null);
+ if (arg instanceof JCDiagnostic)
+ return "(" + s + ")";
+ else
+ return s;
+ }
+
+ @Override
+ protected String localize(Locale l, String s, Object... args) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(s);
+ String sep = ": ";
+ for (Object o : args) {
+ buf.append(sep);
+ buf.append(o);
+ sep = ", ";
+ }
+ return buf.toString();
+ }
+
+ public boolean displaySource(JCDiagnostic d) {
+ return false;
+ }
+}