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

Thu, 09 Oct 2008 16:19:13 +0100

author
mcimadamore
date
Thu, 09 Oct 2008 16:19:13 +0100
changeset 137
e4eaddca54b7
parent 136
8eafba4f61be
child 168
4cdaaf4c5dca
permissions
-rw-r--r--

6731573: diagnostic output should optionally include source line
Summary: Added an -XD option to optionally prints out source lines in error messages
Reviewed-by: jjg

     1 /*
     2  * Copyright 2003-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  */
    26 package com.sun.tools.javac.util;
    28 import java.util.Locale;
    29 import java.util.Map;
    31 import javax.tools.Diagnostic;
    32 import javax.tools.JavaFileObject;
    34 import com.sun.tools.javac.api.DiagnosticFormatter;
    35 import com.sun.tools.javac.file.JavacFileManager;
    36 import com.sun.tools.javac.tree.JCTree;
    38 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
    40 /** An abstraction of a diagnostic message generated by the compiler.
    41  *
    42  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    43  *  you write code that depends on this, you do so at your own risk.
    44  *  This code and its internal interfaces are subject to change or
    45  *  deletion without notice.</b>
    46  */
    47 public class JCDiagnostic implements Diagnostic<JavaFileObject> {
    48     /** A factory for creating diagnostic objects. */
    49     public static class Factory {
    50         /** The context key for the diagnostic factory. */
    51         protected static final Context.Key<JCDiagnostic.Factory> diagnosticFactoryKey =
    52             new Context.Key<JCDiagnostic.Factory>();
    54         /** Get the Factory instance for this context. */
    55         public static Factory instance(Context context) {
    56             Factory instance = context.get(diagnosticFactoryKey);
    57             if (instance == null)
    58                 instance = new Factory(context);
    59             return instance;
    60         }
    62         DiagnosticFormatter<JCDiagnostic> formatter;
    63         final String prefix;
    65         /** Create a new diagnostic factory. */
    66         protected Factory(Context context) {
    67             this(JavacMessages.instance(context), "compiler");
    68             context.put(diagnosticFactoryKey, this);
    69         }
    71         /** Create a new diagnostic factory. */
    72         public Factory(JavacMessages messages, String prefix) {
    73             this.prefix = prefix;
    74             this.formatter = new BasicDiagnosticFormatter(messages);
    75         }
    77         /**
    78          * Create an error diagnostic.
    79          *  @param source The source of the compilation unit, if any, in which to report the error.
    80          *  @param pos    The source position at which to report the error.
    81          *  @param key    The key for the localized error message.
    82          *  @param args   Fields of the error message.
    83          */
    84         public JCDiagnostic error(
    85                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
    86             return new JCDiagnostic(formatter, ERROR, true, source, pos, qualify(ERROR, key), args);
    87         }
    89         /**
    90          * Create a warning diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
    91          *  @param source The source of the compilation unit, if any, in which to report the warning.
    92          *  @param pos    The source position at which to report the warning.
    93          *  @param key    The key for the localized error message.
    94          *  @param args   Fields of the error message.
    95          *  @see MandatoryWarningHandler
    96          */
    97         public JCDiagnostic mandatoryWarning(
    98                  DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
    99             return new JCDiagnostic(formatter, WARNING, true, source, pos, qualify(WARNING, key), args);
   100         }
   102         /**
   103          * Create a warning diagnostic.
   104          *  @param source The source of the compilation unit, if any, in which to report the warning.
   105          *  @param pos    The source position at which to report the warning.
   106          *  @param key    The key for the localized error message.
   107          *  @param args   Fields of the error message.
   108          */
   109         public JCDiagnostic warning(
   110                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   111             return new JCDiagnostic(formatter, WARNING, false, source, pos, qualify(WARNING, key), args);
   112         }
   114         /**
   115          * Create a note diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
   116          *  @param key    The key for the localized error message.
   117          *  @param args   Fields of the error message.
   118          *  @see MandatoryWarningHandler
   119          */
   120         public JCDiagnostic mandatoryNote(DiagnosticSource source, String key, Object... args) {
   121             return new JCDiagnostic(formatter, NOTE, true, source, null, qualify(NOTE, key), args);
   122         }
   124         /**
   125          * Create a note diagnostic.
   126          *  @param key    The key for the localized error message.
   127          *  @param args   Fields of the error message.
   128          */
   129         public JCDiagnostic note(String key, Object... args) {
   130             return note(null, null, key, args);
   131         }
   133         /**
   134          * Create a note diagnostic.
   135          *  @param source The source of the compilation unit, if any, in which to report the note.
   136          *  @param pos    The source position at which to report the note.
   137          *  @param key    The key for the localized error message.
   138          *  @param args   Fields of the error message.
   139          */
   140         public JCDiagnostic note(
   141                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   142             return new JCDiagnostic(formatter, NOTE, false, source, pos, qualify(NOTE, key), args);
   143         }
   145         /**
   146          * Create a fragment diagnostic, for use as an argument in other diagnostics
   147          *  @param key    The key for the localized error message.
   148          *  @param args   Fields of the error message.
   149          */
   150         public JCDiagnostic fragment(String key, Object... args) {
   151             return new JCDiagnostic(formatter, FRAGMENT, false, null, null, qualify(FRAGMENT, key), args);
   152         }
   154         protected String qualify(DiagnosticType t, String key) {
   155             return prefix + "." + t.key + "." + key;
   156         }
   157     }
   161     /**
   162      * Create a fragment diagnostic, for use as an argument in other diagnostics
   163      *  @param key    The key for the localized error message.
   164      *  @param args   Fields of the error message.
   165      *
   166      */
   167     @Deprecated
   168     public static JCDiagnostic fragment(String key, Object... args) {
   169         return new JCDiagnostic(getFragmentFormatter(),
   170                               FRAGMENT,
   171                               false,
   172                               null,
   173                               null,
   174                               "compiler." + FRAGMENT.key + "." + key,
   175                               args);
   176     }
   177     //where
   178     @Deprecated
   179     public static DiagnosticFormatter<JCDiagnostic> getFragmentFormatter() {
   180         if (fragmentFormatter == null) {
   181             fragmentFormatter = new BasicDiagnosticFormatter(JavacMessages.getDefaultMessages());
   182         }
   183         return fragmentFormatter;
   184     }
   186     /**
   187      * A DiagnosticType defines the type of the diagnostic.
   188      **/
   189     public enum DiagnosticType {
   190         /** A fragment of an enclosing diagnostic. */
   191         FRAGMENT("misc"),
   192         /** A note: similar to, but less serious than, a warning. */
   193         NOTE("note"),
   194         /** A warning. */
   195         WARNING("warn"),
   196         /** An error. */
   197         ERROR("err");
   199         final String key;
   201         /** Create a DiagnosticType.
   202          * @param key A string used to create the resource key for the diagnostic.
   203          */
   204         DiagnosticType(String key) {
   205             this.key = key;
   206         }
   207     };
   209     /**
   210      * A DiagnosticPosition provides information about the positions in a file
   211      * that gave rise to a diagnostic. It always defines a "preferred" position
   212      * that most accurately defines the location of the diagnostic, it may also
   213      * provide a related tree node that spans that location.
   214      */
   215     public static interface DiagnosticPosition {
   216         /** Gets the tree node, if any, to which the diagnostic applies. */
   217         JCTree getTree();
   218         /** If there is a tree node, get the start position of the tree node.
   219          *  Otherwise, just returns the same as getPreferredPosition(). */
   220         int getStartPosition();
   221         /** Get the position within the file that most accurately defines the
   222          *  location for the diagnostic. */
   223         int getPreferredPosition();
   224         /** If there is a tree node, and if endPositions are available, get
   225          *  the end position of the tree node. Otherwise, just returns the
   226          *  same as getPreferredPosition(). */
   227         int getEndPosition(Map<JCTree, Integer> endPosTable);
   228     }
   230     /**
   231      * A DiagnosticPosition that simply identifies a position, but no related
   232      * tree node, as the location for a diagnostic. Used for scanner and parser
   233      * diagnostics. */
   234     public static class SimpleDiagnosticPosition implements DiagnosticPosition {
   235         public SimpleDiagnosticPosition(int pos) {
   236             this.pos = pos;
   237         }
   239         public JCTree getTree() {
   240             return null;
   241         }
   243         public int getStartPosition() {
   244             return pos;
   245         }
   247         public int getPreferredPosition() {
   248             return pos;
   249         }
   251         public int getEndPosition(Map<JCTree, Integer> endPosTable) {
   252             return pos;
   253         }
   255         private final int pos;
   256     }
   258     private final DiagnosticType type;
   259     private final DiagnosticSource source;
   260     private final DiagnosticPosition position;
   261     private final int line;
   262     private final int column;
   263     private final String key;
   264     protected Object[] args;
   265     private boolean mandatory;
   267     /**
   268      * Create a diagnostic object.
   269      * @param messages the resource for localized messages
   270      * @param dt the type of diagnostic
   271      * @param name the name of the source file, or null if none.
   272      * @param pos the character offset within the source file, if given.
   273      * @param key a resource key to identify the text of the diagnostic
   274      * @param args arguments to be included in the text of the diagnostic
   275      */
   276     protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
   277                        DiagnosticType dt,
   278                        boolean mandatory,
   279                        DiagnosticSource source,
   280                        DiagnosticPosition pos,
   281                        String key,
   282                        Object ... args) {
   283         if (source == null && pos != null && pos.getPreferredPosition() != Position.NOPOS)
   284             throw new IllegalArgumentException();
   286         this.defaultFormatter = formatter;
   287         this.type = dt;
   288         this.mandatory = mandatory;
   289         this.source = source;
   290         this.position = pos;
   291         this.key = key;
   292         this.args = args;
   294         int n = (pos == null ? Position.NOPOS : pos.getPreferredPosition());
   295         if (n == Position.NOPOS || source == null)
   296             line = column = -1;
   297         else {
   298             line = source.getLineNumber(n);
   299             column = source.getColumnNumber(n, true);
   300         }
   301     }
   303     /**
   304      * Get the type of this diagnostic.
   305      * @return the type of this diagnostic
   306      */
   307     public DiagnosticType getType() {
   308         return type;
   309     }
   311     /**
   312      * Check whether or not this diagnostic is required to be shown.
   313      * @return true if this diagnostic is required to be shown.
   314      */
   315     public boolean isMandatory() {
   316         return mandatory;
   317     }
   319     /**
   320      * Get the name of the source file referred to by this diagnostic.
   321      * @return the name of the source referred to with this diagnostic, or null if none
   322      */
   323     public JavaFileObject getSource() {
   324         if (source == null)
   325             return null;
   326         else
   327             return source.getFile();
   328     }
   330     /**
   331      * Get the name of the source file referred to by this diagnostic.
   332      * @return the name of the source referred to with this diagnostic, or null if none
   333      */
   334     public String getSourceName() {
   335         JavaFileObject s = getSource();
   336         return s == null ? null : JavacFileManager.getJavacFileName(s);
   337     }
   339     /**
   340      * Get the source referred to by this diagnostic.
   341      * @return the source referred to with this diagnostic, or null if none
   342      */
   343     public DiagnosticSource getDiagnosticSource() {
   344         return source;
   345     }
   347     protected int getIntStartPosition() {
   348         return (position == null ? Position.NOPOS : position.getStartPosition());
   349     }
   351     protected int getIntPosition() {
   352         return (position == null ? Position.NOPOS : position.getPreferredPosition());
   353     }
   355     protected int getIntEndPosition() {
   356         return (position == null ? Position.NOPOS : position.getEndPosition(source.getEndPosTable()));
   357     }
   359     public long getStartPosition() {
   360         return getIntStartPosition();
   361     }
   363     public long getPosition() {
   364         return getIntPosition();
   365     }
   367     public long getEndPosition() {
   368         return getIntEndPosition();
   369     }
   371     /**
   372      * Get the line number within the source referred to by this diagnostic.
   373      * @return  the line number within the source referred to by this diagnostic
   374      */
   375     public long getLineNumber() {
   376         return line;
   377     }
   379     /**
   380      * Get the column number within the line of source referred to by this diagnostic.
   381      * @return  the column number within the line of source referred to by this diagnostic
   382      */
   383     public long getColumnNumber() {
   384         return column;
   385     }
   387     /**
   388      * Get the arguments to be included in the text of the diagnostic.
   389      * @return  the arguments to be included in the text of the diagnostic
   390      */
   391     public Object[] getArgs() {
   392         return args;
   393     }
   395     /**
   396      * Get the prefix string associated with this type of diagnostic.
   397      * @return the prefix string associated with this type of diagnostic
   398      */
   399     public String getPrefix() {
   400         return getPrefix(type);
   401     }
   403     /**
   404      * Get the prefix string associated with a particular type of diagnostic.
   405      * @return the prefix string associated with a particular type of diagnostic
   406      */
   407     public String getPrefix(DiagnosticType dt) {
   408         return defaultFormatter.formatKind(this, Locale.getDefault());
   409     }
   411     /**
   412      * Return the standard presentation of this diagnostic.
   413      */
   414     public String toString() {
   415         return defaultFormatter.format(this,Locale.getDefault());
   416     }
   418     private DiagnosticFormatter<JCDiagnostic> defaultFormatter;
   419     @Deprecated
   420     private static DiagnosticFormatter<JCDiagnostic> fragmentFormatter;
   422     // Methods for javax.tools.Diagnostic
   424     public Diagnostic.Kind getKind() {
   425         switch (type) {
   426         case NOTE:
   427             return Diagnostic.Kind.NOTE;
   428         case WARNING:
   429             return mandatory ? Diagnostic.Kind.MANDATORY_WARNING
   430                              : Diagnostic.Kind.WARNING;
   431         case ERROR:
   432             return Diagnostic.Kind.ERROR;
   433         default:
   434             return Diagnostic.Kind.OTHER;
   435         }
   436     }
   438     public String getCode() {
   439         return key;
   440     }
   442     public String getMessage(Locale locale) {
   443         // RFE 6406133: JCDiagnostic.getMessage ignores locale argument
   444         return defaultFormatter.formatMessage(this, locale);
   445     }
   446 }

mercurial