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 (gen.genClass(env, cdef) && (errorCount() == 0))
 789                 return writer.writeClass(cdef.sym);
 790         } catch (ClassWriter.PoolOverflow ex) {
 791             log.error(cdef.pos(), Errors.LimitPool);
 792         } catch (ClassWriter.StringOverflow ex) {
 793             log.error(cdef.pos(),
 794                       Errors.LimitStringOverflow(ex.value.substring(0, 20)));
 795         } catch (CompletionFailure ex) {
 796             chk.completionError(cdef.pos(), ex);
 797         }
 798         return null;
 799     }
 800 
 801     /** Emit plain Java source for a class.
 802      *  @param env    The attribution environment of the outermost class
 803      *                containing this class.
 804      *  @param cdef   The class definition to be printed.
 805      */
 806     JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
 807         JavaFileObject outFile
 808            = fileManager.getJavaFileForOutput(CLASS_OUTPUT,
 809                                                cdef.sym.flatname.toString(),
 810                                                JavaFileObject.Kind.SOURCE,
 811                                                null);
 812         if (inputFiles.contains(outFile)) {
 813             log.error(cdef.pos(), Errors.SourceCantOverwriteInputFile(outFile));
 814             return null;
 815         } else {
 816             try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) {
 817                 new Pretty(out, true).printUnit(env.toplevel, cdef);
 818                 if (verbose)
 819                     log.printVerbose("wrote.file", outFile.getName());
 820             }
 821             return outFile;
 822         }
 823     }
 824 
 825     /** Compile a source file that has been accessed by the class finder.
 826      *  @param c          The class the source file of which needs to be compiled.
 827      */
 828     private void readSourceFile(ClassSymbol c) throws CompletionFailure {
 829         readSourceFile(null, c);
 830     }
 831 
 832     /** Compile a ClassSymbol from source, optionally using the given compilation unit as
 833      *  the source tree.
 834      *  @param tree the compilation unit in which the given ClassSymbol resides,
 835      *              or null if should be parsed from source
 836      *  @param c    the ClassSymbol to complete
 837      */
 838     public void readSourceFile(JCCompilationUnit tree, ClassSymbol c) throws CompletionFailure {
 839         if (completionFailureName == c.fullname) {
 840             throw new CompletionFailure(
 841                 c, () -> diagFactory.fragment(Fragments.UserSelectedCompletionFailure), dcfh);
 842         }
 843         JavaFileObject filename = c.classfile;
 844         JavaFileObject prev = log.useSource(filename);
 845 
 846         if (tree == null) {
 847             try {
 848                 tree = parse(filename, filename.getCharContent(false));
 849             } catch (IOException e) {
 850                 log.error(Errors.ErrorReadingFile(filename, JavacFileManager.getMessage(e)));
 851                 tree = make.TopLevel(List.<JCTree>nil());
 852             } finally {
 853                 log.useSource(prev);
 854             }
 855         }
 856 
 857         if (!taskListener.isEmpty()) {
 858             TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
 859             taskListener.started(e);
 860         }
 861 
 862         // Process module declarations.
 863         // If module resolution fails, ignore trees, and if trying to
 864         // complete a specific symbol, throw CompletionFailure.
 865         // Note that if module resolution failed, we may not even
 866         // have enough modules available to access java.lang, and
 867         // so risk getting FatalError("no.java.lang") from MemberEnter.
 868         if (!modules.enter(List.of(tree), c)) {
 869             throw new CompletionFailure(c, () -> diags.fragment(Fragments.CantResolveModules), dcfh);
 870         }
 871 
 872         enter.complete(List.of(tree), c);
 873 
 874         if (!taskListener.isEmpty()) {
 875             TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
 876             taskListener.finished(e);
 877         }
 878 
 879         if (enter.getEnv(c) == null) {
 880             boolean isPkgInfo =
 881                 tree.sourcefile.isNameCompatible("package-info",
 882                                                  JavaFileObject.Kind.SOURCE);
 883             boolean isModuleInfo =
 884                 tree.sourcefile.isNameCompatible("module-info",
 885                                                  JavaFileObject.Kind.SOURCE);
 886             if (isModuleInfo) {
 887                 if (enter.getEnv(tree.modle) == null) {
 888                     JCDiagnostic diag =
 889                         diagFactory.fragment(Fragments.FileDoesNotContainModule);
 890                     throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory, dcfh);
 891                 }
 892             } else if (isPkgInfo) {
 893                 if (enter.getEnv(tree.packge) == null) {
 894                     JCDiagnostic diag =
 895                         diagFactory.fragment(Fragments.FileDoesNotContainPackage(c.location()));
 896                     throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory, dcfh);
 897                 }
 898             } else {
 899                 JCDiagnostic diag =
 900                         diagFactory.fragment(Fragments.FileDoesntContainClass(c.getQualifiedName()));
 901                 throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory, dcfh);
 902             }
 903         }
 904 
 905         implicitSourceFilesRead = true;
 906     }
 907 
 908     /** Track when the JavaCompiler has been used to compile something. */
 909     private boolean hasBeenUsed = false;
 910     private long start_msec = 0;
 911     public long elapsed_msec = 0;
 912 
 913     public void compile(List<JavaFileObject> sourceFileObject)
 914         throws Throwable {
 915         compile(sourceFileObject, List.nil(), null, List.nil());
 916     }
 917 
 918     /**
 919      * Main method: compile a list of files, return all compiled classes
 920      *
 921      * @param sourceFileObjects file objects to be compiled
 922      * @param classnames class names to process for annotations
 923      * @param processors user provided annotation processors to bypass
 924      * discovery, {@code null} means that no processors were provided
 925      * @param addModules additional root modules to be used during
 926      * module resolution.
 927      */
 928     public void compile(Collection<JavaFileObject> sourceFileObjects,
 929                         Collection<String> classnames,
 930                         Iterable<? extends Processor> processors,
 931                         Collection<String> addModules)
 932     {
 933         if (!taskListener.isEmpty()) {
 934             taskListener.started(new TaskEvent(TaskEvent.Kind.COMPILATION));
 935         }
 936 
 937         // as a JavaCompiler can only be used once, throw an exception if
 938         // it has been used before.
 939         if (hasBeenUsed)
 940             checkReusable();
 941         hasBeenUsed = true;
 942 
 943         start_msec = now();
 944 
 945         try {
 946             initProcessAnnotations(processors, sourceFileObjects, classnames);
 947 
 948             for (String className : classnames) {
 949                 int sep = className.indexOf('/');
 950                 if (sep != -1) {
 951                     modules.addExtraAddModules(className.substring(0, sep));
 952                 }
 953             }
 954 
 955             for (String moduleName : addModules) {
 956                 modules.addExtraAddModules(moduleName);
 957             }
 958 
 959             // These method calls must be chained to avoid memory leaks
 960             processAnnotations(
 961                 enterTrees(
 962                         stopIfError(CompileState.ENTER,
 963                                 initModules(stopIfError(CompileState.ENTER, parseFiles(sourceFileObjects))))
 964                 ),
 965                 classnames
 966             );
 967 
 968             // If it's safe to do so, skip attr / flow / gen for implicit classes
 969             if (taskListener.isEmpty() &&
 970                     implicitSourcePolicy == ImplicitSourcePolicy.NONE) {
 971                 todo.retainFiles(inputFiles);
 972             }
 973 
 974             if (!CompileState.ATTR.isAfter(shouldStopPolicyIfNoError)) {
 975                 switch (compilePolicy) {
 976                 case SIMPLE:
 977                     generate(desugar(warn(flow(attribute(todo)))));
 978                     break;
 979 
 980                 case BY_FILE: {
 981                         Queue<Queue<Env<AttrContext>>> q = todo.groupByFile();
 982                         while (!q.isEmpty() && !shouldStop(CompileState.ATTR)) {
 983                             generate(desugar(warn(flow(attribute(q.remove())))));
 984                         }
 985                     }
 986                     break;
 987 
 988                 case BY_TODO:
 989                     while (!todo.isEmpty())
 990                         generate(desugar(warn(flow(attribute(todo.remove())))));
 991                     break;
 992 
 993                 default:
 994                     Assert.error("unknown compile policy");
 995                 }
 996             }
 997         } catch (Abort ex) {
 998             if (devVerbose)
 999                 ex.printStackTrace(System.err);
1000 
1001             // In case an Abort was thrown before processAnnotations could be called,
1002             // we could have deferred diagnostics that haven't been reported.
1003             reportDeferredDiagnosticAndClearHandler();
1004         } finally {
1005             if (verbose) {
1006                 elapsed_msec = elapsed(start_msec);
1007                 log.printVerbose("total", Long.toString(elapsed_msec));
1008             }
1009 
1010             reportDeferredDiagnostics();
1011 
1012             if (!log.hasDiagnosticListener()) {
1013                 printCount("error", errorCount());
1014                 printCount("warn", warningCount());
1015                 printSuppressedCount(errorCount(), log.nsuppressederrors, "count.error.recompile");
1016                 printSuppressedCount(warningCount(), log.nsuppressedwarns, "count.warn.recompile");
1017             }
1018             if (!taskListener.isEmpty()) {
1019                 taskListener.finished(new TaskEvent(TaskEvent.Kind.COMPILATION));
1020             }
1021             close();
1022             if (procEnvImpl != null)
1023                 procEnvImpl.close();
1024         }
1025     }
1026 
1027     protected void checkReusable() {
1028         throw new AssertionError("attempt to reuse JavaCompiler");
1029     }
1030 
1031     /**
1032      * The list of classes explicitly supplied on the command line for compilation.
1033      * Not always populated.
1034      */
1035     private List<JCClassDecl> rootClasses;
1036 
1037     /**
1038      * Parses a list of files.
1039      */
1040    public List<JCCompilationUnit> parseFiles(Iterable<JavaFileObject> fileObjects) {
1041        return InitialFileParser.instance(context).parse(fileObjects);
1042    }
1043 
1044    public List<JCCompilationUnit> parseFiles(Iterable<JavaFileObject> fileObjects, boolean force) {
1045        if (!force && shouldStop(CompileState.PARSE))
1046            return List.nil();
1047 
1048         //parse all files
1049         ListBuffer<JCCompilationUnit> trees = new ListBuffer<>();
1050         Set<JavaFileObject> filesSoFar = new HashSet<>();
1051         for (JavaFileObject fileObject : fileObjects) {
1052             if (!filesSoFar.contains(fileObject)) {
1053                 filesSoFar.add(fileObject);
1054                 trees.append(parse(fileObject));
1055             }
1056         }
1057         return trees.toList();
1058     }
1059 
1060    /**
1061     * Returns true iff the compilation will continue after annotation processing
1062     * is done.
1063     */
1064     public boolean continueAfterProcessAnnotations() {
1065         return !shouldStop(CompileState.ATTR);
1066     }
1067 
1068     public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
1069         modules.initModules(roots);
1070 
1071         if (modules.modulesInitialized()) {
1072             // This has to happen precisely here. At this point, we have all we need to
1073             // determine whether jdk.incubator.module is part of the module graph
1074             // but we have yet to trigger an ENTER event. This gives the code reflection plugin
1075             // a window to check whether code reflection should be enabled for this compilation unit.
1076             hasCodeReflectionModule = modules.getObservableModule(names.jdk_incubator_code) != null;
1077         }
1078 
1079         if (roots.isEmpty()) {
1080             enterDone();
1081         }
1082         return roots;
1083     }
1084 
1085     /**
1086      * Enter the symbols found in a list of parse trees.
1087      * As a side-effect, this puts elements on the "todo" list.
1088      * Also stores a list of all top level classes in rootClasses.
1089      */
1090     public List<JCCompilationUnit> enterTrees(List<JCCompilationUnit> roots) {
1091         //enter symbols for all files
1092         if (!taskListener.isEmpty()) {
1093             for (JCCompilationUnit unit: roots) {
1094                 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
1095                 taskListener.started(e);
1096             }
1097         }
1098 
1099         enter.main(roots);
1100 
1101         enterDone();
1102 
1103         if (!taskListener.isEmpty()) {
1104             for (JCCompilationUnit unit: roots) {
1105                 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
1106                 taskListener.finished(e);
1107             }
1108         }
1109 
1110         // If generating source, or if tracking public apis,
1111         // then remember the classes declared in
1112         // the original compilation units listed on the command line.
1113         if (sourceOutput) {
1114             ListBuffer<JCClassDecl> cdefs = new ListBuffer<>();
1115             for (JCCompilationUnit unit : roots) {
1116                 for (List<JCTree> defs = unit.defs;
1117                      defs.nonEmpty();
1118                      defs = defs.tail) {
1119                     if (defs.head instanceof JCClassDecl classDecl)
1120                         cdefs.append(classDecl);
1121                 }
1122             }
1123             rootClasses = cdefs.toList();
1124         }
1125 
1126         // Ensure the input files have been recorded. Although this is normally
1127         // done by readSource, it may not have been done if the trees were read
1128         // in a prior round of annotation processing, and the trees have been
1129         // cleaned and are being reused.
1130         for (JCCompilationUnit unit : roots) {
1131             inputFiles.add(unit.sourcefile);
1132         }
1133 
1134         return roots;
1135     }
1136 
1137     /**
1138      * Set to true to enable skeleton annotation processing code.
1139      * Currently, we assume this variable will be replaced more
1140      * advanced logic to figure out if annotation processing is
1141      * needed.
1142      */
1143     boolean processAnnotations = false;
1144 
1145     Log.DeferredDiagnosticHandler deferredDiagnosticHandler;
1146 
1147     /**
1148      * Object to handle annotation processing.
1149      */
1150     private JavacProcessingEnvironment procEnvImpl = null;
1151 
1152     /**
1153      * Check if we should process annotations.
1154      * If so, and if no scanner is yet registered, then set up the DocCommentScanner
1155      * to catch doc comments, and set keepComments so the parser records them in
1156      * the compilation unit.
1157      *
1158      * @param processors user provided annotation processors to bypass
1159      * discovery, {@code null} means that no processors were provided
1160      */
1161     public void initProcessAnnotations(Iterable<? extends Processor> processors,
1162                                        Collection<? extends JavaFileObject> initialFiles,
1163                                        Collection<String> initialClassNames) {
1164         if (processors != null && processors.iterator().hasNext())
1165             explicitAnnotationProcessingRequested = true;
1166 
1167         if (options.isSet(PROC, "none")) {
1168             processAnnotations = false;
1169         } else if (procEnvImpl == null) {
1170             procEnvImpl = JavacProcessingEnvironment.instance(context);
1171             procEnvImpl.setProcessors(processors);
1172 
1173             // Process annotations if processing is requested and there
1174             // is at least one Processor available.
1175             processAnnotations = procEnvImpl.atLeastOneProcessor() &&
1176                 explicitAnnotationProcessingRequested();
1177 
1178             if (processAnnotations) {
1179                 options.put("parameters", "parameters");
1180                 reader.saveParameterNames = true;
1181                 keepComments = true;
1182                 genEndPos = true;
1183                 if (!taskListener.isEmpty())
1184                     taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
1185                 deferredDiagnosticHandler = log.new DeferredDiagnosticHandler();
1186                 procEnvImpl.getFiler().setInitialState(initialFiles, initialClassNames);
1187             }
1188         } else { // free resources
1189             procEnvImpl.close();
1190         }
1191     }
1192 
1193     // TODO: called by JavacTaskImpl
1194     public void processAnnotations(List<JCCompilationUnit> roots) {
1195         processAnnotations(roots, List.nil());
1196     }
1197 
1198     /**
1199      * Process any annotations found in the specified compilation units.
1200      * @param roots a list of compilation units
1201      */
1202     // Implementation note: when this method is called, log.deferredDiagnostics
1203     // will have been set true by initProcessAnnotations, meaning that any diagnostics
1204     // that are reported will go into the log.deferredDiagnostics queue.
1205     // By the time this method exits, log.deferDiagnostics must be set back to false,
1206     // and all deferredDiagnostics must have been handled: i.e. either reported
1207     // or determined to be transient, and therefore suppressed.
1208     public void processAnnotations(List<JCCompilationUnit> roots,
1209                                    Collection<String> classnames) {
1210         if (shouldStop(CompileState.PROCESS)) {
1211             // Errors were encountered.
1212             // Unless all the errors are resolve errors, the errors were parse errors
1213             // or other errors during enter which cannot be fixed by running
1214             // any annotation processors.
1215             if (processAnnotations) {
1216                 reportDeferredDiagnosticAndClearHandler();
1217                 return ;
1218             }
1219         }
1220 
1221         // ASSERT: processAnnotations and procEnvImpl should have been set up by
1222         // by initProcessAnnotations
1223 
1224         // NOTE: The !classnames.isEmpty() checks should be refactored to Main.
1225 
1226         if (!processAnnotations) {
1227             // If there are no annotation processors present, and
1228             // annotation processing is to occur with compilation,
1229             // emit a warning.
1230             if (options.isSet(PROC, "only")) {
1231                 log.warning(Warnings.ProcProcOnlyRequestedNoProcs);
1232                 todo.clear();
1233             }
1234             // If not processing annotations, classnames must be empty
1235             if (!classnames.isEmpty()) {
1236                 log.error(Errors.ProcNoExplicitAnnotationProcessingRequested(classnames));
1237             }
1238             Assert.checkNull(deferredDiagnosticHandler);
1239             return ; // continue regular compilation
1240         }
1241 
1242         Assert.checkNonNull(deferredDiagnosticHandler);
1243 
1244         try {
1245             List<ClassSymbol> classSymbols = List.nil();
1246             List<PackageSymbol> pckSymbols = List.nil();
1247             if (!classnames.isEmpty()) {
1248                  // Check for explicit request for annotation
1249                  // processing
1250                 if (!explicitAnnotationProcessingRequested()) {
1251                     log.error(Errors.ProcNoExplicitAnnotationProcessingRequested(classnames));
1252                     reportDeferredDiagnosticAndClearHandler();
1253                     return ; // TODO: Will this halt compilation?
1254                 } else {
1255                     boolean errors = false;
1256                     for (String nameStr : classnames) {
1257                         Symbol sym = resolveBinaryNameOrIdent(nameStr);
1258                         if (sym == null ||
1259                             (sym.kind == PCK && !processPcks) ||
1260                             sym.kind == ABSENT_TYP) {
1261                             if (sym != silentFail)
1262                                 log.error(Errors.ProcCantFindClass(nameStr));
1263                             errors = true;
1264                             continue;
1265                         }
1266                         try {
1267                             if (sym.kind == PCK)
1268                                 sym.complete();
1269                             if (sym.exists()) {
1270                                 if (sym.kind == PCK)
1271                                     pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
1272                                 else
1273                                     classSymbols = classSymbols.prepend((ClassSymbol)sym);
1274                                 continue;
1275                             }
1276                             Assert.check(sym.kind == PCK);
1277                             log.warning(Warnings.ProcPackageDoesNotExist(nameStr));
1278                             pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
1279                         } catch (CompletionFailure e) {
1280                             log.error(Errors.ProcCantFindClass(nameStr));
1281                             errors = true;
1282                             continue;
1283                         }
1284                     }
1285                     if (errors) {
1286                         reportDeferredDiagnosticAndClearHandler();
1287                         return ;
1288                     }
1289                 }
1290             }
1291             try {
1292                 annotationProcessingOccurred =
1293                         procEnvImpl.doProcessing(roots,
1294                                                  classSymbols,
1295                                                  pckSymbols,
1296                                                  deferredDiagnosticHandler);
1297                 // doProcessing will have handled deferred diagnostics
1298             } finally {
1299                 procEnvImpl.close();
1300             }
1301         } catch (CompletionFailure ex) {
1302             log.error(Errors.CantAccess(ex.sym, ex.getDetailValue()));
1303             reportDeferredDiagnosticAndClearHandler();
1304         }
1305     }
1306 
1307     private boolean unrecoverableError() {
1308         if (deferredDiagnosticHandler != null) {
1309             for (JCDiagnostic d: deferredDiagnosticHandler.getDiagnostics()) {
1310                 if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RECOVERABLE))
1311                     return true;
1312             }
1313         }
1314         return false;
1315     }
1316 
1317     boolean explicitAnnotationProcessingRequested() {
1318         return
1319             explicitAnnotationProcessingRequested ||
1320             explicitAnnotationProcessingRequested(options, fileManager);
1321     }
1322 
1323     static boolean explicitAnnotationProcessingRequested(Options options, JavaFileManager fileManager) {
1324         return
1325             options.isSet(PROCESSOR) ||
1326             options.isSet(PROCESSOR_PATH) ||
1327             options.isSet(PROCESSOR_MODULE_PATH) ||
1328             options.isSet(PROC, "only") ||
1329             options.isSet(PROC, "full") ||
1330             options.isSet(A) ||
1331             options.isSet(XPRINT) ||
1332             fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH);
1333         // Skipping -XprintRounds and -XprintProcessorInfo
1334     }
1335 
1336     public void setDeferredDiagnosticHandler(Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
1337         this.deferredDiagnosticHandler = deferredDiagnosticHandler;
1338     }
1339 
1340     /**
1341      * Attribute a list of parse trees, such as found on the "todo" list.
1342      * Note that attributing classes may cause additional files to be
1343      * parsed and entered via the SourceCompleter.
1344      * Attribution of the entries in the list does not stop if any errors occur.
1345      * @return a list of environments for attribute classes.
1346      */
1347     public Queue<Env<AttrContext>> attribute(Queue<Env<AttrContext>> envs) {
1348         ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1349         while (!envs.isEmpty())
1350             results.append(attribute(envs.remove()));
1351         return stopIfError(CompileState.ATTR, results);
1352     }
1353 
1354     /**
1355      * Attribute a parse tree.
1356      * @return the attributed parse tree
1357      */
1358     public Env<AttrContext> attribute(Env<AttrContext> env) {
1359         if (compileStates.isDone(env, CompileState.ATTR))
1360             return env;
1361 
1362         if (verboseCompilePolicy)
1363             printNote("[attribute " + env.enclClass.sym + "]");
1364         if (verbose)
1365             log.printVerbose("checking.attribution", env.enclClass.sym);
1366 
1367         if (!taskListener.isEmpty()) {
1368             TaskEvent e = newAnalyzeTaskEvent(env);
1369             taskListener.started(e);
1370         }
1371 
1372         JavaFileObject prev = log.useSource(
1373                                   env.enclClass.sym.sourcefile != null ?
1374                                   env.enclClass.sym.sourcefile :
1375                                   env.toplevel.sourcefile);
1376         try {
1377             attr.attrib(env);
1378             if (errorCount() > 0 && !shouldStop(CompileState.ATTR)) {
1379                 //if in fail-over mode, ensure that AST expression nodes
1380                 //are correctly initialized (e.g. they have a type/symbol)
1381                 attr.postAttr(env.tree);
1382             }
1383             compileStates.put(env, CompileState.ATTR);
1384         }
1385         finally {
1386             log.useSource(prev);
1387         }
1388 
1389         return env;
1390     }
1391 
1392     /**
1393      * Perform dataflow checks on attributed parse trees.
1394      * These include checks for definite assignment and unreachable statements.
1395      * If any errors occur, an empty list will be returned.
1396      * @return the list of attributed parse trees
1397      */
1398     public Queue<Env<AttrContext>> flow(Queue<Env<AttrContext>> envs) {
1399         ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1400         for (Env<AttrContext> env: envs) {
1401             flow(env, results);
1402         }
1403         return stopIfError(CompileState.FLOW, results);
1404     }
1405 
1406     /**
1407      * Perform dataflow checks on an attributed parse tree.
1408      */
1409     public Queue<Env<AttrContext>> flow(Env<AttrContext> env) {
1410         ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1411         flow(env, results);
1412         return stopIfError(CompileState.FLOW, results);
1413     }
1414 
1415     /**
1416      * Perform dataflow checks on an attributed parse tree.
1417      */
1418     protected void flow(Env<AttrContext> env, Queue<Env<AttrContext>> results) {
1419         if (compileStates.isDone(env, CompileState.FLOW)) {
1420             results.add(env);
1421             return;
1422         }
1423 
1424         try {
1425             if (shouldStop(CompileState.FLOW))
1426                 return;
1427 
1428             if (verboseCompilePolicy)
1429                 printNote("[flow " + env.enclClass.sym + "]");
1430             JavaFileObject prev = log.useSource(
1431                                                 env.enclClass.sym.sourcefile != null ?
1432                                                 env.enclClass.sym.sourcefile :
1433                                                 env.toplevel.sourcefile);
1434             try {
1435                 make.at(Position.FIRSTPOS);
1436                 TreeMaker localMake = make.forToplevel(env.toplevel);
1437                 flow.analyzeTree(env, localMake);
1438                 compileStates.put(env, CompileState.FLOW);
1439 
1440                 if (shouldStop(CompileState.FLOW))
1441                     return;
1442 
1443                 analyzer.flush(env);
1444 
1445                 results.add(env);
1446             }
1447             finally {
1448                 log.useSource(prev);
1449             }
1450         }
1451         finally {
1452             if (!taskListener.isEmpty()) {
1453                 TaskEvent e = newAnalyzeTaskEvent(env);
1454                 taskListener.finished(e);
1455             }
1456         }
1457     }
1458 
1459     /**
1460      * Check for various things to warn about.
1461      *
1462      * @return the list of attributed parse trees
1463      */
1464     public Queue<Env<AttrContext>> warn(Queue<Env<AttrContext>> envs) {
1465         ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1466         for (Env<AttrContext> env: envs) {
1467             warn(env, results);
1468         }
1469         return stopIfError(CompileState.WARN, results);
1470     }
1471 
1472     /**
1473      * Check for various things to warn about in an attributed parse tree.
1474      */
1475     public Queue<Env<AttrContext>> warn(Env<AttrContext> env) {
1476         ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
1477         warn(env, results);
1478         return stopIfError(CompileState.WARN, results);
1479     }
1480 
1481     /**
1482      * Check for various things to warn about in an attributed parse tree.
1483      */
1484     protected void warn(Env<AttrContext> env, Queue<Env<AttrContext>> results) {
1485         if (compileStates.isDone(env, CompileState.WARN)) {
1486             results.add(env);
1487             return;
1488         }
1489 
1490         if (shouldStop(CompileState.WARN))
1491             return;
1492 
1493         if (verboseCompilePolicy)
1494             printNote("[warn " + env.enclClass.sym + "]");
1495         JavaFileObject prev = log.useSource(
1496                                             env.enclClass.sym.sourcefile != null ?
1497                                             env.enclClass.sym.sourcefile :
1498                                             env.toplevel.sourcefile);
1499         try {
1500             warningAnalyzer.analyzeTree(env);
1501             compileStates.put(env, CompileState.WARN);
1502             results.add(env);
1503         }
1504         finally {
1505             log.useSource(prev);
1506         }
1507     }
1508 
1509     private TaskEvent newAnalyzeTaskEvent(Env<AttrContext> env) {
1510         JCCompilationUnit toplevel = env.toplevel;
1511         ClassSymbol sym;
1512         if (env.enclClass.sym == syms.predefClass) {
1513             if (TreeInfo.isModuleInfo(toplevel)) {
1514                 sym = toplevel.modle.module_info;
1515             } else if (TreeInfo.isPackageInfo(toplevel)) {
1516                 sym = toplevel.packge.package_info;
1517             } else {
1518                 throw new IllegalStateException("unknown env.toplevel");
1519             }
1520         } else {
1521             sym = env.enclClass.sym;
1522         }
1523 
1524         return new TaskEvent(TaskEvent.Kind.ANALYZE, toplevel, sym);
1525     }
1526 
1527     /**
1528      * Prepare attributed parse trees, in conjunction with their attribution contexts,
1529      * for source or code generation.
1530      * If any errors occur, an empty list will be returned.
1531      * @return a list containing the classes to be generated
1532      */
1533     public Queue<Pair<Env<AttrContext>, JCClassDecl>> desugar(Queue<Env<AttrContext>> envs) {
1534         ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = new ListBuffer<>();
1535         for (Env<AttrContext> env: envs)
1536             desugar(env, results);
1537         return stopIfError(CompileState.FLOW, results);
1538     }
1539 
1540     HashMap<Env<AttrContext>, Queue<Pair<Env<AttrContext>, JCClassDecl>>> desugaredEnvs = new HashMap<>();
1541 
1542     /**
1543      * Prepare attributed parse trees, in conjunction with their attribution contexts,
1544      * for source or code generation. If the file was not listed on the command line,
1545      * the current implicitSourcePolicy is taken into account.
1546      * The preparation stops as soon as an error is found.
1547      */
1548     protected void desugar(final Env<AttrContext> env, Queue<Pair<Env<AttrContext>, JCClassDecl>> results) {
1549         if (shouldStop(CompileState.TRANSTYPES))
1550             return;
1551 
1552         if (implicitSourcePolicy == ImplicitSourcePolicy.NONE
1553                 && !inputFiles.contains(env.toplevel.sourcefile)) {
1554             return;
1555         }
1556 
1557         if (!modules.multiModuleMode && env.toplevel.modle != modules.getDefaultModule()) {
1558             //can only generate classfiles for a single module:
1559             return;
1560         }
1561 
1562         if (compileStates.isDone(env, CompileState.LOWER)) {
1563             results.addAll(desugaredEnvs.get(env));
1564             return;
1565         }
1566 
1567         // Ensure the file has reached the WARN state
1568         if (!compileStates.isDone(env, CompileState.WARN))
1569             warn(env);
1570 
1571         /**
1572          * Ensure that superclasses of C are desugared before C itself. This is
1573          * required for two reasons: (i) as erasure (TransTypes) destroys
1574          * information needed in flow analysis and (ii) as some checks carried
1575          * out during lowering require that all synthetic fields/methods have
1576          * already been added to C and its superclasses.
1577          */
1578         class ScanNested extends TreeScanner {
1579             Set<Env<AttrContext>> dependencies = new LinkedHashSet<>();
1580             protected boolean hasLambdas;
1581             protected boolean hasPatterns;
1582             @Override
1583             public void visitClassDef(JCClassDecl node) {
1584                 Type st = types.supertype(node.sym.type);
1585                 boolean envForSuperTypeFound = false;
1586                 while (!envForSuperTypeFound && st.hasTag(CLASS)) {
1587                     ClassSymbol c = st.tsym.outermostClass();
1588                     Env<AttrContext> stEnv = enter.getEnv(c);
1589                     if (stEnv != null && env != stEnv) {
1590                         if (dependencies.add(stEnv)) {
1591                             boolean prevHasLambdas = hasLambdas;
1592                             boolean prevHasPatterns = hasPatterns;
1593                             try {
1594                                 scan(stEnv.tree);
1595                             } finally {
1596                                 /*
1597                                  * ignore any updates to hasLambdas and hasPatterns
1598                                  * made during the nested scan, this ensures an
1599                                  * initialized LambdaToMethod or TransPatterns is
1600                                  * available only to those classes that contain
1601                                  * lambdas or patterns, respectivelly
1602                                  */
1603                                 hasLambdas = prevHasLambdas;
1604                                 hasPatterns = prevHasPatterns;
1605                             }
1606                         }
1607                         envForSuperTypeFound = true;
1608                     }
1609                     st = types.supertype(st);
1610                 }
1611                 super.visitClassDef(node);
1612             }
1613             @Override
1614             public void visitLambda(JCLambda tree) {
1615                 hasLambdas = true;
1616                 super.visitLambda(tree);
1617             }
1618             @Override
1619             public void visitReference(JCMemberReference tree) {
1620                 hasLambdas = true;
1621                 super.visitReference(tree);
1622             }
1623             @Override
1624             public void visitBindingPattern(JCBindingPattern tree) {
1625                 hasPatterns = true;
1626                 super.visitBindingPattern(tree);
1627             }
1628             @Override
1629             public void visitTypeTest(JCInstanceOf tree) {
1630                 if (tree.pattern.type.isPrimitive()) {
1631                     hasPatterns = true;
1632                 }
1633                 super.visitTypeTest(tree);
1634             }
1635             @Override
1636             public void visitRecordPattern(JCRecordPattern that) {
1637                 hasPatterns = true;
1638                 super.visitRecordPattern(that);
1639             }
1640             @Override
1641             public void visitSwitch(JCSwitch tree) {
1642                 hasPatterns |= tree.patternSwitch;
1643                 super.visitSwitch(tree);
1644             }
1645             @Override
1646             public void visitSwitchExpression(JCSwitchExpression tree) {
1647                 hasPatterns |= tree.patternSwitch;
1648                 super.visitSwitchExpression(tree);
1649             }
1650         }
1651         ScanNested scanner = new ScanNested();
1652         scanner.scan(env.tree);
1653         for (Env<AttrContext> dep: scanner.dependencies) {
1654         if (!compileStates.isDone(dep, CompileState.WARN))
1655             desugaredEnvs.put(dep, desugar(warn(flow(attribute(dep)))));
1656         }
1657 
1658         //We need to check for error another time as more classes might
1659         //have been attributed and analyzed at this stage
1660         if (shouldStop(CompileState.TRANSTYPES))
1661             return;
1662 
1663         if (verboseCompilePolicy)
1664             printNote("[desugar " + env.enclClass.sym + "]");
1665 
1666         JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ?
1667                                   env.enclClass.sym.sourcefile :
1668                                   env.toplevel.sourcefile);
1669         try {
1670             //save tree prior to rewriting
1671             JCTree untranslated = env.tree;
1672 
1673             make.at(Position.FIRSTPOS);
1674             TreeMaker localMake = make.forToplevel(env.toplevel);
1675 
1676             if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF) || env.tree.hasTag(JCTree.Tag.MODULEDEF)) {
1677                 if (!(sourceOutput)) {
1678                     if (shouldStop(CompileState.LOWER))
1679                         return;
1680                     List<JCTree> def = lower.translateTopLevelClass(env, env.tree, localMake);
1681                     if (def.head != null) {
1682                         Assert.check(def.tail.isEmpty());
1683                         results.add(new Pair<>(env, (JCClassDecl)def.head));
1684                     }
1685                 }
1686                 return;
1687             }
1688 
1689             if (shouldStop(CompileState.TRANSTYPES))
1690                 return;
1691 
1692             if (Feature.REFLECT_METHODS.allowedInSource(source)) {
1693                 Optional<CodeReflectionTransformer> reflectMethods = reflectMethods();
1694                 if (reflectMethods.isPresent()) {
1695                     env.tree = reflectMethods.get().translateTopLevelClass(context, env.tree, localMake);
1696                 }
1697             }
1698 
1699             env.tree = transTypes.translateTopLevelClass(env.tree, localMake);
1700             compileStates.put(env, CompileState.TRANSTYPES);
1701 
1702             if (shouldStop(CompileState.TRANSPATTERNS))
1703                 return;
1704 
1705             if (scanner.hasPatterns) {
1706                 env.tree = TransPatterns.instance(context).translateTopLevelClass(env, env.tree, localMake);
1707             }
1708 
1709             compileStates.put(env, CompileState.TRANSPATTERNS);
1710 
1711             if (shouldStop(CompileState.LOWER))
1712                 return;
1713 
1714             if (sourceOutput) {
1715                 //emit standard Java source file, only for compilation
1716                 //units enumerated explicitly on the command line
1717                 JCClassDecl cdef = (JCClassDecl)env.tree;
1718                 if (untranslated instanceof JCClassDecl classDecl &&
1719                     rootClasses.contains(classDecl)) {
1720                     results.add(new Pair<>(env, cdef));
1721                 }
1722                 return;
1723             }
1724 
1725             //translate out inner classes
1726             List<JCTree> cdefs = lower.translateTopLevelClass(env, env.tree, localMake);
1727             compileStates.put(env, CompileState.LOWER);
1728 
1729             if (shouldStop(CompileState.LOWER))
1730                 return;
1731 
1732             if (scanner.hasLambdas) {
1733                 if (shouldStop(CompileState.UNLAMBDA))
1734                     return;
1735 
1736                 for (JCTree def : cdefs) {
1737                     LambdaToMethod.instance(context).translateTopLevelClass(env, def, localMake);
1738                 }
1739                 compileStates.put(env, CompileState.UNLAMBDA);
1740             }
1741 
1742             //generate code for each class
1743             for (List<JCTree> l = cdefs; l.nonEmpty(); l = l.tail) {
1744                 JCClassDecl cdef = (JCClassDecl)l.head;
1745                 results.add(new Pair<>(env, cdef));
1746             }
1747         }
1748         finally {
1749             log.useSource(prev);
1750         }
1751 
1752     }
1753 
1754     Optional<CodeReflectionTransformer> reflectMethods() {
1755         return CodeReflectionSupport.CODE_LAYER != null ?
1756                 ServiceLoader.load(CodeReflectionSupport.CODE_LAYER, CodeReflectionTransformer.class).findFirst() :
1757                 Optional.empty();
1758     }
1759 
1760     public static class CodeReflectionSupport {
1761         public static final ModuleLayer CODE_LAYER;
1762 
1763         static {
1764             if (ModuleLayer.boot().findModule("jdk.incubator.code").isPresent()) {
1765                 // we are in an exploded build, so just use the boot layer
1766                 CODE_LAYER = ModuleLayer.boot();
1767             } else if (java.lang.module.ModuleFinder.ofSystem().find("jdk.incubator.code").isPresent()) {
1768                 // the code module is installed, but not in the boot layer, create a new layer which contains it
1769                 ModuleLayer parent = ModuleLayer.boot();
1770                 Configuration cf = parent.configuration()
1771                         .resolve(java.lang.module.ModuleFinder.of(), java.lang.module.ModuleFinder.ofSystem(), Set.of("jdk.incubator.code"));
1772                 ClassLoader scl = ClassLoader.getSystemClassLoader();
1773                 CODE_LAYER = parent.defineModulesWithOneLoader(cf, scl);
1774                 Module codeReflectionModule = CODE_LAYER.findModule("jdk.incubator.code").get();
1775                 Module jdkCompilerModule = JavaCompiler.class.getModule();
1776                 // We need to add exports all jdk.compiler packages so that the plugin can use them
1777                 for (String packageName : jdkCompilerModule.getPackages()) {
1778                     jdkCompilerModule.addExports(packageName, codeReflectionModule);
1779                 }
1780                 // We also need to add exports all java.base packages so that the plugin can use them
1781                 // But we need to do so by calling a method in java.base reflectively
1782                 try {
1783                     Class<?> codeModuleLayerInit = Class.forName("jdk.internal.access.code.CodeModuleLayerInit");
1784                     Method initLayerMethod = codeModuleLayerInit.getDeclaredMethod("initCodeModuleLayer", ModuleLayer.class);
1785                     initLayerMethod.invoke(null, CODE_LAYER);
1786                 } catch (ReflectiveOperationException ex) {
1787                     throw new AssertionError(ex);
1788                 }
1789             } else {
1790                 // if we run in bootstrap mode, there might be no jdk.incubator.code
1791                 CODE_LAYER = null;
1792             }
1793         }
1794     }
1795 
1796     /** Generates the source or class file for a list of classes.
1797      * The decision to generate a source file or a class file is
1798      * based upon the compiler's options.
1799      * Generation stops if an error occurs while writing files.
1800      */
1801     public void generate(Queue<Pair<Env<AttrContext>, JCClassDecl>> queue) {
1802         generate(queue, null);
1803     }
1804 
1805     public void generate(Queue<Pair<Env<AttrContext>, JCClassDecl>> queue, Queue<JavaFileObject> results) {
1806         if (shouldStop(CompileState.GENERATE))
1807             return;
1808 
1809         for (Pair<Env<AttrContext>, JCClassDecl> x: queue) {
1810             Env<AttrContext> env = x.fst;
1811             JCClassDecl cdef = x.snd;
1812 
1813             if (verboseCompilePolicy) {
1814                 printNote("[generate " + (sourceOutput ? " source" : "code") + " " + cdef.sym + "]");
1815             }
1816 
1817             if (!taskListener.isEmpty()) {
1818                 TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym);
1819                 taskListener.started(e);
1820             }
1821 
1822             JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ?
1823                                       env.enclClass.sym.sourcefile :
1824                                       env.toplevel.sourcefile);
1825             try {
1826                 JavaFileObject file;
1827                 if (sourceOutput) {
1828                     file = printSource(env, cdef);
1829                 } else {
1830                     if (fileManager.hasLocation(StandardLocation.NATIVE_HEADER_OUTPUT)
1831                             && jniWriter.needsHeader(cdef.sym)) {
1832                         jniWriter.write(cdef.sym);
1833                     }
1834                     file = genCode(env, cdef);
1835                 }
1836                 if (results != null && file != null)
1837                     results.add(file);
1838             } catch (IOException
1839                     | UncheckedIOException
1840                     | FileSystemNotFoundException
1841                     | InvalidPathException
1842                     | ReadOnlyFileSystemException ex) {
1843                 log.error(cdef.pos(),
1844                           Errors.ClassCantWrite(cdef.sym, ex.getMessage()));
1845                 return;
1846             } finally {
1847                 log.useSource(prev);
1848             }
1849 
1850             if (!taskListener.isEmpty()) {
1851                 TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym);
1852                 taskListener.finished(e);
1853             }
1854         }
1855     }
1856 
1857         // where
1858         Map<JCCompilationUnit, Queue<Env<AttrContext>>> groupByFile(Queue<Env<AttrContext>> envs) {
1859             // use a LinkedHashMap to preserve the order of the original list as much as possible
1860             Map<JCCompilationUnit, Queue<Env<AttrContext>>> map = new LinkedHashMap<>();
1861             for (Env<AttrContext> env: envs) {
1862                 Queue<Env<AttrContext>> sublist = map.get(env.toplevel);
1863                 if (sublist == null) {
1864                     sublist = new ListBuffer<>();
1865                     map.put(env.toplevel, sublist);
1866                 }
1867                 sublist.add(env);
1868             }
1869             return map;
1870         }
1871 
1872         JCClassDecl removeMethodBodies(JCClassDecl cdef) {
1873             final boolean isInterface = (cdef.mods.flags & Flags.INTERFACE) != 0;
1874             class MethodBodyRemover extends TreeTranslator {
1875                 @Override
1876                 public void visitMethodDef(JCMethodDecl tree) {
1877                     tree.mods.flags &= ~Flags.SYNCHRONIZED;
1878                     for (JCVariableDecl vd : tree.params)
1879                         vd.mods.flags &= ~Flags.FINAL;
1880                     tree.body = null;
1881                     super.visitMethodDef(tree);
1882                 }
1883                 @Override
1884                 public void visitVarDef(JCVariableDecl tree) {
1885                     if (tree.init != null && tree.init.type.constValue() == null)
1886                         tree.init = null;
1887                     super.visitVarDef(tree);
1888                 }
1889                 @Override
1890                 public void visitClassDef(JCClassDecl tree) {
1891                     ListBuffer<JCTree> newdefs = new ListBuffer<>();
1892                     for (List<JCTree> it = tree.defs; it.tail != null; it = it.tail) {
1893                         JCTree t = it.head;
1894                         switch (t.getTag()) {
1895                         case CLASSDEF:
1896                             if (isInterface ||
1897                                 (((JCClassDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1898                                 (((JCClassDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCClassDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1899                                 newdefs.append(t);
1900                             break;
1901                         case METHODDEF:
1902                             if (isInterface ||
1903                                 (((JCMethodDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1904                                 ((JCMethodDecl) t).sym.name == names.init ||
1905                                 (((JCMethodDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCMethodDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1906                                 newdefs.append(t);
1907                             break;
1908                         case VARDEF:
1909                             if (isInterface || (((JCVariableDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1910                                 (((JCVariableDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCVariableDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1911                                 newdefs.append(t);
1912                             break;
1913                         default:
1914                             break;
1915                         }
1916                     }
1917                     tree.defs = newdefs.toList();
1918                     super.visitClassDef(tree);
1919                 }
1920             }
1921             MethodBodyRemover r = new MethodBodyRemover();
1922             return r.translate(cdef);
1923         }
1924 
1925     public void reportDeferredDiagnostics() {
1926         if (errorCount() == 0
1927                 && annotationProcessingOccurred
1928                 && implicitSourceFilesRead
1929                 && implicitSourcePolicy == ImplicitSourcePolicy.UNSET) {
1930             if (explicitAnnotationProcessingRequested())
1931                 log.warning(Warnings.ProcUseImplicit);
1932             else
1933                 log.warning(Warnings.ProcUseProcOrImplicit);
1934         }
1935         log.reportOutstandingWarnings();
1936         log.reportOutstandingNotes();
1937         if (log.compressedOutput) {
1938             log.note(Notes.CompressedDiags);
1939         }
1940     }
1941 
1942     public void enterDone() {
1943         enterDone = true;
1944         annotate.enterDone();
1945     }
1946 
1947     public boolean isEnterDone() {
1948         return enterDone;
1949     }
1950 
1951     public boolean hasCodeReflectionModule() {
1952         return hasCodeReflectionModule;
1953     }
1954 
1955     private Name readModuleName(JavaFileObject fo) {
1956         return parseAndGetName(fo, t -> {
1957             JCModuleDecl md = t.getModuleDecl();
1958 
1959             return md != null ? TreeInfo.fullName(md.getName()) : null;
1960         });
1961     }
1962 
1963     private Name findPackageInFile(JavaFileObject fo) {
1964         return parseAndGetName(fo, t -> t.getPackage() != null ?
1965                                         TreeInfo.fullName(t.getPackage().getPackageName()) : null);
1966     }
1967 
1968     private Name parseAndGetName(JavaFileObject fo,
1969                                  Function<JCTree.JCCompilationUnit, Name> tree2Name) {
1970         DiagnosticHandler dh = log.new DiscardDiagnosticHandler();
1971         JavaFileObject prevSource = log.useSource(fo);
1972         try {
1973             JCTree.JCCompilationUnit t = parse(fo, fo.getCharContent(false), true);
1974             return tree2Name.apply(t);
1975         } catch (IOException e) {
1976             return null;
1977         } finally {
1978             log.popDiagnosticHandler(dh);
1979             log.useSource(prevSource);
1980         }
1981     }
1982 
1983     public void reportDeferredDiagnosticAndClearHandler() {
1984         if (deferredDiagnosticHandler != null) {
1985             ToIntFunction<JCDiagnostic> diagValue =
1986                     d -> d.isFlagSet(RECOVERABLE) ? 1 : 0;
1987             Comparator<JCDiagnostic> compareDiags =
1988                     (d1, d2) -> diagValue.applyAsInt(d1) - diagValue.applyAsInt(d2);
1989             deferredDiagnosticHandler.reportDeferredDiagnostics(compareDiags);
1990             log.popDiagnosticHandler(deferredDiagnosticHandler);
1991             deferredDiagnosticHandler = null;
1992         }
1993     }
1994 
1995     /** Close the compiler, flushing the logs
1996      */
1997     public void close() {
1998         rootClasses = null;
1999         finder = null;
2000         reader = null;
2001         make = null;
2002         writer = null;
2003         enter = null;
2004         if (todo != null)
2005             todo.clear();
2006         todo = null;
2007         parserFactory = null;
2008         syms = null;
2009         source = null;
2010         attr = null;
2011         chk = null;
2012         gen = null;
2013         lintMapper = null;
2014         flow = null;
2015         transTypes = null;
2016         lower = null;
2017         annotate = null;
2018         types = null;
2019 
2020         log.flush();
2021         try {
2022             fileManager.flush();
2023         } catch (IOException e) {
2024             throw new Abort(e);
2025         } finally {
2026             if (names != null)
2027                 names.dispose();
2028             names = null;
2029 
2030             FatalError fatalError = null;
2031             for (Closeable c: closeables) {
2032                 try {
2033                     c.close();
2034                 } catch (IOException e) {
2035                     if (fatalError == null) {
2036                         JCDiagnostic msg = diagFactory.fragment(Fragments.FatalErrCantClose);
2037                         fatalError = new FatalError(msg, e);
2038                     } else {
2039                         fatalError.addSuppressed(e);
2040                     }
2041                 }
2042             }
2043             if (fatalError != null) {
2044                 throw fatalError;
2045             }
2046             closeables = List.nil();
2047         }
2048     }
2049 
2050     protected void printNote(String lines) {
2051         log.printRawLines(Log.WriterKind.NOTICE, lines);
2052     }
2053 
2054     /** Print numbers of errors and warnings.
2055      */
2056     public void printCount(String kind, int count) {
2057         if (count != 0) {
2058             String key;
2059             if (count == 1)
2060                 key = "count." + kind;
2061             else
2062                 key = "count." + kind + ".plural";
2063             log.printLines(WriterKind.ERROR, key, String.valueOf(count));
2064             log.flush(Log.WriterKind.ERROR);
2065         }
2066     }
2067 
2068     private void printSuppressedCount(int shown, int suppressed, String diagKey) {
2069         if (suppressed > 0) {
2070             int total = shown + suppressed;
2071             log.printLines(WriterKind.ERROR, diagKey,
2072                     String.valueOf(shown), String.valueOf(total));
2073             log.flush(Log.WriterKind.ERROR);
2074         }
2075     }
2076 
2077     private static long now() {
2078         return System.currentTimeMillis();
2079     }
2080 
2081     private static long elapsed(long then) {
2082         return now() - then;
2083     }
2084 
2085     public void newRound() {
2086         inputFiles.clear();
2087         todo.clear();
2088     }
2089 
2090     public interface InitialFileParserIntf {
2091         public List<JCCompilationUnit> parse(Iterable<JavaFileObject> files);
2092     }
2093 
2094     public static class InitialFileParser implements InitialFileParserIntf {
2095 
2096         public static final Key<InitialFileParserIntf> initialParserKey = new Key<>();
2097 
2098         public static InitialFileParserIntf instance(Context context) {
2099             InitialFileParserIntf instance = context.get(initialParserKey);
2100             if (instance == null)
2101                 instance = new InitialFileParser(context);
2102             return instance;
2103         }
2104 
2105         private final JavaCompiler compiler;
2106 
2107         private InitialFileParser(Context context) {
2108             context.put(initialParserKey, this);
2109             this.compiler = JavaCompiler.instance(context);
2110         }
2111 
2112         @Override
2113         public List<JCCompilationUnit> parse(Iterable<JavaFileObject> fileObjects) {
2114            return compiler.parseFiles(fileObjects, false);
2115         }
2116     }
2117 }