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