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