1 /*
   2  * Copyright (c) 1999, 2025, 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  */
  25 
  26 package com.sun.tools.javac.main;
  27 
  28 import java.io.*;
  29 import java.nio.file.FileSystemNotFoundException;
  30 import java.nio.file.InvalidPathException;
  31 import java.nio.file.ReadOnlyFileSystemException;
  32 import java.util.Collection;
  33 import java.util.Comparator;
  34 import java.util.HashMap;
  35 import java.util.HashSet;
  36 import java.util.LinkedHashMap;
  37 import java.util.LinkedHashSet;
  38 import java.util.Map;
  39 import java.util.MissingResourceException;
  40 import java.util.Queue;
  41 import java.util.ResourceBundle;
  42 import java.util.Set;
  43 import java.util.function.Function;
  44 import java.util.function.ToIntFunction;
  45 
  46 import javax.annotation.processing.Processor;
  47 import javax.lang.model.SourceVersion;
  48 import javax.lang.model.element.ElementVisitor;
  49 import javax.tools.DiagnosticListener;
  50 import javax.tools.JavaFileManager;
  51 import javax.tools.JavaFileObject;
  52 import javax.tools.JavaFileObject.Kind;
  53 import javax.tools.StandardLocation;
  54 
  55 import com.sun.source.util.TaskEvent;
  56 import com.sun.tools.javac.api.MultiTaskListener;
  57 import com.sun.tools.javac.code.*;
  58 import com.sun.tools.javac.code.Source.Feature;
  59 import com.sun.tools.javac.code.Symbol.ClassSymbol;
  60 import com.sun.tools.javac.code.Symbol.CompletionFailure;
  61 import com.sun.tools.javac.code.Symbol.ModuleSymbol;
  62 import com.sun.tools.javac.code.Symbol.PackageSymbol;
  63 import com.sun.tools.javac.comp.*;
  64 import com.sun.tools.javac.comp.CompileStates.CompileState;
  65 import com.sun.tools.javac.file.JavacFileManager;
  66 import com.sun.tools.javac.jvm.*;
  67 import com.sun.tools.javac.parser.*;
  68 import com.sun.tools.javac.platform.PlatformDescription;
  69 import com.sun.tools.javac.processing.*;
  70 import com.sun.tools.javac.tree.*;
  71 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
  72 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
  73 import com.sun.tools.javac.tree.JCTree.JCExpression;
  74 import com.sun.tools.javac.tree.JCTree.JCLambda;
  75 import com.sun.tools.javac.tree.JCTree.JCMemberReference;
  76 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
  77 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
  78 import com.sun.tools.javac.util.*;
  79 import com.sun.tools.javac.util.Context.Key;
  80 import com.sun.tools.javac.util.DefinedBy.Api;
  81 import com.sun.tools.javac.util.JCDiagnostic.Factory;
  82 import com.sun.tools.javac.util.Log.DiagnosticHandler;
  83 import com.sun.tools.javac.util.Log.DiscardDiagnosticHandler;
  84 import com.sun.tools.javac.util.Log.WriterKind;
  85 
  86 import static com.sun.tools.javac.code.Kinds.Kind.*;
  87 
  88 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  89 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  90 import com.sun.tools.javac.resources.CompilerProperties.Notes;
  91 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  92 
  93 import static com.sun.tools.javac.code.TypeTag.CLASS;
  94 import static com.sun.tools.javac.main.Option.*;
  95 import com.sun.tools.javac.tree.JCTree.JCBindingPattern;
  96 import com.sun.tools.javac.tree.JCTree.JCInstanceOf;
  97 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
  98 
  99 import static javax.tools.StandardLocation.CLASS_OUTPUT;
 100 import static javax.tools.StandardLocation.ANNOTATION_PROCESSOR_PATH;
 101 
 102 import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
 103 import com.sun.tools.javac.tree.JCTree.JCRecordPattern;
 104 import com.sun.tools.javac.tree.JCTree.JCSwitch;
 105 import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
 106 
 107 /** This class could be the main entry point for GJC when GJC is used as a
 108  *  component in a larger software system. It provides operations to
 109  *  construct a new compiler, and to run a new compiler on a set of source
 110  *  files.
 111  *
 112  *  <p><b>This is NOT part of any supported API.
 113  *  If you write code that depends on this, you do so at your own risk.
 114  *  This code and its internal interfaces are subject to change or
 115  *  deletion without notice.</b>
 116  */
 117 public class JavaCompiler {
 118     /** The context key for the compiler. */
 119     public static final Context.Key<JavaCompiler> compilerKey = new Context.Key<>();
 120 
 121     /** Get the JavaCompiler instance for this context. */
 122     public static JavaCompiler instance(Context context) {
 123         JavaCompiler instance = context.get(compilerKey);
 124         if (instance == null)
 125             instance = new JavaCompiler(context);
 126         return instance;
 127     }
 128 
 129     /** The current version number as a string.
 130      */
 131     public static String version() {
 132         return version("release");  // mm.nn.oo[-milestone]
 133     }
 134 
 135     /** The current full version number as a string.
 136      */
 137     public static String fullVersion() {
 138         return version("full"); // mm.mm.oo[-milestone]-build
 139     }
 140 
 141     private static final String versionRBName = "com.sun.tools.javac.resources.version";
 142     private static ResourceBundle versionRB;
 143 
 144     private static String version(String key) {
 145         if (versionRB == null) {
 146             try {
 147                 versionRB = ResourceBundle.getBundle(versionRBName);
 148             } catch (MissingResourceException e) {
 149                 return Log.getLocalizedString("version.not.available");
 150             }
 151         }
 152         try {
 153             return versionRB.getString(key);
 154         }
 155         catch (MissingResourceException e) {
 156             return Log.getLocalizedString("version.not.available");
 157         }
 158     }
 159 
 160     /**
 161      * Control how the compiler's latter phases (attr, flow, desugar, generate)
 162      * are connected. Each individual file is processed by each phase in turn,
 163      * but with different compile policies, you can control the order in which
 164      * each class is processed through its next phase.
 165      *
 166      * <p>Generally speaking, the compiler will "fail fast" in the face of
 167      * errors, although not aggressively so. flow, desugar, etc become no-ops
 168      * once any errors have occurred. No attempt is currently made to determine
 169      * if it might be safe to process a class through its next phase because
 170      * it does not depend on any unrelated errors that might have occurred.
 171      */
 172     protected static enum CompilePolicy {
 173         /**
 174          * Attribute everything, then do flow analysis for everything,
 175          * then desugar everything, and only then generate output.
 176          * This means no output will be generated if there are any
 177          * errors in any classes.
 178          */
 179         SIMPLE,
 180 
 181         /**
 182          * Groups the classes for each source file together, then process
 183          * each group in a manner equivalent to the {@code SIMPLE} policy.
 184          * This means no output will be generated if there are any
 185          * errors in any of the classes in a source file.
 186          */
 187         BY_FILE,
 188 
 189         /**
 190          * Completely process each entry on the todo list in turn.
 191          * -- this is the same for 1.5.
 192          * Means output might be generated for some classes in a compilation unit
 193          * and not others.
 194          */
 195         BY_TODO;
 196 
 197         static CompilePolicy decode(String option) {
 198             if (option == null)
 199                 return DEFAULT_COMPILE_POLICY;
 200             else if (option.equals("simple"))
 201                 return SIMPLE;
 202             else if (option.equals("byfile"))
 203                 return BY_FILE;
 204             else if (option.equals("bytodo"))
 205                 return BY_TODO;
 206             else
 207                 return DEFAULT_COMPILE_POLICY;
 208         }
 209     }
 210 
 211     private static final CompilePolicy DEFAULT_COMPILE_POLICY = CompilePolicy.BY_TODO;
 212 
 213     protected static enum ImplicitSourcePolicy {
 214         /** Don't generate or process implicitly read source files. */
 215         NONE,
 216         /** Generate classes for implicitly read source files. */
 217         CLASS,
 218         /** Like CLASS, but generate warnings if annotation processing occurs */
 219         UNSET;
 220 
 221         static ImplicitSourcePolicy decode(String option) {
 222             if (option == null)
 223                 return UNSET;
 224             else if (option.equals("none"))
 225                 return NONE;
 226             else if (option.equals("class"))
 227                 return CLASS;
 228             else
 229                 return UNSET;
 230         }
 231     }
 232 
 233     /** The log to be used for error reporting.
 234      */
 235     public Log log;
 236 
 237     /** Factory for creating diagnostic objects
 238      */
 239     JCDiagnostic.Factory diagFactory;
 240 
 241     /** The tree factory module.
 242      */
 243     protected TreeMaker make;
 244 
 245     /** The class finder.
 246      */
 247     protected ClassFinder finder;
 248 
 249     /** The class reader.
 250      */
 251     protected ClassReader reader;
 252 
 253     /** The class writer.
 254      */
 255     protected ClassWriter writer;
 256 
 257     /** The native header writer.
 258      */
 259     protected JNIWriter jniWriter;
 260 
 261     /** The Lint mapper.
 262      */
 263     protected LintMapper lintMapper;
 264 
 265     /** The module for the symbol table entry phases.
 266      */
 267     protected Enter enter;
 268 
 269     /** The symbol table.
 270      */
 271     protected Symtab syms;
 272 
 273     /** The language version.
 274      */
 275     protected Source source;
 276 
 277     /** The module for code generation.
 278      */
 279     protected Gen gen;
 280 
 281     /** The name table.
 282      */
 283     protected Names names;
 284 
 285     /** The attributor.
 286      */
 287     protected Attr attr;
 288 
 289     /** The analyzer
 290      */
 291     protected Analyzer analyzer;
 292 
 293     /** The attributor.
 294      */
 295     protected Check chk;
 296 
 297     /** The flow analyzer.
 298      */
 299     protected Flow flow;
 300 
 301     /** The warning analyzer.
 302      */
 303     protected WarningAnalyzer warningAnalyzer;
 304 
 305     /** The modules visitor
 306      */
 307     protected Modules modules;
 308 
 309     /** The module finder
 310      */
 311     protected ModuleFinder moduleFinder;
 312 
 313     /** The diagnostics factory
 314      */
 315     protected JCDiagnostic.Factory diags;
 316 
 317     protected DeferredCompletionFailureHandler dcfh;
 318 
 319     /** The type eraser.
 320      */
 321     protected TransTypes transTypes;
 322 
 323     /** The syntactic sugar desweetener.
 324      */
 325     protected Lower lower;
 326 
 327     /** The annotation annotator.
 328      */
 329     protected Annotate annotate;
 330 
 331     /** Force a completion failure on this name
 332      */
 333     protected final Name completionFailureName;
 334 
 335     /** Type utilities.
 336      */
 337     protected Types types;
 338 
 339     /** Access to file objects.
 340      */
 341     protected JavaFileManager fileManager;
 342 
 343     /** Factory for parsers.
 344      */
 345     protected ParserFactory parserFactory;
 346 
 347     /** Broadcasting listener for progress events
 348      */
 349     protected MultiTaskListener taskListener;
 350 
 351     /**
 352      * SourceCompleter that delegates to the readSourceFile method of this class.
 353      */
 354     protected final Symbol.Completer sourceCompleter =
 355             sym -> readSourceFile((ClassSymbol) sym);
 356 
 357     /**
 358      * Command line options.
 359      */
 360     protected Options options;
 361 
 362     protected Context context;
 363 
 364     /**
 365      * Flag set if any annotation processing occurred.
 366      **/
 367     protected boolean annotationProcessingOccurred;
 368 
 369     /**
 370      * Flag set if any implicit source files read.
 371      **/
 372     protected boolean implicitSourceFilesRead;
 373 
 374     private boolean enterDone;
 375 
 376     protected CompileStates compileStates;
 377 
 378     /** Construct a new compiler using a shared context.
 379      */
 380     @SuppressWarnings("this-escape")
 381     public JavaCompiler(Context context) {
 382         this.context = context;
 383         context.put(compilerKey, this);
 384 
 385         // if fileManager not already set, register the JavacFileManager to be used
 386         if (context.get(JavaFileManager.class) == null)
 387             JavacFileManager.preRegister(context);
 388 
 389         names = Names.instance(context);
 390         log = Log.instance(context);
 391         lintMapper = LintMapper.instance(context);
 392         diagFactory = JCDiagnostic.Factory.instance(context);
 393         finder = ClassFinder.instance(context);
 394         reader = ClassReader.instance(context);
 395         make = TreeMaker.instance(context);
 396         writer = ClassWriter.instance(context);
 397         jniWriter = JNIWriter.instance(context);
 398         enter = Enter.instance(context);
 399         todo = Todo.instance(context);
 400 
 401         fileManager = context.get(JavaFileManager.class);
 402         parserFactory = ParserFactory.instance(context);
 403         compileStates = CompileStates.instance(context);
 404 
 405         try {
 406             // catch completion problems with predefineds
 407             syms = Symtab.instance(context);
 408         } catch (CompletionFailure ex) {
 409             // inlined Check.completionError as it is not initialized yet
 410             log.error(Errors.CantAccess(ex.sym, ex.getDetailValue()));
 411         }
 412         source = Source.instance(context);
 413         attr = Attr.instance(context);
 414         analyzer = Analyzer.instance(context);
 415         chk = Check.instance(context);
 416         gen = Gen.instance(context);
 417         flow = Flow.instance(context);
 418         warningAnalyzer = WarningAnalyzer.instance(context);
 419         transTypes = TransTypes.instance(context);
 420         lower = Lower.instance(context);
 421         annotate = Annotate.instance(context);
 422         types = Types.instance(context);
 423         taskListener = MultiTaskListener.instance(context);
 424         modules = Modules.instance(context);
 425         moduleFinder = ModuleFinder.instance(context);
 426         diags = Factory.instance(context);
 427         dcfh = DeferredCompletionFailureHandler.instance(context);
 428 
 429         finder.sourceCompleter = sourceCompleter;
 430         modules.findPackageInFile = this::findPackageInFile;
 431         moduleFinder.moduleNameFromSourceReader = this::readModuleName;
 432 
 433         options = Options.instance(context);
 434 
 435         verbose       = options.isSet(VERBOSE);
 436         sourceOutput  = options.isSet(PRINTSOURCE); // used to be -s
 437         lineDebugInfo = options.isUnset(G_CUSTOM) ||
 438                         options.isSet(G_CUSTOM, "lines");
 439         genEndPos     = options.isSet(XJCOV) ||
 440                         context.get(DiagnosticListener.class) != null;
 441         devVerbose    = options.isSet("dev");
 442         processPcks   = options.isSet("process.packages");
 443         werror        = options.isSet(WERROR);
 444 
 445         verboseCompilePolicy = options.isSet("verboseCompilePolicy");
 446 
 447         compilePolicy = CompilePolicy.decode(options.get("compilePolicy"));
 448 
 449         implicitSourcePolicy = ImplicitSourcePolicy.decode(options.get("-implicit"));
 450 
 451         completionFailureName =
 452             options.isSet("failcomplete")
 453             ? names.fromString(options.get("failcomplete"))
 454             : null;
 455 
 456         shouldStopPolicyIfError =
 457             options.isSet("should-stop.at") // backwards compatible
 458             ? CompileState.valueOf(options.get("should-stop.at"))
 459             : options.isSet("should-stop.ifError")
 460             ? CompileState.valueOf(options.get("should-stop.ifError"))
 461             : CompileState.INIT;
 462         shouldStopPolicyIfNoError =
 463             options.isSet("should-stop.ifNoError")
 464             ? CompileState.valueOf(options.get("should-stop.ifNoError"))
 465             : CompileState.GENERATE;
 466 
 467         if (options.isUnset("diags.legacy"))
 468             log.setDiagnosticFormatter(RichDiagnosticFormatter.instance(context));
 469 
 470         PlatformDescription platformProvider = context.get(PlatformDescription.class);
 471 
 472         if (platformProvider != null)
 473             closeables = closeables.prepend(platformProvider);
 474 
 475         silentFail = new Symbol(ABSENT_TYP, 0, names.empty, Type.noType, syms.rootPackage) {
 476             @DefinedBy(Api.LANGUAGE_MODEL)
 477             public <R, P> R accept(ElementVisitor<R, P> v, P p) {
 478                 return v.visitUnknown(this, p);
 479             }
 480             @Override
 481             public boolean exists() {
 482                 return false;
 483             }
 484         };
 485 
 486     }
 487 
 488     /* Switches:
 489      */
 490 
 491     /** Verbose output.
 492      */
 493     public boolean verbose;
 494 
 495     /** Emit plain Java source files rather than class files.
 496      */
 497     public boolean sourceOutput;
 498 
 499 
 500     /** Generate code with the LineNumberTable attribute for debugging
 501      */
 502     public boolean lineDebugInfo;
 503 
 504     /** Switch: should we store the ending positions?
 505      */
 506     public boolean genEndPos;
 507 
 508     /** Switch: should we debug ignored exceptions
 509      */
 510     protected boolean devVerbose;
 511 
 512     /** Switch: should we (annotation) process packages as well
 513      */
 514     protected boolean processPcks;
 515 
 516     /** Switch: treat warnings as errors
 517      */
 518     protected boolean werror;
 519 
 520     /** Switch: is annotation processing requested explicitly via
 521      * CompilationTask.setProcessors?
 522      */
 523     protected boolean explicitAnnotationProcessingRequested = false;
 524 
 525     /**
 526      * The policy for the order in which to perform the compilation
 527      */
 528     protected CompilePolicy compilePolicy;
 529 
 530     /**
 531      * The policy for what to do with implicitly read source files
 532      */
 533     protected ImplicitSourcePolicy implicitSourcePolicy;
 534 
 535     /**
 536      * Report activity related to compilePolicy
 537      */
 538     public boolean verboseCompilePolicy;
 539 
 540     /**
 541      * Policy of how far to continue compilation after errors have occurred.
 542      * Set this to minimum CompileState (INIT) to stop as soon as possible
 543      * after errors.
 544      */
 545     public CompileState shouldStopPolicyIfError;
 546 
 547     /**
 548      * Policy of how far to continue compilation when no errors have occurred.
 549      * Set this to maximum CompileState (GENERATE) to perform full compilation.
 550      * Set this lower to perform partial compilation, such as -proc:only.
 551      */
 552     public CompileState shouldStopPolicyIfNoError;
 553 
 554     /** A queue of all as yet unattributed classes.
 555      */
 556     public Todo todo;
 557 
 558     /** A list of items to be closed when the compilation is complete.
 559      */
 560     public List<Closeable> closeables = List.nil();
 561 
 562     /** The set of currently compiled inputfiles, needed to ensure
 563      *  we don't accidentally overwrite an input file when -s is set.
 564      *  initialized by `compile'.
 565      */
 566     protected Set<JavaFileObject> inputFiles = new HashSet<>();
 567 
 568     /** Used by the resolveBinaryNameOrIdent to say that the given type cannot be found, and that
 569      *  an error has already been produced about that.
 570      */
 571     private final Symbol silentFail;
 572 
 573     protected boolean shouldStop(CompileState cs) {
 574         CompileState shouldStopPolicy = (errorCount() > 0 || unrecoverableError())
 575             ? shouldStopPolicyIfError
 576             : shouldStopPolicyIfNoError;
 577         return cs.isAfter(shouldStopPolicy);
 578     }
 579 
 580     /** The number of errors reported so far.
 581      */
 582     public int errorCount() {
 583         log.reportOutstandingWarnings();
 584         if (werror && log.nerrors == 0 && log.nwarnings > 0) {
 585             log.error(Errors.WarningsAndWerror);
 586         }
 587         return log.nerrors;
 588     }
 589 
 590     protected final <T> Queue<T> stopIfError(CompileState cs, Queue<T> queue) {
 591         return shouldStop(cs) ? new ListBuffer<T>() : queue;
 592     }
 593 
 594     protected final <T> List<T> stopIfError(CompileState cs, List<T> list) {
 595         return shouldStop(cs) ? List.nil() : list;
 596     }
 597 
 598     /** The number of warnings reported so far.
 599      */
 600     public int warningCount() {
 601         return log.nwarnings;
 602     }
 603 
 604     /** Try to open input stream with given name.
 605      *  Report an error if this fails.
 606      *  @param filename   The file name of the input stream to be opened.
 607      */
 608     public CharSequence readSource(JavaFileObject filename) {
 609         try {
 610             inputFiles.add(filename);
 611             return filename.getCharContent(false);
 612         } catch (IOException e) {
 613             log.error(Errors.ErrorReadingFile(filename, JavacFileManager.getMessage(e)));
 614             return null;
 615         }
 616     }
 617 
 618     /** Parse contents of input stream.
 619      *  @param filename     The name of the file from which input stream comes.
 620      *  @param content      The characters to be parsed.
 621      */
 622     protected JCCompilationUnit parse(JavaFileObject filename, CharSequence content) {
 623         return parse(filename, content, false);
 624     }
 625 
 626     /** Parse contents of input stream.
 627      *  @param filename     The name of the file from which input stream comes.
 628      *  @param content      The characters to be parsed.
 629      *  @param silent       true if TaskListeners should not be notified
 630      */
 631     private JCCompilationUnit parse(JavaFileObject filename, CharSequence content, boolean silent) {
 632         long msec = now();
 633         JCCompilationUnit tree = make.TopLevel(List.nil());
 634         lintMapper.startParsingFile(filename);
 635         if (content != null) {
 636             if (verbose) {
 637                 log.printVerbose("parsing.started", filename);
 638             }
 639             if (!taskListener.isEmpty() && !silent) {
 640                 TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename);
 641                 taskListener.started(e);
 642                 keepComments = true;
 643                 genEndPos = true;
 644             }
 645             Parser parser = parserFactory.newParser(content, keepComments(), genEndPos,
 646                                 lineDebugInfo, filename.isNameCompatible("module-info", Kind.SOURCE));
 647             tree = parser.parseCompilationUnit();
 648             if (verbose) {
 649                 log.printVerbose("parsing.done", Long.toString(elapsed(msec)));
 650             }
 651         }
 652 
 653         tree.sourcefile = filename;
 654         lintMapper.finishParsingFile(tree);
 655 
 656         if (content != null && !taskListener.isEmpty() && !silent) {
 657             TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, tree);
 658             taskListener.finished(e);
 659         }
 660 
 661         return tree;
 662     }
 663     // where
 664         public boolean keepComments = false;
 665         protected boolean keepComments() {
 666             return keepComments || sourceOutput;
 667         }
 668 
 669 
 670     /** Parse contents of file.
 671      *  @param filename     The name of the file to be parsed.
 672      */
 673     @Deprecated
 674     public JCTree.JCCompilationUnit parse(String filename) {
 675         JavacFileManager fm = (JavacFileManager)fileManager;
 676         return parse(fm.getJavaFileObjectsFromStrings(List.of(filename)).iterator().next());
 677     }
 678 
 679     /** Parse contents of file.
 680      *  @param filename     The name of the file to be parsed.
 681      */
 682     public JCTree.JCCompilationUnit parse(JavaFileObject filename) {
 683         JavaFileObject prev = log.useSource(filename);
 684         try {
 685             JCTree.JCCompilationUnit t = parse(filename, readSource(filename));
 686             if (t.endPositions != null)
 687                 log.setEndPosTable(filename, t.endPositions);
 688             return t;
 689         } finally {
 690             log.useSource(prev);
 691         }
 692     }
 693 
 694     /** Resolve an identifier which may be the binary name of a class or
 695      * the Java name of a class or package.
 696      * @param name      The name to resolve
 697      */
 698     public Symbol resolveBinaryNameOrIdent(String name) {
 699         ModuleSymbol msym;
 700         String typeName;
 701         int sep = name.indexOf('/');
 702         if (sep == -1) {
 703             msym = modules.getDefaultModule();
 704             typeName = name;
 705         } else if (Feature.MODULES.allowedInSource(source)) {
 706             Name modName = names.fromString(name.substring(0, sep));
 707 
 708             msym = moduleFinder.findModule(modName);
 709             typeName = name.substring(sep + 1);
 710         } else {
 711             log.error(Errors.InvalidModuleSpecifier(name));
 712             return silentFail;
 713         }
 714 
 715         return resolveBinaryNameOrIdent(msym, typeName);
 716     }
 717 
 718     /** Resolve an identifier which may be the binary name of a class or
 719      * the Java name of a class or package.
 720      * @param msym      The module in which the search should be performed
 721      * @param name      The name to resolve
 722      */
 723     public Symbol resolveBinaryNameOrIdent(ModuleSymbol msym, String name) {
 724         try {
 725             Name flatname = names.fromString(name.replace("/", "."));
 726             return finder.loadClass(msym, flatname);
 727         } catch (CompletionFailure ignore) {
 728             return resolveIdent(msym, name);
 729         }
 730     }
 731 
 732     /** Resolve an identifier.
 733      * @param msym      The module in which the search should be performed
 734      * @param name      The identifier to resolve
 735      */
 736     public Symbol resolveIdent(ModuleSymbol msym, String name) {
 737         if (name.equals(""))
 738             return syms.errSymbol;
 739         JavaFileObject prev = log.useSource(null);
 740         try {
 741             JCExpression tree = null;
 742             for (String s : name.split("\\.", -1)) {
 743                 if (!SourceVersion.isIdentifier(s)) // TODO: check for keywords
 744                     return syms.errSymbol;
 745                 tree = (tree == null) ? make.Ident(names.fromString(s))
 746                                       : make.Select(tree, names.fromString(s));
 747             }
 748             JCCompilationUnit toplevel =
 749                 make.TopLevel(List.nil());
 750             toplevel.modle = msym;
 751             toplevel.packge = msym.unnamedPackage;
 752             return attr.attribIdent(tree, toplevel);
 753         } finally {
 754             log.useSource(prev);
 755         }
 756     }
 757 
 758     /** Generate code and emit a class file for a given class
 759      *  @param env    The attribution environment of the outermost class
 760      *                containing this class.
 761      *  @param cdef   The class definition from which code is generated.
 762      */
 763     JavaFileObject genCode(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
 764         try {
 765             if (gen.genClass(env, cdef) && (errorCount() == 0))
 766                 return writer.writeClass(cdef.sym);
 767         } catch (ClassWriter.PoolOverflow ex) {
 768             log.error(cdef.pos(), Errors.LimitPool);
 769         } catch (ClassWriter.StringOverflow ex) {
 770             log.error(cdef.pos(),
 771                       Errors.LimitStringOverflow(ex.value.substring(0, 20)));
 772         } catch (CompletionFailure ex) {
 773             chk.completionError(cdef.pos(), ex);
 774         }
 775         return null;
 776     }
 777 
 778     /** Emit plain Java source for a class.
 779      *  @param env    The attribution environment of the outermost class
 780      *                containing this class.
 781      *  @param cdef   The class definition to be printed.
 782      */
 783     JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
 784         JavaFileObject outFile
 785            = fileManager.getJavaFileForOutput(CLASS_OUTPUT,
 786                                                cdef.sym.flatname.toString(),
 787                                                JavaFileObject.Kind.SOURCE,
 788                                                null);
 789         if (inputFiles.contains(outFile)) {
 790             log.error(cdef.pos(), Errors.SourceCantOverwriteInputFile(outFile));
 791             return null;
 792         } else {
 793             try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) {
 794                 new Pretty(out, true).printUnit(env.toplevel, cdef);
 795                 if (verbose)
 796                     log.printVerbose("wrote.file", outFile.getName());
 797             }
 798             return outFile;
 799         }
 800     }
 801 
 802     /** Compile a source file that has been accessed by the class finder.
 803      *  @param c          The class the source file of which needs to be compiled.
 804      */
 805     private void readSourceFile(ClassSymbol c) throws CompletionFailure {
 806         readSourceFile(null, c);
 807     }
 808 
 809     /** Compile a ClassSymbol from source, optionally using the given compilation unit as
 810      *  the source tree.
 811      *  @param tree the compilation unit in which the given ClassSymbol resides,
 812      *              or null if should be parsed from source
 813      *  @param c    the ClassSymbol to complete
 814      */
 815     public void readSourceFile(JCCompilationUnit tree, ClassSymbol c) throws CompletionFailure {
 816         if (completionFailureName == c.fullname) {
 817             throw new CompletionFailure(
 818                 c, () -> diagFactory.fragment(Fragments.UserSelectedCompletionFailure), dcfh);
 819         }
 820         JavaFileObject filename = c.classfile;
 821         JavaFileObject prev = log.useSource(filename);
 822 
 823         if (tree == null) {
 824             try {
 825                 tree = parse(filename, filename.getCharContent(false));
 826             } catch (IOException e) {
 827                 log.error(Errors.ErrorReadingFile(filename, JavacFileManager.getMessage(e)));
 828                 tree = make.TopLevel(List.<JCTree>nil());
 829             } finally {
 830                 log.useSource(prev);
 831             }
 832         }
 833 
 834         if (!taskListener.isEmpty()) {
 835             TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
 836             taskListener.started(e);
 837         }
 838 
 839         // Process module declarations.
 840         // If module resolution fails, ignore trees, and if trying to
 841         // complete a specific symbol, throw CompletionFailure.
 842         // Note that if module resolution failed, we may not even
 843         // have enough modules available to access java.lang, and
 844         // so risk getting FatalError("no.java.lang") from MemberEnter.
 845         if (!modules.enter(List.of(tree), c)) {
 846             throw new CompletionFailure(c, () -> diags.fragment(Fragments.CantResolveModules), dcfh);
 847         }
 848 
 849         enter.complete(List.of(tree), c);
 850 
 851         if (!taskListener.isEmpty()) {
 852             TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
 853             taskListener.finished(e);
 854         }
 855 
 856         if (enter.getEnv(c) == null) {
 857             boolean isPkgInfo =
 858                 tree.sourcefile.isNameCompatible("package-info",
 859                                                  JavaFileObject.Kind.SOURCE);
 860             boolean isModuleInfo =
 861                 tree.sourcefile.isNameCompatible("module-info",
 862                                                  JavaFileObject.Kind.SOURCE);
 863             if (isModuleInfo) {
 864                 if (enter.getEnv(tree.modle) == null) {
 865                     JCDiagnostic diag =
 866                         diagFactory.fragment(Fragments.FileDoesNotContainModule);
 867                     throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory, dcfh);
 868                 }
 869             } else if (isPkgInfo) {
 870                 if (enter.getEnv(tree.packge) == null) {
 871                     JCDiagnostic diag =
 872                         diagFactory.fragment(Fragments.FileDoesNotContainPackage(c.location()));
 873                     throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory, dcfh);
 874                 }
 875             } else {
 876                 JCDiagnostic diag =
 877                         diagFactory.fragment(Fragments.FileDoesntContainClass(c.getQualifiedName()));
 878                 throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory, dcfh);
 879             }
 880         }
 881 
 882         implicitSourceFilesRead = true;
 883     }
 884 
 885     /** Track when the JavaCompiler has been used to compile something. */
 886     private boolean hasBeenUsed = false;
 887     private long start_msec = 0;
 888     public long elapsed_msec = 0;
 889 
 890     public void compile(List<JavaFileObject> sourceFileObject)
 891         throws Throwable {
 892         compile(sourceFileObject, List.nil(), null, List.nil());
 893     }
 894 
 895     /**
 896      * Main method: compile a list of files, return all compiled classes
 897      *
 898      * @param sourceFileObjects file objects to be compiled
 899      * @param classnames class names to process for annotations
 900      * @param processors user provided annotation processors to bypass
 901      * discovery, {@code null} means that no processors were provided
 902      * @param addModules additional root modules to be used during
 903      * module resolution.
 904      */
 905     public void compile(Collection<JavaFileObject> sourceFileObjects,
 906                         Collection<String> classnames,
 907                         Iterable<? extends Processor> processors,
 908                         Collection<String> addModules)
 909     {
 910         if (!taskListener.isEmpty()) {
 911             taskListener.started(new TaskEvent(TaskEvent.Kind.COMPILATION));
 912         }
 913 
 914         // as a JavaCompiler can only be used once, throw an exception if
 915         // it has been used before.
 916         if (hasBeenUsed)
 917             checkReusable();
 918         hasBeenUsed = true;
 919 
 920         start_msec = now();
 921 
 922         try {
 923             initProcessAnnotations(processors, sourceFileObjects, classnames);
 924 
 925             for (String className : classnames) {
 926                 int sep = className.indexOf('/');
 927                 if (sep != -1) {
 928                     modules.addExtraAddModules(className.substring(0, sep));
 929                 }
 930             }
 931 
 932             for (String moduleName : addModules) {
 933                 modules.addExtraAddModules(moduleName);
 934             }
 935 
 936             // These method calls must be chained to avoid memory leaks
 937             processAnnotations(
 938                 enterTrees(
 939                         stopIfError(CompileState.ENTER,
 940                                 initModules(stopIfError(CompileState.ENTER, parseFiles(sourceFileObjects))))
 941                 ),
 942                 classnames
 943             );
 944 
 945             // If it's safe to do so, skip attr / flow / gen for implicit classes
 946             if (taskListener.isEmpty() &&
 947                     implicitSourcePolicy == ImplicitSourcePolicy.NONE) {
 948                 todo.retainFiles(inputFiles);
 949             }
 950 
 951             if (!CompileState.ATTR.isAfter(shouldStopPolicyIfNoError)) {
 952                 switch (compilePolicy) {
 953                 case SIMPLE:
 954                     generate(desugar(warn(flow(attribute(todo)))));
 955                     break;
 956 
 957                 case BY_FILE: {
 958                         Queue<Queue<Env<AttrContext>>> q = todo.groupByFile();
 959                         while (!q.isEmpty() && !shouldStop(CompileState.ATTR)) {
 960                             generate(desugar(warn(flow(attribute(q.remove())))));
 961                         }
 962                     }
 963                     break;
 964 
 965                 case BY_TODO:
 966                     while (!todo.isEmpty())
 967                         generate(desugar(warn(flow(attribute(todo.remove())))));
 968                     break;
 969 
 970                 default:
 971                     Assert.error("unknown compile policy");
 972                 }
 973             }
 974         } catch (Abort ex) {
 975             if (devVerbose)
 976                 ex.printStackTrace(System.err);
 977 
 978             // In case an Abort was thrown before processAnnotations could be called,
 979             // we could have deferred diagnostics that haven't been reported.
 980             reportDeferredDiagnosticAndClearHandler();
 981         } finally {
 982             if (verbose) {
 983                 elapsed_msec = elapsed(start_msec);
 984                 log.printVerbose("total", Long.toString(elapsed_msec));
 985             }
 986 
 987             reportDeferredDiagnostics();
 988 
 989             if (!log.hasDiagnosticListener()) {
 990                 printCount("error", errorCount());
 991                 printCount("warn", warningCount());
 992                 printSuppressedCount(errorCount(), log.nsuppressederrors, "count.error.recompile");
 993                 printSuppressedCount(warningCount(), log.nsuppressedwarns, "count.warn.recompile");
 994             }
 995             if (!taskListener.isEmpty()) {
 996                 taskListener.finished(new TaskEvent(TaskEvent.Kind.COMPILATION));
 997             }
 998             close();
 999             if (procEnvImpl != null)
1000                 procEnvImpl.close();
1001         }
1002     }
1003 
1004     protected void checkReusable() {
1005         throw new AssertionError("attempt to reuse JavaCompiler");
1006     }
1007 
1008     /**
1009      * The list of classes explicitly supplied on the command line for compilation.
1010      * Not always populated.
1011      */
1012     private List<JCClassDecl> rootClasses;
1013 
1014     /**
1015      * Parses a list of files.
1016      */
1017    public List<JCCompilationUnit> parseFiles(Iterable<JavaFileObject> fileObjects) {
1018        return InitialFileParser.instance(context).parse(fileObjects);
1019    }
1020 
1021    public List<JCCompilationUnit> parseFiles(Iterable<JavaFileObject> fileObjects, boolean force) {
1022        if (!force && shouldStop(CompileState.PARSE))
1023            return List.nil();
1024 
1025         //parse all files
1026         ListBuffer<JCCompilationUnit> trees = new ListBuffer<>();
1027         Set<JavaFileObject> filesSoFar = new HashSet<>();
1028         for (JavaFileObject fileObject : fileObjects) {
1029             if (!filesSoFar.contains(fileObject)) {
1030                 filesSoFar.add(fileObject);
1031                 trees.append(parse(fileObject));
1032             }
1033         }
1034         return trees.toList();
1035     }
1036 
1037    /**
1038     * Returns true iff the compilation will continue after annotation processing
1039     * is done.
1040     */
1041     public boolean continueAfterProcessAnnotations() {
1042         return !shouldStop(CompileState.ATTR);
1043     }
1044 
1045     public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
1046         modules.initModules(roots);
1047         if (roots.isEmpty()) {
1048             enterDone();
1049         }
1050         return roots;
1051     }
1052 
1053     /**
1054      * Enter the symbols found in a list of parse trees.
1055      * As a side-effect, this puts elements on the "todo" list.
1056      * Also stores a list of all top level classes in rootClasses.
1057      */
1058     public List<JCCompilationUnit> enterTrees(List<JCCompilationUnit> roots) {
1059         //enter symbols for all files
1060         if (!taskListener.isEmpty()) {
1061             for (JCCompilationUnit unit: roots) {
1062                 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
1063                 taskListener.started(e);
1064             }
1065         }
1066 
1067         enter.main(roots);
1068 
1069         enterDone();
1070 
1071         if (!taskListener.isEmpty()) {
1072             for (JCCompilationUnit unit: roots) {
1073                 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
1074                 taskListener.finished(e);
1075             }
1076         }
1077 
1078         // If generating source, or if tracking public apis,
1079         // then remember the classes declared in
1080         // the original compilation units listed on the command line.
1081         if (sourceOutput) {
1082             ListBuffer<JCClassDecl> cdefs = new ListBuffer<>();
1083             for (JCCompilationUnit unit : roots) {
1084                 for (List<JCTree> defs = unit.defs;
1085                      defs.nonEmpty();
1086                      defs = defs.tail) {
1087                     if (defs.head instanceof JCClassDecl classDecl)
1088                         cdefs.append(classDecl);
1089                 }
1090             }
1091             rootClasses = cdefs.toList();
1092         }
1093 
1094         // Ensure the input files have been recorded. Although this is normally
1095         // done by readSource, it may not have been done if the trees were read
1096         // in a prior round of annotation processing, and the trees have been
1097         // cleaned and are being reused.
1098         for (JCCompilationUnit unit : roots) {
1099             inputFiles.add(unit.sourcefile);
1100         }
1101 
1102         return roots;
1103     }
1104 
1105     /**
1106      * Set to true to enable skeleton annotation processing code.
1107      * Currently, we assume this variable will be replaced more
1108      * advanced logic to figure out if annotation processing is
1109      * needed.
1110      */
1111     boolean processAnnotations = false;
1112 
1113     Log.DeferredDiagnosticHandler deferredDiagnosticHandler;
1114 
1115     /**
1116      * Object to handle annotation processing.
1117      */
1118     private JavacProcessingEnvironment procEnvImpl = null;
1119 
1120     /**
1121      * Check if we should process annotations.
1122      * If so, and if no scanner is yet registered, then set up the DocCommentScanner
1123      * to catch doc comments, and set keepComments so the parser records them in
1124      * the compilation unit.
1125      *
1126      * @param processors user provided annotation processors to bypass
1127      * discovery, {@code null} means that no processors were provided
1128      */
1129     public void initProcessAnnotations(Iterable<? extends Processor> processors,
1130                                        Collection<? extends JavaFileObject> initialFiles,
1131                                        Collection<String> initialClassNames) {
1132         if (processors != null && processors.iterator().hasNext())
1133             explicitAnnotationProcessingRequested = true;
1134 
1135         if (options.isSet(PROC, "none")) {
1136             processAnnotations = false;
1137         } else if (procEnvImpl == null) {
1138             procEnvImpl = JavacProcessingEnvironment.instance(context);
1139             procEnvImpl.setProcessors(processors);
1140 
1141             // Process annotations if processing is requested and there
1142             // is at least one Processor available.
1143             processAnnotations = procEnvImpl.atLeastOneProcessor() &&
1144                 explicitAnnotationProcessingRequested();
1145 
1146             if (processAnnotations) {
1147                 options.put("parameters", "parameters");
1148                 reader.saveParameterNames = true;
1149                 keepComments = true;
1150                 genEndPos = true;
1151                 if (!taskListener.isEmpty())
1152                     taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
1153                 deferredDiagnosticHandler = log.new DeferredDiagnosticHandler();
1154                 procEnvImpl.getFiler().setInitialState(initialFiles, initialClassNames);
1155             }
1156         } else { // free resources
1157             procEnvImpl.close();
1158         }
1159     }
1160 
1161     // TODO: called by JavacTaskImpl
1162     public void processAnnotations(List<JCCompilationUnit> roots) {
1163         processAnnotations(roots, List.nil());
1164     }
1165 
1166     /**
1167      * Process any annotations found in the specified compilation units.
1168      * @param roots a list of compilation units
1169      */
1170     // Implementation note: when this method is called, log.deferredDiagnostics
1171     // will have been set true by initProcessAnnotations, meaning that any diagnostics
1172     // that are reported will go into the log.deferredDiagnostics queue.
1173     // By the time this method exits, log.deferDiagnostics must be set back to false,
1174     // and all deferredDiagnostics must have been handled: i.e. either reported
1175     // or determined to be transient, and therefore suppressed.
1176     public void processAnnotations(List<JCCompilationUnit> roots,
1177                                    Collection<String> classnames) {
1178         if (shouldStop(CompileState.PROCESS)) {
1179             // Errors were encountered.
1180             // Unless all the errors are resolve errors, the errors were parse errors
1181             // or other errors during enter which cannot be fixed by running
1182             // any annotation processors.
1183             if (processAnnotations) {
1184                 reportDeferredDiagnosticAndClearHandler();
1185                 return ;
1186             }
1187         }
1188 
1189         // ASSERT: processAnnotations and procEnvImpl should have been set up by
1190         // by initProcessAnnotations
1191 
1192         // NOTE: The !classnames.isEmpty() checks should be refactored to Main.
1193 
1194         if (!processAnnotations) {
1195             // If there are no annotation processors present, and
1196             // annotation processing is to occur with compilation,
1197             // emit a warning.
1198             if (options.isSet(PROC, "only")) {
1199                 log.warning(Warnings.ProcProcOnlyRequestedNoProcs);
1200                 todo.clear();
1201             }
1202             // If not processing annotations, classnames must be empty
1203             if (!classnames.isEmpty()) {
1204                 log.error(Errors.ProcNoExplicitAnnotationProcessingRequested(classnames));
1205             }
1206             Assert.checkNull(deferredDiagnosticHandler);
1207             return ; // continue regular compilation
1208         }
1209 
1210         Assert.checkNonNull(deferredDiagnosticHandler);
1211 
1212         try {
1213             List<ClassSymbol> classSymbols = List.nil();
1214             List<PackageSymbol> pckSymbols = List.nil();
1215             if (!classnames.isEmpty()) {
1216                  // Check for explicit request for annotation
1217                  // processing
1218                 if (!explicitAnnotationProcessingRequested()) {
1219                     log.error(Errors.ProcNoExplicitAnnotationProcessingRequested(classnames));
1220                     reportDeferredDiagnosticAndClearHandler();
1221                     return ; // TODO: Will this halt compilation?
1222                 } else {
1223                     boolean errors = false;
1224                     for (String nameStr : classnames) {
1225                         Symbol sym = resolveBinaryNameOrIdent(nameStr);
1226                         if (sym == null ||
1227                             (sym.kind == PCK && !processPcks) ||
1228                             sym.kind == ABSENT_TYP) {
1229                             if (sym != silentFail)
1230                                 log.error(Errors.ProcCantFindClass(nameStr));
1231                             errors = true;
1232                             continue;
1233                         }
1234                         try {
1235                             if (sym.kind == PCK)
1236                                 sym.complete();
1237                             if (sym.exists()) {
1238                                 if (sym.kind == PCK)
1239                                     pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
1240                                 else
1241                                     classSymbols = classSymbols.prepend((ClassSymbol)sym);
1242                                 continue;
1243                             }
1244                             Assert.check(sym.kind == PCK);
1245                             log.warning(Warnings.ProcPackageDoesNotExist(nameStr));
1246                             pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
1247                         } catch (CompletionFailure e) {
1248                             log.error(Errors.ProcCantFindClass(nameStr));
1249                             errors = true;
1250                             continue;
1251                         }
1252                     }
1253                     if (errors) {
1254                         reportDeferredDiagnosticAndClearHandler();
1255                         return ;
1256                     }
1257                 }
1258             }
1259             try {
1260                 annotationProcessingOccurred =
1261                         procEnvImpl.doProcessing(roots,
1262                                                  classSymbols,
1263                                                  pckSymbols,
1264                                                  deferredDiagnosticHandler);
1265                 // doProcessing will have handled deferred diagnostics
1266             } finally {
1267                 procEnvImpl.close();
1268             }
1269         } catch (CompletionFailure ex) {
1270             log.error(Errors.CantAccess(ex.sym, ex.getDetailValue()));
1271             reportDeferredDiagnosticAndClearHandler();
1272         }
1273     }
1274 
1275     private boolean unrecoverableError() {
1276         if (deferredDiagnosticHandler != null) {
1277             for (JCDiagnostic d: deferredDiagnosticHandler.getDiagnostics()) {
1278                 if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RECOVERABLE))
1279                     return true;
1280             }
1281         }
1282         return false;
1283     }
1284 
1285     boolean explicitAnnotationProcessingRequested() {
1286         return
1287             explicitAnnotationProcessingRequested ||
1288             explicitAnnotationProcessingRequested(options, fileManager);
1289     }
1290 
1291     static boolean explicitAnnotationProcessingRequested(Options options, JavaFileManager fileManager) {
1292         return
1293             options.isSet(PROCESSOR) ||
1294             options.isSet(PROCESSOR_PATH) ||
1295             options.isSet(PROCESSOR_MODULE_PATH) ||
1296             options.isSet(PROC, "only") ||
1297             options.isSet(PROC, "full") ||
1298             options.isSet(A) ||
1299             options.isSet(XPRINT) ||
1300             fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH);
1301         // Skipping -XprintRounds and -XprintProcessorInfo
1302     }
1303 
1304     public void setDeferredDiagnosticHandler(Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
1305         this.deferredDiagnosticHandler = deferredDiagnosticHandler;
1306     }
1307 
1308     /**
1309      * Attribute a list of parse trees, such as found on the "todo" list.
1310      * Note that attributing classes may cause additional files to be
1311      * parsed and entered via the SourceCompleter.
1312      * Attribution of the entries in the list does not stop if any errors occur.
1313      * @return a list of environments for attribute classes.
1314      */
1315     public Queue<Env<AttrContext>> attribute(Queue<Env<AttrContext>> envs) {
1316         ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1317         while (!envs.isEmpty())
1318             results.append(attribute(envs.remove()));
1319         return stopIfError(CompileState.ATTR, results);
1320     }
1321 
1322     /**
1323      * Attribute a parse tree.
1324      * @return the attributed parse tree
1325      */
1326     public Env<AttrContext> attribute(Env<AttrContext> env) {
1327         if (compileStates.isDone(env, CompileState.ATTR))
1328             return env;
1329 
1330         if (verboseCompilePolicy)
1331             printNote("[attribute " + env.enclClass.sym + "]");
1332         if (verbose)
1333             log.printVerbose("checking.attribution", env.enclClass.sym);
1334 
1335         if (!taskListener.isEmpty()) {
1336             TaskEvent e = newAnalyzeTaskEvent(env);
1337             taskListener.started(e);
1338         }
1339 
1340         JavaFileObject prev = log.useSource(
1341                                   env.enclClass.sym.sourcefile != null ?
1342                                   env.enclClass.sym.sourcefile :
1343                                   env.toplevel.sourcefile);
1344         try {
1345             attr.attrib(env);
1346             if (errorCount() > 0 && !shouldStop(CompileState.ATTR)) {
1347                 //if in fail-over mode, ensure that AST expression nodes
1348                 //are correctly initialized (e.g. they have a type/symbol)
1349                 attr.postAttr(env.tree);
1350             }
1351             compileStates.put(env, CompileState.ATTR);
1352         }
1353         finally {
1354             log.useSource(prev);
1355         }
1356 
1357         return env;
1358     }
1359 
1360     /**
1361      * Perform dataflow checks on attributed parse trees.
1362      * These include checks for definite assignment and unreachable statements.
1363      * If any errors occur, an empty list will be returned.
1364      * @return the list of attributed parse trees
1365      */
1366     public Queue<Env<AttrContext>> flow(Queue<Env<AttrContext>> envs) {
1367         ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1368         for (Env<AttrContext> env: envs) {
1369             flow(env, results);
1370         }
1371         return stopIfError(CompileState.FLOW, results);
1372     }
1373 
1374     /**
1375      * Perform dataflow checks on an attributed parse tree.
1376      */
1377     public Queue<Env<AttrContext>> flow(Env<AttrContext> env) {
1378         ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1379         flow(env, results);
1380         return stopIfError(CompileState.FLOW, results);
1381     }
1382 
1383     /**
1384      * Perform dataflow checks on an attributed parse tree.
1385      */
1386     protected void flow(Env<AttrContext> env, Queue<Env<AttrContext>> results) {
1387         if (compileStates.isDone(env, CompileState.FLOW)) {
1388             results.add(env);
1389             return;
1390         }
1391 
1392         try {
1393             if (shouldStop(CompileState.FLOW))
1394                 return;
1395 
1396             if (verboseCompilePolicy)
1397                 printNote("[flow " + env.enclClass.sym + "]");
1398             JavaFileObject prev = log.useSource(
1399                                                 env.enclClass.sym.sourcefile != null ?
1400                                                 env.enclClass.sym.sourcefile :
1401                                                 env.toplevel.sourcefile);
1402             try {
1403                 make.at(Position.FIRSTPOS);
1404                 TreeMaker localMake = make.forToplevel(env.toplevel);
1405                 flow.analyzeTree(env, localMake);
1406                 compileStates.put(env, CompileState.FLOW);
1407 
1408                 if (shouldStop(CompileState.FLOW))
1409                     return;
1410 
1411                 analyzer.flush(env);
1412 
1413                 results.add(env);
1414             }
1415             finally {
1416                 log.useSource(prev);
1417             }
1418         }
1419         finally {
1420             if (!taskListener.isEmpty()) {
1421                 TaskEvent e = newAnalyzeTaskEvent(env);
1422                 taskListener.finished(e);
1423             }
1424         }
1425     }
1426 
1427     /**
1428      * Check for various things to warn about.
1429      *
1430      * @return the list of attributed parse trees
1431      */
1432     public Queue<Env<AttrContext>> warn(Queue<Env<AttrContext>> envs) {
1433         ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1434         for (Env<AttrContext> env: envs) {
1435             warn(env, results);
1436         }
1437         return stopIfError(CompileState.WARN, results);
1438     }
1439 
1440     /**
1441      * Check for various things to warn about in an attributed parse tree.
1442      */
1443     public Queue<Env<AttrContext>> warn(Env<AttrContext> env) {
1444         ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1445         warn(env, results);
1446         return stopIfError(CompileState.WARN, results);
1447     }
1448 
1449     /**
1450      * Check for various things to warn about in an attributed parse tree.
1451      */
1452     protected void warn(Env<AttrContext> env, Queue<Env<AttrContext>> results) {
1453         if (compileStates.isDone(env, CompileState.WARN)) {
1454             results.add(env);
1455             return;
1456         }
1457 
1458         if (shouldStop(CompileState.WARN))
1459             return;
1460 
1461         if (verboseCompilePolicy)
1462             printNote("[warn " + env.enclClass.sym + "]");
1463         JavaFileObject prev = log.useSource(
1464                                             env.enclClass.sym.sourcefile != null ?
1465                                             env.enclClass.sym.sourcefile :
1466                                             env.toplevel.sourcefile);
1467         try {
1468             warningAnalyzer.analyzeTree(env);
1469             compileStates.put(env, CompileState.WARN);
1470             results.add(env);
1471         }
1472         finally {
1473             log.useSource(prev);
1474         }
1475     }
1476 
1477     private TaskEvent newAnalyzeTaskEvent(Env<AttrContext> env) {
1478         JCCompilationUnit toplevel = env.toplevel;
1479         ClassSymbol sym;
1480         if (env.enclClass.sym == syms.predefClass) {
1481             if (TreeInfo.isModuleInfo(toplevel)) {
1482                 sym = toplevel.modle.module_info;
1483             } else if (TreeInfo.isPackageInfo(toplevel)) {
1484                 sym = toplevel.packge.package_info;
1485             } else {
1486                 throw new IllegalStateException("unknown env.toplevel");
1487             }
1488         } else {
1489             sym = env.enclClass.sym;
1490         }
1491 
1492         return new TaskEvent(TaskEvent.Kind.ANALYZE, toplevel, sym);
1493     }
1494 
1495     /**
1496      * Prepare attributed parse trees, in conjunction with their attribution contexts,
1497      * for source or code generation.
1498      * If any errors occur, an empty list will be returned.
1499      * @return a list containing the classes to be generated
1500      */
1501     public Queue<Pair<Env<AttrContext>, JCClassDecl>> desugar(Queue<Env<AttrContext>> envs) {
1502         ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = new ListBuffer<>();
1503         for (Env<AttrContext> env: envs)
1504             desugar(env, results);
1505         return stopIfError(CompileState.FLOW, results);
1506     }
1507 
1508     HashMap<Env<AttrContext>, Queue<Pair<Env<AttrContext>, JCClassDecl>>> desugaredEnvs = new HashMap<>();
1509 
1510     /**
1511      * Prepare attributed parse trees, in conjunction with their attribution contexts,
1512      * for source or code generation. If the file was not listed on the command line,
1513      * the current implicitSourcePolicy is taken into account.
1514      * The preparation stops as soon as an error is found.
1515      */
1516     protected void desugar(final Env<AttrContext> env, Queue<Pair<Env<AttrContext>, JCClassDecl>> results) {
1517         if (shouldStop(CompileState.TRANSTYPES))
1518             return;
1519 
1520         if (implicitSourcePolicy == ImplicitSourcePolicy.NONE
1521                 && !inputFiles.contains(env.toplevel.sourcefile)) {
1522             return;
1523         }
1524 
1525         if (!modules.multiModuleMode && env.toplevel.modle != modules.getDefaultModule()) {
1526             //can only generate classfiles for a single module:
1527             return;
1528         }
1529 
1530         if (compileStates.isDone(env, CompileState.LOWER)) {
1531             results.addAll(desugaredEnvs.get(env));
1532             return;
1533         }
1534 
1535         // Ensure the file has reached the WARN state
1536         if (!compileStates.isDone(env, CompileState.WARN))
1537             warn(env);
1538 
1539         /**
1540          * Ensure that superclasses of C are desugared before C itself. This is
1541          * required for two reasons: (i) as erasure (TransTypes) destroys
1542          * information needed in flow analysis and (ii) as some checks carried
1543          * out during lowering require that all synthetic fields/methods have
1544          * already been added to C and its superclasses.
1545          */
1546         class ScanNested extends TreeScanner {
1547             Set<Env<AttrContext>> dependencies = new LinkedHashSet<>();
1548             protected boolean hasLambdas;
1549             protected boolean hasPatterns;
1550             @Override
1551             public void visitClassDef(JCClassDecl node) {
1552                 Type st = types.supertype(node.sym.type);
1553                 boolean envForSuperTypeFound = false;
1554                 while (!envForSuperTypeFound && st.hasTag(CLASS)) {
1555                     ClassSymbol c = st.tsym.outermostClass();
1556                     Env<AttrContext> stEnv = enter.getEnv(c);
1557                     if (stEnv != null && env != stEnv) {
1558                         if (dependencies.add(stEnv)) {
1559                             boolean prevHasLambdas = hasLambdas;
1560                             boolean prevHasPatterns = hasPatterns;
1561                             try {
1562                                 scan(stEnv.tree);
1563                             } finally {
1564                                 /*
1565                                  * ignore any updates to hasLambdas and hasPatterns
1566                                  * made during the nested scan, this ensures an
1567                                  * initialized LambdaToMethod or TransPatterns is
1568                                  * available only to those classes that contain
1569                                  * lambdas or patterns, respectivelly
1570                                  */
1571                                 hasLambdas = prevHasLambdas;
1572                                 hasPatterns = prevHasPatterns;
1573                             }
1574                         }
1575                         envForSuperTypeFound = true;
1576                     }
1577                     st = types.supertype(st);
1578                 }
1579                 super.visitClassDef(node);
1580             }
1581             @Override
1582             public void visitLambda(JCLambda tree) {
1583                 hasLambdas = true;
1584                 super.visitLambda(tree);
1585             }
1586             @Override
1587             public void visitReference(JCMemberReference tree) {
1588                 hasLambdas = true;
1589                 super.visitReference(tree);
1590             }
1591             @Override
1592             public void visitBindingPattern(JCBindingPattern tree) {
1593                 hasPatterns = true;
1594                 super.visitBindingPattern(tree);
1595             }
1596             @Override
1597             public void visitTypeTest(JCInstanceOf tree) {
1598                 if (tree.pattern.type.isPrimitive()) {
1599                     hasPatterns = true;
1600                 }
1601                 super.visitTypeTest(tree);
1602             }
1603             @Override
1604             public void visitRecordPattern(JCRecordPattern that) {
1605                 hasPatterns = true;
1606                 super.visitRecordPattern(that);
1607             }
1608             @Override
1609             public void visitSwitch(JCSwitch tree) {
1610                 hasPatterns |= tree.patternSwitch;
1611                 super.visitSwitch(tree);
1612             }
1613             @Override
1614             public void visitSwitchExpression(JCSwitchExpression tree) {
1615                 hasPatterns |= tree.patternSwitch;
1616                 super.visitSwitchExpression(tree);
1617             }
1618         }
1619         ScanNested scanner = new ScanNested();
1620         scanner.scan(env.tree);
1621         for (Env<AttrContext> dep: scanner.dependencies) {
1622             if (!compileStates.isDone(dep, CompileState.WARN))
1623                 desugaredEnvs.put(dep, desugar(warn(flow(attribute(dep)))));
1624         }
1625 
1626         //We need to check for error another time as more classes might
1627         //have been attributed and analyzed at this stage
1628         if (shouldStop(CompileState.TRANSTYPES))
1629             return;
1630 
1631         if (verboseCompilePolicy)
1632             printNote("[desugar " + env.enclClass.sym + "]");
1633 
1634         JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ?
1635                                   env.enclClass.sym.sourcefile :
1636                                   env.toplevel.sourcefile);
1637         try {
1638             //save tree prior to rewriting
1639             JCTree untranslated = env.tree;
1640 
1641             make.at(Position.FIRSTPOS);
1642             TreeMaker localMake = make.forToplevel(env.toplevel);
1643 
1644             if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF) || env.tree.hasTag(JCTree.Tag.MODULEDEF)) {
1645                 if (!(sourceOutput)) {
1646                     if (shouldStop(CompileState.LOWER))
1647                         return;
1648                     List<JCTree> def = lower.translateTopLevelClass(env, env.tree, localMake);
1649                     if (def.head != null) {
1650                         Assert.check(def.tail.isEmpty());
1651                         results.add(new Pair<>(env, (JCClassDecl)def.head));
1652                     }
1653                 }
1654                 return;
1655             }
1656 
1657             if (shouldStop(CompileState.TRANSTYPES))
1658                 return;
1659 
1660             env.tree = transTypes.translateTopLevelClass(env.tree, localMake);
1661             compileStates.put(env, CompileState.TRANSTYPES);
1662 
1663             if (shouldStop(CompileState.TRANSPATTERNS))
1664                 return;
1665 
1666             if (scanner.hasPatterns) {
1667                 env.tree = TransPatterns.instance(context).translateTopLevelClass(env, env.tree, localMake);
1668             }
1669 
1670             compileStates.put(env, CompileState.TRANSPATTERNS);
1671 
1672             if (shouldStop(CompileState.LOWER))
1673                 return;
1674 
1675             if (sourceOutput) {
1676                 //emit standard Java source file, only for compilation
1677                 //units enumerated explicitly on the command line
1678                 JCClassDecl cdef = (JCClassDecl)env.tree;
1679                 if (untranslated instanceof JCClassDecl classDecl &&
1680                     rootClasses.contains(classDecl)) {
1681                     results.add(new Pair<>(env, cdef));
1682                 }
1683                 return;
1684             }
1685 
1686             //translate out inner classes
1687             List<JCTree> cdefs = lower.translateTopLevelClass(env, env.tree, localMake);
1688             compileStates.put(env, CompileState.LOWER);
1689 
1690             if (shouldStop(CompileState.LOWER))
1691                 return;
1692 
1693             if (scanner.hasLambdas) {
1694                 if (shouldStop(CompileState.UNLAMBDA))
1695                     return;
1696 
1697                 for (JCTree def : cdefs) {
1698                     LambdaToMethod.instance(context).translateTopLevelClass(env, def, localMake);
1699                 }
1700                 compileStates.put(env, CompileState.UNLAMBDA);
1701             }
1702 
1703             if (shouldStop(CompileState.STRICT_FIELDS_PROXIES))
1704                 return;
1705             for (JCTree def : cdefs) {
1706                 LocalProxyVarsGen.instance(context).translateTopLevelClass(def, localMake);
1707             }
1708             compileStates.put(env, CompileState.STRICT_FIELDS_PROXIES);
1709 
1710             //generate code for each class
1711             for (List<JCTree> l = cdefs; l.nonEmpty(); l = l.tail) {
1712                 JCClassDecl cdef = (JCClassDecl)l.head;
1713                 results.add(new Pair<>(env, cdef));
1714             }
1715         }
1716         finally {
1717             log.useSource(prev);
1718         }
1719 
1720     }
1721 
1722     /** Generates the source or class file for a list of classes.
1723      * The decision to generate a source file or a class file is
1724      * based upon the compiler's options.
1725      * Generation stops if an error occurs while writing files.
1726      */
1727     public void generate(Queue<Pair<Env<AttrContext>, JCClassDecl>> queue) {
1728         generate(queue, null);
1729     }
1730 
1731     public void generate(Queue<Pair<Env<AttrContext>, JCClassDecl>> queue, Queue<JavaFileObject> results) {
1732         if (shouldStop(CompileState.GENERATE))
1733             return;
1734 
1735         for (Pair<Env<AttrContext>, JCClassDecl> x: queue) {
1736             Env<AttrContext> env = x.fst;
1737             JCClassDecl cdef = x.snd;
1738 
1739             if (verboseCompilePolicy) {
1740                 printNote("[generate " + (sourceOutput ? " source" : "code") + " " + cdef.sym + "]");
1741             }
1742 
1743             if (!taskListener.isEmpty()) {
1744                 TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym);
1745                 taskListener.started(e);
1746             }
1747 
1748             JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ?
1749                                       env.enclClass.sym.sourcefile :
1750                                       env.toplevel.sourcefile);
1751             try {
1752                 JavaFileObject file;
1753                 if (sourceOutput) {
1754                     file = printSource(env, cdef);
1755                 } else {
1756                     if (fileManager.hasLocation(StandardLocation.NATIVE_HEADER_OUTPUT)
1757                             && jniWriter.needsHeader(cdef.sym)) {
1758                         jniWriter.write(cdef.sym);
1759                     }
1760                     file = genCode(env, cdef);
1761                 }
1762                 if (results != null && file != null)
1763                     results.add(file);
1764             } catch (IOException
1765                     | UncheckedIOException
1766                     | FileSystemNotFoundException
1767                     | InvalidPathException
1768                     | ReadOnlyFileSystemException ex) {
1769                 log.error(cdef.pos(),
1770                           Errors.ClassCantWrite(cdef.sym, ex.getMessage()));
1771                 return;
1772             } finally {
1773                 log.useSource(prev);
1774             }
1775 
1776             if (!taskListener.isEmpty()) {
1777                 TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym);
1778                 taskListener.finished(e);
1779             }
1780         }
1781     }
1782 
1783         // where
1784         Map<JCCompilationUnit, Queue<Env<AttrContext>>> groupByFile(Queue<Env<AttrContext>> envs) {
1785             // use a LinkedHashMap to preserve the order of the original list as much as possible
1786             Map<JCCompilationUnit, Queue<Env<AttrContext>>> map = new LinkedHashMap<>();
1787             for (Env<AttrContext> env: envs) {
1788                 Queue<Env<AttrContext>> sublist = map.get(env.toplevel);
1789                 if (sublist == null) {
1790                     sublist = new ListBuffer<>();
1791                     map.put(env.toplevel, sublist);
1792                 }
1793                 sublist.add(env);
1794             }
1795             return map;
1796         }
1797 
1798         JCClassDecl removeMethodBodies(JCClassDecl cdef) {
1799             final boolean isInterface = (cdef.mods.flags & Flags.INTERFACE) != 0;
1800             class MethodBodyRemover extends TreeTranslator {
1801                 @Override
1802                 public void visitMethodDef(JCMethodDecl tree) {
1803                     tree.mods.flags &= ~Flags.SYNCHRONIZED;
1804                     for (JCVariableDecl vd : tree.params)
1805                         vd.mods.flags &= ~Flags.FINAL;
1806                     tree.body = null;
1807                     super.visitMethodDef(tree);
1808                 }
1809                 @Override
1810                 public void visitVarDef(JCVariableDecl tree) {
1811                     if (tree.init != null && tree.init.type.constValue() == null)
1812                         tree.init = null;
1813                     super.visitVarDef(tree);
1814                 }
1815                 @Override
1816                 public void visitClassDef(JCClassDecl tree) {
1817                     ListBuffer<JCTree> newdefs = new ListBuffer<>();
1818                     for (List<JCTree> it = tree.defs; it.tail != null; it = it.tail) {
1819                         JCTree t = it.head;
1820                         switch (t.getTag()) {
1821                         case CLASSDEF:
1822                             if (isInterface ||
1823                                 (((JCClassDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1824                                 (((JCClassDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCClassDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1825                                 newdefs.append(t);
1826                             break;
1827                         case METHODDEF:
1828                             if (isInterface ||
1829                                 (((JCMethodDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1830                                 ((JCMethodDecl) t).sym.name == names.init ||
1831                                 (((JCMethodDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCMethodDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1832                                 newdefs.append(t);
1833                             break;
1834                         case VARDEF:
1835                             if (isInterface || (((JCVariableDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1836                                 (((JCVariableDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCVariableDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1837                                 newdefs.append(t);
1838                             break;
1839                         default:
1840                             break;
1841                         }
1842                     }
1843                     tree.defs = newdefs.toList();
1844                     super.visitClassDef(tree);
1845                 }
1846             }
1847             MethodBodyRemover r = new MethodBodyRemover();
1848             return r.translate(cdef);
1849         }
1850 
1851     public void reportDeferredDiagnostics() {
1852         if (errorCount() == 0
1853                 && annotationProcessingOccurred
1854                 && implicitSourceFilesRead
1855                 && implicitSourcePolicy == ImplicitSourcePolicy.UNSET) {
1856             if (explicitAnnotationProcessingRequested())
1857                 log.warning(Warnings.ProcUseImplicit);
1858             else
1859                 log.warning(Warnings.ProcUseProcOrImplicit);
1860         }
1861         log.reportOutstandingWarnings();
1862         log.reportOutstandingNotes();
1863         if (log.compressedOutput) {
1864             log.note(Notes.CompressedDiags);
1865         }
1866     }
1867 
1868     public void enterDone() {
1869         enterDone = true;
1870         annotate.enterDone();
1871     }
1872 
1873     public boolean isEnterDone() {
1874         return enterDone;
1875     }
1876 
1877     private Name readModuleName(JavaFileObject fo) {
1878         return parseAndGetName(fo, t -> {
1879             JCModuleDecl md = t.getModuleDecl();
1880 
1881             return md != null ? TreeInfo.fullName(md.getName()) : null;
1882         });
1883     }
1884 
1885     private Name findPackageInFile(JavaFileObject fo) {
1886         return parseAndGetName(fo, t -> t.getPackage() != null ?
1887                                         TreeInfo.fullName(t.getPackage().getPackageName()) : null);
1888     }
1889 
1890     private Name parseAndGetName(JavaFileObject fo,
1891                                  Function<JCTree.JCCompilationUnit, Name> tree2Name) {
1892         DiagnosticHandler dh = log.new DiscardDiagnosticHandler();
1893         JavaFileObject prevSource = log.useSource(fo);
1894         try {
1895             JCTree.JCCompilationUnit t = parse(fo, fo.getCharContent(false), true);
1896             return tree2Name.apply(t);
1897         } catch (IOException e) {
1898             return null;
1899         } finally {
1900             log.popDiagnosticHandler(dh);
1901             log.useSource(prevSource);
1902         }
1903     }
1904 
1905     public void reportDeferredDiagnosticAndClearHandler() {
1906         if (deferredDiagnosticHandler != null) {
1907             ToIntFunction<JCDiagnostic> diagValue =
1908                     d -> d.isFlagSet(RECOVERABLE) ? 1 : 0;
1909             Comparator<JCDiagnostic> compareDiags =
1910                     (d1, d2) -> diagValue.applyAsInt(d1) - diagValue.applyAsInt(d2);
1911             deferredDiagnosticHandler.reportDeferredDiagnostics(compareDiags);
1912             log.popDiagnosticHandler(deferredDiagnosticHandler);
1913             deferredDiagnosticHandler = null;
1914         }
1915     }
1916 
1917     /** Close the compiler, flushing the logs
1918      */
1919     public void close() {
1920         rootClasses = null;
1921         finder = null;
1922         reader = null;
1923         make = null;
1924         writer = null;
1925         enter = null;
1926         if (todo != null)
1927             todo.clear();
1928         todo = null;
1929         parserFactory = null;
1930         syms = null;
1931         source = null;
1932         attr = null;
1933         chk = null;
1934         gen = null;
1935         lintMapper = null;
1936         flow = null;
1937         transTypes = null;
1938         lower = null;
1939         annotate = null;
1940         types = null;
1941 
1942         log.flush();
1943         try {
1944             fileManager.flush();
1945         } catch (IOException e) {
1946             throw new Abort(e);
1947         } finally {
1948             if (names != null)
1949                 names.dispose();
1950             names = null;
1951 
1952             FatalError fatalError = null;
1953             for (Closeable c: closeables) {
1954                 try {
1955                     c.close();
1956                 } catch (IOException e) {
1957                     if (fatalError == null) {
1958                         JCDiagnostic msg = diagFactory.fragment(Fragments.FatalErrCantClose);
1959                         fatalError = new FatalError(msg, e);
1960                     } else {
1961                         fatalError.addSuppressed(e);
1962                     }
1963                 }
1964             }
1965             if (fatalError != null) {
1966                 throw fatalError;
1967             }
1968             closeables = List.nil();
1969         }
1970     }
1971 
1972     protected void printNote(String lines) {
1973         log.printRawLines(Log.WriterKind.NOTICE, lines);
1974     }
1975 
1976     /** Print numbers of errors and warnings.
1977      */
1978     public void printCount(String kind, int count) {
1979         if (count != 0) {
1980             String key;
1981             if (count == 1)
1982                 key = "count." + kind;
1983             else
1984                 key = "count." + kind + ".plural";
1985             log.printLines(WriterKind.ERROR, key, String.valueOf(count));
1986             log.flush(Log.WriterKind.ERROR);
1987         }
1988     }
1989 
1990     private void printSuppressedCount(int shown, int suppressed, String diagKey) {
1991         if (suppressed > 0) {
1992             int total = shown + suppressed;
1993             log.printLines(WriterKind.ERROR, diagKey,
1994                     String.valueOf(shown), String.valueOf(total));
1995             log.flush(Log.WriterKind.ERROR);
1996         }
1997     }
1998 
1999     private static long now() {
2000         return System.currentTimeMillis();
2001     }
2002 
2003     private static long elapsed(long then) {
2004         return now() - then;
2005     }
2006 
2007     public void newRound() {
2008         inputFiles.clear();
2009         todo.clear();
2010     }
2011 
2012     public interface InitialFileParserIntf {
2013         public List<JCCompilationUnit> parse(Iterable<JavaFileObject> files);
2014     }
2015 
2016     public static class InitialFileParser implements InitialFileParserIntf {
2017 
2018         public static final Key<InitialFileParserIntf> initialParserKey = new Key<>();
2019 
2020         public static InitialFileParserIntf instance(Context context) {
2021             InitialFileParserIntf instance = context.get(initialParserKey);
2022             if (instance == null)
2023                 instance = new InitialFileParser(context);
2024             return instance;
2025         }
2026 
2027         private final JavaCompiler compiler;
2028 
2029         private InitialFileParser(Context context) {
2030             context.put(initialParserKey, this);
2031             this.compiler = JavaCompiler.instance(context);
2032         }
2033 
2034         @Override
2035         public List<JCCompilationUnit> parse(Iterable<JavaFileObject> fileObjects) {
2036            return compiler.parseFiles(fileObjects, false);
2037         }
2038     }
2039 }