langtools/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java
changeset 10 06bc494ca11e
child 731 1dd22bdb9ca5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2005-2006 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 javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticSource;
+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
+                sb.append(arg);
+            sep = ", ";
+        }
+        return sb.toString();
+    }
+
+    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();
+    }
+}