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