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