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

Mon, 26 Jul 2010 14:25:56 -0700

author
jjg
date
Mon, 26 Jul 2010 14:25:56 -0700
changeset 612
d1bd93028447
parent 581
f2fdd52e4e87
child 798
4868a36f6fd8
permissions
-rw-r--r--

6957438: improve code for generating warning messages containing option names
Reviewed-by: mcimadamore

     1 /*
     2  * Copyright (c) 2005, 2008, 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.HashSet;
    29 import java.util.Set;
    30 import javax.tools.JavaFileObject;
    32 import com.sun.tools.javac.code.Lint.LintCategory;
    33 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    36 /**
    37  * A handler to process mandatory warnings, setting up a deferred diagnostic
    38  * to be printed at the end of the compilation if some warnings get suppressed
    39  * because too many warnings have already been generated.
    40  *
    41  * Note that the SuppressWarnings annotation can be used to suppress warnings
    42  * about conditions that would otherwise merit a warning. Such processing
    43  * is done when the condition is detected, and in those cases, no call is
    44  * made on any API to generate a warning at all. In consequence, this handler only
    45  * gets to handle those warnings that JLS says must be generated.
    46  *
    47  *  <p><b>This is NOT part of any supported API.
    48  *  If you write code that depends on this, you do so at your own risk.
    49  *  This code and its internal interfaces are subject to change or
    50  *  deletion without notice.</b>
    51  */
    52 public class MandatoryWarningHandler {
    54     /**
    55      * The kinds of different deferred diagnostics that might be generated
    56      * if a mandatory warning is suppressed because too many warnings have
    57      * already been output.
    58      *
    59      * The parameter is a fragment used to build an I18N message key for Log.
    60      */
    61     private enum DeferredDiagnosticKind {
    62         /**
    63          * This kind is used when a single specific file is found to have warnings
    64          * and no similar warnings have already been given.
    65          * It generates a message like:
    66          *      FILE has ISSUES
    67          */
    68         IN_FILE(".filename"),
    69         /**
    70          * This kind is used when a single specific file is found to have warnings
    71          * and when similar warnings have already been reported for the file.
    72          * It generates a message like:
    73          *      FILE has additional ISSUES
    74          */
    75         ADDITIONAL_IN_FILE(".filename.additional"),
    76         /**
    77          * This kind is used when multiple files have been found to have warnings,
    78          * and none of them have had any similar warnings.
    79          * It generates a message like:
    80          *      Some files have ISSUES
    81          */
    82         IN_FILES(".plural"),
    83         /**
    84          * This kind is used when multiple files have been found to have warnings,
    85          * and some of them have had already had specific similar warnings.
    86          * It generates a message like:
    87          *      Some files have additional ISSUES
    88          */
    89         ADDITIONAL_IN_FILES(".plural.additional");
    91         DeferredDiagnosticKind(String v) { value = v; }
    92         String getKey(String prefix) { return prefix + value; }
    94         private String value;
    95     }
    98     /**
    99      * Create a handler for mandatory warnings.
   100      * @param log     The log on which to generate any diagnostics
   101      * @param verbose Specify whether or not detailed messages about
   102      *                individual instances should be given, or whether an aggregate
   103      *                message should be generated at the end of the compilation.
   104      *                Typically set via  -Xlint:option.
   105      * @param enforceMandatory
   106      *                True if mandatory warnings and notes are being enforced.
   107      * @param prefix  A common prefix for the set of message keys for
   108      *                the messages that may be generated.
   109      * @param lc      An associated lint category for the warnings, or null if none.
   110      */
   111     public MandatoryWarningHandler(Log log, boolean verbose,
   112                                    boolean enforceMandatory, String prefix,
   113                                    LintCategory lc) {
   114         this.log = log;
   115         this.verbose = verbose;
   116         this.prefix = prefix;
   117         this.enforceMandatory = enforceMandatory;
   118         this.lintCategory = lc;
   119     }
   121     /**
   122      * Report a mandatory warning.
   123      */
   124     public void report(DiagnosticPosition pos, String msg, Object... args) {
   125         JavaFileObject currentSource = log.currentSourceFile();
   127         if (verbose) {
   128             if (sourcesWithReportedWarnings == null)
   129                 sourcesWithReportedWarnings = new HashSet<JavaFileObject>();
   131             if (log.nwarnings < log.MaxWarnings) {
   132                 // generate message and remember the source file
   133                 logMandatoryWarning(pos, msg, args);
   134                 sourcesWithReportedWarnings.add(currentSource);
   135             } else if (deferredDiagnosticKind == null) {
   136                 // set up deferred message
   137                 if (sourcesWithReportedWarnings.contains(currentSource)) {
   138                     // more errors in a file that already has reported warnings
   139                     deferredDiagnosticKind = DeferredDiagnosticKind.ADDITIONAL_IN_FILE;
   140                 } else {
   141                     // warnings in a new source file
   142                     deferredDiagnosticKind = DeferredDiagnosticKind.IN_FILE;
   143                 }
   144                 deferredDiagnosticSource = currentSource;
   145                 deferredDiagnosticArg = currentSource;
   146             } else if ((deferredDiagnosticKind == DeferredDiagnosticKind.IN_FILE
   147                         || deferredDiagnosticKind == DeferredDiagnosticKind.ADDITIONAL_IN_FILE)
   148                        && !equal(deferredDiagnosticSource, currentSource)) {
   149                 // additional errors in more than one source file
   150                 deferredDiagnosticKind = DeferredDiagnosticKind.ADDITIONAL_IN_FILES;
   151                 deferredDiagnosticArg = null;
   152             }
   153         } else {
   154             if (deferredDiagnosticKind == null) {
   155                 // warnings in a single source
   156                 deferredDiagnosticKind = DeferredDiagnosticKind.IN_FILE;
   157                 deferredDiagnosticSource = currentSource;
   158                 deferredDiagnosticArg = currentSource;
   159             }  else if (deferredDiagnosticKind == DeferredDiagnosticKind.IN_FILE &&
   160                         !equal(deferredDiagnosticSource, currentSource)) {
   161                 // warnings in multiple source files
   162                 deferredDiagnosticKind = DeferredDiagnosticKind.IN_FILES;
   163                 deferredDiagnosticArg = null;
   164             }
   165         }
   166     }
   168     /**
   169      * Report any diagnostic that might have been deferred by previous calls of report().
   170      */
   171     public void reportDeferredDiagnostic() {
   172         if (deferredDiagnosticKind != null) {
   173             if (deferredDiagnosticArg == null)
   174                 logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix));
   175             else
   176                 logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), deferredDiagnosticArg);
   178             if (!verbose)
   179                 logMandatoryNote(deferredDiagnosticSource, prefix + ".recompile");
   180         }
   181     }
   183     /**
   184      * Check two objects, each possibly null, are either both null or are equal.
   185      */
   186     private static boolean equal(Object o1, Object o2) {
   187         return ((o1 == null || o2 == null) ? (o1 == o2) : o1.equals(o2));
   188     }
   190     /**
   191      * The log to which to report warnings.
   192      */
   193     private Log log;
   195     /**
   196      * Whether or not to report individual warnings, or simply to report a
   197      * single aggregate warning at the end of the compilation.
   198      */
   199     private boolean verbose;
   201     /**
   202      * The common prefix for all I18N message keys generated by this handler.
   203      */
   204     private String prefix;
   206     /**
   207      * A set containing the names of the source files for which specific
   208      * warnings have been generated -- i.e. in verbose mode.  If a source name
   209      * appears in this list, then deferred diagnostics will be phrased to
   210      * include "additionally"...
   211      */
   212     private Set<JavaFileObject> sourcesWithReportedWarnings;
   214     /**
   215      * A variable indicating the latest best guess at what the final
   216      * deferred diagnostic will be. Initially as specific and helpful
   217      * as possible, as more warnings are reported, the scope of the
   218      * diagnostic will be broadened.
   219      */
   220     private DeferredDiagnosticKind deferredDiagnosticKind;
   222     /**
   223      * If deferredDiagnosticKind is IN_FILE or ADDITIONAL_IN_FILE, this variable
   224      * gives the value of log.currentSource() for the file in question.
   225      */
   226     private JavaFileObject deferredDiagnosticSource;
   228     /**
   229      * An optional argument to be used when constructing the
   230      * deferred diagnostic message, based on deferredDiagnosticKind.
   231      * This variable should normally be set/updated whenever
   232      * deferredDiagnosticKind is updated.
   233      */
   234     private Object deferredDiagnosticArg;
   236     /**
   237      * True if mandatory warnings and notes are being enforced.
   238      */
   239     private final boolean enforceMandatory;
   241     /**
   242      * A LintCategory to be included in point-of-use diagnostics to indicate
   243      * how messages might be suppressed (i.e. with @SuppressWarnings).
   244      */
   245     private final LintCategory lintCategory;
   247     /**
   248      * Reports a mandatory warning to the log.  If mandatory warnings
   249      * are not being enforced, treat this as an ordinary warning.
   250      */
   251     private void logMandatoryWarning(DiagnosticPosition pos, String msg,
   252                                      Object... args) {
   253         // Note: the following log methods are safe if lintCategory is null.
   254         if (enforceMandatory)
   255             log.mandatoryWarning(lintCategory, pos, msg, args);
   256         else
   257             log.warning(lintCategory, pos, msg, args);
   258     }
   260     /**
   261      * Reports a mandatory note to the log.  If mandatory notes are
   262      * not being enforced, treat this as an ordinary note.
   263      */
   264     private void logMandatoryNote(JavaFileObject file, String msg, Object... args) {
   265         if (enforceMandatory)
   266             log.mandatoryNote(file, msg, args);
   267         else
   268             log.note(file, msg, args);
   269     }
   270 }

mercurial