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