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

Mon, 16 Jun 2008 13:28:00 -0700

author
jjg
date
Mon, 16 Jun 2008 13:28:00 -0700
changeset 50
b9bcea8bbe24
parent 1
9a66ca7c79fa
child 54
eaf608c64fec
permissions
-rw-r--r--

6714364: refactor javac File handling code into new javac.file package
Reviewed-by: mcimadamore

     1 /*
     2  * Copyright 2003-2006 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.file.JavacFileManager;
    35 import com.sun.tools.javac.tree.JCTree;
    37 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
    39 /** An abstraction of a diagnostic message generated by the compiler.
    40  *
    41  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    42  *  you write code that depends on this, you do so at your own risk.
    43  *  This code and its internal interfaces are subject to change or
    44  *  deletion without notice.</b>
    45  */
    46 public class JCDiagnostic implements Diagnostic<JavaFileObject> {
    47     /** A factory for creating diagnostic objects. */
    48     public static class Factory {
    49         /** The context key for the diagnostic factory. */
    50         protected static final Context.Key<JCDiagnostic.Factory> diagnosticFactoryKey =
    51             new Context.Key<JCDiagnostic.Factory>();
    53         /** Get the Factory instance for this context. */
    54         public static Factory instance(Context context) {
    55             Factory instance = context.get(diagnosticFactoryKey);
    56             if (instance == null)
    57                 instance = new Factory(context);
    58             return instance;
    59         }
    61         final Messages messages;
    62         final String prefix;
    64         /** Create a new diagnostic factory. */
    65         protected Factory(Context context) {
    66             context.put(diagnosticFactoryKey, this);
    67             messages = Messages.instance(context);
    68             prefix = "compiler";
    69         }
    71         /** Create a new diagnostic factory. */
    72         public Factory(Messages messages, String prefix) {
    73             this.messages = messages;
    74             this.prefix = prefix;
    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(messages, 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(messages, 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(messages, 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(messages, 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(messages, 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(messages, 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     // should be deprecated
   167     public static JCDiagnostic fragment(String key, Object... args) {
   168         return new JCDiagnostic(Messages.getDefaultMessages(),
   169                               FRAGMENT,
   170                               false,
   171                               null,
   172                               null,
   173                               "compiler." + FRAGMENT.key + "." + key,
   174                               args);
   175     }
   177     /**
   178      * A simple abstraction of a source file, as needed for use in a diagnostic message.
   179      */
   180     // Note: This class may be superceded by a more general abstraction
   181     public interface DiagnosticSource {
   182         JavaFileObject getFile();
   183         CharSequence getName();
   184         int getLineNumber(int pos);
   185         int getColumnNumber(int pos);
   186         Map<JCTree, Integer> getEndPosTable();
   187     };
   189     /**
   190      * A DiagnosticType defines the type of the diagnostic.
   191      **/
   192     public enum DiagnosticType {
   193         /** A fragment of an enclosing diagnostic. */
   194         FRAGMENT("misc"),
   195         /** A note: similar to, but less serious than, a warning. */
   196         NOTE("note"),
   197         /** A warning. */
   198         WARNING("warn"),
   199         /** An error. */
   200         ERROR("err");
   202         final String key;
   204         /** Create a DiagnosticType.
   205          * @param key A string used to create the resource key for the diagnostic.
   206          */
   207         DiagnosticType(String key) {
   208             this.key = key;
   209         }
   210     };
   212     /**
   213      * A DiagnosticPosition provides information about the positions in a file
   214      * that gave rise to a diagnostic. It always defines a "preferred" position
   215      * that most accurately defines the location of the diagnostic, it may also
   216      * provide a related tree node that spans that location.
   217      */
   218     public static interface DiagnosticPosition {
   219         /** Gets the tree node, if any, to which the diagnostic applies. */
   220         JCTree getTree();
   221         /** If there is a tree node, get the start position of the tree node.
   222          *  Otherwise, just returns the same as getPreferredPosition(). */
   223         int getStartPosition();
   224         /** Get the position within the file that most accurately defines the
   225          *  location for the diagnostic. */
   226         int getPreferredPosition();
   227         /** If there is a tree node, and if endPositions are available, get
   228          *  the end position of the tree node. Otherwise, just returns the
   229          *  same as getPreferredPosition(). */
   230         int getEndPosition(Map<JCTree, Integer> endPosTable);
   231     }
   233     /**
   234      * A DiagnosticPosition that simply identifies a position, but no related
   235      * tree node, as the location for a diagnostic. Used for scanner and parser
   236      * diagnostics. */
   237     public static class SimpleDiagnosticPosition implements DiagnosticPosition {
   238         public SimpleDiagnosticPosition(int pos) {
   239             this.pos = pos;
   240         }
   242         public JCTree getTree() {
   243             return null;
   244         }
   246         public int getStartPosition() {
   247             return pos;
   248         }
   250         public int getPreferredPosition() {
   251             return pos;
   252         }
   254         public int getEndPosition(Map<JCTree, Integer> endPosTable) {
   255             return pos;
   256         }
   258         private final int pos;
   259     }
   261     private final Messages messages;
   262     private final DiagnosticType type;
   263     private final DiagnosticSource source;
   264     private final DiagnosticPosition position;
   265     private final int line;
   266     private final int column;
   267     private final String key;
   268     private final Object[] args;
   269     private boolean mandatory;
   271     /**
   272      * Create a diagnostic object.
   273      * @param messages the resource for localized messages
   274      * @param dt the type of diagnostic
   275      * @param name the name of the source file, or null if none.
   276      * @param pos the character offset within the source file, if given.
   277      * @param key a resource key to identify the text of the diagnostic
   278      * @param args arguments to be included in the text of the diagnostic
   279      */
   280     protected JCDiagnostic(Messages messages,
   281                        DiagnosticType dt,
   282                        boolean mandatory,
   283                        DiagnosticSource source,
   284                        DiagnosticPosition pos,
   285                        String key,
   286                        Object ... args) {
   287         if (source == null && pos != null && pos.getPreferredPosition() != Position.NOPOS)
   288             throw new IllegalArgumentException();
   290         this.messages = messages;
   291         this.type = dt;
   292         this.mandatory = mandatory;
   293         this.source = source;
   294         this.position = pos;
   295         this.key = key;
   296         this.args = args;
   298         int n = (pos == null ? Position.NOPOS : pos.getPreferredPosition());
   299         if (n == Position.NOPOS || source == null)
   300             line = column = -1;
   301         else {
   302             line = source.getLineNumber(n);
   303             column = source.getColumnNumber(n);
   304         }
   305     }
   307     /**
   308      * Get the type of this diagnostic.
   309      * @return the type of this diagnostic
   310      */
   311     public DiagnosticType getType() {
   312         return type;
   313     }
   315     /**
   316      * Check whether or not this diagnostic is required to be shown.
   317      * @return true if this diagnostic is required to be shown.
   318      */
   319     public boolean isMandatory() {
   320         return mandatory;
   321     }
   323     /**
   324      * Get the name of the source file referred to by this diagnostic.
   325      * @return the name of the source referred to with this diagnostic, or null if none
   326      */
   327     public JavaFileObject getSource() {
   328         if (source == null)
   329             return null;
   330         else
   331             return source.getFile();
   332     }
   334     /**
   335      * Get the name of the source file referred to by this diagnostic.
   336      * @return the name of the source referred to with this diagnostic, or null if none
   337      */
   338     public String getSourceName() {
   339         JavaFileObject s = getSource();
   340         return s == null ? null : JavacFileManager.getJavacFileName(s);
   341     }
   343     /**
   344      * Get the source referred to by this diagnostic.
   345      * @return the source referred to with this diagnostic, or null if none
   346      */
   347     public DiagnosticSource getDiagnosticSource() {
   348         return source;
   349     }
   351     protected int getIntStartPosition() {
   352         return (position == null ? Position.NOPOS : position.getStartPosition());
   353     }
   355     protected int getIntPosition() {
   356         return (position == null ? Position.NOPOS : position.getPreferredPosition());
   357     }
   359     protected int getIntEndPosition() {
   360         return (position == null ? Position.NOPOS : position.getEndPosition(source.getEndPosTable()));
   361     }
   363     public long getStartPosition() {
   364         return getIntStartPosition();
   365     }
   367     public long getPosition() {
   368         return getIntPosition();
   369     }
   371     public long getEndPosition() {
   372         return getIntEndPosition();
   373     }
   375     /**
   376      * Get the line number within the source referred to by this diagnostic.
   377      * @return  the line number within the source referred to by this diagnostic
   378      */
   379     public long getLineNumber() {
   380         return line;
   381     }
   383     /**
   384      * Get the column number within the line of source referred to by this diagnostic.
   385      * @return  the column number within the line of source referred to by this diagnostic
   386      */
   387     public long getColumnNumber() {
   388         return column;
   389     }
   391     /**
   392      * Get the arguments to be included in the text of the diagnostic.
   393      * @return  the arguments to be included in the text of the diagnostic
   394      */
   395     public Object[] getArgs() {
   396         return args;
   397     }
   399     /**
   400      * Get the prefix string associated with this type of diagnostic.
   401      * @return the prefix string associated with this type of diagnostic
   402      */
   403     public String getPrefix() {
   404         return getPrefix(type);
   405     }
   407     /**
   408      * Get the prefix string associated with a particular type of diagnostic.
   409      * @return the prefix string associated with a particular type of diagnostic
   410      */
   411     public String getPrefix(DiagnosticType dt) {
   412         switch (dt) {
   413         case FRAGMENT: return "";
   414         case NOTE:     return getLocalizedString("compiler.note.note");
   415         case WARNING:  return getLocalizedString("compiler.warn.warning");
   416         case ERROR:    return getLocalizedString("compiler.err.error");
   417         default:
   418             throw new AssertionError("Unknown diagnostic type: " + dt);
   419         }
   420     }
   422     /**
   423      * Return the standard presentation of this diagnostic.
   424      */
   425     public String toString() {
   426         if (defaultFormatter == null) {
   427             defaultFormatter =
   428                 new DiagnosticFormatter();
   429         }
   430         return defaultFormatter.format(this);
   431     }
   433     private static DiagnosticFormatter defaultFormatter;
   435     private static final String messageBundleName =
   436         "com.sun.tools.javac.resources.compiler";
   438     private String getLocalizedString(String key, Object... args) {
   439         String[] strings = new String[args.length];
   440         for (int i = 0; i < strings.length; i++) {
   441             Object arg = args[i];
   442             if (arg == null)
   443                 strings[i] = null;
   444             else if (arg instanceof JCDiagnostic)
   445                 strings[i] = ((JCDiagnostic) arg).getMessage(null);
   446             else
   447                 strings[i] = arg.toString();
   448         }
   450         return messages.getLocalizedString(key, (Object[]) strings);
   451     }
   453     // Methods for javax.tools.Diagnostic
   455     public Diagnostic.Kind getKind() {
   456         switch (type) {
   457         case NOTE:
   458             return Diagnostic.Kind.NOTE;
   459         case WARNING:
   460             return mandatory ? Diagnostic.Kind.MANDATORY_WARNING
   461                              : Diagnostic.Kind.WARNING;
   462         case ERROR:
   463             return Diagnostic.Kind.ERROR;
   464         default:
   465             return Diagnostic.Kind.OTHER;
   466         }
   467     }
   469     public String getCode() {
   470         return key;
   471     }
   473     public String getMessage(Locale locale) {
   474         // RFE 6406133: JCDiagnostic.getMessage ignores locale argument
   475         return getLocalizedString(key, args);
   476     }
   478 }

mercurial