6720185: DiagnosticFormatter refactoring
Brand new hierarchy of diagnostic formatters for achieving better reusability Reviewed-by: jjg
This commit is contained in:
parent
fbde930522
commit
c936a75ed0
@ -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
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
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 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
* @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 class JCDiagnostic implements Diagnostic<JavaFileObject> {
|
||||
|
||||
public String getMessage(Locale locale) {
|
||||
// RFE 6406133: JCDiagnostic.getMessage ignores locale argument
|
||||
return getLocalizedString(key, args);
|
||||
return getFormatter().formatMessage(this, locale);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,11 +29,13 @@ import java.io.*;
|
||||
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 class Log extends AbstractLog {
|
||||
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 @@ public class Log extends AbstractLog {
|
||||
/**
|
||||
* Formatter for diagnostics
|
||||
*/
|
||||
private DiagnosticFormatter diagFormatter;
|
||||
private DiagnosticFormatter<JCDiagnostic> diagFormatter;
|
||||
|
||||
/** Construct a log with given I/O redirections.
|
||||
*/
|
||||
@ -115,9 +113,11 @@ public class Log extends AbstractLog {
|
||||
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 @@ public class Log extends AbstractLog {
|
||||
|
||||
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());
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user