1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,270 @@ 1.4 +/* 1.5 + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.javac.util; 1.30 + 1.31 +import java.util.HashSet; 1.32 +import java.util.Set; 1.33 +import javax.tools.JavaFileObject; 1.34 + 1.35 +import com.sun.tools.javac.code.Lint.LintCategory; 1.36 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 1.37 + 1.38 + 1.39 +/** 1.40 + * A handler to process mandatory warnings, setting up a deferred diagnostic 1.41 + * to be printed at the end of the compilation if some warnings get suppressed 1.42 + * because too many warnings have already been generated. 1.43 + * 1.44 + * Note that the SuppressWarnings annotation can be used to suppress warnings 1.45 + * about conditions that would otherwise merit a warning. Such processing 1.46 + * is done when the condition is detected, and in those cases, no call is 1.47 + * made on any API to generate a warning at all. In consequence, this handler only 1.48 + * gets to handle those warnings that JLS says must be generated. 1.49 + * 1.50 + * <p><b>This is NOT part of any supported API. 1.51 + * If you write code that depends on this, you do so at your own risk. 1.52 + * This code and its internal interfaces are subject to change or 1.53 + * deletion without notice.</b> 1.54 + */ 1.55 +public class MandatoryWarningHandler { 1.56 + 1.57 + /** 1.58 + * The kinds of different deferred diagnostics that might be generated 1.59 + * if a mandatory warning is suppressed because too many warnings have 1.60 + * already been output. 1.61 + * 1.62 + * The parameter is a fragment used to build an I18N message key for Log. 1.63 + */ 1.64 + private enum DeferredDiagnosticKind { 1.65 + /** 1.66 + * This kind is used when a single specific file is found to have warnings 1.67 + * and no similar warnings have already been given. 1.68 + * It generates a message like: 1.69 + * FILE has ISSUES 1.70 + */ 1.71 + IN_FILE(".filename"), 1.72 + /** 1.73 + * This kind is used when a single specific file is found to have warnings 1.74 + * and when similar warnings have already been reported for the file. 1.75 + * It generates a message like: 1.76 + * FILE has additional ISSUES 1.77 + */ 1.78 + ADDITIONAL_IN_FILE(".filename.additional"), 1.79 + /** 1.80 + * This kind is used when multiple files have been found to have warnings, 1.81 + * and none of them have had any similar warnings. 1.82 + * It generates a message like: 1.83 + * Some files have ISSUES 1.84 + */ 1.85 + IN_FILES(".plural"), 1.86 + /** 1.87 + * This kind is used when multiple files have been found to have warnings, 1.88 + * and some of them have had already had specific similar warnings. 1.89 + * It generates a message like: 1.90 + * Some files have additional ISSUES 1.91 + */ 1.92 + ADDITIONAL_IN_FILES(".plural.additional"); 1.93 + 1.94 + DeferredDiagnosticKind(String v) { value = v; } 1.95 + String getKey(String prefix) { return prefix + value; } 1.96 + 1.97 + private final String value; 1.98 + } 1.99 + 1.100 + 1.101 + /** 1.102 + * Create a handler for mandatory warnings. 1.103 + * @param log The log on which to generate any diagnostics 1.104 + * @param verbose Specify whether or not detailed messages about 1.105 + * individual instances should be given, or whether an aggregate 1.106 + * message should be generated at the end of the compilation. 1.107 + * Typically set via -Xlint:option. 1.108 + * @param enforceMandatory 1.109 + * True if mandatory warnings and notes are being enforced. 1.110 + * @param prefix A common prefix for the set of message keys for 1.111 + * the messages that may be generated. 1.112 + * @param lc An associated lint category for the warnings, or null if none. 1.113 + */ 1.114 + public MandatoryWarningHandler(Log log, boolean verbose, 1.115 + boolean enforceMandatory, String prefix, 1.116 + LintCategory lc) { 1.117 + this.log = log; 1.118 + this.verbose = verbose; 1.119 + this.prefix = prefix; 1.120 + this.enforceMandatory = enforceMandatory; 1.121 + this.lintCategory = lc; 1.122 + } 1.123 + 1.124 + /** 1.125 + * Report a mandatory warning. 1.126 + */ 1.127 + public void report(DiagnosticPosition pos, String msg, Object... args) { 1.128 + JavaFileObject currentSource = log.currentSourceFile(); 1.129 + 1.130 + if (verbose) { 1.131 + if (sourcesWithReportedWarnings == null) 1.132 + sourcesWithReportedWarnings = new HashSet<JavaFileObject>(); 1.133 + 1.134 + if (log.nwarnings < log.MaxWarnings) { 1.135 + // generate message and remember the source file 1.136 + logMandatoryWarning(pos, msg, args); 1.137 + sourcesWithReportedWarnings.add(currentSource); 1.138 + } else if (deferredDiagnosticKind == null) { 1.139 + // set up deferred message 1.140 + if (sourcesWithReportedWarnings.contains(currentSource)) { 1.141 + // more errors in a file that already has reported warnings 1.142 + deferredDiagnosticKind = DeferredDiagnosticKind.ADDITIONAL_IN_FILE; 1.143 + } else { 1.144 + // warnings in a new source file 1.145 + deferredDiagnosticKind = DeferredDiagnosticKind.IN_FILE; 1.146 + } 1.147 + deferredDiagnosticSource = currentSource; 1.148 + deferredDiagnosticArg = currentSource; 1.149 + } else if ((deferredDiagnosticKind == DeferredDiagnosticKind.IN_FILE 1.150 + || deferredDiagnosticKind == DeferredDiagnosticKind.ADDITIONAL_IN_FILE) 1.151 + && !equal(deferredDiagnosticSource, currentSource)) { 1.152 + // additional errors in more than one source file 1.153 + deferredDiagnosticKind = DeferredDiagnosticKind.ADDITIONAL_IN_FILES; 1.154 + deferredDiagnosticArg = null; 1.155 + } 1.156 + } else { 1.157 + if (deferredDiagnosticKind == null) { 1.158 + // warnings in a single source 1.159 + deferredDiagnosticKind = DeferredDiagnosticKind.IN_FILE; 1.160 + deferredDiagnosticSource = currentSource; 1.161 + deferredDiagnosticArg = currentSource; 1.162 + } else if (deferredDiagnosticKind == DeferredDiagnosticKind.IN_FILE && 1.163 + !equal(deferredDiagnosticSource, currentSource)) { 1.164 + // warnings in multiple source files 1.165 + deferredDiagnosticKind = DeferredDiagnosticKind.IN_FILES; 1.166 + deferredDiagnosticArg = null; 1.167 + } 1.168 + } 1.169 + } 1.170 + 1.171 + /** 1.172 + * Report any diagnostic that might have been deferred by previous calls of report(). 1.173 + */ 1.174 + public void reportDeferredDiagnostic() { 1.175 + if (deferredDiagnosticKind != null) { 1.176 + if (deferredDiagnosticArg == null) 1.177 + logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix)); 1.178 + else 1.179 + logMandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), deferredDiagnosticArg); 1.180 + 1.181 + if (!verbose) 1.182 + logMandatoryNote(deferredDiagnosticSource, prefix + ".recompile"); 1.183 + } 1.184 + } 1.185 + 1.186 + /** 1.187 + * Check two objects, each possibly null, are either both null or are equal. 1.188 + */ 1.189 + private static boolean equal(Object o1, Object o2) { 1.190 + return ((o1 == null || o2 == null) ? (o1 == o2) : o1.equals(o2)); 1.191 + } 1.192 + 1.193 + /** 1.194 + * The log to which to report warnings. 1.195 + */ 1.196 + private Log log; 1.197 + 1.198 + /** 1.199 + * Whether or not to report individual warnings, or simply to report a 1.200 + * single aggregate warning at the end of the compilation. 1.201 + */ 1.202 + private boolean verbose; 1.203 + 1.204 + /** 1.205 + * The common prefix for all I18N message keys generated by this handler. 1.206 + */ 1.207 + private String prefix; 1.208 + 1.209 + /** 1.210 + * A set containing the names of the source files for which specific 1.211 + * warnings have been generated -- i.e. in verbose mode. If a source name 1.212 + * appears in this list, then deferred diagnostics will be phrased to 1.213 + * include "additionally"... 1.214 + */ 1.215 + private Set<JavaFileObject> sourcesWithReportedWarnings; 1.216 + 1.217 + /** 1.218 + * A variable indicating the latest best guess at what the final 1.219 + * deferred diagnostic will be. Initially as specific and helpful 1.220 + * as possible, as more warnings are reported, the scope of the 1.221 + * diagnostic will be broadened. 1.222 + */ 1.223 + private DeferredDiagnosticKind deferredDiagnosticKind; 1.224 + 1.225 + /** 1.226 + * If deferredDiagnosticKind is IN_FILE or ADDITIONAL_IN_FILE, this variable 1.227 + * gives the value of log.currentSource() for the file in question. 1.228 + */ 1.229 + private JavaFileObject deferredDiagnosticSource; 1.230 + 1.231 + /** 1.232 + * An optional argument to be used when constructing the 1.233 + * deferred diagnostic message, based on deferredDiagnosticKind. 1.234 + * This variable should normally be set/updated whenever 1.235 + * deferredDiagnosticKind is updated. 1.236 + */ 1.237 + private Object deferredDiagnosticArg; 1.238 + 1.239 + /** 1.240 + * True if mandatory warnings and notes are being enforced. 1.241 + */ 1.242 + private final boolean enforceMandatory; 1.243 + 1.244 + /** 1.245 + * A LintCategory to be included in point-of-use diagnostics to indicate 1.246 + * how messages might be suppressed (i.e. with @SuppressWarnings). 1.247 + */ 1.248 + private final LintCategory lintCategory; 1.249 + 1.250 + /** 1.251 + * Reports a mandatory warning to the log. If mandatory warnings 1.252 + * are not being enforced, treat this as an ordinary warning. 1.253 + */ 1.254 + private void logMandatoryWarning(DiagnosticPosition pos, String msg, 1.255 + Object... args) { 1.256 + // Note: the following log methods are safe if lintCategory is null. 1.257 + if (enforceMandatory) 1.258 + log.mandatoryWarning(lintCategory, pos, msg, args); 1.259 + else 1.260 + log.warning(lintCategory, pos, msg, args); 1.261 + } 1.262 + 1.263 + /** 1.264 + * Reports a mandatory note to the log. If mandatory notes are 1.265 + * not being enforced, treat this as an ordinary note. 1.266 + */ 1.267 + private void logMandatoryNote(JavaFileObject file, String msg, Object... args) { 1.268 + if (enforceMandatory) 1.269 + log.mandatoryNote(file, msg, args); 1.270 + else 1.271 + log.note(file, msg, args); 1.272 + } 1.273 +}