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