src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java

Thu, 24 Jul 2008 19:06:57 +0100

author
mcimadamore
date
Thu, 24 Jul 2008 19:06:57 +0100
changeset 80
5c9cdeb740f2
parent 73
1cf29847eb6e
permissions
-rw-r--r--

6717241: some diagnostic argument is prematurely converted into a String object
Summary: removed early toString() conversions applied to diagnostic arguments
Reviewed-by: jjg

duke@1 1 /*
xdono@54 2 * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
duke@1 7 * published by the Free Software Foundation. Sun designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
duke@1 9 * by Sun in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
duke@1 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@1 22 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@1 23 * have any questions.
duke@1 24 */
duke@1 25
duke@1 26 package com.sun.tools.javac.util;
duke@1 27
mcimadamore@80 28 import java.util.Collection;
duke@1 29 import javax.tools.JavaFileObject;
duke@1 30
jjg@50 31 import com.sun.tools.javac.file.JavacFileManager;
duke@1 32 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
duke@1 33
duke@1 34 /**
duke@1 35 * A formatter for diagnostic messages.
duke@1 36 * The formatter will format a diagnostic according to one of two format strings, depending on whether
duke@1 37 * or not the source name and position are set. The format is a printf-like string,
duke@1 38 * with the following special characters:
duke@1 39 * <ul>
duke@1 40 * <li>%b: the base of the source name, or "-" if not set
duke@1 41 * <li>%f: the source name, or "-" if not set
duke@1 42 * <li>%l: the line number of the diagnostic, derived from the character offset if set, or "-" otherwise
duke@1 43 * <li>%c: the column number of the diagnostic, derived from the character offset if set, or "-" otherwise
duke@1 44 * <li>%o: the character offset of the diagnostic if set, or "-" otherwise
duke@1 45 * <li>%p: the prefix for the diagnostic, derived from the diagnostic type
duke@1 46 * <li>%t: the prefix as it normally appears in standard diagnostics. In this case, no prefix is
duke@1 47 * shown if the type is ERROR and if a source name is set
duke@1 48 * <li>%m: the text or the diagnostic, including any appropriate arguments
duke@1 49 * </ul>
duke@1 50 */
duke@1 51 public class DiagnosticFormatter {
duke@1 52 /**
duke@1 53 * A format string to be used for diagnostics with a given position.
duke@1 54 */
duke@1 55 protected String posFormat;
duke@1 56
duke@1 57 /**
duke@1 58 * A format string to be used for diagnostics regarding classfiles
duke@1 59 */
duke@1 60 protected String classFormat = DEFAULT_CLASS_FORMAT;
duke@1 61
duke@1 62 /**
duke@1 63 * A format string to be used for diagnostics without a given position.
duke@1 64 */
duke@1 65 protected String noPosFormat;
duke@1 66
duke@1 67 /**
duke@1 68 * A value to indicate whether to output the i18n key and args, instead of
duke@1 69 * the derived l10n message.
duke@1 70 */
duke@1 71 protected boolean raw;
duke@1 72
duke@1 73 /** The context key for the formatter. */
duke@1 74 protected static final Context.Key<DiagnosticFormatter> formatterKey =
duke@1 75 new Context.Key<DiagnosticFormatter>();
duke@1 76
duke@1 77 /** Get the DiagnosticFormatter instance for this context. */
duke@1 78 public static DiagnosticFormatter instance(Context context) {
duke@1 79 DiagnosticFormatter instance = context.get(formatterKey);
duke@1 80 if (instance == null)
duke@1 81 instance = new DiagnosticFormatter(context);
duke@1 82 return instance;
duke@1 83 }
duke@1 84
duke@1 85 /**
duke@1 86 * Create a formatter based on the supplied options.
duke@1 87 */
duke@1 88 protected DiagnosticFormatter(Context context) {
duke@1 89 Options options = Options.instance(context);
duke@1 90 raw = options.get("rawDiagnostics") != null;
duke@1 91 String fmt = options.get("diags");
duke@1 92 if (fmt != null) {
duke@1 93 int sep = fmt.indexOf('|');
duke@1 94 if (sep == -1)
duke@1 95 posFormat = noPosFormat = fmt;
duke@1 96 else {
duke@1 97 posFormat = fmt.substring(0, sep);
duke@1 98 noPosFormat = fmt.substring(sep + 1);
duke@1 99 }
duke@1 100 }
duke@1 101 else {
duke@1 102 posFormat = DEFAULT_POS_FORMAT;
duke@1 103 noPosFormat = DEFAULT_NO_POS_FORMAT;
duke@1 104 }
duke@1 105 }
duke@1 106
duke@1 107 public static final String DEFAULT_POS_FORMAT = "%f:%l: %t%m";
duke@1 108 public static final String DEFAULT_CLASS_FORMAT = "%f: %t%m";
duke@1 109 public static final String DEFAULT_NO_POS_FORMAT = "%p%m";
duke@1 110
duke@1 111 public DiagnosticFormatter() {
duke@1 112 posFormat = DEFAULT_POS_FORMAT;
duke@1 113 noPosFormat = DEFAULT_NO_POS_FORMAT;
duke@1 114 raw = false;
duke@1 115 }
duke@1 116
duke@1 117 public DiagnosticFormatter(String pos, String noPos) {
duke@1 118 posFormat = pos;
duke@1 119 noPosFormat = noPos;
duke@1 120 raw = false;
duke@1 121 }
duke@1 122
duke@1 123 String format(JCDiagnostic d) {
duke@1 124 return (raw ? format_raw(d) : format_std(d));
duke@1 125 }
duke@1 126
duke@1 127 private String format_raw(JCDiagnostic d) {
duke@1 128 DiagnosticSource source = d.getDiagnosticSource();
duke@1 129 int position = d.getIntPosition();
duke@1 130
duke@1 131 StringBuilder sb = new StringBuilder();
duke@1 132 if (position == Position.NOPOS)
duke@1 133 sb.append("-");
duke@1 134 else {
duke@1 135 sb.append(source.getName() + ":" + source.getLineNumber(position) + ":" + source.getColumnNumber(position) + ":");
duke@1 136 }
duke@1 137 sb.append(" ");
duke@1 138 sb.append(d.getCode());
duke@1 139 String sep = ": ";
duke@1 140 for (Object arg: d.getArgs()) {
duke@1 141 sb.append(sep);
duke@1 142 if (arg instanceof JCDiagnostic) {
duke@1 143 sb.append('(');
duke@1 144 sb.append(format_raw((JCDiagnostic) arg));
duke@1 145 sb.append(')');
duke@1 146 }
duke@1 147 else if (arg instanceof JavaFileObject)
duke@1 148 sb.append(JavacFileManager.getJavacBaseFileName((JavaFileObject) arg));
mcimadamore@80 149 else if (arg instanceof Collection<?>)
mcimadamore@80 150 sb.append(convert((Collection<?>)arg));
duke@1 151 else
duke@1 152 sb.append(arg);
duke@1 153 sep = ", ";
duke@1 154 }
duke@1 155 return sb.toString();
duke@1 156 }
duke@1 157
mcimadamore@80 158 static <T> List<T> convert(Collection<T> c) {
mcimadamore@80 159 if (c instanceof List<?>)
mcimadamore@80 160 return (List<T>)c;
mcimadamore@80 161 else {
mcimadamore@80 162 List<T> l = List.<T>nil();
mcimadamore@80 163 for (T t : c) {
mcimadamore@80 164 l = l.prepend(t);
mcimadamore@80 165 }
mcimadamore@80 166 return l.reverse();
mcimadamore@80 167 }
mcimadamore@80 168 }
mcimadamore@80 169
duke@1 170 private String format_std(JCDiagnostic d) {
duke@1 171 DiagnosticSource source = d.getDiagnosticSource();
duke@1 172 DiagnosticType type = d.getType();
duke@1 173 int position = d.getIntPosition();
duke@1 174
duke@1 175
duke@1 176 String format = noPosFormat;
duke@1 177 if (source != null) {
duke@1 178 if (position != Position.NOPOS) {
duke@1 179 format = posFormat;
duke@1 180 } else if (source.getFile() != null &&
duke@1 181 source.getFile().getKind() == JavaFileObject.Kind.CLASS) {
duke@1 182 format = classFormat;
duke@1 183 }
duke@1 184 }
duke@1 185
duke@1 186 StringBuilder sb = new StringBuilder();
duke@1 187
duke@1 188 for (int i = 0; i < format.length(); i++) {
duke@1 189 char c = format.charAt(i);
duke@1 190 if (c == '%' && i < format.length() - 1) {
duke@1 191 c = format.charAt(++i);
duke@1 192 switch (c) {
duke@1 193 case 'b':
duke@1 194 sb.append(source == null ? "-" : source.getName());
duke@1 195 break;
duke@1 196
duke@1 197 case 'e':
duke@1 198 sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getEndPosition()));
duke@1 199 break;
duke@1 200
duke@1 201 case 'f':
duke@1 202 sb.append(source == null ? "-" : d.getSourceName());
duke@1 203 break;
duke@1 204
duke@1 205 case 'l':
duke@1 206 sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getLineNumber()));
duke@1 207 break;
duke@1 208
duke@1 209 case 'c':
duke@1 210 sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getColumnNumber()));
duke@1 211 break;
duke@1 212
duke@1 213 case 'o':
duke@1 214 sb.append(position == Position.NOPOS ? "-" : String.valueOf(position));
duke@1 215 break;
duke@1 216
duke@1 217 case 'p':
duke@1 218 sb.append(d.getPrefix());
duke@1 219 break;
duke@1 220
duke@1 221 case 's':
duke@1 222 sb.append(position == Position.NOPOS ? "-" : String.valueOf(d.getStartPosition()));
duke@1 223 break;
duke@1 224
duke@1 225 case 't': {
duke@1 226 boolean usePrefix;
duke@1 227 switch (type) {
duke@1 228 case FRAGMENT:
duke@1 229 usePrefix = false;
duke@1 230 break;
duke@1 231
duke@1 232 case ERROR:
duke@1 233 usePrefix = (position == Position.NOPOS);
duke@1 234 break;
duke@1 235
duke@1 236 default:
duke@1 237 usePrefix = true;
duke@1 238 }
duke@1 239
duke@1 240 if (usePrefix)
duke@1 241 sb.append(d.getPrefix());
duke@1 242 break;
duke@1 243 }
duke@1 244
duke@1 245 case 'm':
duke@1 246 sb.append(d.getMessage(null));
duke@1 247 break;
duke@1 248
duke@1 249 case '_':
duke@1 250 sb.append(' ');
duke@1 251 break;
duke@1 252
duke@1 253 case '%':
duke@1 254 sb.append('%');
duke@1 255 break;
duke@1 256
duke@1 257 default:
duke@1 258 sb.append(c);
duke@1 259 break;
duke@1 260 }
duke@1 261 }
duke@1 262 else
duke@1 263 sb.append(c);
duke@1 264 }
duke@1 265 return sb.toString();
duke@1 266 }
duke@1 267 }

mercurial