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