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