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