Mon, 28 Jul 2008 10:22:10 +0100
6720185: DiagnosticFormatter refactoring
Summary: Brand new hierarchy of diagnostic formatters for achieving better reusability
Reviewed-by: jjg
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java Mon Jul 28 10:22:10 2008 +0100 1.3 @@ -0,0 +1,117 @@ 1.4 +/* 1.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Sun designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Sun in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.26 + * have any questions. 1.27 + */ 1.28 +package com.sun.tools.javac.api; 1.29 + 1.30 +import java.util.Locale; 1.31 +import javax.tools.Diagnostic; 1.32 + 1.33 +/** 1.34 + * Provides simple functionalities for javac diagnostic formatting 1.35 + * @param <D> type of diagnostic handled by this formatter 1.36 + */ 1.37 +public interface DiagnosticFormatter<D extends Diagnostic<?>> { 1.38 + 1.39 + /** 1.40 + * Whether the source code output for this diagnostic is to be displayed 1.41 + * 1.42 + * @param diag diagnostic to be formatted 1.43 + * @return true if the source line this diagnostic refers to is to be displayed 1.44 + */ 1.45 + boolean displaySource(D diag); 1.46 + 1.47 + /** 1.48 + * Format the contents of a diagnostics 1.49 + * 1.50 + * @param diag the diagnostic to be formatted 1.51 + * @param l locale object to be used for i18n 1.52 + * @return a string representing the diagnostic 1.53 + */ 1.54 + public String format(D diag, Locale l); 1.55 + 1.56 + /** 1.57 + * Controls the way in which a diagnostic message is displayed. 1.58 + * 1.59 + * @param diag diagnostic to be formatted 1.60 + * @param l locale object to be used for i18n 1.61 + * @return string representation of the diagnostic message 1.62 + */ 1.63 + public String formatMessage(D diag,Locale l); 1.64 + 1.65 + /** 1.66 + * Controls the way in which a diagnostic kind is displayed. 1.67 + * 1.68 + * @param diag diagnostic to be formatted 1.69 + * @param l locale object to be used for i18n 1.70 + * @return string representation of the diagnostic prefix 1.71 + */ 1.72 + public String formatKind(D diag, Locale l); 1.73 + 1.74 + /** 1.75 + * Controls the way in which a diagnostic source is displayed. 1.76 + * 1.77 + * @param diag diagnostic to be formatted 1.78 + * @param l locale object to be used for i18n 1.79 + * @return string representation of the diagnostic source 1.80 + */ 1.81 + public String formatSource(D diag, Locale l); 1.82 + 1.83 + /** 1.84 + * Controls the way in which a diagnostic position is displayed. 1.85 + * 1.86 + * @param diag diagnostic to be formatted 1.87 + * @param pk enum constant representing the position kind 1.88 + * @param l locale object to be used for i18n 1.89 + * @return string representation of the diagnostic position 1.90 + */ 1.91 + public String formatPosition(D diag, PositionKind pk, Locale l); 1.92 + //where 1.93 + /** 1.94 + * This enum defines a set of constants for all the kinds of position 1.95 + * that a diagnostic can be asked for. All positions are intended to be 1.96 + * relative to a given diagnostic source. 1.97 + */ 1.98 + public enum PositionKind { 1.99 + /** 1.100 + * Start position 1.101 + */ 1.102 + START, 1.103 + /** 1.104 + * End position 1.105 + */ 1.106 + END, 1.107 + /** 1.108 + * Line number 1.109 + */ 1.110 + LINE, 1.111 + /** 1.112 + * Column number 1.113 + */ 1.114 + COLUMN, 1.115 + /** 1.116 + * Offset position 1.117 + */ 1.118 + OFFSET 1.119 + } 1.120 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Mon Jul 28 10:22:10 2008 +0100 2.3 @@ -0,0 +1,169 @@ 2.4 +/* 2.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. Sun designates this 2.11 + * particular file as subject to the "Classpath" exception as provided 2.12 + * by Sun in the LICENSE file that accompanied this code. 2.13 + * 2.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.17 + * version 2 for more details (a copy is included in the LICENSE file that 2.18 + * accompanied this code). 2.19 + * 2.20 + * You should have received a copy of the GNU General Public License version 2.21 + * 2 along with this work; if not, write to the Free Software Foundation, 2.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.23 + * 2.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 2.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 2.26 + * have any questions. 2.27 + */ 2.28 +package com.sun.tools.javac.util; 2.29 + 2.30 +import java.util.Collection; 2.31 +import java.util.Locale; 2.32 +import javax.tools.JavaFileObject; 2.33 + 2.34 +import com.sun.tools.javac.api.DiagnosticFormatter; 2.35 +import com.sun.tools.javac.api.Formattable; 2.36 +import com.sun.tools.javac.api.DiagnosticFormatter.PositionKind; 2.37 +import com.sun.tools.javac.file.JavacFileManager; 2.38 + 2.39 +/** 2.40 + * This abstract class provides a basic implementation of the functionalities that should be provided 2.41 + * by any formatter used by javac. Among the main features provided by AbstractDiagnosticFormatter are: 2.42 + * 2.43 + * <ul> 2.44 + * <li> Provides a standard implementation of the visitor-like methods defined in the interface DiagnisticFormatter. 2.45 + * Those implementations are specifically targeting JCDiagnostic objects. 2.46 + * <li> Provides basic support for i18n and a method for executing all locale-dependent conversions 2.47 + * <li> Provides the formatting logic for rendering the arguments of a JCDiagnostic object. 2.48 + * <ul> 2.49 + * 2.50 + */ 2.51 +public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter<JCDiagnostic> { 2.52 + 2.53 + /** 2.54 + * Messages object used by this formatter for i18n 2.55 + */ 2.56 + protected Messages messages; 2.57 + 2.58 + /** 2.59 + * Initialize an AbstractDiagnosticFormatter by setting its Messages object 2.60 + * @param messages 2.61 + */ 2.62 + protected AbstractDiagnosticFormatter(Messages messages) { 2.63 + this.messages = messages; 2.64 + } 2.65 + 2.66 + public String formatMessage(JCDiagnostic d, Locale l) { 2.67 + //this code should rely on the locale settings but it's not! See RFE 6443132 2.68 + Collection<String> args = formatArguments(d, l); 2.69 + return localize(l, d.getCode(), args.toArray()); 2.70 + } 2.71 + 2.72 + public String formatKind(JCDiagnostic d, Locale l) { 2.73 + switch (d.getType()) { 2.74 + case FRAGMENT: return ""; 2.75 + case NOTE: return localize(l, "compiler.note.note"); 2.76 + case WARNING: return localize(l, "compiler.warn.warning"); 2.77 + case ERROR: return localize(l, "compiler.err.error"); 2.78 + default: 2.79 + throw new AssertionError("Unknown diagnostic type: " + d.getType()); 2.80 + } 2.81 + } 2.82 + 2.83 + public String formatPosition(JCDiagnostic d, PositionKind pk,Locale l) { 2.84 + assert (d.getPosition() != Position.NOPOS); 2.85 + return String.valueOf(getPosition(d, pk)); 2.86 + } 2.87 + //WHERE 2.88 + public long getPosition(JCDiagnostic d, PositionKind pk) { 2.89 + switch (pk) { 2.90 + case START: return d.getIntStartPosition(); 2.91 + case END: return d.getIntEndPosition(); 2.92 + case LINE: return d.getLineNumber(); 2.93 + case COLUMN: return d.getColumnNumber(); 2.94 + case OFFSET: return d.getIntPosition(); 2.95 + default: 2.96 + throw new AssertionError("Unknown diagnostic position: " + pk); 2.97 + } 2.98 + } 2.99 + 2.100 + public String formatSource(JCDiagnostic d,Locale l) { 2.101 + assert (d.getSource() != null); 2.102 + return d.getSource().getName(); 2.103 + } 2.104 + 2.105 + /** 2.106 + * Format the arguments of a given diagnostic. 2.107 + * 2.108 + * @param d diagnostic whose arguments are to be formatted 2.109 + * @param l locale object to be used for i18n 2.110 + * @return a Collection whose elements are the formatted arguments of the diagnostic 2.111 + */ 2.112 + protected Collection<String> formatArguments(JCDiagnostic d, Locale l) { 2.113 + ListBuffer<String> buf = new ListBuffer<String>(); 2.114 + for (Object o : d.getArgs()) { 2.115 + buf.append(formatArgument(d, o, l)); 2.116 + } 2.117 + return buf.toList(); 2.118 + } 2.119 + 2.120 + /** 2.121 + * Format a single argument of a given diagnostic. 2.122 + * 2.123 + * @param d diagnostic whose argument is to be formatted 2.124 + * @param arg argument to be formatted 2.125 + * @param l locale object to be used for i18n 2.126 + * @return string representation of the diagnostic argument 2.127 + */ 2.128 + protected String formatArgument(JCDiagnostic d, Object arg, Locale l) { 2.129 + if (arg instanceof JCDiagnostic) 2.130 + return format((JCDiagnostic)arg, l); 2.131 + else if (arg instanceof Iterable<?>) { 2.132 + return formatIterable(d, (Iterable<?>)arg, l); 2.133 + } 2.134 + else if (arg instanceof JavaFileObject) 2.135 + return JavacFileManager.getJavacBaseFileName((JavaFileObject)arg); 2.136 + else if (arg instanceof Formattable) 2.137 + return ((Formattable)arg).toString(Messages.getDefaultBundle()); 2.138 + else 2.139 + return String.valueOf(arg); 2.140 + } 2.141 + 2.142 + /** 2.143 + * Format an iterable argument of a given diagnostic. 2.144 + * 2.145 + * @param d diagnostic whose argument is to be formatted 2.146 + * @param it iterable argument to be formatted 2.147 + * @param l locale object to be used for i18n 2.148 + * @return string representation of the diagnostic iterable argument 2.149 + */ 2.150 + protected String formatIterable(JCDiagnostic d, Iterable<?> it, Locale l) { 2.151 + StringBuilder sbuf = new StringBuilder(); 2.152 + String sep = ""; 2.153 + for (Object o : it) { 2.154 + sbuf.append(sep); 2.155 + sbuf.append(formatArgument(d, o, l)); 2.156 + sep = ","; 2.157 + } 2.158 + return sbuf.toString(); 2.159 + } 2.160 + 2.161 + /** 2.162 + * Converts a String into a locale-dependent representation accordingly to a given locale 2.163 + * 2.164 + * @param l locale object to be used for i18n 2.165 + * @param key locale-independent key used for looking up in a resource file 2.166 + * @param args localization arguments 2.167 + * @return a locale-dependent string 2.168 + */ 2.169 + protected String localize(Locale l, String key, Object... args) { 2.170 + return messages.getLocalizedString(key, args); 2.171 + } 2.172 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java Mon Jul 28 10:22:10 2008 +0100 3.3 @@ -0,0 +1,190 @@ 3.4 +/* 3.5 + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. Sun designates this 3.11 + * particular file as subject to the "Classpath" exception as provided 3.12 + * by Sun in the LICENSE file that accompanied this code. 3.13 + * 3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.17 + * version 2 for more details (a copy is included in the LICENSE file that 3.18 + * accompanied this code). 3.19 + * 3.20 + * You should have received a copy of the GNU General Public License version 3.21 + * 2 along with this work; if not, write to the Free Software Foundation, 3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.23 + * 3.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 3.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 3.26 + * have any questions. 3.27 + */ 3.28 + 3.29 +package com.sun.tools.javac.util; 3.30 + 3.31 +import java.util.HashMap; 3.32 +import java.util.Locale; 3.33 +import java.util.Map; 3.34 +import javax.tools.JavaFileObject; 3.35 + 3.36 +import static com.sun.tools.javac.util.BasicDiagnosticFormatter.BasicFormatKind.*; 3.37 +import static com.sun.tools.javac.api.DiagnosticFormatter.PositionKind.*; 3.38 + 3.39 +/** 3.40 + * A basic formatter for diagnostic messages. 3.41 + * The basic formatter will format a diagnostic according to one of three format patterns, depending on whether 3.42 + * or not the source name and position are set. The formatter supports a printf-like string for patterns 3.43 + * with the following special characters: 3.44 + * <ul> 3.45 + * <li>%b: the base of the source name 3.46 + * <li>%f: the source name (full absolute path) 3.47 + * <li>%l: the line number of the diagnostic, derived from the character offset 3.48 + * <li>%c: the column number of the diagnostic, derived from the character offset 3.49 + * <li>%o: the character offset of the diagnostic if set 3.50 + * <li>%p: the prefix for the diagnostic, derived from the diagnostic type 3.51 + * <li>%t: the prefix as it normally appears in standard diagnostics. In this case, no prefix is 3.52 + * shown if the type is ERROR and if a source name is set 3.53 + * <li>%m: the text or the diagnostic, including any appropriate arguments 3.54 + * <li>%_: space delimiter, useful for formatting purposes 3.55 + * </ul> 3.56 + */ 3.57 +public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter { 3.58 + 3.59 + protected Map<BasicFormatKind, String> availableFormats; 3.60 + 3.61 + /** 3.62 + * Create a basic formatter based on the supplied options. 3.63 + * 3.64 + * @param opts list of command-line options 3.65 + * @param msgs Messages object used for i18n 3.66 + */ 3.67 + BasicDiagnosticFormatter(Options opts, Messages msgs) { 3.68 + this(msgs); //common init 3.69 + String fmt = opts.get("diags"); 3.70 + if (fmt != null) { 3.71 + String[] formats = fmt.split("\\|"); 3.72 + switch (formats.length) { 3.73 + case 3: 3.74 + availableFormats.put(DEFAULT_CLASS_FORMAT, formats[2]); 3.75 + case 2: 3.76 + availableFormats.put(DEFAULT_NO_POS_FORMAT, formats[1]); 3.77 + default: 3.78 + availableFormats.put(DEFAULT_POS_FORMAT, formats[0]); 3.79 + } 3.80 + } 3.81 + } 3.82 + 3.83 + /** 3.84 + * Create a standard basic formatter 3.85 + * 3.86 + * @param msgs Messages object used for i18n 3.87 + */ 3.88 + public BasicDiagnosticFormatter(Messages msgs) { 3.89 + super(msgs); 3.90 + availableFormats = new HashMap<BasicFormatKind, String>(); 3.91 + availableFormats.put(DEFAULT_POS_FORMAT, "%f:%l:%_%t%m"); 3.92 + availableFormats.put(DEFAULT_NO_POS_FORMAT, "%p%m"); 3.93 + availableFormats.put(DEFAULT_CLASS_FORMAT, "%f:%_%t%m"); 3.94 + } 3.95 + 3.96 + public String format(JCDiagnostic d, Locale l) { 3.97 + String format = selectFormat(d); 3.98 + StringBuilder buf = new StringBuilder(); 3.99 + for (int i = 0; i < format.length(); i++) { 3.100 + char c = format.charAt(i); 3.101 + boolean meta = false; 3.102 + if (c == '%' && i < format.length() - 1) { 3.103 + meta = true; 3.104 + c = format.charAt(++i); 3.105 + } 3.106 + buf.append(meta ? formatMeta(c, d, l) : String.valueOf(c)); 3.107 + } 3.108 + return buf.toString(); 3.109 + } 3.110 + 3.111 + protected String formatMeta(char c, JCDiagnostic d, Locale l) { 3.112 + switch (c) { 3.113 + case 'b': 3.114 + return formatSource(d, l); 3.115 + case 'e': 3.116 + return formatPosition(d, END, l); 3.117 + case 'f': 3.118 + return formatSource(d, l); 3.119 + case 'l': 3.120 + return formatPosition(d, LINE, l); 3.121 + case 'c': 3.122 + return formatPosition(d, COLUMN, l); 3.123 + case 'o': 3.124 + return formatPosition(d, OFFSET, l); 3.125 + case 'p': 3.126 + return formatKind(d, l); 3.127 + case 's': 3.128 + return formatPosition(d, START, l); 3.129 + case 't': { 3.130 + boolean usePrefix; 3.131 + switch (d.getType()) { 3.132 + case FRAGMENT: 3.133 + usePrefix = false; 3.134 + break; 3.135 + case ERROR: 3.136 + usePrefix = (d.getIntPosition() == Position.NOPOS); 3.137 + break; 3.138 + default: 3.139 + usePrefix = true; 3.140 + } 3.141 + if (usePrefix) 3.142 + return formatKind(d, l); 3.143 + else 3.144 + return ""; 3.145 + } 3.146 + case 'm': 3.147 + return formatMessage(d, l); 3.148 + case '_': 3.149 + return " "; 3.150 + case '%': 3.151 + return "%"; 3.152 + default: 3.153 + return String.valueOf(c); 3.154 + } 3.155 + } 3.156 + 3.157 + private String selectFormat(JCDiagnostic d) { 3.158 + DiagnosticSource source = d.getDiagnosticSource(); 3.159 + String format = availableFormats.get(DEFAULT_NO_POS_FORMAT); 3.160 + if (source != null) { 3.161 + if (d.getIntPosition() != Position.NOPOS) { 3.162 + format = availableFormats.get(DEFAULT_POS_FORMAT); 3.163 + } else if (source.getFile() != null && 3.164 + source.getFile().getKind() == JavaFileObject.Kind.CLASS) { 3.165 + format = availableFormats.get(DEFAULT_CLASS_FORMAT); 3.166 + } 3.167 + } 3.168 + return format; 3.169 + } 3.170 + 3.171 + public boolean displaySource(JCDiagnostic d) { 3.172 + return true; 3.173 + } 3.174 + 3.175 + /** 3.176 + * This enum contains all the kinds of formatting patterns supported 3.177 + * by a basic diagnostic formatter. 3.178 + */ 3.179 + public enum BasicFormatKind { 3.180 + /** 3.181 + * A format string to be used for diagnostics with a given position. 3.182 + */ 3.183 + DEFAULT_POS_FORMAT, 3.184 + /** 3.185 + * A format string to be used for diagnostics without a given position. 3.186 + */ 3.187 + DEFAULT_NO_POS_FORMAT, 3.188 + /** 3.189 + * A format string to be used for diagnostics regarding classfiles 3.190 + */ 3.191 + DEFAULT_CLASS_FORMAT; 3.192 + } 3.193 +}
4.1 --- a/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java Fri Jul 25 12:22:09 2008 +0100 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,267 +0,0 @@ 4.4 -/* 4.5 - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. 4.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 - * 4.8 - * This code is free software; you can redistribute it and/or modify it 4.9 - * under the terms of the GNU General Public License version 2 only, as 4.10 - * published by the Free Software Foundation. Sun designates this 4.11 - * particular file as subject to the "Classpath" exception as provided 4.12 - * by Sun in the LICENSE file that accompanied this code. 4.13 - * 4.14 - * This code is distributed in the hope that it will be useful, but WITHOUT 4.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.17 - * version 2 for more details (a copy is included in the LICENSE file that 4.18 - * accompanied this code). 4.19 - * 4.20 - * You should have received a copy of the GNU General Public License version 4.21 - * 2 along with this work; if not, write to the Free Software Foundation, 4.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.23 - * 4.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 4.25 - * CA 95054 USA or visit www.sun.com if you need additional information or 4.26 - * have any questions. 4.27 - */ 4.28 - 4.29 -package com.sun.tools.javac.util; 4.30 - 4.31 -import java.util.Collection; 4.32 -import javax.tools.JavaFileObject; 4.33 - 4.34 -import com.sun.tools.javac.file.JavacFileManager; 4.35 -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; 4.36 - 4.37 -/** 4.38 - * A formatter for diagnostic messages. 4.39 - * The formatter will format a diagnostic according to one of two format strings, depending on whether 4.40 - * or not the source name and position are set. The format is a printf-like string, 4.41 - * with the following special characters: 4.42 - * <ul> 4.43 - * <li>%b: the base of the source name, or "-" if not set 4.44 - * <li>%f: the source name, or "-" if not set 4.45 - * <li>%l: the line number of the diagnostic, derived from the character offset if set, or "-" otherwise 4.46 - * <li>%c: the column number of the diagnostic, derived from the character offset if set, or "-" otherwise 4.47 - * <li>%o: the character offset of the diagnostic if set, or "-" otherwise 4.48 - * <li>%p: the prefix for the diagnostic, derived from the diagnostic type 4.49 - * <li>%t: the prefix as it normally appears in standard diagnostics. In this case, no prefix is 4.50 - * shown if the type is ERROR and if a source name is set 4.51 - * <li>%m: the text or the diagnostic, including any appropriate arguments 4.52 - * </ul> 4.53 - */ 4.54 -public class DiagnosticFormatter { 4.55 - /** 4.56 - * A format string to be used for diagnostics with a given position. 4.57 - */ 4.58 - protected String posFormat; 4.59 - 4.60 - /** 4.61 - * A format string to be used for diagnostics regarding classfiles 4.62 - */ 4.63 - protected String classFormat = DEFAULT_CLASS_FORMAT; 4.64 - 4.65 - /** 4.66 - * A format string to be used for diagnostics without a given position. 4.67 - */ 4.68 - protected String noPosFormat; 4.69 - 4.70 - /** 4.71 - * A value to indicate whether to output the i18n key and args, instead of 4.72 - * the derived l10n message. 4.73 - */ 4.74 - protected boolean raw; 4.75 - 4.76 - /** The context key for the formatter. */ 4.77 - protected static final Context.Key<DiagnosticFormatter> formatterKey = 4.78 - new Context.Key<DiagnosticFormatter>(); 4.79 - 4.80 - /** Get the DiagnosticFormatter instance for this context. */ 4.81 - public static DiagnosticFormatter instance(Context context) { 4.82 - DiagnosticFormatter instance = context.get(formatterKey); 4.83 - if (instance == null) 4.84 - instance = new DiagnosticFormatter(context); 4.85 - return instance; 4.86 - } 4.87 - 4.88 - /** 4.89 - * Create a formatter based on the supplied options. 4.90 - */ 4.91 - protected DiagnosticFormatter(Context context) { 4.92 - Options options = Options.instance(context); 4.93 - raw = options.get("rawDiagnostics") != null; 4.94 - String fmt = options.get("diags"); 4.95 - if (fmt != null) { 4.96 - int sep = fmt.indexOf('|'); 4.97 - if (sep == -1) 4.98 - posFormat = noPosFormat = fmt; 4.99 - else { 4.100 - posFormat = fmt.substring(0, sep); 4.101 - noPosFormat = fmt.substring(sep + 1); 4.102 - } 4.103 - } 4.104 - else { 4.105 - posFormat = DEFAULT_POS_FORMAT; 4.106 - noPosFormat = DEFAULT_NO_POS_FORMAT; 4.107 - } 4.108 - } 4.109 - 4.110 - public static final String DEFAULT_POS_FORMAT = "%f:%l: %t%m"; 4.111 - public static final String DEFAULT_CLASS_FORMAT = "%f: %t%m"; 4.112 - public static final String DEFAULT_NO_POS_FORMAT = "%p%m"; 4.113 - 4.114 - public DiagnosticFormatter() { 4.115 - posFormat = DEFAULT_POS_FORMAT; 4.116 - noPosFormat = DEFAULT_NO_POS_FORMAT; 4.117 - raw = false; 4.118 - } 4.119 - 4.120 - public DiagnosticFormatter(String pos, String noPos) { 4.121 - posFormat = pos; 4.122 - noPosFormat = noPos; 4.123 - raw = false; 4.124 - } 4.125 - 4.126 - String format(JCDiagnostic d) { 4.127 - return (raw ? format_raw(d) : format_std(d)); 4.128 - } 4.129 - 4.130 - private String format_raw(JCDiagnostic d) { 4.131 - DiagnosticSource source = d.getDiagnosticSource(); 4.132 - int position = d.getIntPosition(); 4.133 - 4.134 - StringBuilder sb = new StringBuilder(); 4.135 - if (position == Position.NOPOS) 4.136 - sb.append("-"); 4.137 - else { 4.138 - sb.append(source.getName() + ":" + source.getLineNumber(position) + ":" + source.getColumnNumber(position) + ":"); 4.139 - } 4.140 - sb.append(" "); 4.141 - sb.append(d.getCode()); 4.142 - String sep = ": "; 4.143 - for (Object arg: d.getArgs()) { 4.144 - sb.append(sep); 4.145 - if (arg instanceof JCDiagnostic) { 4.146 - sb.append('('); 4.147 - sb.append(format_raw((JCDiagnostic) arg)); 4.148 - sb.append(')'); 4.149 - } 4.150 - else if (arg instanceof JavaFileObject) 4.151 - sb.append(JavacFileManager.getJavacBaseFileName((JavaFileObject) arg)); 4.152 - else if (arg instanceof Collection<?>) 4.153 - sb.append(convert((Collection<?>)arg)); 4.154 - else 4.155 - sb.append(arg); 4.156 - sep = ", "; 4.157 - } 4.158 - return sb.toString(); 4.159 - } 4.160 - 4.161 - static <T> List<T> convert(Collection<T> c) { 4.162 - if (c instanceof List<?>) 4.163 - return (List<T>)c; 4.164 - else { 4.165 - List<T> l = List.<T>nil(); 4.166 - for (T t : c) { 4.167 - l = l.prepend(t); 4.168 - } 4.169 - return l.reverse(); 4.170 - } 4.171 - } 4.172 - 4.173 - private String format_std(JCDiagnostic d) { 4.174 - DiagnosticSource source = d.getDiagnosticSource(); 4.175 - DiagnosticType type = d.getType(); 4.176 - int position = d.getIntPosition(); 4.177 - 4.178 - 4.179 - String format = noPosFormat; 4.180 - if (source != null) { 4.181 - if (position != Position.NOPOS) { 4.182 - format = posFormat; 4.183 - } else if (source.getFile() != null && 4.184 - source.getFile().getKind() == JavaFileObject.Kind.CLASS) { 4.185 - format = classFormat; 4.186 - } 4.187 - } 4.188 - 4.189 - StringBuilder sb = new StringBuilder(); 4.190 - 4.191 - for (int i = 0; i < format.length(); i++) { 4.192 - char c = format.charAt(i); 4.193 - if (c == '%' && i < format.length() - 1) { 4.194 - c = format.charAt(++i); 4.195 - switch (c) { 4.196 - case 'b': 4.197 - sb.append(source == null ? "-" : source.getName()); 4.198 - break; 4.199 - 4.200 - case 'e': 4.201 - sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getEndPosition())); 4.202 - break; 4.203 - 4.204 - case 'f': 4.205 - sb.append(source == null ? "-" : d.getSourceName()); 4.206 - break; 4.207 - 4.208 - case 'l': 4.209 - sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getLineNumber())); 4.210 - break; 4.211 - 4.212 - case 'c': 4.213 - sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getColumnNumber())); 4.214 - break; 4.215 - 4.216 - case 'o': 4.217 - sb.append(position == Position.NOPOS ? "-" : String.valueOf(position)); 4.218 - break; 4.219 - 4.220 - case 'p': 4.221 - sb.append(d.getPrefix()); 4.222 - break; 4.223 - 4.224 - case 's': 4.225 - sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getStartPosition())); 4.226 - break; 4.227 - 4.228 - case 't': { 4.229 - boolean usePrefix; 4.230 - switch (type) { 4.231 - case FRAGMENT: 4.232 - usePrefix = false; 4.233 - break; 4.234 - 4.235 - case ERROR: 4.236 - usePrefix = (position == Position.NOPOS); 4.237 - break; 4.238 - 4.239 - default: 4.240 - usePrefix = true; 4.241 - } 4.242 - 4.243 - if (usePrefix) 4.244 - sb.append(d.getPrefix()); 4.245 - break; 4.246 - } 4.247 - 4.248 - case 'm': 4.249 - sb.append(d.getMessage(null)); 4.250 - break; 4.251 - 4.252 - case '_': 4.253 - sb.append(' '); 4.254 - break; 4.255 - 4.256 - case '%': 4.257 - sb.append('%'); 4.258 - break; 4.259 - 4.260 - default: 4.261 - sb.append(c); 4.262 - break; 4.263 - } 4.264 - } 4.265 - else 4.266 - sb.append(c); 4.267 - } 4.268 - return sb.toString(); 4.269 - } 4.270 -}
5.1 --- a/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Fri Jul 25 12:22:09 2008 +0100 5.2 +++ b/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java Mon Jul 28 10:22:10 2008 +0100 5.3 @@ -25,15 +25,13 @@ 5.4 5.5 package com.sun.tools.javac.util; 5.6 5.7 -import java.util.ResourceBundle; 5.8 -import java.util.Collection; 5.9 import java.util.Locale; 5.10 import java.util.Map; 5.11 5.12 import javax.tools.Diagnostic; 5.13 import javax.tools.JavaFileObject; 5.14 5.15 -import com.sun.tools.javac.api.Formattable; 5.16 +import com.sun.tools.javac.api.DiagnosticFormatter; 5.17 import com.sun.tools.javac.file.JavacFileManager; 5.18 import com.sun.tools.javac.tree.JCTree; 5.19 5.20 @@ -256,7 +254,7 @@ 5.21 private final int line; 5.22 private final int column; 5.23 private final String key; 5.24 - private final Object[] args; 5.25 + protected Object[] args; 5.26 private boolean mandatory; 5.27 5.28 /** 5.29 @@ -400,52 +398,25 @@ 5.30 * @return the prefix string associated with a particular type of diagnostic 5.31 */ 5.32 public String getPrefix(DiagnosticType dt) { 5.33 - switch (dt) { 5.34 - case FRAGMENT: return ""; 5.35 - case NOTE: return getLocalizedString("compiler.note.note"); 5.36 - case WARNING: return getLocalizedString("compiler.warn.warning"); 5.37 - case ERROR: return getLocalizedString("compiler.err.error"); 5.38 - default: 5.39 - throw new AssertionError("Unknown diagnostic type: " + dt); 5.40 + return getFormatter().formatKind(this, Locale.getDefault()); 5.41 + } 5.42 + 5.43 + private DiagnosticFormatter<JCDiagnostic> getFormatter() { 5.44 + if (defaultFormatter == null) { 5.45 + defaultFormatter = new BasicDiagnosticFormatter(messages); 5.46 } 5.47 + return defaultFormatter; 5.48 } 5.49 5.50 + 5.51 /** 5.52 * Return the standard presentation of this diagnostic. 5.53 */ 5.54 public String toString() { 5.55 - if (defaultFormatter == null) { 5.56 - defaultFormatter = 5.57 - new DiagnosticFormatter(); 5.58 - } 5.59 - return defaultFormatter.format(this); 5.60 + return getFormatter().format(this,Locale.getDefault()); 5.61 } 5.62 5.63 - private static DiagnosticFormatter defaultFormatter; 5.64 - 5.65 - private static final String messageBundleName = 5.66 - "com.sun.tools.javac.resources.compiler"; 5.67 - 5.68 - private String getLocalizedString(String key, Object... args) { 5.69 - String[] strings = new String[args.length]; 5.70 - for (int i = 0; i < strings.length; i++) { 5.71 - Object arg = args[i]; 5.72 - if (arg == null) 5.73 - strings[i] = null; 5.74 - else if (arg instanceof JCDiagnostic) 5.75 - strings[i] = ((JCDiagnostic) arg).getMessage(null); 5.76 - else if (arg instanceof Collection<?>) 5.77 - strings[i] = DiagnosticFormatter.convert((Collection<?>)arg).toString(); 5.78 - else if (arg instanceof Formattable) { 5.79 - ResourceBundle rb = ResourceBundle.getBundle(messageBundleName); 5.80 - strings[i] = ((Formattable)arg).toString(rb); 5.81 - } 5.82 - else 5.83 - strings[i] = arg.toString(); 5.84 - } 5.85 - 5.86 - return messages.getLocalizedString(key, (Object[]) strings); 5.87 - } 5.88 + private static DiagnosticFormatter<JCDiagnostic> defaultFormatter; 5.89 5.90 // Methods for javax.tools.Diagnostic 5.91 5.92 @@ -469,7 +440,6 @@ 5.93 5.94 public String getMessage(Locale locale) { 5.95 // RFE 6406133: JCDiagnostic.getMessage ignores locale argument 5.96 - return getLocalizedString(key, args); 5.97 + return getFormatter().formatMessage(this, locale); 5.98 } 5.99 - 5.100 }
6.1 --- a/src/share/classes/com/sun/tools/javac/util/Log.java Fri Jul 25 12:22:09 2008 +0100 6.2 +++ b/src/share/classes/com/sun/tools/javac/util/Log.java Mon Jul 28 10:22:10 2008 +0100 6.3 @@ -29,11 +29,13 @@ 6.4 import java.util.HashSet; 6.5 import java.util.Map; 6.6 import java.util.Set; 6.7 +import java.util.Locale; 6.8 import javax.tools.DiagnosticListener; 6.9 import javax.tools.JavaFileObject; 6.10 6.11 import com.sun.tools.javac.file.JavacFileManager; 6.12 import com.sun.tools.javac.tree.JCTree; 6.13 +import com.sun.tools.javac.api.DiagnosticFormatter; 6.14 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 6.15 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; 6.16 6.17 @@ -68,10 +70,6 @@ 6.18 public final int MaxErrors; 6.19 public final int MaxWarnings; 6.20 6.21 - /** Whether or not to display the line of source containing a diagnostic. 6.22 - */ 6.23 - private final boolean showSourceLine; 6.24 - 6.25 /** Switch: prompt user on each error. 6.26 */ 6.27 public boolean promptOnError; 6.28 @@ -97,7 +95,7 @@ 6.29 /** 6.30 * Formatter for diagnostics 6.31 */ 6.32 - private DiagnosticFormatter diagFormatter; 6.33 + private DiagnosticFormatter<JCDiagnostic> diagFormatter; 6.34 6.35 /** Construct a log with given I/O redirections. 6.36 */ 6.37 @@ -115,9 +113,11 @@ 6.38 this.emitWarnings = options.get("-Xlint:none") == null; 6.39 this.MaxErrors = getIntOption(options, "-Xmaxerrs", 100); 6.40 this.MaxWarnings = getIntOption(options, "-Xmaxwarns", 100); 6.41 - this.showSourceLine = options.get("rawDiagnostics") == null; 6.42 6.43 - this.diagFormatter = DiagnosticFormatter.instance(context); 6.44 + boolean rawDiagnostics = options.get("rawDiagnostics") != null; 6.45 + Messages msgs = Messages.instance(context); 6.46 + this.diagFormatter = rawDiagnostics ? new RawDiagnosticFormatter(msgs) : 6.47 + new BasicDiagnosticFormatter(options, msgs); 6.48 @SuppressWarnings("unchecked") // FIXME 6.49 DiagnosticListener<? super JavaFileObject> diagListener = 6.50 context.get(DiagnosticListener.class); 6.51 @@ -335,8 +335,8 @@ 6.52 6.53 PrintWriter writer = getWriterForDiagnosticType(diag.getType()); 6.54 6.55 - printLines(writer, diagFormatter.format(diag)); 6.56 - if (showSourceLine) { 6.57 + printLines(writer, diagFormatter.format(diag, Locale.getDefault())); 6.58 + if (diagFormatter.displaySource(diag)) { 6.59 int pos = diag.getIntPosition(); 6.60 if (pos != Position.NOPOS) { 6.61 JavaFileObject prev = useSource(diag.getSource());
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java Mon Jul 28 10:22:10 2008 +0100 7.3 @@ -0,0 +1,107 @@ 7.4 +/* 7.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. 7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.7 + * 7.8 + * This code is free software; you can redistribute it and/or modify it 7.9 + * under the terms of the GNU General Public License version 2 only, as 7.10 + * published by the Free Software Foundation. Sun designates this 7.11 + * particular file as subject to the "Classpath" exception as provided 7.12 + * by Sun in the LICENSE file that accompanied this code. 7.13 + * 7.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 7.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 7.17 + * version 2 for more details (a copy is included in the LICENSE file that 7.18 + * accompanied this code). 7.19 + * 7.20 + * You should have received a copy of the GNU General Public License version 7.21 + * 2 along with this work; if not, write to the Free Software Foundation, 7.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 7.23 + * 7.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 7.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 7.26 + * have any questions. 7.27 + */ 7.28 +package com.sun.tools.javac.util; 7.29 + 7.30 +import java.util.Locale; 7.31 + 7.32 +import com.sun.tools.javac.api.Formattable; 7.33 +import static com.sun.tools.javac.api.DiagnosticFormatter.PositionKind.*; 7.34 + 7.35 +/** 7.36 + * A raw formatter for diagnostic messages. 7.37 + * The raw formatter will format a diagnostic according to one of two format patterns, depending on whether 7.38 + * or not the source name and position are set. This formatter provides a standardized, localize-independent 7.39 + * implementation of a diagnostic formatter; as such, this formatter is best suited for testing purposes. 7.40 + */ 7.41 +public class RawDiagnosticFormatter extends AbstractDiagnosticFormatter { 7.42 + 7.43 + /** 7.44 + * Create a formatter based on the supplied options. 7.45 + * @param msgs 7.46 + */ 7.47 + public RawDiagnosticFormatter(Messages msgs) { 7.48 + super(null); 7.49 + } 7.50 + 7.51 + //provide common default formats 7.52 + public String format(JCDiagnostic d, Locale l) { 7.53 + try { 7.54 + StringBuffer buf = new StringBuffer(); 7.55 + if (d.getPosition() != Position.NOPOS) { 7.56 + buf.append(formatSource(d, null)); 7.57 + buf.append(':'); 7.58 + buf.append(formatPosition(d, LINE, null)); 7.59 + buf.append(':'); 7.60 + buf.append(formatPosition(d, COLUMN, null)); 7.61 + buf.append(':'); 7.62 + } 7.63 + else 7.64 + buf.append('-'); 7.65 + buf.append(' '); 7.66 + buf.append(formatMessage(d, null)); 7.67 + return buf.toString(); 7.68 + } 7.69 + catch (Exception e) { 7.70 + e.printStackTrace(); 7.71 + return null; 7.72 + } 7.73 + } 7.74 + 7.75 + @Override 7.76 + public String formatSource(JCDiagnostic d,Locale l) { 7.77 + assert(d.getSource() != null); 7.78 + return d.getSource().getName(); 7.79 + } 7.80 + 7.81 + @Override 7.82 + protected String formatArgument(JCDiagnostic diag, Object arg, Locale l) { 7.83 + String s; 7.84 + if (arg instanceof Formattable) 7.85 + s = arg.toString(); 7.86 + else 7.87 + s = super.formatArgument(diag, arg, null); 7.88 + if (arg instanceof JCDiagnostic) 7.89 + return "(" + s + ")"; 7.90 + else 7.91 + return s; 7.92 + } 7.93 + 7.94 + @Override 7.95 + protected String localize(Locale l, String s, Object... args) { 7.96 + StringBuffer buf = new StringBuffer(); 7.97 + buf.append(s); 7.98 + String sep = ": "; 7.99 + for (Object o : args) { 7.100 + buf.append(sep); 7.101 + buf.append(o); 7.102 + sep = ", "; 7.103 + } 7.104 + return buf.toString(); 7.105 + } 7.106 + 7.107 + public boolean displaySource(JCDiagnostic d) { 7.108 + return false; 7.109 + } 7.110 +}