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