1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,1764 @@ 1.4 +/* 1.5 + * Copyright (c) 1999, 2013, 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.main; 1.30 + 1.31 +import java.io.*; 1.32 +import java.util.HashMap; 1.33 +import java.util.HashSet; 1.34 +import java.util.LinkedHashMap; 1.35 +import java.util.LinkedHashSet; 1.36 +import java.util.Map; 1.37 +import java.util.MissingResourceException; 1.38 +import java.util.Queue; 1.39 +import java.util.ResourceBundle; 1.40 +import java.util.Set; 1.41 + 1.42 +import javax.annotation.processing.Processor; 1.43 +import javax.lang.model.SourceVersion; 1.44 +import javax.tools.DiagnosticListener; 1.45 +import javax.tools.JavaFileManager; 1.46 +import javax.tools.JavaFileObject; 1.47 +import javax.tools.StandardLocation; 1.48 + 1.49 +import static javax.tools.StandardLocation.CLASS_OUTPUT; 1.50 + 1.51 +import com.sun.source.util.TaskEvent; 1.52 +import com.sun.tools.javac.api.MultiTaskListener; 1.53 +import com.sun.tools.javac.code.*; 1.54 +import com.sun.tools.javac.code.Lint.LintCategory; 1.55 +import com.sun.tools.javac.code.Symbol.*; 1.56 +import com.sun.tools.javac.comp.*; 1.57 +import com.sun.tools.javac.comp.CompileStates.CompileState; 1.58 +import com.sun.tools.javac.file.JavacFileManager; 1.59 +import com.sun.tools.javac.jvm.*; 1.60 +import com.sun.tools.javac.parser.*; 1.61 +import com.sun.tools.javac.processing.*; 1.62 +import com.sun.tools.javac.tree.*; 1.63 +import com.sun.tools.javac.tree.JCTree.*; 1.64 +import com.sun.tools.javac.util.*; 1.65 +import com.sun.tools.javac.util.Log.WriterKind; 1.66 + 1.67 +import static com.sun.tools.javac.code.TypeTag.CLASS; 1.68 +import static com.sun.tools.javac.main.Option.*; 1.69 +import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; 1.70 + 1.71 + 1.72 +/** This class could be the main entry point for GJC when GJC is used as a 1.73 + * component in a larger software system. It provides operations to 1.74 + * construct a new compiler, and to run a new compiler on a set of source 1.75 + * files. 1.76 + * 1.77 + * <p><b>This is NOT part of any supported API. 1.78 + * If you write code that depends on this, you do so at your own risk. 1.79 + * This code and its internal interfaces are subject to change or 1.80 + * deletion without notice.</b> 1.81 + */ 1.82 +public class JavaCompiler { 1.83 + /** The context key for the compiler. */ 1.84 + protected static final Context.Key<JavaCompiler> compilerKey = 1.85 + new Context.Key<JavaCompiler>(); 1.86 + 1.87 + /** Get the JavaCompiler instance for this context. */ 1.88 + public static JavaCompiler instance(Context context) { 1.89 + JavaCompiler instance = context.get(compilerKey); 1.90 + if (instance == null) 1.91 + instance = new JavaCompiler(context); 1.92 + return instance; 1.93 + } 1.94 + 1.95 + /** The current version number as a string. 1.96 + */ 1.97 + public static String version() { 1.98 + return version("release"); // mm.nn.oo[-milestone] 1.99 + } 1.100 + 1.101 + /** The current full version number as a string. 1.102 + */ 1.103 + public static String fullVersion() { 1.104 + return version("full"); // mm.mm.oo[-milestone]-build 1.105 + } 1.106 + 1.107 + private static final String versionRBName = "com.sun.tools.javac.resources.version"; 1.108 + private static ResourceBundle versionRB; 1.109 + 1.110 + private static String version(String key) { 1.111 + if (versionRB == null) { 1.112 + try { 1.113 + versionRB = ResourceBundle.getBundle(versionRBName); 1.114 + } catch (MissingResourceException e) { 1.115 + return Log.getLocalizedString("version.not.available"); 1.116 + } 1.117 + } 1.118 + try { 1.119 + return versionRB.getString(key); 1.120 + } 1.121 + catch (MissingResourceException e) { 1.122 + return Log.getLocalizedString("version.not.available"); 1.123 + } 1.124 + } 1.125 + 1.126 + /** 1.127 + * Control how the compiler's latter phases (attr, flow, desugar, generate) 1.128 + * are connected. Each individual file is processed by each phase in turn, 1.129 + * but with different compile policies, you can control the order in which 1.130 + * each class is processed through its next phase. 1.131 + * 1.132 + * <p>Generally speaking, the compiler will "fail fast" in the face of 1.133 + * errors, although not aggressively so. flow, desugar, etc become no-ops 1.134 + * once any errors have occurred. No attempt is currently made to determine 1.135 + * if it might be safe to process a class through its next phase because 1.136 + * it does not depend on any unrelated errors that might have occurred. 1.137 + */ 1.138 + protected static enum CompilePolicy { 1.139 + /** 1.140 + * Just attribute the parse trees. 1.141 + */ 1.142 + ATTR_ONLY, 1.143 + 1.144 + /** 1.145 + * Just attribute and do flow analysis on the parse trees. 1.146 + * This should catch most user errors. 1.147 + */ 1.148 + CHECK_ONLY, 1.149 + 1.150 + /** 1.151 + * Attribute everything, then do flow analysis for everything, 1.152 + * then desugar everything, and only then generate output. 1.153 + * This means no output will be generated if there are any 1.154 + * errors in any classes. 1.155 + */ 1.156 + SIMPLE, 1.157 + 1.158 + /** 1.159 + * Groups the classes for each source file together, then process 1.160 + * each group in a manner equivalent to the {@code SIMPLE} policy. 1.161 + * This means no output will be generated if there are any 1.162 + * errors in any of the classes in a source file. 1.163 + */ 1.164 + BY_FILE, 1.165 + 1.166 + /** 1.167 + * Completely process each entry on the todo list in turn. 1.168 + * -- this is the same for 1.5. 1.169 + * Means output might be generated for some classes in a compilation unit 1.170 + * and not others. 1.171 + */ 1.172 + BY_TODO; 1.173 + 1.174 + static CompilePolicy decode(String option) { 1.175 + if (option == null) 1.176 + return DEFAULT_COMPILE_POLICY; 1.177 + else if (option.equals("attr")) 1.178 + return ATTR_ONLY; 1.179 + else if (option.equals("check")) 1.180 + return CHECK_ONLY; 1.181 + else if (option.equals("simple")) 1.182 + return SIMPLE; 1.183 + else if (option.equals("byfile")) 1.184 + return BY_FILE; 1.185 + else if (option.equals("bytodo")) 1.186 + return BY_TODO; 1.187 + else 1.188 + return DEFAULT_COMPILE_POLICY; 1.189 + } 1.190 + } 1.191 + 1.192 + private static final CompilePolicy DEFAULT_COMPILE_POLICY = CompilePolicy.BY_TODO; 1.193 + 1.194 + protected static enum ImplicitSourcePolicy { 1.195 + /** Don't generate or process implicitly read source files. */ 1.196 + NONE, 1.197 + /** Generate classes for implicitly read source files. */ 1.198 + CLASS, 1.199 + /** Like CLASS, but generate warnings if annotation processing occurs */ 1.200 + UNSET; 1.201 + 1.202 + static ImplicitSourcePolicy decode(String option) { 1.203 + if (option == null) 1.204 + return UNSET; 1.205 + else if (option.equals("none")) 1.206 + return NONE; 1.207 + else if (option.equals("class")) 1.208 + return CLASS; 1.209 + else 1.210 + return UNSET; 1.211 + } 1.212 + } 1.213 + 1.214 + /** The log to be used for error reporting. 1.215 + */ 1.216 + public Log log; 1.217 + 1.218 + /** Factory for creating diagnostic objects 1.219 + */ 1.220 + JCDiagnostic.Factory diagFactory; 1.221 + 1.222 + /** The tree factory module. 1.223 + */ 1.224 + protected TreeMaker make; 1.225 + 1.226 + /** The class reader. 1.227 + */ 1.228 + protected ClassReader reader; 1.229 + 1.230 + /** The class writer. 1.231 + */ 1.232 + protected ClassWriter writer; 1.233 + 1.234 + /** The native header writer. 1.235 + */ 1.236 + protected JNIWriter jniWriter; 1.237 + 1.238 + /** The module for the symbol table entry phases. 1.239 + */ 1.240 + protected Enter enter; 1.241 + 1.242 + /** The symbol table. 1.243 + */ 1.244 + protected Symtab syms; 1.245 + 1.246 + /** The language version. 1.247 + */ 1.248 + protected Source source; 1.249 + 1.250 + /** The module for code generation. 1.251 + */ 1.252 + protected Gen gen; 1.253 + 1.254 + /** The name table. 1.255 + */ 1.256 + protected Names names; 1.257 + 1.258 + /** The attributor. 1.259 + */ 1.260 + protected Attr attr; 1.261 + 1.262 + /** The attributor. 1.263 + */ 1.264 + protected Check chk; 1.265 + 1.266 + /** The flow analyzer. 1.267 + */ 1.268 + protected Flow flow; 1.269 + 1.270 + /** The type eraser. 1.271 + */ 1.272 + protected TransTypes transTypes; 1.273 + 1.274 + /** The syntactic sugar desweetener. 1.275 + */ 1.276 + protected Lower lower; 1.277 + 1.278 + /** The annotation annotator. 1.279 + */ 1.280 + protected Annotate annotate; 1.281 + 1.282 + /** Force a completion failure on this name 1.283 + */ 1.284 + protected final Name completionFailureName; 1.285 + 1.286 + /** Type utilities. 1.287 + */ 1.288 + protected Types types; 1.289 + 1.290 + /** Access to file objects. 1.291 + */ 1.292 + protected JavaFileManager fileManager; 1.293 + 1.294 + /** Factory for parsers. 1.295 + */ 1.296 + protected ParserFactory parserFactory; 1.297 + 1.298 + /** Broadcasting listener for progress events 1.299 + */ 1.300 + protected MultiTaskListener taskListener; 1.301 + 1.302 + /** 1.303 + * Annotation processing may require and provide a new instance 1.304 + * of the compiler to be used for the analyze and generate phases. 1.305 + */ 1.306 + protected JavaCompiler delegateCompiler; 1.307 + 1.308 + /** 1.309 + * SourceCompleter that delegates to the complete-method of this class. 1.310 + */ 1.311 + protected final ClassReader.SourceCompleter thisCompleter = 1.312 + new ClassReader.SourceCompleter() { 1.313 + @Override 1.314 + public void complete(ClassSymbol sym) throws CompletionFailure { 1.315 + JavaCompiler.this.complete(sym); 1.316 + } 1.317 + }; 1.318 + 1.319 + /** 1.320 + * Command line options. 1.321 + */ 1.322 + protected Options options; 1.323 + 1.324 + protected Context context; 1.325 + 1.326 + /** 1.327 + * Flag set if any annotation processing occurred. 1.328 + **/ 1.329 + protected boolean annotationProcessingOccurred; 1.330 + 1.331 + /** 1.332 + * Flag set if any implicit source files read. 1.333 + **/ 1.334 + protected boolean implicitSourceFilesRead; 1.335 + 1.336 + protected CompileStates compileStates; 1.337 + 1.338 + /** Construct a new compiler using a shared context. 1.339 + */ 1.340 + public JavaCompiler(Context context) { 1.341 + this.context = context; 1.342 + context.put(compilerKey, this); 1.343 + 1.344 + // if fileManager not already set, register the JavacFileManager to be used 1.345 + if (context.get(JavaFileManager.class) == null) 1.346 + JavacFileManager.preRegister(context); 1.347 + 1.348 + names = Names.instance(context); 1.349 + log = Log.instance(context); 1.350 + diagFactory = JCDiagnostic.Factory.instance(context); 1.351 + reader = ClassReader.instance(context); 1.352 + make = TreeMaker.instance(context); 1.353 + writer = ClassWriter.instance(context); 1.354 + jniWriter = JNIWriter.instance(context); 1.355 + enter = Enter.instance(context); 1.356 + todo = Todo.instance(context); 1.357 + 1.358 + fileManager = context.get(JavaFileManager.class); 1.359 + parserFactory = ParserFactory.instance(context); 1.360 + compileStates = CompileStates.instance(context); 1.361 + 1.362 + try { 1.363 + // catch completion problems with predefineds 1.364 + syms = Symtab.instance(context); 1.365 + } catch (CompletionFailure ex) { 1.366 + // inlined Check.completionError as it is not initialized yet 1.367 + log.error("cant.access", ex.sym, ex.getDetailValue()); 1.368 + if (ex instanceof ClassReader.BadClassFile) 1.369 + throw new Abort(); 1.370 + } 1.371 + source = Source.instance(context); 1.372 + Target target = Target.instance(context); 1.373 + attr = Attr.instance(context); 1.374 + chk = Check.instance(context); 1.375 + gen = Gen.instance(context); 1.376 + flow = Flow.instance(context); 1.377 + transTypes = TransTypes.instance(context); 1.378 + lower = Lower.instance(context); 1.379 + annotate = Annotate.instance(context); 1.380 + types = Types.instance(context); 1.381 + taskListener = MultiTaskListener.instance(context); 1.382 + 1.383 + reader.sourceCompleter = thisCompleter; 1.384 + 1.385 + options = Options.instance(context); 1.386 + 1.387 + verbose = options.isSet(VERBOSE); 1.388 + sourceOutput = options.isSet(PRINTSOURCE); // used to be -s 1.389 + stubOutput = options.isSet("-stubs"); 1.390 + relax = options.isSet("-relax"); 1.391 + printFlat = options.isSet("-printflat"); 1.392 + attrParseOnly = options.isSet("-attrparseonly"); 1.393 + encoding = options.get(ENCODING); 1.394 + lineDebugInfo = options.isUnset(G_CUSTOM) || 1.395 + options.isSet(G_CUSTOM, "lines"); 1.396 + genEndPos = options.isSet(XJCOV) || 1.397 + context.get(DiagnosticListener.class) != null; 1.398 + devVerbose = options.isSet("dev"); 1.399 + processPcks = options.isSet("process.packages"); 1.400 + werror = options.isSet(WERROR); 1.401 + 1.402 + if (source.compareTo(Source.DEFAULT) < 0) { 1.403 + if (options.isUnset(XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option)) { 1.404 + if (fileManager instanceof BaseFileManager) { 1.405 + if (((BaseFileManager) fileManager).isDefaultBootClassPath()) 1.406 + log.warning(LintCategory.OPTIONS, "source.no.bootclasspath", source.name); 1.407 + } 1.408 + } 1.409 + } 1.410 + 1.411 + checkForObsoleteOptions(target); 1.412 + 1.413 + verboseCompilePolicy = options.isSet("verboseCompilePolicy"); 1.414 + 1.415 + if (attrParseOnly) 1.416 + compilePolicy = CompilePolicy.ATTR_ONLY; 1.417 + else 1.418 + compilePolicy = CompilePolicy.decode(options.get("compilePolicy")); 1.419 + 1.420 + implicitSourcePolicy = ImplicitSourcePolicy.decode(options.get("-implicit")); 1.421 + 1.422 + completionFailureName = 1.423 + options.isSet("failcomplete") 1.424 + ? names.fromString(options.get("failcomplete")) 1.425 + : null; 1.426 + 1.427 + shouldStopPolicyIfError = 1.428 + options.isSet("shouldStopPolicy") // backwards compatible 1.429 + ? CompileState.valueOf(options.get("shouldStopPolicy")) 1.430 + : options.isSet("shouldStopPolicyIfError") 1.431 + ? CompileState.valueOf(options.get("shouldStopPolicyIfError")) 1.432 + : CompileState.INIT; 1.433 + shouldStopPolicyIfNoError = 1.434 + options.isSet("shouldStopPolicyIfNoError") 1.435 + ? CompileState.valueOf(options.get("shouldStopPolicyIfNoError")) 1.436 + : CompileState.GENERATE; 1.437 + 1.438 + if (options.isUnset("oldDiags")) 1.439 + log.setDiagnosticFormatter(RichDiagnosticFormatter.instance(context)); 1.440 + } 1.441 + 1.442 + private void checkForObsoleteOptions(Target target) { 1.443 + // Unless lint checking on options is disabled, check for 1.444 + // obsolete source and target options. 1.445 + boolean obsoleteOptionFound = false; 1.446 + if (options.isUnset(XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option)) { 1.447 + if (source.compareTo(Source.JDK1_5) <= 0) { 1.448 + log.warning(LintCategory.OPTIONS, "option.obsolete.source", source.name); 1.449 + obsoleteOptionFound = true; 1.450 + } 1.451 + 1.452 + if (target.compareTo(Target.JDK1_5) <= 0) { 1.453 + log.warning(LintCategory.OPTIONS, "option.obsolete.target", target.name); 1.454 + obsoleteOptionFound = true; 1.455 + } 1.456 + 1.457 + if (obsoleteOptionFound) 1.458 + log.warning(LintCategory.OPTIONS, "option.obsolete.suppression"); 1.459 + } 1.460 + } 1.461 + 1.462 + /* Switches: 1.463 + */ 1.464 + 1.465 + /** Verbose output. 1.466 + */ 1.467 + public boolean verbose; 1.468 + 1.469 + /** Emit plain Java source files rather than class files. 1.470 + */ 1.471 + public boolean sourceOutput; 1.472 + 1.473 + /** Emit stub source files rather than class files. 1.474 + */ 1.475 + public boolean stubOutput; 1.476 + 1.477 + /** Generate attributed parse tree only. 1.478 + */ 1.479 + public boolean attrParseOnly; 1.480 + 1.481 + /** Switch: relax some constraints for producing the jsr14 prototype. 1.482 + */ 1.483 + boolean relax; 1.484 + 1.485 + /** Debug switch: Emit Java sources after inner class flattening. 1.486 + */ 1.487 + public boolean printFlat; 1.488 + 1.489 + /** The encoding to be used for source input. 1.490 + */ 1.491 + public String encoding; 1.492 + 1.493 + /** Generate code with the LineNumberTable attribute for debugging 1.494 + */ 1.495 + public boolean lineDebugInfo; 1.496 + 1.497 + /** Switch: should we store the ending positions? 1.498 + */ 1.499 + public boolean genEndPos; 1.500 + 1.501 + /** Switch: should we debug ignored exceptions 1.502 + */ 1.503 + protected boolean devVerbose; 1.504 + 1.505 + /** Switch: should we (annotation) process packages as well 1.506 + */ 1.507 + protected boolean processPcks; 1.508 + 1.509 + /** Switch: treat warnings as errors 1.510 + */ 1.511 + protected boolean werror; 1.512 + 1.513 + /** Switch: is annotation processing requested explicitly via 1.514 + * CompilationTask.setProcessors? 1.515 + */ 1.516 + protected boolean explicitAnnotationProcessingRequested = false; 1.517 + 1.518 + /** 1.519 + * The policy for the order in which to perform the compilation 1.520 + */ 1.521 + protected CompilePolicy compilePolicy; 1.522 + 1.523 + /** 1.524 + * The policy for what to do with implicitly read source files 1.525 + */ 1.526 + protected ImplicitSourcePolicy implicitSourcePolicy; 1.527 + 1.528 + /** 1.529 + * Report activity related to compilePolicy 1.530 + */ 1.531 + public boolean verboseCompilePolicy; 1.532 + 1.533 + /** 1.534 + * Policy of how far to continue compilation after errors have occurred. 1.535 + * Set this to minimum CompileState (INIT) to stop as soon as possible 1.536 + * after errors. 1.537 + */ 1.538 + public CompileState shouldStopPolicyIfError; 1.539 + 1.540 + /** 1.541 + * Policy of how far to continue compilation when no errors have occurred. 1.542 + * Set this to maximum CompileState (GENERATE) to perform full compilation. 1.543 + * Set this lower to perform partial compilation, such as -proc:only. 1.544 + */ 1.545 + public CompileState shouldStopPolicyIfNoError; 1.546 + 1.547 + /** A queue of all as yet unattributed classes. 1.548 + */ 1.549 + public Todo todo; 1.550 + 1.551 + /** A list of items to be closed when the compilation is complete. 1.552 + */ 1.553 + public List<Closeable> closeables = List.nil(); 1.554 + 1.555 + /** The set of currently compiled inputfiles, needed to ensure 1.556 + * we don't accidentally overwrite an input file when -s is set. 1.557 + * initialized by `compile'. 1.558 + */ 1.559 + protected Set<JavaFileObject> inputFiles = new HashSet<JavaFileObject>(); 1.560 + 1.561 + protected boolean shouldStop(CompileState cs) { 1.562 + CompileState shouldStopPolicy = (errorCount() > 0 || unrecoverableError()) 1.563 + ? shouldStopPolicyIfError 1.564 + : shouldStopPolicyIfNoError; 1.565 + return cs.isAfter(shouldStopPolicy); 1.566 + } 1.567 + 1.568 + /** The number of errors reported so far. 1.569 + */ 1.570 + public int errorCount() { 1.571 + if (delegateCompiler != null && delegateCompiler != this) 1.572 + return delegateCompiler.errorCount(); 1.573 + else { 1.574 + if (werror && log.nerrors == 0 && log.nwarnings > 0) { 1.575 + log.error("warnings.and.werror"); 1.576 + } 1.577 + } 1.578 + return log.nerrors; 1.579 + } 1.580 + 1.581 + protected final <T> Queue<T> stopIfError(CompileState cs, Queue<T> queue) { 1.582 + return shouldStop(cs) ? new ListBuffer<T>() : queue; 1.583 + } 1.584 + 1.585 + protected final <T> List<T> stopIfError(CompileState cs, List<T> list) { 1.586 + return shouldStop(cs) ? List.<T>nil() : list; 1.587 + } 1.588 + 1.589 + /** The number of warnings reported so far. 1.590 + */ 1.591 + public int warningCount() { 1.592 + if (delegateCompiler != null && delegateCompiler != this) 1.593 + return delegateCompiler.warningCount(); 1.594 + else 1.595 + return log.nwarnings; 1.596 + } 1.597 + 1.598 + /** Try to open input stream with given name. 1.599 + * Report an error if this fails. 1.600 + * @param filename The file name of the input stream to be opened. 1.601 + */ 1.602 + public CharSequence readSource(JavaFileObject filename) { 1.603 + try { 1.604 + inputFiles.add(filename); 1.605 + return filename.getCharContent(false); 1.606 + } catch (IOException e) { 1.607 + log.error("error.reading.file", filename, JavacFileManager.getMessage(e)); 1.608 + return null; 1.609 + } 1.610 + } 1.611 + 1.612 + /** Parse contents of input stream. 1.613 + * @param filename The name of the file from which input stream comes. 1.614 + * @param content The characters to be parsed. 1.615 + */ 1.616 + protected JCCompilationUnit parse(JavaFileObject filename, CharSequence content) { 1.617 + long msec = now(); 1.618 + JCCompilationUnit tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(), 1.619 + null, List.<JCTree>nil()); 1.620 + if (content != null) { 1.621 + if (verbose) { 1.622 + log.printVerbose("parsing.started", filename); 1.623 + } 1.624 + if (!taskListener.isEmpty()) { 1.625 + TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename); 1.626 + taskListener.started(e); 1.627 + keepComments = true; 1.628 + genEndPos = true; 1.629 + } 1.630 + Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo); 1.631 + tree = parser.parseCompilationUnit(); 1.632 + if (verbose) { 1.633 + log.printVerbose("parsing.done", Long.toString(elapsed(msec))); 1.634 + } 1.635 + } 1.636 + 1.637 + tree.sourcefile = filename; 1.638 + 1.639 + if (content != null && !taskListener.isEmpty()) { 1.640 + TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, tree); 1.641 + taskListener.finished(e); 1.642 + } 1.643 + 1.644 + return tree; 1.645 + } 1.646 + // where 1.647 + public boolean keepComments = false; 1.648 + protected boolean keepComments() { 1.649 + return keepComments || sourceOutput || stubOutput; 1.650 + } 1.651 + 1.652 + 1.653 + /** Parse contents of file. 1.654 + * @param filename The name of the file to be parsed. 1.655 + */ 1.656 + @Deprecated 1.657 + public JCTree.JCCompilationUnit parse(String filename) { 1.658 + JavacFileManager fm = (JavacFileManager)fileManager; 1.659 + return parse(fm.getJavaFileObjectsFromStrings(List.of(filename)).iterator().next()); 1.660 + } 1.661 + 1.662 + /** Parse contents of file. 1.663 + * @param filename The name of the file to be parsed. 1.664 + */ 1.665 + public JCTree.JCCompilationUnit parse(JavaFileObject filename) { 1.666 + JavaFileObject prev = log.useSource(filename); 1.667 + try { 1.668 + JCTree.JCCompilationUnit t = parse(filename, readSource(filename)); 1.669 + if (t.endPositions != null) 1.670 + log.setEndPosTable(filename, t.endPositions); 1.671 + return t; 1.672 + } finally { 1.673 + log.useSource(prev); 1.674 + } 1.675 + } 1.676 + 1.677 + /** Resolve an identifier which may be the binary name of a class or 1.678 + * the Java name of a class or package. 1.679 + * @param name The name to resolve 1.680 + */ 1.681 + public Symbol resolveBinaryNameOrIdent(String name) { 1.682 + try { 1.683 + Name flatname = names.fromString(name.replace("/", ".")); 1.684 + return reader.loadClass(flatname); 1.685 + } catch (CompletionFailure ignore) { 1.686 + return resolveIdent(name); 1.687 + } 1.688 + } 1.689 + 1.690 + /** Resolve an identifier. 1.691 + * @param name The identifier to resolve 1.692 + */ 1.693 + public Symbol resolveIdent(String name) { 1.694 + if (name.equals("")) 1.695 + return syms.errSymbol; 1.696 + JavaFileObject prev = log.useSource(null); 1.697 + try { 1.698 + JCExpression tree = null; 1.699 + for (String s : name.split("\\.", -1)) { 1.700 + if (!SourceVersion.isIdentifier(s)) // TODO: check for keywords 1.701 + return syms.errSymbol; 1.702 + tree = (tree == null) ? make.Ident(names.fromString(s)) 1.703 + : make.Select(tree, names.fromString(s)); 1.704 + } 1.705 + JCCompilationUnit toplevel = 1.706 + make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil()); 1.707 + toplevel.packge = syms.unnamedPackage; 1.708 + return attr.attribIdent(tree, toplevel); 1.709 + } finally { 1.710 + log.useSource(prev); 1.711 + } 1.712 + } 1.713 + 1.714 + /** Emit plain Java source for a class. 1.715 + * @param env The attribution environment of the outermost class 1.716 + * containing this class. 1.717 + * @param cdef The class definition to be printed. 1.718 + */ 1.719 + JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException { 1.720 + JavaFileObject outFile 1.721 + = fileManager.getJavaFileForOutput(CLASS_OUTPUT, 1.722 + cdef.sym.flatname.toString(), 1.723 + JavaFileObject.Kind.SOURCE, 1.724 + null); 1.725 + if (inputFiles.contains(outFile)) { 1.726 + log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile); 1.727 + return null; 1.728 + } else { 1.729 + BufferedWriter out = new BufferedWriter(outFile.openWriter()); 1.730 + try { 1.731 + new Pretty(out, true).printUnit(env.toplevel, cdef); 1.732 + if (verbose) 1.733 + log.printVerbose("wrote.file", outFile); 1.734 + } finally { 1.735 + out.close(); 1.736 + } 1.737 + return outFile; 1.738 + } 1.739 + } 1.740 + 1.741 + /** Generate code and emit a class file for a given class 1.742 + * @param env The attribution environment of the outermost class 1.743 + * containing this class. 1.744 + * @param cdef The class definition from which code is generated. 1.745 + */ 1.746 + JavaFileObject genCode(Env<AttrContext> env, JCClassDecl cdef) throws IOException { 1.747 + try { 1.748 + if (gen.genClass(env, cdef) && (errorCount() == 0)) 1.749 + return writer.writeClass(cdef.sym); 1.750 + } catch (ClassWriter.PoolOverflow ex) { 1.751 + log.error(cdef.pos(), "limit.pool"); 1.752 + } catch (ClassWriter.StringOverflow ex) { 1.753 + log.error(cdef.pos(), "limit.string.overflow", 1.754 + ex.value.substring(0, 20)); 1.755 + } catch (CompletionFailure ex) { 1.756 + chk.completionError(cdef.pos(), ex); 1.757 + } 1.758 + return null; 1.759 + } 1.760 + 1.761 + /** Complete compiling a source file that has been accessed 1.762 + * by the class file reader. 1.763 + * @param c The class the source file of which needs to be compiled. 1.764 + */ 1.765 + public void complete(ClassSymbol c) throws CompletionFailure { 1.766 +// System.err.println("completing " + c);//DEBUG 1.767 + if (completionFailureName == c.fullname) { 1.768 + throw new CompletionFailure(c, "user-selected completion failure by class name"); 1.769 + } 1.770 + JCCompilationUnit tree; 1.771 + JavaFileObject filename = c.classfile; 1.772 + JavaFileObject prev = log.useSource(filename); 1.773 + 1.774 + try { 1.775 + tree = parse(filename, filename.getCharContent(false)); 1.776 + } catch (IOException e) { 1.777 + log.error("error.reading.file", filename, JavacFileManager.getMessage(e)); 1.778 + tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil()); 1.779 + } finally { 1.780 + log.useSource(prev); 1.781 + } 1.782 + 1.783 + if (!taskListener.isEmpty()) { 1.784 + TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree); 1.785 + taskListener.started(e); 1.786 + } 1.787 + 1.788 + enter.complete(List.of(tree), c); 1.789 + 1.790 + if (!taskListener.isEmpty()) { 1.791 + TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree); 1.792 + taskListener.finished(e); 1.793 + } 1.794 + 1.795 + if (enter.getEnv(c) == null) { 1.796 + boolean isPkgInfo = 1.797 + tree.sourcefile.isNameCompatible("package-info", 1.798 + JavaFileObject.Kind.SOURCE); 1.799 + if (isPkgInfo) { 1.800 + if (enter.getEnv(tree.packge) == null) { 1.801 + JCDiagnostic diag = 1.802 + diagFactory.fragment("file.does.not.contain.package", 1.803 + c.location()); 1.804 + throw reader.new BadClassFile(c, filename, diag); 1.805 + } 1.806 + } else { 1.807 + JCDiagnostic diag = 1.808 + diagFactory.fragment("file.doesnt.contain.class", 1.809 + c.getQualifiedName()); 1.810 + throw reader.new BadClassFile(c, filename, diag); 1.811 + } 1.812 + } 1.813 + 1.814 + implicitSourceFilesRead = true; 1.815 + } 1.816 + 1.817 + /** Track when the JavaCompiler has been used to compile something. */ 1.818 + private boolean hasBeenUsed = false; 1.819 + private long start_msec = 0; 1.820 + public long elapsed_msec = 0; 1.821 + 1.822 + public void compile(List<JavaFileObject> sourceFileObject) 1.823 + throws Throwable { 1.824 + compile(sourceFileObject, List.<String>nil(), null); 1.825 + } 1.826 + 1.827 + /** 1.828 + * Main method: compile a list of files, return all compiled classes 1.829 + * 1.830 + * @param sourceFileObjects file objects to be compiled 1.831 + * @param classnames class names to process for annotations 1.832 + * @param processors user provided annotation processors to bypass 1.833 + * discovery, {@code null} means that no processors were provided 1.834 + */ 1.835 + public void compile(List<JavaFileObject> sourceFileObjects, 1.836 + List<String> classnames, 1.837 + Iterable<? extends Processor> processors) 1.838 + { 1.839 + if (processors != null && processors.iterator().hasNext()) 1.840 + explicitAnnotationProcessingRequested = true; 1.841 + // as a JavaCompiler can only be used once, throw an exception if 1.842 + // it has been used before. 1.843 + if (hasBeenUsed) 1.844 + throw new AssertionError("attempt to reuse JavaCompiler"); 1.845 + hasBeenUsed = true; 1.846 + 1.847 + // forcibly set the equivalent of -Xlint:-options, so that no further 1.848 + // warnings about command line options are generated from this point on 1.849 + options.put(XLINT_CUSTOM.text + "-" + LintCategory.OPTIONS.option, "true"); 1.850 + options.remove(XLINT_CUSTOM.text + LintCategory.OPTIONS.option); 1.851 + 1.852 + start_msec = now(); 1.853 + 1.854 + try { 1.855 + initProcessAnnotations(processors); 1.856 + 1.857 + // These method calls must be chained to avoid memory leaks 1.858 + delegateCompiler = 1.859 + processAnnotations( 1.860 + enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))), 1.861 + classnames); 1.862 + 1.863 + delegateCompiler.compile2(); 1.864 + delegateCompiler.close(); 1.865 + elapsed_msec = delegateCompiler.elapsed_msec; 1.866 + } catch (Abort ex) { 1.867 + if (devVerbose) 1.868 + ex.printStackTrace(System.err); 1.869 + } finally { 1.870 + if (procEnvImpl != null) 1.871 + procEnvImpl.close(); 1.872 + } 1.873 + } 1.874 + 1.875 + /** 1.876 + * The phases following annotation processing: attribution, 1.877 + * desugar, and finally code generation. 1.878 + */ 1.879 + private void compile2() { 1.880 + try { 1.881 + switch (compilePolicy) { 1.882 + case ATTR_ONLY: 1.883 + attribute(todo); 1.884 + break; 1.885 + 1.886 + case CHECK_ONLY: 1.887 + flow(attribute(todo)); 1.888 + break; 1.889 + 1.890 + case SIMPLE: 1.891 + generate(desugar(flow(attribute(todo)))); 1.892 + break; 1.893 + 1.894 + case BY_FILE: { 1.895 + Queue<Queue<Env<AttrContext>>> q = todo.groupByFile(); 1.896 + while (!q.isEmpty() && !shouldStop(CompileState.ATTR)) { 1.897 + generate(desugar(flow(attribute(q.remove())))); 1.898 + } 1.899 + } 1.900 + break; 1.901 + 1.902 + case BY_TODO: 1.903 + while (!todo.isEmpty()) 1.904 + generate(desugar(flow(attribute(todo.remove())))); 1.905 + break; 1.906 + 1.907 + default: 1.908 + Assert.error("unknown compile policy"); 1.909 + } 1.910 + } catch (Abort ex) { 1.911 + if (devVerbose) 1.912 + ex.printStackTrace(System.err); 1.913 + } 1.914 + 1.915 + if (verbose) { 1.916 + elapsed_msec = elapsed(start_msec); 1.917 + log.printVerbose("total", Long.toString(elapsed_msec)); 1.918 + } 1.919 + 1.920 + reportDeferredDiagnostics(); 1.921 + 1.922 + if (!log.hasDiagnosticListener()) { 1.923 + printCount("error", errorCount()); 1.924 + printCount("warn", warningCount()); 1.925 + } 1.926 + } 1.927 + 1.928 + /** 1.929 + * Set needRootClasses to true, in JavaCompiler subclass constructor 1.930 + * that want to collect public apis of classes supplied on the command line. 1.931 + */ 1.932 + protected boolean needRootClasses = false; 1.933 + 1.934 + /** 1.935 + * The list of classes explicitly supplied on the command line for compilation. 1.936 + * Not always populated. 1.937 + */ 1.938 + private List<JCClassDecl> rootClasses; 1.939 + 1.940 + /** 1.941 + * Parses a list of files. 1.942 + */ 1.943 + public List<JCCompilationUnit> parseFiles(Iterable<JavaFileObject> fileObjects) { 1.944 + if (shouldStop(CompileState.PARSE)) 1.945 + return List.nil(); 1.946 + 1.947 + //parse all files 1.948 + ListBuffer<JCCompilationUnit> trees = new ListBuffer<>(); 1.949 + Set<JavaFileObject> filesSoFar = new HashSet<JavaFileObject>(); 1.950 + for (JavaFileObject fileObject : fileObjects) { 1.951 + if (!filesSoFar.contains(fileObject)) { 1.952 + filesSoFar.add(fileObject); 1.953 + trees.append(parse(fileObject)); 1.954 + } 1.955 + } 1.956 + return trees.toList(); 1.957 + } 1.958 + 1.959 + /** 1.960 + * Enter the symbols found in a list of parse trees if the compilation 1.961 + * is expected to proceed beyond anno processing into attr. 1.962 + * As a side-effect, this puts elements on the "todo" list. 1.963 + * Also stores a list of all top level classes in rootClasses. 1.964 + */ 1.965 + public List<JCCompilationUnit> enterTreesIfNeeded(List<JCCompilationUnit> roots) { 1.966 + if (shouldStop(CompileState.ATTR)) 1.967 + return List.nil(); 1.968 + return enterTrees(roots); 1.969 + } 1.970 + 1.971 + /** 1.972 + * Enter the symbols found in a list of parse trees. 1.973 + * As a side-effect, this puts elements on the "todo" list. 1.974 + * Also stores a list of all top level classes in rootClasses. 1.975 + */ 1.976 + public List<JCCompilationUnit> enterTrees(List<JCCompilationUnit> roots) { 1.977 + //enter symbols for all files 1.978 + if (!taskListener.isEmpty()) { 1.979 + for (JCCompilationUnit unit: roots) { 1.980 + TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit); 1.981 + taskListener.started(e); 1.982 + } 1.983 + } 1.984 + 1.985 + enter.main(roots); 1.986 + 1.987 + if (!taskListener.isEmpty()) { 1.988 + for (JCCompilationUnit unit: roots) { 1.989 + TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit); 1.990 + taskListener.finished(e); 1.991 + } 1.992 + } 1.993 + 1.994 + // If generating source, or if tracking public apis, 1.995 + // then remember the classes declared in 1.996 + // the original compilation units listed on the command line. 1.997 + if (needRootClasses || sourceOutput || stubOutput) { 1.998 + ListBuffer<JCClassDecl> cdefs = new ListBuffer<>(); 1.999 + for (JCCompilationUnit unit : roots) { 1.1000 + for (List<JCTree> defs = unit.defs; 1.1001 + defs.nonEmpty(); 1.1002 + defs = defs.tail) { 1.1003 + if (defs.head instanceof JCClassDecl) 1.1004 + cdefs.append((JCClassDecl)defs.head); 1.1005 + } 1.1006 + } 1.1007 + rootClasses = cdefs.toList(); 1.1008 + } 1.1009 + 1.1010 + // Ensure the input files have been recorded. Although this is normally 1.1011 + // done by readSource, it may not have been done if the trees were read 1.1012 + // in a prior round of annotation processing, and the trees have been 1.1013 + // cleaned and are being reused. 1.1014 + for (JCCompilationUnit unit : roots) { 1.1015 + inputFiles.add(unit.sourcefile); 1.1016 + } 1.1017 + 1.1018 + return roots; 1.1019 + } 1.1020 + 1.1021 + /** 1.1022 + * Set to true to enable skeleton annotation processing code. 1.1023 + * Currently, we assume this variable will be replaced more 1.1024 + * advanced logic to figure out if annotation processing is 1.1025 + * needed. 1.1026 + */ 1.1027 + boolean processAnnotations = false; 1.1028 + 1.1029 + Log.DeferredDiagnosticHandler deferredDiagnosticHandler; 1.1030 + 1.1031 + /** 1.1032 + * Object to handle annotation processing. 1.1033 + */ 1.1034 + private JavacProcessingEnvironment procEnvImpl = null; 1.1035 + 1.1036 + /** 1.1037 + * Check if we should process annotations. 1.1038 + * If so, and if no scanner is yet registered, then set up the DocCommentScanner 1.1039 + * to catch doc comments, and set keepComments so the parser records them in 1.1040 + * the compilation unit. 1.1041 + * 1.1042 + * @param processors user provided annotation processors to bypass 1.1043 + * discovery, {@code null} means that no processors were provided 1.1044 + */ 1.1045 + public void initProcessAnnotations(Iterable<? extends Processor> processors) { 1.1046 + // Process annotations if processing is not disabled and there 1.1047 + // is at least one Processor available. 1.1048 + if (options.isSet(PROC, "none")) { 1.1049 + processAnnotations = false; 1.1050 + } else if (procEnvImpl == null) { 1.1051 + procEnvImpl = JavacProcessingEnvironment.instance(context); 1.1052 + procEnvImpl.setProcessors(processors); 1.1053 + processAnnotations = procEnvImpl.atLeastOneProcessor(); 1.1054 + 1.1055 + if (processAnnotations) { 1.1056 + options.put("save-parameter-names", "save-parameter-names"); 1.1057 + reader.saveParameterNames = true; 1.1058 + keepComments = true; 1.1059 + genEndPos = true; 1.1060 + if (!taskListener.isEmpty()) 1.1061 + taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); 1.1062 + deferredDiagnosticHandler = new Log.DeferredDiagnosticHandler(log); 1.1063 + } else { // free resources 1.1064 + procEnvImpl.close(); 1.1065 + } 1.1066 + } 1.1067 + } 1.1068 + 1.1069 + // TODO: called by JavacTaskImpl 1.1070 + public JavaCompiler processAnnotations(List<JCCompilationUnit> roots) { 1.1071 + return processAnnotations(roots, List.<String>nil()); 1.1072 + } 1.1073 + 1.1074 + /** 1.1075 + * Process any annotations found in the specified compilation units. 1.1076 + * @param roots a list of compilation units 1.1077 + * @return an instance of the compiler in which to complete the compilation 1.1078 + */ 1.1079 + // Implementation note: when this method is called, log.deferredDiagnostics 1.1080 + // will have been set true by initProcessAnnotations, meaning that any diagnostics 1.1081 + // that are reported will go into the log.deferredDiagnostics queue. 1.1082 + // By the time this method exits, log.deferDiagnostics must be set back to false, 1.1083 + // and all deferredDiagnostics must have been handled: i.e. either reported 1.1084 + // or determined to be transient, and therefore suppressed. 1.1085 + public JavaCompiler processAnnotations(List<JCCompilationUnit> roots, 1.1086 + List<String> classnames) { 1.1087 + if (shouldStop(CompileState.PROCESS)) { 1.1088 + // Errors were encountered. 1.1089 + // Unless all the errors are resolve errors, the errors were parse errors 1.1090 + // or other errors during enter which cannot be fixed by running 1.1091 + // any annotation processors. 1.1092 + if (unrecoverableError()) { 1.1093 + deferredDiagnosticHandler.reportDeferredDiagnostics(); 1.1094 + log.popDiagnosticHandler(deferredDiagnosticHandler); 1.1095 + return this; 1.1096 + } 1.1097 + } 1.1098 + 1.1099 + // ASSERT: processAnnotations and procEnvImpl should have been set up by 1.1100 + // by initProcessAnnotations 1.1101 + 1.1102 + // NOTE: The !classnames.isEmpty() checks should be refactored to Main. 1.1103 + 1.1104 + if (!processAnnotations) { 1.1105 + // If there are no annotation processors present, and 1.1106 + // annotation processing is to occur with compilation, 1.1107 + // emit a warning. 1.1108 + if (options.isSet(PROC, "only")) { 1.1109 + log.warning("proc.proc-only.requested.no.procs"); 1.1110 + todo.clear(); 1.1111 + } 1.1112 + // If not processing annotations, classnames must be empty 1.1113 + if (!classnames.isEmpty()) { 1.1114 + log.error("proc.no.explicit.annotation.processing.requested", 1.1115 + classnames); 1.1116 + } 1.1117 + Assert.checkNull(deferredDiagnosticHandler); 1.1118 + return this; // continue regular compilation 1.1119 + } 1.1120 + 1.1121 + Assert.checkNonNull(deferredDiagnosticHandler); 1.1122 + 1.1123 + try { 1.1124 + List<ClassSymbol> classSymbols = List.nil(); 1.1125 + List<PackageSymbol> pckSymbols = List.nil(); 1.1126 + if (!classnames.isEmpty()) { 1.1127 + // Check for explicit request for annotation 1.1128 + // processing 1.1129 + if (!explicitAnnotationProcessingRequested()) { 1.1130 + log.error("proc.no.explicit.annotation.processing.requested", 1.1131 + classnames); 1.1132 + deferredDiagnosticHandler.reportDeferredDiagnostics(); 1.1133 + log.popDiagnosticHandler(deferredDiagnosticHandler); 1.1134 + return this; // TODO: Will this halt compilation? 1.1135 + } else { 1.1136 + boolean errors = false; 1.1137 + for (String nameStr : classnames) { 1.1138 + Symbol sym = resolveBinaryNameOrIdent(nameStr); 1.1139 + if (sym == null || 1.1140 + (sym.kind == Kinds.PCK && !processPcks) || 1.1141 + sym.kind == Kinds.ABSENT_TYP) { 1.1142 + log.error("proc.cant.find.class", nameStr); 1.1143 + errors = true; 1.1144 + continue; 1.1145 + } 1.1146 + try { 1.1147 + if (sym.kind == Kinds.PCK) 1.1148 + sym.complete(); 1.1149 + if (sym.exists()) { 1.1150 + if (sym.kind == Kinds.PCK) 1.1151 + pckSymbols = pckSymbols.prepend((PackageSymbol)sym); 1.1152 + else 1.1153 + classSymbols = classSymbols.prepend((ClassSymbol)sym); 1.1154 + continue; 1.1155 + } 1.1156 + Assert.check(sym.kind == Kinds.PCK); 1.1157 + log.warning("proc.package.does.not.exist", nameStr); 1.1158 + pckSymbols = pckSymbols.prepend((PackageSymbol)sym); 1.1159 + } catch (CompletionFailure e) { 1.1160 + log.error("proc.cant.find.class", nameStr); 1.1161 + errors = true; 1.1162 + continue; 1.1163 + } 1.1164 + } 1.1165 + if (errors) { 1.1166 + deferredDiagnosticHandler.reportDeferredDiagnostics(); 1.1167 + log.popDiagnosticHandler(deferredDiagnosticHandler); 1.1168 + return this; 1.1169 + } 1.1170 + } 1.1171 + } 1.1172 + try { 1.1173 + JavaCompiler c = procEnvImpl.doProcessing(context, roots, classSymbols, pckSymbols, 1.1174 + deferredDiagnosticHandler); 1.1175 + if (c != this) 1.1176 + annotationProcessingOccurred = c.annotationProcessingOccurred = true; 1.1177 + // doProcessing will have handled deferred diagnostics 1.1178 + return c; 1.1179 + } finally { 1.1180 + procEnvImpl.close(); 1.1181 + } 1.1182 + } catch (CompletionFailure ex) { 1.1183 + log.error("cant.access", ex.sym, ex.getDetailValue()); 1.1184 + deferredDiagnosticHandler.reportDeferredDiagnostics(); 1.1185 + log.popDiagnosticHandler(deferredDiagnosticHandler); 1.1186 + return this; 1.1187 + } 1.1188 + } 1.1189 + 1.1190 + private boolean unrecoverableError() { 1.1191 + if (deferredDiagnosticHandler != null) { 1.1192 + for (JCDiagnostic d: deferredDiagnosticHandler.getDiagnostics()) { 1.1193 + if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RECOVERABLE)) 1.1194 + return true; 1.1195 + } 1.1196 + } 1.1197 + return false; 1.1198 + } 1.1199 + 1.1200 + boolean explicitAnnotationProcessingRequested() { 1.1201 + return 1.1202 + explicitAnnotationProcessingRequested || 1.1203 + explicitAnnotationProcessingRequested(options); 1.1204 + } 1.1205 + 1.1206 + static boolean explicitAnnotationProcessingRequested(Options options) { 1.1207 + return 1.1208 + options.isSet(PROCESSOR) || 1.1209 + options.isSet(PROCESSORPATH) || 1.1210 + options.isSet(PROC, "only") || 1.1211 + options.isSet(XPRINT); 1.1212 + } 1.1213 + 1.1214 + /** 1.1215 + * Attribute a list of parse trees, such as found on the "todo" list. 1.1216 + * Note that attributing classes may cause additional files to be 1.1217 + * parsed and entered via the SourceCompleter. 1.1218 + * Attribution of the entries in the list does not stop if any errors occur. 1.1219 + * @returns a list of environments for attributd classes. 1.1220 + */ 1.1221 + public Queue<Env<AttrContext>> attribute(Queue<Env<AttrContext>> envs) { 1.1222 + ListBuffer<Env<AttrContext>> results = new ListBuffer<>(); 1.1223 + while (!envs.isEmpty()) 1.1224 + results.append(attribute(envs.remove())); 1.1225 + return stopIfError(CompileState.ATTR, results); 1.1226 + } 1.1227 + 1.1228 + /** 1.1229 + * Attribute a parse tree. 1.1230 + * @returns the attributed parse tree 1.1231 + */ 1.1232 + public Env<AttrContext> attribute(Env<AttrContext> env) { 1.1233 + if (compileStates.isDone(env, CompileState.ATTR)) 1.1234 + return env; 1.1235 + 1.1236 + if (verboseCompilePolicy) 1.1237 + printNote("[attribute " + env.enclClass.sym + "]"); 1.1238 + if (verbose) 1.1239 + log.printVerbose("checking.attribution", env.enclClass.sym); 1.1240 + 1.1241 + if (!taskListener.isEmpty()) { 1.1242 + TaskEvent e = new TaskEvent(TaskEvent.Kind.ANALYZE, env.toplevel, env.enclClass.sym); 1.1243 + taskListener.started(e); 1.1244 + } 1.1245 + 1.1246 + JavaFileObject prev = log.useSource( 1.1247 + env.enclClass.sym.sourcefile != null ? 1.1248 + env.enclClass.sym.sourcefile : 1.1249 + env.toplevel.sourcefile); 1.1250 + try { 1.1251 + attr.attrib(env); 1.1252 + if (errorCount() > 0 && !shouldStop(CompileState.ATTR)) { 1.1253 + //if in fail-over mode, ensure that AST expression nodes 1.1254 + //are correctly initialized (e.g. they have a type/symbol) 1.1255 + attr.postAttr(env.tree); 1.1256 + } 1.1257 + compileStates.put(env, CompileState.ATTR); 1.1258 + if (rootClasses != null && rootClasses.contains(env.enclClass)) { 1.1259 + // This was a class that was explicitly supplied for compilation. 1.1260 + // If we want to capture the public api of this class, 1.1261 + // then now is a good time to do it. 1.1262 + reportPublicApi(env.enclClass.sym); 1.1263 + } 1.1264 + } 1.1265 + finally { 1.1266 + log.useSource(prev); 1.1267 + } 1.1268 + 1.1269 + return env; 1.1270 + } 1.1271 + 1.1272 + /** Report the public api of a class that was supplied explicitly for compilation, 1.1273 + * for example on the command line to javac. 1.1274 + * @param sym The symbol of the class. 1.1275 + */ 1.1276 + public void reportPublicApi(ClassSymbol sym) { 1.1277 + // Override to collect the reported public api. 1.1278 + } 1.1279 + 1.1280 + /** 1.1281 + * Perform dataflow checks on attributed parse trees. 1.1282 + * These include checks for definite assignment and unreachable statements. 1.1283 + * If any errors occur, an empty list will be returned. 1.1284 + * @returns the list of attributed parse trees 1.1285 + */ 1.1286 + public Queue<Env<AttrContext>> flow(Queue<Env<AttrContext>> envs) { 1.1287 + ListBuffer<Env<AttrContext>> results = new ListBuffer<>(); 1.1288 + for (Env<AttrContext> env: envs) { 1.1289 + flow(env, results); 1.1290 + } 1.1291 + return stopIfError(CompileState.FLOW, results); 1.1292 + } 1.1293 + 1.1294 + /** 1.1295 + * Perform dataflow checks on an attributed parse tree. 1.1296 + */ 1.1297 + public Queue<Env<AttrContext>> flow(Env<AttrContext> env) { 1.1298 + ListBuffer<Env<AttrContext>> results = new ListBuffer<>(); 1.1299 + flow(env, results); 1.1300 + return stopIfError(CompileState.FLOW, results); 1.1301 + } 1.1302 + 1.1303 + /** 1.1304 + * Perform dataflow checks on an attributed parse tree. 1.1305 + */ 1.1306 + protected void flow(Env<AttrContext> env, Queue<Env<AttrContext>> results) { 1.1307 + if (compileStates.isDone(env, CompileState.FLOW)) { 1.1308 + results.add(env); 1.1309 + return; 1.1310 + } 1.1311 + 1.1312 + try { 1.1313 + if (shouldStop(CompileState.FLOW)) 1.1314 + return; 1.1315 + 1.1316 + if (relax) { 1.1317 + results.add(env); 1.1318 + return; 1.1319 + } 1.1320 + 1.1321 + if (verboseCompilePolicy) 1.1322 + printNote("[flow " + env.enclClass.sym + "]"); 1.1323 + JavaFileObject prev = log.useSource( 1.1324 + env.enclClass.sym.sourcefile != null ? 1.1325 + env.enclClass.sym.sourcefile : 1.1326 + env.toplevel.sourcefile); 1.1327 + try { 1.1328 + make.at(Position.FIRSTPOS); 1.1329 + TreeMaker localMake = make.forToplevel(env.toplevel); 1.1330 + flow.analyzeTree(env, localMake); 1.1331 + compileStates.put(env, CompileState.FLOW); 1.1332 + 1.1333 + if (shouldStop(CompileState.FLOW)) 1.1334 + return; 1.1335 + 1.1336 + results.add(env); 1.1337 + } 1.1338 + finally { 1.1339 + log.useSource(prev); 1.1340 + } 1.1341 + } 1.1342 + finally { 1.1343 + if (!taskListener.isEmpty()) { 1.1344 + TaskEvent e = new TaskEvent(TaskEvent.Kind.ANALYZE, env.toplevel, env.enclClass.sym); 1.1345 + taskListener.finished(e); 1.1346 + } 1.1347 + } 1.1348 + } 1.1349 + 1.1350 + /** 1.1351 + * Prepare attributed parse trees, in conjunction with their attribution contexts, 1.1352 + * for source or code generation. 1.1353 + * If any errors occur, an empty list will be returned. 1.1354 + * @returns a list containing the classes to be generated 1.1355 + */ 1.1356 + public Queue<Pair<Env<AttrContext>, JCClassDecl>> desugar(Queue<Env<AttrContext>> envs) { 1.1357 + ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = new ListBuffer<>(); 1.1358 + for (Env<AttrContext> env: envs) 1.1359 + desugar(env, results); 1.1360 + return stopIfError(CompileState.FLOW, results); 1.1361 + } 1.1362 + 1.1363 + HashMap<Env<AttrContext>, Queue<Pair<Env<AttrContext>, JCClassDecl>>> desugaredEnvs = 1.1364 + new HashMap<Env<AttrContext>, Queue<Pair<Env<AttrContext>, JCClassDecl>>>(); 1.1365 + 1.1366 + /** 1.1367 + * Prepare attributed parse trees, in conjunction with their attribution contexts, 1.1368 + * for source or code generation. If the file was not listed on the command line, 1.1369 + * the current implicitSourcePolicy is taken into account. 1.1370 + * The preparation stops as soon as an error is found. 1.1371 + */ 1.1372 + protected void desugar(final Env<AttrContext> env, Queue<Pair<Env<AttrContext>, JCClassDecl>> results) { 1.1373 + if (shouldStop(CompileState.TRANSTYPES)) 1.1374 + return; 1.1375 + 1.1376 + if (implicitSourcePolicy == ImplicitSourcePolicy.NONE 1.1377 + && !inputFiles.contains(env.toplevel.sourcefile)) { 1.1378 + return; 1.1379 + } 1.1380 + 1.1381 + if (compileStates.isDone(env, CompileState.LOWER)) { 1.1382 + results.addAll(desugaredEnvs.get(env)); 1.1383 + return; 1.1384 + } 1.1385 + 1.1386 + /** 1.1387 + * Ensure that superclasses of C are desugared before C itself. This is 1.1388 + * required for two reasons: (i) as erasure (TransTypes) destroys 1.1389 + * information needed in flow analysis and (ii) as some checks carried 1.1390 + * out during lowering require that all synthetic fields/methods have 1.1391 + * already been added to C and its superclasses. 1.1392 + */ 1.1393 + class ScanNested extends TreeScanner { 1.1394 + Set<Env<AttrContext>> dependencies = new LinkedHashSet<Env<AttrContext>>(); 1.1395 + protected boolean hasLambdas; 1.1396 + @Override 1.1397 + public void visitClassDef(JCClassDecl node) { 1.1398 + Type st = types.supertype(node.sym.type); 1.1399 + boolean envForSuperTypeFound = false; 1.1400 + while (!envForSuperTypeFound && st.hasTag(CLASS)) { 1.1401 + ClassSymbol c = st.tsym.outermostClass(); 1.1402 + Env<AttrContext> stEnv = enter.getEnv(c); 1.1403 + if (stEnv != null && env != stEnv) { 1.1404 + if (dependencies.add(stEnv)) { 1.1405 + boolean prevHasLambdas = hasLambdas; 1.1406 + try { 1.1407 + scan(stEnv.tree); 1.1408 + } finally { 1.1409 + /* 1.1410 + * ignore any updates to hasLambdas made during 1.1411 + * the nested scan, this ensures an initalized 1.1412 + * LambdaToMethod is available only to those 1.1413 + * classes that contain lambdas 1.1414 + */ 1.1415 + hasLambdas = prevHasLambdas; 1.1416 + } 1.1417 + } 1.1418 + envForSuperTypeFound = true; 1.1419 + } 1.1420 + st = types.supertype(st); 1.1421 + } 1.1422 + super.visitClassDef(node); 1.1423 + } 1.1424 + @Override 1.1425 + public void visitLambda(JCLambda tree) { 1.1426 + hasLambdas = true; 1.1427 + super.visitLambda(tree); 1.1428 + } 1.1429 + @Override 1.1430 + public void visitReference(JCMemberReference tree) { 1.1431 + hasLambdas = true; 1.1432 + super.visitReference(tree); 1.1433 + } 1.1434 + } 1.1435 + ScanNested scanner = new ScanNested(); 1.1436 + scanner.scan(env.tree); 1.1437 + for (Env<AttrContext> dep: scanner.dependencies) { 1.1438 + if (!compileStates.isDone(dep, CompileState.FLOW)) 1.1439 + desugaredEnvs.put(dep, desugar(flow(attribute(dep)))); 1.1440 + } 1.1441 + 1.1442 + //We need to check for error another time as more classes might 1.1443 + //have been attributed and analyzed at this stage 1.1444 + if (shouldStop(CompileState.TRANSTYPES)) 1.1445 + return; 1.1446 + 1.1447 + if (verboseCompilePolicy) 1.1448 + printNote("[desugar " + env.enclClass.sym + "]"); 1.1449 + 1.1450 + JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ? 1.1451 + env.enclClass.sym.sourcefile : 1.1452 + env.toplevel.sourcefile); 1.1453 + try { 1.1454 + //save tree prior to rewriting 1.1455 + JCTree untranslated = env.tree; 1.1456 + 1.1457 + make.at(Position.FIRSTPOS); 1.1458 + TreeMaker localMake = make.forToplevel(env.toplevel); 1.1459 + 1.1460 + if (env.tree instanceof JCCompilationUnit) { 1.1461 + if (!(stubOutput || sourceOutput || printFlat)) { 1.1462 + if (shouldStop(CompileState.LOWER)) 1.1463 + return; 1.1464 + List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake); 1.1465 + if (pdef.head != null) { 1.1466 + Assert.check(pdef.tail.isEmpty()); 1.1467 + results.add(new Pair<Env<AttrContext>, JCClassDecl>(env, (JCClassDecl)pdef.head)); 1.1468 + } 1.1469 + } 1.1470 + return; 1.1471 + } 1.1472 + 1.1473 + if (stubOutput) { 1.1474 + //emit stub Java source file, only for compilation 1.1475 + //units enumerated explicitly on the command line 1.1476 + JCClassDecl cdef = (JCClassDecl)env.tree; 1.1477 + if (untranslated instanceof JCClassDecl && 1.1478 + rootClasses.contains((JCClassDecl)untranslated) && 1.1479 + ((cdef.mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || 1.1480 + cdef.sym.packge().getQualifiedName() == names.java_lang)) { 1.1481 + results.add(new Pair<Env<AttrContext>, JCClassDecl>(env, removeMethodBodies(cdef))); 1.1482 + } 1.1483 + return; 1.1484 + } 1.1485 + 1.1486 + if (shouldStop(CompileState.TRANSTYPES)) 1.1487 + return; 1.1488 + 1.1489 + env.tree = transTypes.translateTopLevelClass(env.tree, localMake); 1.1490 + compileStates.put(env, CompileState.TRANSTYPES); 1.1491 + 1.1492 + if (source.allowLambda() && scanner.hasLambdas) { 1.1493 + if (shouldStop(CompileState.UNLAMBDA)) 1.1494 + return; 1.1495 + 1.1496 + env.tree = LambdaToMethod.instance(context).translateTopLevelClass(env, env.tree, localMake); 1.1497 + compileStates.put(env, CompileState.UNLAMBDA); 1.1498 + } 1.1499 + 1.1500 + if (shouldStop(CompileState.LOWER)) 1.1501 + return; 1.1502 + 1.1503 + if (sourceOutput) { 1.1504 + //emit standard Java source file, only for compilation 1.1505 + //units enumerated explicitly on the command line 1.1506 + JCClassDecl cdef = (JCClassDecl)env.tree; 1.1507 + if (untranslated instanceof JCClassDecl && 1.1508 + rootClasses.contains((JCClassDecl)untranslated)) { 1.1509 + results.add(new Pair<Env<AttrContext>, JCClassDecl>(env, cdef)); 1.1510 + } 1.1511 + return; 1.1512 + } 1.1513 + 1.1514 + //translate out inner classes 1.1515 + List<JCTree> cdefs = lower.translateTopLevelClass(env, env.tree, localMake); 1.1516 + compileStates.put(env, CompileState.LOWER); 1.1517 + 1.1518 + if (shouldStop(CompileState.LOWER)) 1.1519 + return; 1.1520 + 1.1521 + //generate code for each class 1.1522 + for (List<JCTree> l = cdefs; l.nonEmpty(); l = l.tail) { 1.1523 + JCClassDecl cdef = (JCClassDecl)l.head; 1.1524 + results.add(new Pair<Env<AttrContext>, JCClassDecl>(env, cdef)); 1.1525 + } 1.1526 + } 1.1527 + finally { 1.1528 + log.useSource(prev); 1.1529 + } 1.1530 + 1.1531 + } 1.1532 + 1.1533 + /** Generates the source or class file for a list of classes. 1.1534 + * The decision to generate a source file or a class file is 1.1535 + * based upon the compiler's options. 1.1536 + * Generation stops if an error occurs while writing files. 1.1537 + */ 1.1538 + public void generate(Queue<Pair<Env<AttrContext>, JCClassDecl>> queue) { 1.1539 + generate(queue, null); 1.1540 + } 1.1541 + 1.1542 + public void generate(Queue<Pair<Env<AttrContext>, JCClassDecl>> queue, Queue<JavaFileObject> results) { 1.1543 + if (shouldStop(CompileState.GENERATE)) 1.1544 + return; 1.1545 + 1.1546 + boolean usePrintSource = (stubOutput || sourceOutput || printFlat); 1.1547 + 1.1548 + for (Pair<Env<AttrContext>, JCClassDecl> x: queue) { 1.1549 + Env<AttrContext> env = x.fst; 1.1550 + JCClassDecl cdef = x.snd; 1.1551 + 1.1552 + if (verboseCompilePolicy) { 1.1553 + printNote("[generate " 1.1554 + + (usePrintSource ? " source" : "code") 1.1555 + + " " + cdef.sym + "]"); 1.1556 + } 1.1557 + 1.1558 + if (!taskListener.isEmpty()) { 1.1559 + TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym); 1.1560 + taskListener.started(e); 1.1561 + } 1.1562 + 1.1563 + JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ? 1.1564 + env.enclClass.sym.sourcefile : 1.1565 + env.toplevel.sourcefile); 1.1566 + try { 1.1567 + JavaFileObject file; 1.1568 + if (usePrintSource) 1.1569 + file = printSource(env, cdef); 1.1570 + else { 1.1571 + if (fileManager.hasLocation(StandardLocation.NATIVE_HEADER_OUTPUT) 1.1572 + && jniWriter.needsHeader(cdef.sym)) { 1.1573 + jniWriter.write(cdef.sym); 1.1574 + } 1.1575 + file = genCode(env, cdef); 1.1576 + } 1.1577 + if (results != null && file != null) 1.1578 + results.add(file); 1.1579 + } catch (IOException ex) { 1.1580 + log.error(cdef.pos(), "class.cant.write", 1.1581 + cdef.sym, ex.getMessage()); 1.1582 + return; 1.1583 + } finally { 1.1584 + log.useSource(prev); 1.1585 + } 1.1586 + 1.1587 + if (!taskListener.isEmpty()) { 1.1588 + TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym); 1.1589 + taskListener.finished(e); 1.1590 + } 1.1591 + } 1.1592 + } 1.1593 + 1.1594 + // where 1.1595 + Map<JCCompilationUnit, Queue<Env<AttrContext>>> groupByFile(Queue<Env<AttrContext>> envs) { 1.1596 + // use a LinkedHashMap to preserve the order of the original list as much as possible 1.1597 + Map<JCCompilationUnit, Queue<Env<AttrContext>>> map = new LinkedHashMap<JCCompilationUnit, Queue<Env<AttrContext>>>(); 1.1598 + for (Env<AttrContext> env: envs) { 1.1599 + Queue<Env<AttrContext>> sublist = map.get(env.toplevel); 1.1600 + if (sublist == null) { 1.1601 + sublist = new ListBuffer<Env<AttrContext>>(); 1.1602 + map.put(env.toplevel, sublist); 1.1603 + } 1.1604 + sublist.add(env); 1.1605 + } 1.1606 + return map; 1.1607 + } 1.1608 + 1.1609 + JCClassDecl removeMethodBodies(JCClassDecl cdef) { 1.1610 + final boolean isInterface = (cdef.mods.flags & Flags.INTERFACE) != 0; 1.1611 + class MethodBodyRemover extends TreeTranslator { 1.1612 + @Override 1.1613 + public void visitMethodDef(JCMethodDecl tree) { 1.1614 + tree.mods.flags &= ~Flags.SYNCHRONIZED; 1.1615 + for (JCVariableDecl vd : tree.params) 1.1616 + vd.mods.flags &= ~Flags.FINAL; 1.1617 + tree.body = null; 1.1618 + super.visitMethodDef(tree); 1.1619 + } 1.1620 + @Override 1.1621 + public void visitVarDef(JCVariableDecl tree) { 1.1622 + if (tree.init != null && tree.init.type.constValue() == null) 1.1623 + tree.init = null; 1.1624 + super.visitVarDef(tree); 1.1625 + } 1.1626 + @Override 1.1627 + public void visitClassDef(JCClassDecl tree) { 1.1628 + ListBuffer<JCTree> newdefs = new ListBuffer<>(); 1.1629 + for (List<JCTree> it = tree.defs; it.tail != null; it = it.tail) { 1.1630 + JCTree t = it.head; 1.1631 + switch (t.getTag()) { 1.1632 + case CLASSDEF: 1.1633 + if (isInterface || 1.1634 + (((JCClassDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || 1.1635 + (((JCClassDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCClassDecl) t).sym.packge().getQualifiedName() == names.java_lang) 1.1636 + newdefs.append(t); 1.1637 + break; 1.1638 + case METHODDEF: 1.1639 + if (isInterface || 1.1640 + (((JCMethodDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || 1.1641 + ((JCMethodDecl) t).sym.name == names.init || 1.1642 + (((JCMethodDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCMethodDecl) t).sym.packge().getQualifiedName() == names.java_lang) 1.1643 + newdefs.append(t); 1.1644 + break; 1.1645 + case VARDEF: 1.1646 + if (isInterface || (((JCVariableDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || 1.1647 + (((JCVariableDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCVariableDecl) t).sym.packge().getQualifiedName() == names.java_lang) 1.1648 + newdefs.append(t); 1.1649 + break; 1.1650 + default: 1.1651 + break; 1.1652 + } 1.1653 + } 1.1654 + tree.defs = newdefs.toList(); 1.1655 + super.visitClassDef(tree); 1.1656 + } 1.1657 + } 1.1658 + MethodBodyRemover r = new MethodBodyRemover(); 1.1659 + return r.translate(cdef); 1.1660 + } 1.1661 + 1.1662 + public void reportDeferredDiagnostics() { 1.1663 + if (errorCount() == 0 1.1664 + && annotationProcessingOccurred 1.1665 + && implicitSourceFilesRead 1.1666 + && implicitSourcePolicy == ImplicitSourcePolicy.UNSET) { 1.1667 + if (explicitAnnotationProcessingRequested()) 1.1668 + log.warning("proc.use.implicit"); 1.1669 + else 1.1670 + log.warning("proc.use.proc.or.implicit"); 1.1671 + } 1.1672 + chk.reportDeferredDiagnostics(); 1.1673 + if (log.compressedOutput) { 1.1674 + log.mandatoryNote(null, "compressed.diags"); 1.1675 + } 1.1676 + } 1.1677 + 1.1678 + /** Close the compiler, flushing the logs 1.1679 + */ 1.1680 + public void close() { 1.1681 + close(true); 1.1682 + } 1.1683 + 1.1684 + public void close(boolean disposeNames) { 1.1685 + rootClasses = null; 1.1686 + reader = null; 1.1687 + make = null; 1.1688 + writer = null; 1.1689 + enter = null; 1.1690 + if (todo != null) 1.1691 + todo.clear(); 1.1692 + todo = null; 1.1693 + parserFactory = null; 1.1694 + syms = null; 1.1695 + source = null; 1.1696 + attr = null; 1.1697 + chk = null; 1.1698 + gen = null; 1.1699 + flow = null; 1.1700 + transTypes = null; 1.1701 + lower = null; 1.1702 + annotate = null; 1.1703 + types = null; 1.1704 + 1.1705 + log.flush(); 1.1706 + try { 1.1707 + fileManager.flush(); 1.1708 + } catch (IOException e) { 1.1709 + throw new Abort(e); 1.1710 + } finally { 1.1711 + if (names != null && disposeNames) 1.1712 + names.dispose(); 1.1713 + names = null; 1.1714 + 1.1715 + for (Closeable c: closeables) { 1.1716 + try { 1.1717 + c.close(); 1.1718 + } catch (IOException e) { 1.1719 + // When javac uses JDK 7 as a baseline, this code would be 1.1720 + // better written to set any/all exceptions from all the 1.1721 + // Closeables as suppressed exceptions on the FatalError 1.1722 + // that is thrown. 1.1723 + JCDiagnostic msg = diagFactory.fragment("fatal.err.cant.close"); 1.1724 + throw new FatalError(msg, e); 1.1725 + } 1.1726 + } 1.1727 + closeables = List.nil(); 1.1728 + } 1.1729 + } 1.1730 + 1.1731 + protected void printNote(String lines) { 1.1732 + log.printRawLines(Log.WriterKind.NOTICE, lines); 1.1733 + } 1.1734 + 1.1735 + /** Print numbers of errors and warnings. 1.1736 + */ 1.1737 + public void printCount(String kind, int count) { 1.1738 + if (count != 0) { 1.1739 + String key; 1.1740 + if (count == 1) 1.1741 + key = "count." + kind; 1.1742 + else 1.1743 + key = "count." + kind + ".plural"; 1.1744 + log.printLines(WriterKind.ERROR, key, String.valueOf(count)); 1.1745 + log.flush(Log.WriterKind.ERROR); 1.1746 + } 1.1747 + } 1.1748 + 1.1749 + private static long now() { 1.1750 + return System.currentTimeMillis(); 1.1751 + } 1.1752 + 1.1753 + private static long elapsed(long then) { 1.1754 + return now() - then; 1.1755 + } 1.1756 + 1.1757 + public void initRound(JavaCompiler prev) { 1.1758 + genEndPos = prev.genEndPos; 1.1759 + keepComments = prev.keepComments; 1.1760 + start_msec = prev.start_msec; 1.1761 + hasBeenUsed = true; 1.1762 + closeables = prev.closeables; 1.1763 + prev.closeables = List.nil(); 1.1764 + shouldStopPolicyIfError = prev.shouldStopPolicyIfError; 1.1765 + shouldStopPolicyIfNoError = prev.shouldStopPolicyIfNoError; 1.1766 + } 1.1767 +}