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