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

Wed, 06 Apr 2011 20:33:44 -0700

author
ohair
date
Wed, 06 Apr 2011 20:33:44 -0700
changeset 962
0ff2bbd38f10
parent 798
4868a36f6fd8
child 1135
36553cb94345
permissions
-rw-r--r--

7033660: Update copyright year to 2011 on any files changed in 2011
Reviewed-by: dholmes

     1 /*
     2  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. 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.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.javac.util;
    28 import java.util.EnumSet;
    29 import java.util.Locale;
    30 import java.util.Map;
    31 import java.util.Set;
    33 import javax.tools.Diagnostic;
    34 import javax.tools.JavaFileObject;
    36 import com.sun.tools.javac.api.DiagnosticFormatter;
    37 import com.sun.tools.javac.code.Lint.LintCategory;
    38 import com.sun.tools.javac.tree.JCTree;
    40 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
    42 /** An abstraction of a diagnostic message generated by the compiler.
    43  *
    44  *  <p><b>This is NOT part of any supported API.
    45  *  If you write code that depends on this, you do so at your own risk.
    46  *  This code and its internal interfaces are subject to change or
    47  *  deletion without notice.</b>
    48  */
    49 public class JCDiagnostic implements Diagnostic<JavaFileObject> {
    50     /** A factory for creating diagnostic objects. */
    51     public static class Factory {
    52         /** The context key for the diagnostic factory. */
    53         protected static final Context.Key<JCDiagnostic.Factory> diagnosticFactoryKey =
    54             new Context.Key<JCDiagnostic.Factory>();
    56         /** Get the Factory instance for this context. */
    57         public static Factory instance(Context context) {
    58             Factory instance = context.get(diagnosticFactoryKey);
    59             if (instance == null)
    60                 instance = new Factory(context);
    61             return instance;
    62         }
    64         DiagnosticFormatter<JCDiagnostic> formatter;
    65         final String prefix;
    66         final Set<DiagnosticFlag> defaultErrorFlags;
    68         /** Create a new diagnostic factory. */
    69         protected Factory(Context context) {
    70             this(JavacMessages.instance(context), "compiler");
    71             context.put(diagnosticFactoryKey, this);
    73             Options options = Options.instance(context);
    74             if (options.isSet("onlySyntaxErrorsUnrecoverable"))
    75                 defaultErrorFlags.add(DiagnosticFlag.RECOVERABLE);
    76         }
    78         /** Create a new diagnostic factory. */
    79         public Factory(JavacMessages messages, String prefix) {
    80             this.prefix = prefix;
    81             this.formatter = new BasicDiagnosticFormatter(messages);
    82             defaultErrorFlags = EnumSet.of(DiagnosticFlag.MANDATORY);
    83         }
    85         /**
    86          * Create an error diagnostic.
    87          *  @param source The source of the compilation unit, if any, in which to report the error.
    88          *  @param pos    The source position at which to report the error.
    89          *  @param key    The key for the localized error message.
    90          *  @param args   Fields of the error message.
    91          */
    92         public JCDiagnostic error(
    93                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
    94             return create(ERROR, null, defaultErrorFlags, source, pos, key, args);
    95         }
    97         /**
    98          * Create a warning diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
    99          *  @param source The source of the compilation unit, if any, in which to report the warning.
   100          *  @param pos    The source position at which to report the warning.
   101          *  @param key    The key for the localized warning message.
   102          *  @param args   Fields of the warning message.
   103          *  @see MandatoryWarningHandler
   104          */
   105         public JCDiagnostic mandatoryWarning(
   106                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   107             return create(WARNING, null, EnumSet.of(DiagnosticFlag.MANDATORY), source, pos, key, args);
   108         }
   110         /**
   111          * Create a warning diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
   112          *  @param lc     The lint category for the diagnostic
   113          *  @param source The source of the compilation unit, if any, in which to report the warning.
   114          *  @param pos    The source position at which to report the warning.
   115          *  @param key    The key for the localized warning message.
   116          *  @param args   Fields of the warning message.
   117          *  @see MandatoryWarningHandler
   118          */
   119         public JCDiagnostic mandatoryWarning(
   120                 LintCategory lc,
   121                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   122             return create(WARNING, lc, EnumSet.of(DiagnosticFlag.MANDATORY), source, pos, key, args);
   123         }
   125         /**
   126          * Create a warning diagnostic.
   127          *  @param lc     The lint category for the diagnostic
   128          *  @param key    The key for the localized error message.
   129          *  @param args   Fields of the warning message.
   130          *  @see MandatoryWarningHandler
   131          */
   132         public JCDiagnostic warning(
   133                  LintCategory lc, String key, Object... args) {
   134             return create(WARNING, lc, EnumSet.noneOf(DiagnosticFlag.class), null, null, key, args);
   135         }
   137         /**
   138          * Create a warning diagnostic.
   139          *  @param source The source of the compilation unit, if any, in which to report the warning.
   140          *  @param pos    The source position at which to report the warning.
   141          *  @param key    The key for the localized warning message.
   142          *  @param args   Fields of the warning message.
   143          */
   144         public JCDiagnostic warning(
   145                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   146             return create(WARNING, null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
   147         }
   149         /**
   150          * Create a warning diagnostic.
   151          *  @param lc     The lint category for the diagnostic
   152          *  @param source The source of the compilation unit, if any, in which to report the warning.
   153          *  @param pos    The source position at which to report the warning.
   154          *  @param key    The key for the localized warning message.
   155          *  @param args   Fields of the warning message.
   156          *  @see MandatoryWarningHandler
   157          */
   158         public JCDiagnostic warning(
   159                  LintCategory lc, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   160             return create(WARNING, lc, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
   161         }
   163         /**
   164          * Create a note diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
   165          *  @param key    The key for the localized message.
   166          *  @param args   Fields of the message.
   167          *  @see MandatoryWarningHandler
   168          */
   169         public JCDiagnostic mandatoryNote(DiagnosticSource source, String key, Object... args) {
   170             return create(NOTE, null, EnumSet.of(DiagnosticFlag.MANDATORY), source, null, key, args);
   171         }
   173         /**
   174          * Create a note diagnostic.
   175          *  @param key    The key for the localized error message.
   176          *  @param args   Fields of the message.
   177          */
   178         public JCDiagnostic note(String key, Object... args) {
   179             return create(NOTE, null, EnumSet.noneOf(DiagnosticFlag.class), null, null, key, args);
   180         }
   182         /**
   183          * Create a note diagnostic.
   184          *  @param source The source of the compilation unit, if any, in which to report the note.
   185          *  @param pos    The source position at which to report the note.
   186          *  @param key    The key for the localized message.
   187          *  @param args   Fields of the message.
   188          */
   189         public JCDiagnostic note(
   190                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   191             return create(NOTE, null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
   192         }
   194         /**
   195          * Create a fragment diagnostic, for use as an argument in other diagnostics
   196          *  @param key    The key for the localized message.
   197          *  @param args   Fields of the message.
   198          */
   199         public JCDiagnostic fragment(String key, Object... args) {
   200             return create(FRAGMENT, null, EnumSet.noneOf(DiagnosticFlag.class), null, null, key, args);
   201         }
   203         /**
   204          * Create a new diagnostic of the given kind, which is not mandatory and which has
   205          * no lint category.
   206          *  @param kind        The diagnostic kind
   207          *  @param ls          The lint category, if applicable, or null
   208          *  @param source      The source of the compilation unit, if any, in which to report the message.
   209          *  @param pos         The source position at which to report the message.
   210          *  @param key         The key for the localized message.
   211          *  @param args        Fields of the message.
   212          */
   213         public JCDiagnostic create(
   214                 DiagnosticType kind, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   215             return create(kind, null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
   216         }
   218         /**
   219          * Create a new diagnostic of the given kind.
   220          *  @param kind        The diagnostic kind
   221          *  @param lc          The lint category, if applicable, or null
   222          *  @param isMandatory is diagnostic mandatory?
   223          *  @param source      The source of the compilation unit, if any, in which to report the message.
   224          *  @param pos         The source position at which to report the message.
   225          *  @param key         The key for the localized message.
   226          *  @param args        Fields of the message.
   227          */
   228         public JCDiagnostic create(
   229                 DiagnosticType kind, LintCategory lc, Set<DiagnosticFlag> flags, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   230             return new JCDiagnostic(formatter, kind, lc, flags, source, pos, qualify(kind, key), args);
   231         }
   233         protected String qualify(DiagnosticType t, String key) {
   234             return prefix + "." + t.key + "." + key;
   235         }
   236     }
   240     /**
   241      * Create a fragment diagnostic, for use as an argument in other diagnostics
   242      *  @param key    The key for the localized error message.
   243      *  @param args   Fields of the error message.
   244      *
   245      */
   246     @Deprecated
   247     public static JCDiagnostic fragment(String key, Object... args) {
   248         return new JCDiagnostic(getFragmentFormatter(),
   249                               FRAGMENT,
   250                               null,
   251                               EnumSet.noneOf(DiagnosticFlag.class),
   252                               null,
   253                               null,
   254                               "compiler." + FRAGMENT.key + "." + key,
   255                               args);
   256     }
   257     //where
   258     @Deprecated
   259     public static DiagnosticFormatter<JCDiagnostic> getFragmentFormatter() {
   260         if (fragmentFormatter == null) {
   261             fragmentFormatter = new BasicDiagnosticFormatter(JavacMessages.getDefaultMessages());
   262         }
   263         return fragmentFormatter;
   264     }
   266     /**
   267      * A DiagnosticType defines the type of the diagnostic.
   268      **/
   269     public enum DiagnosticType {
   270         /** A fragment of an enclosing diagnostic. */
   271         FRAGMENT("misc"),
   272         /** A note: similar to, but less serious than, a warning. */
   273         NOTE("note"),
   274         /** A warning. */
   275         WARNING("warn"),
   276         /** An error. */
   277         ERROR("err");
   279         final String key;
   281         /** Create a DiagnosticType.
   282          * @param key A string used to create the resource key for the diagnostic.
   283          */
   284         DiagnosticType(String key) {
   285             this.key = key;
   286         }
   287     };
   289     /**
   290      * A DiagnosticPosition provides information about the positions in a file
   291      * that gave rise to a diagnostic. It always defines a "preferred" position
   292      * that most accurately defines the location of the diagnostic, it may also
   293      * provide a related tree node that spans that location.
   294      */
   295     public static interface DiagnosticPosition {
   296         /** Gets the tree node, if any, to which the diagnostic applies. */
   297         JCTree getTree();
   298         /** If there is a tree node, get the start position of the tree node.
   299          *  Otherwise, just returns the same as getPreferredPosition(). */
   300         int getStartPosition();
   301         /** Get the position within the file that most accurately defines the
   302          *  location for the diagnostic. */
   303         int getPreferredPosition();
   304         /** If there is a tree node, and if endPositions are available, get
   305          *  the end position of the tree node. Otherwise, just returns the
   306          *  same as getPreferredPosition(). */
   307         int getEndPosition(Map<JCTree, Integer> endPosTable);
   308     }
   310     /**
   311      * A DiagnosticPosition that simply identifies a position, but no related
   312      * tree node, as the location for a diagnostic. Used for scanner and parser
   313      * diagnostics. */
   314     public static class SimpleDiagnosticPosition implements DiagnosticPosition {
   315         public SimpleDiagnosticPosition(int pos) {
   316             this.pos = pos;
   317         }
   319         public JCTree getTree() {
   320             return null;
   321         }
   323         public int getStartPosition() {
   324             return pos;
   325         }
   327         public int getPreferredPosition() {
   328             return pos;
   329         }
   331         public int getEndPosition(Map<JCTree, Integer> endPosTable) {
   332             return pos;
   333         }
   335         private final int pos;
   336     }
   338     public enum DiagnosticFlag {
   339         MANDATORY,
   340         RESOLVE_ERROR,
   341         SYNTAX,
   342         RECOVERABLE
   343     }
   345     private final DiagnosticType type;
   346     private final DiagnosticSource source;
   347     private final DiagnosticPosition position;
   348     private final int line;
   349     private final int column;
   350     private final String key;
   351     protected final Object[] args;
   352     private final Set<DiagnosticFlag> flags;
   353     private final LintCategory lintCategory;
   355     /**
   356      * Create a diagnostic object.
   357      * @param fomatter the formatter to use for the diagnostic
   358      * @param dt the type of diagnostic
   359      * @param lc     the lint category for the diagnostic
   360      * @param source the name of the source file, or null if none.
   361      * @param pos the character offset within the source file, if given.
   362      * @param key a resource key to identify the text of the diagnostic
   363      * @param args arguments to be included in the text of the diagnostic
   364      */
   365     protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
   366                        DiagnosticType dt,
   367                        LintCategory lc,
   368                        Set<DiagnosticFlag> flags,
   369                        DiagnosticSource source,
   370                        DiagnosticPosition pos,
   371                        String key,
   372                        Object... args) {
   373         if (source == null && pos != null && pos.getPreferredPosition() != Position.NOPOS)
   374             throw new IllegalArgumentException();
   376         this.defaultFormatter = formatter;
   377         this.type = dt;
   378         this.lintCategory = lc;
   379         this.flags = flags;
   380         this.source = source;
   381         this.position = pos;
   382         this.key = key;
   383             this.args = args;
   385         int n = (pos == null ? Position.NOPOS : pos.getPreferredPosition());
   386         if (n == Position.NOPOS || source == null)
   387             line = column = -1;
   388         else {
   389             line = source.getLineNumber(n);
   390             column = source.getColumnNumber(n, true);
   391         }
   392     }
   394     /**
   395      * Get the type of this diagnostic.
   396      * @return the type of this diagnostic
   397      */
   398     public DiagnosticType getType() {
   399         return type;
   400     }
   402     /**
   403      * Get the subdiagnostic list
   404      * @return subdiagnostic list
   405      */
   406     public List<JCDiagnostic> getSubdiagnostics() {
   407         return List.nil();
   408     }
   410     public boolean isMultiline() {
   411         return false;
   412     }
   414     /**
   415      * Check whether or not this diagnostic is required to be shown.
   416      * @return true if this diagnostic is required to be shown.
   417      */
   418     public boolean isMandatory() {
   419         return flags.contains(DiagnosticFlag.MANDATORY);
   420     }
   422     /**
   423      * Check whether this diagnostic has an associated lint category.
   424      */
   425     public boolean hasLintCategory() {
   426         return (lintCategory != null);
   427     }
   429     /**
   430      * Get the associated lint category, or null if none.
   431      */
   432     public LintCategory getLintCategory() {
   433         return lintCategory;
   434     }
   436     /**
   437      * Get the name of the source file referred to by this diagnostic.
   438      * @return the name of the source referred to with this diagnostic, or null if none
   439      */
   440     public JavaFileObject getSource() {
   441         if (source == null)
   442             return null;
   443         else
   444             return source.getFile();
   445     }
   447     /**
   448      * Get the source referred to by this diagnostic.
   449      * @return the source referred to with this diagnostic, or null if none
   450      */
   451     public DiagnosticSource getDiagnosticSource() {
   452         return source;
   453     }
   455     protected int getIntStartPosition() {
   456         return (position == null ? Position.NOPOS : position.getStartPosition());
   457     }
   459     protected int getIntPosition() {
   460         return (position == null ? Position.NOPOS : position.getPreferredPosition());
   461     }
   463     protected int getIntEndPosition() {
   464         return (position == null ? Position.NOPOS : position.getEndPosition(source.getEndPosTable()));
   465     }
   467     public long getStartPosition() {
   468         return getIntStartPosition();
   469     }
   471     public long getPosition() {
   472         return getIntPosition();
   473     }
   475     public long getEndPosition() {
   476         return getIntEndPosition();
   477     }
   479     /**
   480      * Get the line number within the source referred to by this diagnostic.
   481      * @return  the line number within the source referred to by this diagnostic
   482      */
   483     public long getLineNumber() {
   484         return line;
   485     }
   487     /**
   488      * Get the column number within the line of source referred to by this diagnostic.
   489      * @return  the column number within the line of source referred to by this diagnostic
   490      */
   491     public long getColumnNumber() {
   492         return column;
   493     }
   495     /**
   496      * Get the arguments to be included in the text of the diagnostic.
   497      * @return  the arguments to be included in the text of the diagnostic
   498      */
   499     public Object[] getArgs() {
   500         return args;
   501     }
   503     /**
   504      * Get the prefix string associated with this type of diagnostic.
   505      * @return the prefix string associated with this type of diagnostic
   506      */
   507     public String getPrefix() {
   508         return getPrefix(type);
   509     }
   511     /**
   512      * Get the prefix string associated with a particular type of diagnostic.
   513      * @return the prefix string associated with a particular type of diagnostic
   514      */
   515     public String getPrefix(DiagnosticType dt) {
   516         return defaultFormatter.formatKind(this, Locale.getDefault());
   517     }
   519     /**
   520      * Return the standard presentation of this diagnostic.
   521      */
   522     @Override
   523     public String toString() {
   524         return defaultFormatter.format(this,Locale.getDefault());
   525     }
   527     private DiagnosticFormatter<JCDiagnostic> defaultFormatter;
   528     @Deprecated
   529     private static DiagnosticFormatter<JCDiagnostic> fragmentFormatter;
   531     // Methods for javax.tools.Diagnostic
   533     public Diagnostic.Kind getKind() {
   534         switch (type) {
   535         case NOTE:
   536             return Diagnostic.Kind.NOTE;
   537         case WARNING:
   538             return flags.contains(DiagnosticFlag.MANDATORY)
   539                     ? Diagnostic.Kind.MANDATORY_WARNING
   540                     : Diagnostic.Kind.WARNING;
   541         case ERROR:
   542             return Diagnostic.Kind.ERROR;
   543         default:
   544             return Diagnostic.Kind.OTHER;
   545         }
   546     }
   548     public String getCode() {
   549         return key;
   550     }
   552     public String getMessage(Locale locale) {
   553         return defaultFormatter.formatMessage(this, locale);
   554     }
   556     public void setFlag(DiagnosticFlag flag) {
   557         flags.add(flag);
   559         if (type == DiagnosticType.ERROR) {
   560             switch (flag) {
   561                 case SYNTAX:
   562                     flags.remove(DiagnosticFlag.RECOVERABLE);
   563                     break;
   564                 case RESOLVE_ERROR:
   565                     flags.add(DiagnosticFlag.RECOVERABLE);
   566                     break;
   567             }
   568         }
   569     }
   571     public boolean isFlagSet(DiagnosticFlag flag) {
   572         return flags.contains(flag);
   573     }
   575     public static class MultilineDiagnostic extends JCDiagnostic {
   577         private final List<JCDiagnostic> subdiagnostics;
   579         public MultilineDiagnostic(JCDiagnostic other, List<JCDiagnostic> subdiagnostics) {
   580             super(other.defaultFormatter,
   581                   other.getType(),
   582                   other.getLintCategory(),
   583                   other.flags,
   584                   other.getDiagnosticSource(),
   585                   other.position,
   586                   other.getCode(),
   587                   other.getArgs());
   588             this.subdiagnostics = subdiagnostics;
   589         }
   591         @Override
   592         public List<JCDiagnostic> getSubdiagnostics() {
   593             return subdiagnostics;
   594         }
   596         @Override
   597         public boolean isMultiline() {
   598             return true;
   599         }
   600     }
   601 }

mercurial