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

Wed, 10 Jun 2015 14:22:04 -0700

author
mfang
date
Wed, 10 Jun 2015 14:22:04 -0700
changeset 2815
d4051d4f5daf
parent 2426
829f01e7f732
child 2525
2eb010b6cb22
permissions
-rw-r--r--

8083601: jdk8u60 l10n resource file translation update 2
Reviewed-by: ksrini, yhuang

     1 /*
     2  * Copyright (c) 2003, 2013, 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.Set;
    32 import javax.tools.Diagnostic;
    33 import javax.tools.JavaFileObject;
    35 import com.sun.tools.javac.api.DiagnosticFormatter;
    36 import com.sun.tools.javac.code.Lint.LintCategory;
    37 import com.sun.tools.javac.tree.EndPosTable;
    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             final Options options = Options.instance(context);
    74             initOptions(options);
    75             options.addListener(new Runnable() {
    76                public void run() {
    77                    initOptions(options);
    78                }
    79             });
    80         }
    82         private void initOptions(Options options) {
    83             if (options.isSet("onlySyntaxErrorsUnrecoverable"))
    84                 defaultErrorFlags.add(DiagnosticFlag.RECOVERABLE);
    85         }
    87         /** Create a new diagnostic factory. */
    88         public Factory(JavacMessages messages, String prefix) {
    89             this.prefix = prefix;
    90             this.formatter = new BasicDiagnosticFormatter(messages);
    91             defaultErrorFlags = EnumSet.of(DiagnosticFlag.MANDATORY);
    92         }
    94         /**
    95          * Create an error diagnostic.
    96          *  @param source The source of the compilation unit, if any, in which to report the error.
    97          *  @param pos    The source position at which to report the error.
    98          *  @param key    The key for the localized error message.
    99          *  @param args   Fields of the error message.
   100          */
   101         public JCDiagnostic error(
   102                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   103             return create(ERROR, null, defaultErrorFlags, source, pos, key, args);
   104         }
   106         /**
   107          * Create a warning diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
   108          *  @param source The source of the compilation unit, if any, in which to report the warning.
   109          *  @param pos    The source position at which to report the warning.
   110          *  @param key    The key for the localized warning message.
   111          *  @param args   Fields of the warning message.
   112          *  @see MandatoryWarningHandler
   113          */
   114         public JCDiagnostic mandatoryWarning(
   115                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   116             return create(WARNING, null, EnumSet.of(DiagnosticFlag.MANDATORY), source, pos, key, args);
   117         }
   119         /**
   120          * Create a warning diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
   121          *  @param lc     The lint category for the diagnostic
   122          *  @param source The source of the compilation unit, if any, in which to report the warning.
   123          *  @param pos    The source position at which to report the warning.
   124          *  @param key    The key for the localized warning message.
   125          *  @param args   Fields of the warning message.
   126          *  @see MandatoryWarningHandler
   127          */
   128         public JCDiagnostic mandatoryWarning(
   129                 LintCategory lc,
   130                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   131             return create(WARNING, lc, EnumSet.of(DiagnosticFlag.MANDATORY), source, pos, key, args);
   132         }
   134         /**
   135          * Create a warning diagnostic.
   136          *  @param lc     The lint category for the diagnostic
   137          *  @param key    The key for the localized error message.
   138          *  @param args   Fields of the warning message.
   139          *  @see MandatoryWarningHandler
   140          */
   141         public JCDiagnostic warning(
   142                  LintCategory lc, String key, Object... args) {
   143             return create(WARNING, lc, EnumSet.noneOf(DiagnosticFlag.class), null, null, key, args);
   144         }
   146         /**
   147          * Create a warning diagnostic.
   148          *  @param source The source of the compilation unit, if any, in which to report the warning.
   149          *  @param pos    The source position at which to report the warning.
   150          *  @param key    The key for the localized warning message.
   151          *  @param args   Fields of the warning message.
   152          */
   153         public JCDiagnostic warning(
   154                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   155             return create(WARNING, null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
   156         }
   158         /**
   159          * Create a warning diagnostic.
   160          *  @param lc     The lint category for the diagnostic
   161          *  @param source The source of the compilation unit, if any, in which to report the warning.
   162          *  @param pos    The source position at which to report the warning.
   163          *  @param key    The key for the localized warning message.
   164          *  @param args   Fields of the warning message.
   165          *  @see MandatoryWarningHandler
   166          */
   167         public JCDiagnostic warning(
   168                  LintCategory lc, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   169             return create(WARNING, lc, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
   170         }
   172         /**
   173          * Create a note diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
   174          *  @param key    The key for the localized message.
   175          *  @param args   Fields of the message.
   176          *  @see MandatoryWarningHandler
   177          */
   178         public JCDiagnostic mandatoryNote(DiagnosticSource source, String key, Object... args) {
   179             return create(NOTE, null, EnumSet.of(DiagnosticFlag.MANDATORY), source, null, key, args);
   180         }
   182         /**
   183          * Create a note diagnostic.
   184          *  @param key    The key for the localized error message.
   185          *  @param args   Fields of the message.
   186          */
   187         public JCDiagnostic note(String key, Object... args) {
   188             return create(NOTE, null, EnumSet.noneOf(DiagnosticFlag.class), null, null, key, args);
   189         }
   191         /**
   192          * Create a note diagnostic.
   193          *  @param source The source of the compilation unit, if any, in which to report the note.
   194          *  @param pos    The source position at which to report the note.
   195          *  @param key    The key for the localized message.
   196          *  @param args   Fields of the message.
   197          */
   198         public JCDiagnostic note(
   199                 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   200             return create(NOTE, null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
   201         }
   203         /**
   204          * Create a fragment diagnostic, for use as an argument in other diagnostics
   205          *  @param key    The key for the localized message.
   206          *  @param args   Fields of the message.
   207          */
   208         public JCDiagnostic fragment(String key, Object... args) {
   209             return create(FRAGMENT, null, EnumSet.noneOf(DiagnosticFlag.class), null, null, key, args);
   210         }
   212         /**
   213          * Create a new diagnostic of the given kind, which is not mandatory and which has
   214          * no lint category.
   215          *  @param kind        The diagnostic kind
   216          *  @param source      The source of the compilation unit, if any, in which to report the message.
   217          *  @param pos         The source position at which to report the message.
   218          *  @param key         The key for the localized message.
   219          *  @param args        Fields of the message.
   220          */
   221         public JCDiagnostic create(
   222                 DiagnosticType kind, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   223             return create(kind, null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
   224         }
   226         /**
   227          * Create a new diagnostic of the given kind.
   228          *  @param kind        The diagnostic kind
   229          *  @param lc          The lint category, if applicable, or null
   230          *  @param flags       The set of flags for the diagnostic
   231          *  @param source      The source of the compilation unit, if any, in which to report the message.
   232          *  @param pos         The source position at which to report the message.
   233          *  @param key         The key for the localized message.
   234          *  @param args        Fields of the message.
   235          */
   236         public JCDiagnostic create(
   237                 DiagnosticType kind, LintCategory lc, Set<DiagnosticFlag> flags, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
   238             return new JCDiagnostic(formatter, kind, lc, flags, source, pos, qualify(kind, key), args);
   239         }
   241         protected String qualify(DiagnosticType t, String key) {
   242             return prefix + "." + t.key + "." + key;
   243         }
   244     }
   248     /**
   249      * Create a fragment diagnostic, for use as an argument in other diagnostics
   250      *  @param key    The key for the localized error message.
   251      *  @param args   Fields of the error message.
   252      *
   253      */
   254     @Deprecated
   255     public static JCDiagnostic fragment(String key, Object... args) {
   256         return new JCDiagnostic(getFragmentFormatter(),
   257                               FRAGMENT,
   258                               null,
   259                               EnumSet.noneOf(DiagnosticFlag.class),
   260                               null,
   261                               null,
   262                               "compiler." + FRAGMENT.key + "." + key,
   263                               args);
   264     }
   265     //where
   266     @Deprecated
   267     public static DiagnosticFormatter<JCDiagnostic> getFragmentFormatter() {
   268         if (fragmentFormatter == null) {
   269             fragmentFormatter = new BasicDiagnosticFormatter(JavacMessages.getDefaultMessages());
   270         }
   271         return fragmentFormatter;
   272     }
   274     /**
   275      * A DiagnosticType defines the type of the diagnostic.
   276      **/
   277     public enum DiagnosticType {
   278         /** A fragment of an enclosing diagnostic. */
   279         FRAGMENT("misc"),
   280         /** A note: similar to, but less serious than, a warning. */
   281         NOTE("note"),
   282         /** A warning. */
   283         WARNING("warn"),
   284         /** An error. */
   285         ERROR("err");
   287         final String key;
   289         /** Create a DiagnosticType.
   290          * @param key A string used to create the resource key for the diagnostic.
   291          */
   292         DiagnosticType(String key) {
   293             this.key = key;
   294         }
   295     };
   297     /**
   298      * A DiagnosticPosition provides information about the positions in a file
   299      * that gave rise to a diagnostic. It always defines a "preferred" position
   300      * that most accurately defines the location of the diagnostic, it may also
   301      * provide a related tree node that spans that location.
   302      */
   303     public static interface DiagnosticPosition {
   304         /** Gets the tree node, if any, to which the diagnostic applies. */
   305         JCTree getTree();
   306         /** If there is a tree node, get the start position of the tree node.
   307          *  Otherwise, just returns the same as getPreferredPosition(). */
   308         int getStartPosition();
   309         /** Get the position within the file that most accurately defines the
   310          *  location for the diagnostic. */
   311         int getPreferredPosition();
   312         /** If there is a tree node, and if endPositions are available, get
   313          *  the end position of the tree node. Otherwise, just returns the
   314          *  same as getPreferredPosition(). */
   315         int getEndPosition(EndPosTable endPosTable);
   316     }
   318     /**
   319      * A DiagnosticPosition that simply identifies a position, but no related
   320      * tree node, as the location for a diagnostic. Used for scanner and parser
   321      * diagnostics. */
   322     public static class SimpleDiagnosticPosition implements DiagnosticPosition {
   323         public SimpleDiagnosticPosition(int pos) {
   324             this.pos = pos;
   325         }
   327         public JCTree getTree() {
   328             return null;
   329         }
   331         public int getStartPosition() {
   332             return pos;
   333         }
   335         public int getPreferredPosition() {
   336             return pos;
   337         }
   339         public int getEndPosition(EndPosTable endPosTable) {
   340             return pos;
   341         }
   343         private final int pos;
   344     }
   346     public enum DiagnosticFlag {
   347         MANDATORY,
   348         RESOLVE_ERROR,
   349         SYNTAX,
   350         RECOVERABLE,
   351         NON_DEFERRABLE,
   352         COMPRESSED
   353     }
   355     private final DiagnosticType type;
   356     private final DiagnosticSource source;
   357     private final DiagnosticPosition position;
   358     private final String key;
   359     protected final Object[] args;
   360     private final Set<DiagnosticFlag> flags;
   361     private final LintCategory lintCategory;
   363     /** source line position (set lazily) */
   364     private SourcePosition sourcePosition;
   366     /**
   367      * This class is used to defer the line/column position fetch logic after diagnostic construction.
   368      */
   369     class SourcePosition {
   371         private final int line;
   372         private final int column;
   374         SourcePosition() {
   375             int n = (position == null ? Position.NOPOS : position.getPreferredPosition());
   376             if (n == Position.NOPOS || source == null)
   377                 line = column = -1;
   378             else {
   379                 line = source.getLineNumber(n);
   380                 column = source.getColumnNumber(n, true);
   381             }
   382         }
   384         public int getLineNumber() {
   385             return line;
   386         }
   388         public int getColumnNumber() {
   389             return column;
   390         }
   391     }
   393     /**
   394      * Create a diagnostic object.
   395      * @param formatter the formatter to use for the diagnostic
   396      * @param dt the type of diagnostic
   397      * @param lc     the lint category for the diagnostic
   398      * @param source the name of the source file, or null if none.
   399      * @param pos the character offset within the source file, if given.
   400      * @param key a resource key to identify the text of the diagnostic
   401      * @param args arguments to be included in the text of the diagnostic
   402      */
   403     protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
   404                        DiagnosticType dt,
   405                        LintCategory lc,
   406                        Set<DiagnosticFlag> flags,
   407                        DiagnosticSource source,
   408                        DiagnosticPosition pos,
   409                        String key,
   410                        Object... args) {
   411         if (source == null && pos != null && pos.getPreferredPosition() != Position.NOPOS)
   412             throw new IllegalArgumentException();
   414         this.defaultFormatter = formatter;
   415         this.type = dt;
   416         this.lintCategory = lc;
   417         this.flags = flags;
   418         this.source = source;
   419         this.position = pos;
   420         this.key = key;
   421         this.args = args;
   422     }
   424     /**
   425      * Get the type of this diagnostic.
   426      * @return the type of this diagnostic
   427      */
   428     public DiagnosticType getType() {
   429         return type;
   430     }
   432     /**
   433      * Get the subdiagnostic list
   434      * @return subdiagnostic list
   435      */
   436     public List<JCDiagnostic> getSubdiagnostics() {
   437         return List.nil();
   438     }
   440     public boolean isMultiline() {
   441         return false;
   442     }
   444     /**
   445      * Check whether or not this diagnostic is required to be shown.
   446      * @return true if this diagnostic is required to be shown.
   447      */
   448     public boolean isMandatory() {
   449         return flags.contains(DiagnosticFlag.MANDATORY);
   450     }
   452     /**
   453      * Check whether this diagnostic has an associated lint category.
   454      */
   455     public boolean hasLintCategory() {
   456         return (lintCategory != null);
   457     }
   459     /**
   460      * Get the associated lint category, or null if none.
   461      */
   462     public LintCategory getLintCategory() {
   463         return lintCategory;
   464     }
   466     /**
   467      * Get the name of the source file referred to by this diagnostic.
   468      * @return the name of the source referred to with this diagnostic, or null if none
   469      */
   470     public JavaFileObject getSource() {
   471         if (source == null)
   472             return null;
   473         else
   474             return source.getFile();
   475     }
   477     /**
   478      * Get the source referred to by this diagnostic.
   479      * @return the source referred to with this diagnostic, or null if none
   480      */
   481     public DiagnosticSource getDiagnosticSource() {
   482         return source;
   483     }
   485     protected int getIntStartPosition() {
   486         return (position == null ? Position.NOPOS : position.getStartPosition());
   487     }
   489     protected int getIntPosition() {
   490         return (position == null ? Position.NOPOS : position.getPreferredPosition());
   491     }
   493     protected int getIntEndPosition() {
   494         return (position == null ? Position.NOPOS : position.getEndPosition(source.getEndPosTable()));
   495     }
   497     public long getStartPosition() {
   498         return getIntStartPosition();
   499     }
   501     public long getPosition() {
   502         return getIntPosition();
   503     }
   505     public long getEndPosition() {
   506         return getIntEndPosition();
   507     }
   509     public DiagnosticPosition getDiagnosticPosition() {
   510         return position;
   511     }
   513     /**
   514      * Get the line number within the source referred to by this diagnostic.
   515      * @return  the line number within the source referred to by this diagnostic
   516      */
   517     public long getLineNumber() {
   518         if (sourcePosition == null) {
   519             sourcePosition = new SourcePosition();
   520         }
   521         return sourcePosition.getLineNumber();
   522     }
   524     /**
   525      * Get the column number within the line of source referred to by this diagnostic.
   526      * @return  the column number within the line of source referred to by this diagnostic
   527      */
   528     public long getColumnNumber() {
   529         if (sourcePosition == null) {
   530             sourcePosition = new SourcePosition();
   531         }
   532         return sourcePosition.getColumnNumber();
   533     }
   535     /**
   536      * Get the arguments to be included in the text of the diagnostic.
   537      * @return  the arguments to be included in the text of the diagnostic
   538      */
   539     public Object[] getArgs() {
   540         return args;
   541     }
   543     /**
   544      * Get the prefix string associated with this type of diagnostic.
   545      * @return the prefix string associated with this type of diagnostic
   546      */
   547     public String getPrefix() {
   548         return getPrefix(type);
   549     }
   551     /**
   552      * Get the prefix string associated with a particular type of diagnostic.
   553      * @return the prefix string associated with a particular type of diagnostic
   554      */
   555     public String getPrefix(DiagnosticType dt) {
   556         return defaultFormatter.formatKind(this, Locale.getDefault());
   557     }
   559     /**
   560      * Return the standard presentation of this diagnostic.
   561      */
   562     @Override
   563     public String toString() {
   564         return defaultFormatter.format(this,Locale.getDefault());
   565     }
   567     private DiagnosticFormatter<JCDiagnostic> defaultFormatter;
   568     @Deprecated
   569     private static DiagnosticFormatter<JCDiagnostic> fragmentFormatter;
   571     // Methods for javax.tools.Diagnostic
   573     public Diagnostic.Kind getKind() {
   574         switch (type) {
   575         case NOTE:
   576             return Diagnostic.Kind.NOTE;
   577         case WARNING:
   578             return flags.contains(DiagnosticFlag.MANDATORY)
   579                     ? Diagnostic.Kind.MANDATORY_WARNING
   580                     : Diagnostic.Kind.WARNING;
   581         case ERROR:
   582             return Diagnostic.Kind.ERROR;
   583         default:
   584             return Diagnostic.Kind.OTHER;
   585         }
   586     }
   588     public String getCode() {
   589         return key;
   590     }
   592     public String getMessage(Locale locale) {
   593         return defaultFormatter.formatMessage(this, locale);
   594     }
   596     public void setFlag(DiagnosticFlag flag) {
   597         flags.add(flag);
   599         if (type == DiagnosticType.ERROR) {
   600             switch (flag) {
   601                 case SYNTAX:
   602                     flags.remove(DiagnosticFlag.RECOVERABLE);
   603                     break;
   604                 case RESOLVE_ERROR:
   605                     flags.add(DiagnosticFlag.RECOVERABLE);
   606                     break;
   607             }
   608         }
   609     }
   611     public boolean isFlagSet(DiagnosticFlag flag) {
   612         return flags.contains(flag);
   613     }
   615     public static class MultilineDiagnostic extends JCDiagnostic {
   617         private final List<JCDiagnostic> subdiagnostics;
   619         public MultilineDiagnostic(JCDiagnostic other, List<JCDiagnostic> subdiagnostics) {
   620             super(other.defaultFormatter,
   621                   other.getType(),
   622                   other.getLintCategory(),
   623                   other.flags,
   624                   other.getDiagnosticSource(),
   625                   other.position,
   626                   other.getCode(),
   627                   other.getArgs());
   628             this.subdiagnostics = subdiagnostics;
   629         }
   631         @Override
   632         public List<JCDiagnostic> getSubdiagnostics() {
   633             return subdiagnostics;
   634         }
   636         @Override
   637         public boolean isMultiline() {
   638             return true;
   639         }
   640     }
   641 }

mercurial