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 Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,227 @@ 1.4 +/* 1.5 + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.26 + * have any 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.util.JCDiagnostic.DiagnosticPosition; 1.36 + 1.37 + 1.38 +/** 1.39 + * A handler to process mandatory warnings, setting up a deferred diagnostic 1.40 + * to be printed at the end of the compilation if some warnings get suppressed 1.41 + * because too many warnings have already been generated. 1.42 + * 1.43 + * Note that the SuppressWarnings annotation can be used to suppress warnings 1.44 + * about conditions that would otherwise merit a warning. Such processing 1.45 + * is done when the condition is detected, and in those cases, no call is 1.46 + * made on any API to generate a warning at all. In consequence, this handler only 1.47 + * gets to handle those warnings that JLS says must be generated. 1.48 + * 1.49 + * <p><b>This is NOT part of any API supported by Sun Microsystems. If 1.50 + * you write code that depends on this, you do so at your own risk. 1.51 + * This code and its internal interfaces are subject to change or 1.52 + * deletion without notice.</b> 1.53 + */ 1.54 +public class MandatoryWarningHandler { 1.55 + 1.56 + /** 1.57 + * The kinds of different deferred diagnostics that might be generated 1.58 + * if a mandatory warning is suppressed because too many warnings have 1.59 + * already been output. 1.60 + * 1.61 + * The parameter is a fragment used to build an I18N message key for Log. 1.62 + */ 1.63 + private enum DeferredDiagnosticKind { 1.64 + /** 1.65 + * This kind is used when a single specific file is found to have warnings 1.66 + * and no similar warnings have already been given. 1.67 + * It generates a message like: 1.68 + * FILE has ISSUES 1.69 + */ 1.70 + IN_FILE(".filename"), 1.71 + /** 1.72 + * This kind is used when a single specific file is found to have warnings 1.73 + * and when similar warnings have already been reported for the file. 1.74 + * It generates a message like: 1.75 + * FILE has additional ISSUES 1.76 + */ 1.77 + ADDITIONAL_IN_FILE(".filename.additional"), 1.78 + /** 1.79 + * This kind is used when multiple files have been found to have warnings, 1.80 + * and none of them have had any similar warnings. 1.81 + * It generates a message like: 1.82 + * Some files have ISSUES 1.83 + */ 1.84 + IN_FILES(".plural"), 1.85 + /** 1.86 + * This kind is used when multiple files have been found to have warnings, 1.87 + * and some of them have had already had specific similar warnings. 1.88 + * It generates a message like: 1.89 + * Some files have additional ISSUES 1.90 + */ 1.91 + ADDITIONAL_IN_FILES(".plural.additional"); 1.92 + 1.93 + DeferredDiagnosticKind(String v) { value = v; } 1.94 + String getKey(String prefix) { return prefix + value; } 1.95 + 1.96 + private String value; 1.97 + } 1.98 + 1.99 + 1.100 + /** 1.101 + * Create a handler for mandatory warnings. 1.102 + * @param log The log on which to generate any diagnostics 1.103 + * @param verbose Specify whether or not detailed messages about 1.104 + * individual instances should be given, or whether an aggregate 1.105 + * message should be generated at the end of the compilation. 1.106 + * Typically set via -Xlint:option. 1.107 + * @param prefix A common prefix for the set of message keys for 1.108 + * the messages that may be generated. 1.109 + */ 1.110 + public MandatoryWarningHandler(Log log, boolean verbose, String prefix) { 1.111 + this.log = log; 1.112 + this.verbose = verbose; 1.113 + this.prefix = prefix; 1.114 + } 1.115 + 1.116 + /** 1.117 + * Report a mandatory warning. 1.118 + */ 1.119 + public void report(DiagnosticPosition pos, String msg, Object... args) { 1.120 + JavaFileObject currentSource = log.currentSource(); 1.121 + 1.122 + if (verbose) { 1.123 + if (sourcesWithReportedWarnings == null) 1.124 + sourcesWithReportedWarnings = new HashSet<JavaFileObject>(); 1.125 + 1.126 + if (log.nwarnings < log.MaxWarnings) { 1.127 + // generate message and remember the source file 1.128 + log.mandatoryWarning(pos, msg, args); 1.129 + sourcesWithReportedWarnings.add(currentSource); 1.130 + } else if (deferredDiagnosticKind == null) { 1.131 + // set up deferred message 1.132 + if (sourcesWithReportedWarnings.contains(currentSource)) { 1.133 + // more errors in a file that already has reported warnings 1.134 + deferredDiagnosticKind = DeferredDiagnosticKind.ADDITIONAL_IN_FILE; 1.135 + } else { 1.136 + // warnings in a new source file 1.137 + deferredDiagnosticKind = DeferredDiagnosticKind.IN_FILE; 1.138 + } 1.139 + deferredDiagnosticSource = currentSource; 1.140 + deferredDiagnosticArg = currentSource; 1.141 + } else if ((deferredDiagnosticKind == DeferredDiagnosticKind.IN_FILE 1.142 + || deferredDiagnosticKind == DeferredDiagnosticKind.ADDITIONAL_IN_FILE) 1.143 + && !equal(deferredDiagnosticSource, currentSource)) { 1.144 + // additional errors in more than one source file 1.145 + deferredDiagnosticKind = DeferredDiagnosticKind.ADDITIONAL_IN_FILES; 1.146 + deferredDiagnosticArg = null; 1.147 + } 1.148 + } else { 1.149 + if (deferredDiagnosticKind == null) { 1.150 + // warnings in a single source 1.151 + deferredDiagnosticKind = DeferredDiagnosticKind.IN_FILE; 1.152 + deferredDiagnosticSource = currentSource; 1.153 + deferredDiagnosticArg = currentSource; 1.154 + } else if (deferredDiagnosticKind == DeferredDiagnosticKind.IN_FILE && 1.155 + !equal(deferredDiagnosticSource, currentSource)) { 1.156 + // warnings in multiple source files 1.157 + deferredDiagnosticKind = DeferredDiagnosticKind.IN_FILES; 1.158 + deferredDiagnosticArg = null; 1.159 + } 1.160 + } 1.161 + } 1.162 + 1.163 + /** 1.164 + * Report any diagnostic that might have been deferred by previous calls of report(). 1.165 + */ 1.166 + public void reportDeferredDiagnostic() { 1.167 + if (deferredDiagnosticKind != null) { 1.168 + if (deferredDiagnosticArg == null) 1.169 + log.mandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix)); 1.170 + else 1.171 + log.mandatoryNote(deferredDiagnosticSource, deferredDiagnosticKind.getKey(prefix), deferredDiagnosticArg); 1.172 + 1.173 + if (!verbose) 1.174 + log.mandatoryNote(deferredDiagnosticSource, prefix + ".recompile"); 1.175 + } 1.176 + } 1.177 + 1.178 + /** 1.179 + * Check two objects, each possibly null, are either both null or are equal. 1.180 + */ 1.181 + private static boolean equal(Object o1, Object o2) { 1.182 + return ((o1 == null || o2 == null) ? (o1 == o2) : o1.equals(o2)); 1.183 + } 1.184 + 1.185 + /** 1.186 + * The log to which to report warnings. 1.187 + */ 1.188 + private Log log; 1.189 + 1.190 + /** 1.191 + * Whether or not to report individual warnings, or simply to report a 1.192 + * single aggregate warning at the end of the compilation. 1.193 + */ 1.194 + private boolean verbose; 1.195 + 1.196 + /** 1.197 + * The common prefix for all I18N message keys generated by this handler. 1.198 + */ 1.199 + private String prefix; 1.200 + 1.201 + /** 1.202 + * A set containing the names of the source files for which specific 1.203 + * warnings have been generated -- i.e. in verbose mode. If a source name 1.204 + * appears in this list, then deferred diagnostics will be phrased to 1.205 + * include "additionally"... 1.206 + */ 1.207 + private Set<JavaFileObject> sourcesWithReportedWarnings; 1.208 + 1.209 + /** 1.210 + * A variable indicating the latest best guess at what the final 1.211 + * deferred diagnostic will be. Initially as specific and helpful 1.212 + * as possible, as more warnings are reported, the scope of the 1.213 + * diagnostic will be broadened. 1.214 + */ 1.215 + private DeferredDiagnosticKind deferredDiagnosticKind; 1.216 + 1.217 + /** 1.218 + * If deferredDiagnosticKind is IN_FILE or ADDITIONAL_IN_FILE, this variable 1.219 + * gives the value of log.currentSource() for the file in question. 1.220 + */ 1.221 + private JavaFileObject deferredDiagnosticSource; 1.222 + 1.223 + /** 1.224 + * An optional argument to be used when constructing the 1.225 + * deferred diagnostic message, based on deferredDiagnosticKind. 1.226 + * This variable should normally be set/updated whenever 1.227 + * deferredDiagnosticKind is updated. 1.228 + */ 1.229 + private Object deferredDiagnosticArg; 1.230 +}