EMMA Coverage Report (generated Thu Dec 06 15:52:10 GMT 2007)
[all classes][com.sun.tools.javac.main]

COVERAGE SUMMARY FOR SOURCE FILE [JavaCompiler.java]

nameclass, %method, %block, %line, %
JavaCompiler.java83%  (5/6)62%  (43/69)39%  (1310/3326)46%  (269.2/583)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JavaCompiler$1MethodBodyRemover0%   (0/1)0%   (0/4)0%   (0/201)0%   (0/24)
JavaCompiler$1MethodBodyRemover (JavaCompiler, boolean): void 0%   (0/1)0%   (0/9)0%   (0/1)
visitClassDef (JCTree$JCClassDecl): void 0%   (0/1)0%   (0/144)0%   (0/13)
visitMethodDef (JCTree$JCMethodDecl): void 0%   (0/1)0%   (0/33)0%   (0/6)
visitVarDef (JCTree$JCVariableDecl): void 0%   (0/1)0%   (0/15)0%   (0/4)
     
class JavaCompiler100% (1/1)63%  (33/52)39%  (1123/2863)48%  (246.8/519)
attribute (ListBuffer): List 0%   (0/1)0%   (0/17)0%   (0/4)
compile (List): void 0%   (0/1)0%   (0/6)0%   (0/2)
complete (Symbol$ClassSymbol): void 0%   (0/1)0%   (0/161)0%   (0/26)
elapsed (long): long 0%   (0/1)0%   (0/4)0%   (0/1)
enableLogging (): void 0%   (0/1)0%   (0/30)0%   (0/5)
explicitAnnotationProcessingRequested (): boolean 0%   (0/1)0%   (0/27)0%   (0/2)
flow (List): List 0%   (0/1)0%   (0/21)0%   (0/4)
fullVersion (): String 0%   (0/1)0%   (0/3)0%   (0/1)
groupByFile (List): Map 0%   (0/1)0%   (0/70)0%   (0/13)
initRound (JavaCompiler): void 0%   (0/1)0%   (0/12)0%   (0/4)
parse (String): JCTree$JCCompilationUnit 0%   (0/1)0%   (0/14)0%   (0/2)
parseErrors (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
printSource (Env, JCTree$JCClassDecl): JavaFileObject 0%   (0/1)0%   (0/62)0%   (0/11)
printVerbose (String, Object): void 0%   (0/1)0%   (0/23)0%   (0/2)
processAnnotations (List): JavaCompiler 0%   (0/1)0%   (0/5)0%   (0/1)
removeMethodBodies (JCTree$JCClassDecl): JCTree$JCClassDecl 0%   (0/1)0%   (0/23)0%   (0/3)
resolveIdent (String): Symbol 0%   (0/1)0%   (0/100)0%   (0/12)
version (): String 0%   (0/1)0%   (0/3)0%   (0/1)
version (String): String 0%   (0/1)0%   (0/32)0%   (0/8)
processAnnotations (List, List): JavaCompiler 100% (1/1)11%  (25/218)16%  (8/50)
enterTrees (List): List 100% (1/1)19%  (18/97)24%  (5/21)
reportDeferredDiagnostics (): void 100% (1/1)23%  (7/30)38%  (2.3/6)
genCode (Env, JCTree$JCClassDecl): JavaFileObject 100% (1/1)24%  (12/51)20%  (2/10)
readSource (JavaFileObject): CharSequence 100% (1/1)33%  (9/27)40%  (2/5)
flow (Env, ListBuffer): void 100% (1/1)35%  (66/190)64%  (11.6/18)
desugar (Env, ListBuffer): void 100% (1/1)35%  (107/304)51%  (20.4/40)
compile2 (): void 100% (1/1)37%  (44/118)40%  (10/25)
generate (List, ListBuffer): void 100% (1/1)41%  (71/174)56%  (13.4/24)
attribute (Env): Env 100% (1/1)44%  (40/90)63%  (7.6/12)
desugarLater (Env): boolean 100% (1/1)46%  (28/61)55%  (6/11)
initProcessAnnotations (Iterable): void 100% (1/1)48%  (31/65)50%  (8/16)
parse (JavaFileObject): JCTree$JCCompilationUnit 100% (1/1)63%  (24/38)75%  (4.5/6)
compile (List, List, Iterable): void 100% (1/1)68%  (39/57)65%  (10.3/16)
parse (JavaFileObject, CharSequence): JCTree$JCCompilationUnit 100% (1/1)70%  (71/101)73%  (16/22)
errorCount (): int 100% (1/1)73%  (11/15)67%  (2/3)
warningCount (): int 100% (1/1)73%  (11/15)67%  (2/3)
close (boolean): void 100% (1/1)79%  (76/96)89%  (24.8/28)
JavaCompiler (Context): void 100% (1/1)80%  (249/311)87%  (52.2/60)
keepComments (): boolean 100% (1/1)85%  (11/13)84%  (0.8/1)
parseFiles (List): List 100% (1/1)93%  (25/27)83%  (5/6)
<static initializer> 100% (1/1)93%  (13/14)97%  (2.9/3)
access$000 (): JavaCompiler$CompilePolicy 100% (1/1)100% (2/2)100% (1/1)
close (): void 100% (1/1)100% (4/4)100% (2/2)
desugar (List): List 100% (1/1)100% (21/21)100% (4/4)
flow (Env): List 100% (1/1)100% (10/10)100% (3/3)
generate (List): void 100% (1/1)100% (5/5)100% (2/2)
getScannerFactory (): Scanner$Factory 100% (1/1)100% (4/4)100% (1/1)
instance (Context): JavaCompiler 100% (1/1)100% (14/14)100% (4/4)
now (): long 100% (1/1)100% (2/2)100% (1/1)
printCount (String, int): void 100% (1/1)100% (58/58)100% (7/7)
stopIfError (List): List 100% (1/1)100% (7/7)100% (3/3)
stopIfError (ListBuffer): List 100% (1/1)100% (8/8)100% (3/3)
     
class JavaCompiler$CompilePolicy100% (1/1)80%  (4/5)64%  (67/104)42%  (7.9/19)
valueOf (String): JavaCompiler$CompilePolicy 0%   (0/1)0%   (0/5)0%   (0/1)
decode (String): JavaCompiler$CompilePolicy 100% (1/1)11%  (4/36)15%  (2/13)
<static initializer> 100% (1/1)100% (54/54)100% (6/6)
JavaCompiler$CompilePolicy (String, int): void 100% (1/1)100% (5/5)100% (1/1)
values (): JavaCompiler$CompilePolicy [] 100% (1/1)100% (4/4)100% (1/1)
     
class JavaCompiler$ImplicitSourcePolicy100% (1/1)60%  (3/5)65%  (43/66)53%  (5.8/11)
valueOf (String): JavaCompiler$ImplicitSourcePolicy 0%   (0/1)0%   (0/5)0%   (0/1)
values (): JavaCompiler$ImplicitSourcePolicy [] 0%   (0/1)0%   (0/4)0%   (0/1)
decode (String): JavaCompiler$ImplicitSourcePolicy 100% (1/1)22%  (4/18)29%  (2/7)
<static initializer> 100% (1/1)100% (34/34)100% (4/4)
JavaCompiler$ImplicitSourcePolicy (String, int): void 100% (1/1)100% (5/5)100% (1/1)
     
class JavaCompiler$1ScanNested100% (1/1)100% (2/2)81%  (42/52)88%  (8.8/10)
visitClassDef (JCTree$JCClassDecl): void 100% (1/1)74%  (28/38)84%  (6.8/8)
JavaCompiler$1ScanNested (JavaCompiler, Env): void 100% (1/1)100% (14/14)100% (2/2)
     
class JavaCompiler$1100% (1/1)100% (1/1)88%  (35/40)87%  (0.9/1)
<static initializer> 100% (1/1)88%  (35/40)87%  (0.9/1)

1/*
2 * Copyright 1999-2006 Sun Microsystems, Inc.  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.  Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 
26package com.sun.tools.javac.main;
27 
28import java.io.*;
29import java.util.HashSet;
30import java.util.LinkedHashMap;
31import java.util.Map;
32import java.util.MissingResourceException;
33import java.util.ResourceBundle;
34import java.util.Set;
35import java.util.logging.Handler;
36import java.util.logging.Level;
37import java.util.logging.Logger;
38 
39import javax.tools.JavaFileManager;
40import javax.tools.JavaFileObject;
41import javax.tools.DiagnosticListener;
42 
43import com.sun.source.util.TaskEvent;
44import com.sun.source.util.TaskListener;
45 
46import com.sun.tools.javac.util.*;
47import com.sun.tools.javac.code.*;
48import com.sun.tools.javac.tree.*;
49import com.sun.tools.javac.parser.*;
50import com.sun.tools.javac.comp.*;
51import com.sun.tools.javac.jvm.*;
52 
53import com.sun.tools.javac.code.Symbol.*;
54import com.sun.tools.javac.tree.JCTree.*;
55 
56import com.sun.tools.javac.processing.*;
57import javax.annotation.processing.Processor;
58 
59import static javax.tools.StandardLocation.CLASS_OUTPUT;
60import static com.sun.tools.javac.util.ListBuffer.lb;
61 
62// TEMP, until we have a more efficient way to save doc comment info
63import com.sun.tools.javac.parser.DocCommentScanner;
64 
65import javax.lang.model.SourceVersion;
66 
67/** This class could be the main entry point for GJC when GJC is used as a
68 *  component in a larger software system. It provides operations to
69 *  construct a new compiler, and to run a new compiler on a set of source
70 *  files.
71 *
72 *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
73 *  you write code that depends on this, you do so at your own risk.
74 *  This code and its internal interfaces are subject to change or
75 *  deletion without notice.</b>
76 */
77public class JavaCompiler implements ClassReader.SourceCompleter {
78    /** The context key for the compiler. */
79    protected static final Context.Key<JavaCompiler> compilerKey =
80        new Context.Key<JavaCompiler>();
81 
82    /** Get the JavaCompiler instance for this context. */
83    public static JavaCompiler instance(Context context) {
84        JavaCompiler instance = context.get(compilerKey);
85        if (instance == null)
86            instance = new JavaCompiler(context);
87        return instance;
88    }
89 
90    /** The current version number as a string.
91     */
92    public static String version() {
93        return version("release");  // mm.nn.oo[-milestone]
94    }
95 
96    /** The current full version number as a string.
97     */
98    public static String fullVersion() {
99        return version("full"); // mm.mm.oo[-milestone]-build
100    }
101 
102    private static final String versionRBName = "com.sun.tools.javac.resources.version";
103    private static ResourceBundle versionRB;
104 
105    private static String version(String key) {
106        if (versionRB == null) {
107            try {
108                versionRB = ResourceBundle.getBundle(versionRBName);
109            } catch (MissingResourceException e) {
110                return Log.getLocalizedString("version.resource.missing", System.getProperty("java.version"));
111            }
112        }
113        try {
114            return versionRB.getString(key);
115        }
116        catch (MissingResourceException e) {
117            return Log.getLocalizedString("version.unknown", System.getProperty("java.version"));
118        }
119    }
120 
121    private static enum CompilePolicy {
122        /*
123         * Just attribute the parse trees
124         */
125        ATTR_ONLY,
126 
127        /*
128         * Just attribute and do flow analysis on the parse trees.
129         * This should catch most user errors.
130         */
131        CHECK_ONLY,
132 
133        /*
134         * Attribute everything, then do flow analysis for everything,
135         * then desugar everything, and only then generate output.
136         * Means nothing is generated if there are any errors in any classes.
137         */
138        SIMPLE,
139 
140        /*
141         * After attributing everything and doing flow analysis,
142         * group the work by compilation unit.
143         * Then, process the work for each compilation unit together.
144         * Means nothing is generated for a compilation unit if the are any errors
145         * in the compilation unit  (or in any preceding compilation unit.)
146         */
147        BY_FILE,
148 
149        /*
150         * Completely process each entry on the todo list in turn.
151         * -- this is the same for 1.5.
152         * Means output might be generated for some classes in a compilation unit
153         * and not others.
154         */
155        BY_TODO;
156 
157        static CompilePolicy decode(String option) {
158            if (option == null)
159                return DEFAULT_COMPILE_POLICY;
160            else if (option.equals("attr"))
161                return ATTR_ONLY;
162            else if (option.equals("check"))
163                return CHECK_ONLY;
164            else if (option.equals("simple"))
165                return SIMPLE;
166            else if (option.equals("byfile"))
167                return BY_FILE;
168            else if (option.equals("bytodo"))
169                return BY_TODO;
170            else
171                return DEFAULT_COMPILE_POLICY;
172        }
173    }
174 
175    private static CompilePolicy DEFAULT_COMPILE_POLICY = CompilePolicy.BY_TODO;
176 
177    private static enum ImplicitSourcePolicy {
178        /** Don't generate or process implicitly read source files. */
179        NONE,
180        /** Generate classes for implicitly read source files. */
181        CLASS,
182        /** Like CLASS, but generate warnings if annotation processing occurs */
183        UNSET;
184 
185        static ImplicitSourcePolicy decode(String option) {
186            if (option == null)
187                return UNSET;
188            else if (option.equals("none"))
189                return NONE;
190            else if (option.equals("class"))
191                return CLASS;
192            else
193                return UNSET;
194        }
195    }
196 
197    /** The log to be used for error reporting.
198     */
199    public Log log;
200 
201    /** The tree factory module.
202     */
203    protected TreeMaker make;
204 
205    /** The class reader.
206     */
207    protected ClassReader reader;
208 
209    /** The class writer.
210     */
211    protected ClassWriter writer;
212 
213    /** The module for the symbol table entry phases.
214     */
215    protected Enter enter;
216 
217    /** The symbol table.
218     */
219    protected Symtab syms;
220 
221    /** The language version.
222     */
223    protected Source source;
224 
225    /** The module for code generation.
226     */
227    protected Gen gen;
228 
229    /** The name table.
230     */
231    protected Name.Table names;
232 
233    /** The attributor.
234     */
235    protected Attr attr;
236 
237    /** The attributor.
238     */
239    protected Check chk;
240 
241    /** The flow analyzer.
242     */
243    protected Flow flow;
244 
245    /** The type eraser.
246     */
247    TransTypes transTypes;
248 
249    /** The syntactic sugar desweetener.
250     */
251    Lower lower;
252 
253    /** The annotation annotator.
254     */
255    protected Annotate annotate;
256 
257    /** Force a completion failure on this name
258     */
259    protected final Name completionFailureName;
260 
261    /** Type utilities.
262     */
263    protected Types types;
264 
265    /** Access to file objects.
266     */
267    protected JavaFileManager fileManager;
268 
269    /** Factory for parsers.
270     */
271    protected Parser.Factory parserFactory;
272 
273    /** Optional listener for progress events
274     */
275    protected TaskListener taskListener;
276 
277    /**
278     * Annotation processing may require and provide a new instance
279     * of the compiler to be used for the analyze and generate phases.
280     */
281    protected JavaCompiler delegateCompiler;
282 
283    /**
284     * Flag set if any annotation processing occurred.
285     **/
286    protected boolean annotationProcessingOccurred;
287 
288    /**
289     * Flag set if any implicit source files read.
290     **/
291    protected boolean implicitSourceFilesRead;
292 
293    protected Context context;
294 
295    /** Construct a new compiler using a shared context.
296     */
297    public JavaCompiler(final Context context) {
298        this.context = context;
299        context.put(compilerKey, this);
300 
301        // if fileManager not already set, register the JavacFileManager to be used
302        if (context.get(JavaFileManager.class) == null)
303            JavacFileManager.preRegister(context);
304 
305        names = Name.Table.instance(context);
306        log = Log.instance(context);
307        reader = ClassReader.instance(context);
308        make = TreeMaker.instance(context);
309        writer = ClassWriter.instance(context);
310        enter = Enter.instance(context);
311        todo = Todo.instance(context);
312 
313        fileManager = context.get(JavaFileManager.class);
314        parserFactory = Parser.Factory.instance(context);
315 
316        try {
317            // catch completion problems with predefineds
318            syms = Symtab.instance(context);
319        } catch (CompletionFailure ex) {
320            // inlined Check.completionError as it is not initialized yet
321            log.error("cant.access", ex.sym, ex.errmsg);
322            if (ex instanceof ClassReader.BadClassFile)
323                throw new Abort();
324        }
325        source = Source.instance(context);
326        attr = Attr.instance(context);
327        chk = Check.instance(context);
328        gen = Gen.instance(context);
329        flow = Flow.instance(context);
330        transTypes = TransTypes.instance(context);
331        lower = Lower.instance(context);
332        annotate = Annotate.instance(context);
333        types = Types.instance(context);
334        taskListener = context.get(TaskListener.class);
335 
336        reader.sourceCompleter = this;
337 
338        Options options = Options.instance(context);
339 
340        verbose       = options.get("-verbose")       != null;
341        sourceOutput  = options.get("-printsource")   != null; // used to be -s
342        stubOutput    = options.get("-stubs")         != null;
343        relax         = options.get("-relax")         != null;
344        printFlat     = options.get("-printflat")     != null;
345        attrParseOnly = options.get("-attrparseonly") != null;
346        encoding      = options.get("-encoding");
347        lineDebugInfo = options.get("-g:")            == null ||
348                        options.get("-g:lines")       != null;
349        genEndPos     = options.get("-Xjcov")         != null ||
350                        context.get(DiagnosticListener.class) != null;
351        devVerbose    = options.get("dev") != null;
352        processPcks   = options.get("process.packages") != null;
353 
354        verboseCompilePolicy = options.get("verboseCompilePolicy") != null;
355 
356        if (attrParseOnly)
357            compilePolicy = CompilePolicy.ATTR_ONLY;
358        else
359            compilePolicy = CompilePolicy.decode(options.get("compilePolicy"));
360 
361        implicitSourcePolicy = ImplicitSourcePolicy.decode(options.get("-implicit"));
362 
363        completionFailureName =
364            (options.get("failcomplete") != null)
365            ? names.fromString(options.get("failcomplete"))
366            : null;
367    }
368 
369    /* Switches:
370     */
371 
372    /** Verbose output.
373     */
374    public boolean verbose;
375 
376    /** Emit plain Java source files rather than class files.
377     */
378    public boolean sourceOutput;
379 
380    /** Emit stub source files rather than class files.
381     */
382    public boolean stubOutput;
383 
384    /** Generate attributed parse tree only.
385     */
386    public boolean attrParseOnly;
387 
388    /** Switch: relax some constraints for producing the jsr14 prototype.
389     */
390    boolean relax;
391 
392    /** Debug switch: Emit Java sources after inner class flattening.
393     */
394    public boolean printFlat;
395 
396    /** The encoding to be used for source input.
397     */
398    public String encoding;
399 
400    /** Generate code with the LineNumberTable attribute for debugging
401     */
402    public boolean lineDebugInfo;
403 
404    /** Switch: should we store the ending positions?
405     */
406    public boolean genEndPos;
407 
408    /** Switch: should we debug ignored exceptions
409     */
410    protected boolean devVerbose;
411 
412    /** Switch: should we (annotation) process packages as well
413     */
414    protected boolean processPcks;
415 
416    /** Switch: is annotation processing requested explitly via
417     * CompilationTask.setProcessors?
418     */
419    protected boolean explicitAnnotationProcessingRequested = false;
420 
421    /**
422     * The policy for the order in which to perform the compilation
423     */
424    protected CompilePolicy compilePolicy;
425 
426    /**
427     * The policy for what to do with implicitly read source files
428     */
429    protected ImplicitSourcePolicy implicitSourcePolicy;
430 
431    /**
432     * Report activity related to compilePolicy
433     */
434    public boolean verboseCompilePolicy;
435 
436    /** A queue of all as yet unattributed classes.
437     */
438    public Todo todo;
439 
440    private Set<Env<AttrContext>> deferredSugar = new HashSet<Env<AttrContext>>();
441 
442    /** The set of currently compiled inputfiles, needed to ensure
443     *  we don't accidentally overwrite an input file when -s is set.
444     *  initialized by `compile'.
445     */
446    protected Set<JavaFileObject> inputFiles = new HashSet<JavaFileObject>();
447 
448    /** The number of errors reported so far.
449     */
450    public int errorCount() {
451        if (delegateCompiler != null && delegateCompiler != this)
452            return delegateCompiler.errorCount();
453        else
454            return log.nerrors;
455    }
456 
457    protected final <T> List<T> stopIfError(ListBuffer<T> listBuffer) {
458        if (errorCount() == 0)
459            return listBuffer.toList();
460        else
461            return List.nil();
462    }
463 
464    protected final <T> List<T> stopIfError(List<T> list) {
465        if (errorCount() == 0)
466            return list;
467        else
468            return List.nil();
469    }
470 
471    /** The number of warnings reported so far.
472     */
473    public int warningCount() {
474        if (delegateCompiler != null && delegateCompiler != this)
475            return delegateCompiler.warningCount();
476        else
477            return log.nwarnings;
478    }
479 
480    /** Whether or not any parse errors have occurred.
481     */
482    public boolean parseErrors() {
483        return parseErrors;
484    }
485 
486    protected Scanner.Factory getScannerFactory() {
487        return Scanner.Factory.instance(context);
488    }
489 
490    /** Try to open input stream with given name.
491     *  Report an error if this fails.
492     *  @param filename   The file name of the input stream to be opened.
493     */
494    public CharSequence readSource(JavaFileObject filename) {
495        try {
496            inputFiles.add(filename);
497            return filename.getCharContent(false);
498        } catch (IOException e) {
499            log.error("error.reading.file", filename, e.getLocalizedMessage());
500            return null;
501        }
502    }
503 
504    /** Parse contents of input stream.
505     *  @param filename     The name of the file from which input stream comes.
506     *  @param input        The input stream to be parsed.
507     */
508    protected JCCompilationUnit parse(JavaFileObject filename, CharSequence content) {
509        long msec = now();
510        JCCompilationUnit tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(),
511                                      null, List.<JCTree>nil());
512        if (content != null) {
513            if (verbose) {
514                printVerbose("parsing.started", filename);
515            }
516            if (taskListener != null) {
517                TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename);
518                taskListener.started(e);
519            }
520            int initialErrorCount = log.nerrors;
521            Scanner scanner = getScannerFactory().newScanner(content);
522            Parser parser = parserFactory.newParser(scanner, keepComments(), genEndPos);
523            tree = parser.compilationUnit();
524            parseErrors |= (log.nerrors > initialErrorCount);
525            if (lineDebugInfo) {
526                tree.lineMap = scanner.getLineMap();
527            }
528            if (verbose) {
529                printVerbose("parsing.done", Long.toString(elapsed(msec)));
530            }
531        }
532 
533        tree.sourcefile = filename;
534 
535        if (content != null && taskListener != null) {
536            TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, tree);
537            taskListener.finished(e);
538        }
539 
540        return tree;
541    }
542    // where
543        public boolean keepComments = false;
544        protected boolean keepComments() {
545            return keepComments || sourceOutput || stubOutput;
546        }
547 
548 
549    /** Parse contents of file.
550     *  @param filename     The name of the file to be parsed.
551     */
552    @Deprecated
553    public JCTree.JCCompilationUnit parse(String filename) throws IOException {
554        JavacFileManager fm = (JavacFileManager)fileManager;
555        return parse(fm.getJavaFileObjectsFromStrings(List.of(filename)).iterator().next());
556    }
557 
558    /** Parse contents of file.
559     *  @param filename     The name of the file to be parsed.
560     */
561    public JCTree.JCCompilationUnit parse(JavaFileObject filename) {
562        JavaFileObject prev = log.useSource(filename);
563        try {
564            JCTree.JCCompilationUnit t = parse(filename, readSource(filename));
565            if (t.endPositions != null)
566                log.setEndPosTable(filename, t.endPositions);
567            return t;
568        } finally {
569            log.useSource(prev);
570        }
571    }
572 
573    /** Resolve an identifier.
574     * @param name      The identifier to resolve
575     */
576    public Symbol resolveIdent(String name) {
577        if (name.equals(""))
578            return syms.errSymbol;
579        JavaFileObject prev = log.useSource(null);
580        try {
581            JCExpression tree = null;
582            for (String s : name.split("\\.", -1)) {
583                if (!SourceVersion.isIdentifier(s)) // TODO: check for keywords
584                    return syms.errSymbol;
585                tree = (tree == null) ? make.Ident(names.fromString(s))
586                                      : make.Select(tree, names.fromString(s));
587            }
588            JCCompilationUnit toplevel =
589                make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil());
590            toplevel.packge = syms.unnamedPackage;
591            return attr.attribIdent(tree, toplevel);
592        } finally {
593            log.useSource(prev);
594        }
595    }
596 
597    /** Emit plain Java source for a class.
598     *  @param env    The attribution environment of the outermost class
599     *                containing this class.
600     *  @param cdef   The class definition to be printed.
601     */
602    JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
603        JavaFileObject outFile
604            = fileManager.getJavaFileForOutput(CLASS_OUTPUT,
605                                               cdef.sym.flatname.toString(),
606                                               JavaFileObject.Kind.SOURCE,
607                                               null);
608        if (inputFiles.contains(outFile)) {
609            log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile);
610            return null;
611        } else {
612            BufferedWriter out = new BufferedWriter(outFile.openWriter());
613            try {
614                new Pretty(out, true).printUnit(env.toplevel, cdef);
615                if (verbose)
616                    printVerbose("wrote.file", outFile);
617            } finally {
618                out.close();
619            }
620            return outFile;
621        }
622    }
623 
624    /** Generate code and emit a class file for a given class
625     *  @param env    The attribution environment of the outermost class
626     *                containing this class.
627     *  @param cdef   The class definition from which code is generated.
628     */
629    JavaFileObject genCode(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
630        try {
631            if (gen.genClass(env, cdef))
632                return writer.writeClass(cdef.sym);
633        } catch (ClassWriter.PoolOverflow ex) {
634            log.error(cdef.pos(), "limit.pool");
635        } catch (ClassWriter.StringOverflow ex) {
636            log.error(cdef.pos(), "limit.string.overflow",
637                      ex.value.substring(0, 20));
638        } catch (CompletionFailure ex) {
639            chk.completionError(cdef.pos(), ex);
640        }
641        return null;
642    }
643 
644    /** Complete compiling a source file that has been accessed
645     *  by the class file reader.
646     *  @param c          The class the source file of which needs to be compiled.
647     *  @param filename   The name of the source file.
648     *  @param f          An input stream that reads the source file.
649     */
650    public void complete(ClassSymbol c) throws CompletionFailure {
651//      System.err.println("completing " + c);//DEBUG
652        if (completionFailureName == c.fullname) {
653            throw new CompletionFailure(c, "user-selected completion failure by class name");
654        }
655        JCCompilationUnit tree;
656        JavaFileObject filename = c.classfile;
657        JavaFileObject prev = log.useSource(filename);
658 
659        try {
660            tree = parse(filename, filename.getCharContent(false));
661        } catch (IOException e) {
662            log.error("error.reading.file", filename, e);
663            tree = make.TopLevel(List.<JCTree.JCAnnotation>nil(), null, List.<JCTree>nil());
664        } finally {
665            log.useSource(prev);
666        }
667 
668        if (taskListener != null) {
669            TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
670            taskListener.started(e);
671        }
672 
673        enter.complete(List.of(tree), c);
674 
675        if (taskListener != null) {
676            TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
677            taskListener.finished(e);
678        }
679 
680        if (enter.getEnv(c) == null) {
681            boolean isPkgInfo =
682                tree.sourcefile.isNameCompatible("package-info",
683                                                 JavaFileObject.Kind.SOURCE);
684            if (isPkgInfo) {
685                if (enter.getEnv(tree.packge) == null) {
686                    String msg
687                        = log.getLocalizedString("file.does.not.contain.package",
688                                                 c.location());
689                    throw new ClassReader.BadClassFile(c, filename, msg);
690                }
691            } else {
692                throw new
693                    ClassReader.BadClassFile(c, filename, log.
694                                             getLocalizedString("file.doesnt.contain.class",
695                                                                c.fullname));
696            }
697        }
698 
699        implicitSourceFilesRead = true;
700    }
701 
702    /** Track when the JavaCompiler has been used to compile something. */
703    private boolean hasBeenUsed = false;
704    private long start_msec = 0;
705    public long elapsed_msec = 0;
706 
707    /** Track whether any errors occurred while parsing source text. */
708    private boolean parseErrors = false;
709 
710    public void compile(List<JavaFileObject> sourceFileObject)
711        throws Throwable {
712        compile(sourceFileObject, List.<String>nil(), null);
713    }
714 
715    /**
716     * Main method: compile a list of files, return all compiled classes
717     *
718     * @param sourceFileObjects file objects to be compiled
719     * @param classnames class names to process for annotations
720     * @param processors user provided annotation processors to bypass
721     * discovery, {@code null} means that no processors were provided
722     */
723    public void compile(List<JavaFileObject> sourceFileObjects,
724                        List<String> classnames,
725                        Iterable<? extends Processor> processors)
726        throws IOException // TODO: temp, from JavacProcessingEnvironment
727    {
728        if (processors != null && processors.iterator().hasNext())
729            explicitAnnotationProcessingRequested = true;
730        // as a JavaCompiler can only be used once, throw an exception if
731        // it has been used before.
732        if (hasBeenUsed)
733            throw new AssertionError("attempt to reuse JavaCompiler");
734        hasBeenUsed = true;
735 
736        start_msec = now();
737        try {
738            initProcessAnnotations(processors);
739 
740            // These method calls must be chained to avoid memory leaks
741            delegateCompiler = processAnnotations(enterTrees(stopIfError(parseFiles(sourceFileObjects))),
742                                                  classnames);
743 
744            delegateCompiler.compile2();
745            delegateCompiler.close();
746            elapsed_msec = delegateCompiler.elapsed_msec;
747        } catch (Abort ex) {
748            if (devVerbose)
749                ex.printStackTrace();
750        }
751    }
752 
753    /**
754     * The phases following annotation processing: attribution,
755     * desugar, and finally code generation.
756     */
757    private void compile2() {
758        try {
759            switch (compilePolicy) {
760            case ATTR_ONLY:
761                attribute(todo);
762                break;
763 
764            case CHECK_ONLY:
765                flow(attribute(todo));
766                break;
767 
768            case SIMPLE:
769                generate(desugar(flow(attribute(todo))));
770                break;
771 
772            case BY_FILE:
773                for (List<Env<AttrContext>> list : groupByFile(flow(attribute(todo))).values())
774                    generate(desugar(list));
775                break;
776 
777            case BY_TODO:
778                while (todo.nonEmpty())
779                    generate(desugar(flow(attribute(todo.next()))));
780                break;
781 
782            default:
783                assert false: "unknown compile policy";
784            }
785        } catch (Abort ex) {
786            if (devVerbose)
787                ex.printStackTrace();
788        }
789 
790        if (verbose) {
791            elapsed_msec = elapsed(start_msec);;
792            printVerbose("total", Long.toString(elapsed_msec));
793        }
794 
795        reportDeferredDiagnostics();
796 
797        if (!log.hasDiagnosticListener()) {
798            printCount("error", errorCount());
799            printCount("warn", warningCount());
800        }
801    }
802 
803    private List<JCClassDecl> rootClasses;
804 
805    /**
806     * Parses a list of files.
807     */
808   public List<JCCompilationUnit> parseFiles(List<JavaFileObject> fileObjects) throws IOException {
809       if (errorCount() > 0)
810           return List.nil();
811 
812        //parse all files
813        ListBuffer<JCCompilationUnit> trees = lb();
814        for (JavaFileObject fileObject : fileObjects)
815            trees.append(parse(fileObject));
816        return trees.toList();
817    }
818 
819    /**
820     * Enter the symbols found in a list of parse trees.
821     * As a side-effect, this puts elements on the "todo" list.
822     * Also stores a list of all top level classes in rootClasses.
823     */
824    public List<JCCompilationUnit> enterTrees(List<JCCompilationUnit> roots) {
825        //enter symbols for all files
826        if (taskListener != null) {
827            for (JCCompilationUnit unit: roots) {
828                TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
829                taskListener.started(e);
830            }
831        }
832 
833        enter.main(roots);
834 
835        if (taskListener != null) {
836            for (JCCompilationUnit unit: roots) {
837                TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
838                taskListener.finished(e);
839            }
840        }
841 
842        //If generating source, remember the classes declared in
843        //the original compilation units listed on the command line.
844        if (sourceOutput || stubOutput) {
845            ListBuffer<JCClassDecl> cdefs = lb();
846            for (JCCompilationUnit unit : roots) {
847                for (List<JCTree> defs = unit.defs;
848                     defs.nonEmpty();
849                     defs = defs.tail) {
850                    if (defs.head instanceof JCClassDecl)
851                        cdefs.append((JCClassDecl)defs.head);
852                }
853            }
854            rootClasses = cdefs.toList();
855        }
856        return roots;
857    }
858 
859    /**
860     * Set to true to enable skeleton annotation processing code.
861     * Currently, we assume this variable will be replaced more
862     * advanced logic to figure out if annotation processing is
863     * needed.
864     */
865    boolean processAnnotations = false;
866 
867    /**
868     * Object to handle annotation processing.
869     */
870    JavacProcessingEnvironment procEnvImpl = null;
871 
872    /**
873     * Check if we should process annotations.
874     * If so, and if no scanner is yet registered, then set up the DocCommentScanner
875     * to catch doc comments, and set keepComments so the parser records them in
876     * the compilation unit.
877     *
878     * @param processors user provided annotation processors to bypass
879     * discovery, {@code null} means that no processors were provided
880     */
881    public void initProcessAnnotations(Iterable<? extends Processor> processors) {
882        // Process annotations if processing is not disabled and there
883        // is at least one Processor available.
884        Options options = Options.instance(context);
885        if (options.get("-proc:none") != null) {
886            processAnnotations = false;
887        } else if (procEnvImpl == null) {
888            procEnvImpl = new JavacProcessingEnvironment(context, processors);
889            processAnnotations = procEnvImpl.atLeastOneProcessor();
890 
891            if (processAnnotations) {
892                if (context.get(Scanner.Factory.scannerFactoryKey) == null)
893                    DocCommentScanner.Factory.preRegister(context);
894                options.put("save-parameter-names", "save-parameter-names");
895                reader.saveParameterNames = true;
896                keepComments = true;
897                if (taskListener != null)
898                    taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
899 
900 
901            } else { // free resources
902                procEnvImpl.close();
903            }
904        }
905    }
906 
907    // TODO: called by JavacTaskImpl
908    public JavaCompiler processAnnotations(List<JCCompilationUnit> roots) throws IOException {
909        return processAnnotations(roots, List.<String>nil());
910    }
911 
912    /**
913     * Process any anotations found in the specifed compilation units.
914     * @param roots a list of compilation units
915     * @return an instance of the compiler in which to complete the compilation
916     */
917    public JavaCompiler processAnnotations(List<JCCompilationUnit> roots,
918                                           List<String> classnames)
919        throws IOException  { // TODO: see TEMP note in JavacProcessingEnvironment
920        if (errorCount() != 0) {
921            // Errors were encountered.  If todo is empty, then the
922            // encountered errors were parse errors.  Otherwise, the
923            // errors were found during the enter phase which should
924            // be ignored when processing annotations.
925 
926            if (todo.isEmpty())
927                return this;
928        }
929 
930        // ASSERT: processAnnotations and procEnvImpl should have been set up by
931        // by initProcessAnnotations
932 
933        // NOTE: The !classnames.isEmpty() checks should be refactored to Main.
934 
935        if (!processAnnotations) {
936            // If there are no annotation processors present, and
937            // annotation processing is to occur with compilation,
938            // emit a warning.
939            Options options = Options.instance(context);
940            if (options.get("-proc:only") != null) {
941                log.warning("proc.proc-only.requested.no.procs");
942                todo.clear();
943            }
944            // If not processing annotations, classnames must be empty
945            if (!classnames.isEmpty()) {
946                log.error("proc.no.explicit.annotation.processing.requested",
947                          classnames);
948            }
949            return this; // continue regular compilation
950        }
951 
952        try {
953            List<ClassSymbol> classSymbols = List.nil();
954            List<PackageSymbol> pckSymbols = List.nil();
955            if (!classnames.isEmpty()) {
956                 // Check for explicit request for annotation
957                 // processing
958                if (!explicitAnnotationProcessingRequested()) {
959                    log.error("proc.no.explicit.annotation.processing.requested",
960                              classnames);
961                    return this; // TODO: Will this halt compilation?
962                } else {
963                    boolean errors = false;
964                    for (String nameStr : classnames) {
965                        Symbol sym = resolveIdent(nameStr);
966                        if (sym == null || (sym.kind == Kinds.PCK && !processPcks)) {
967                            log.error("proc.cant.find.class", nameStr);
968                            errors = true;
969                            continue;
970                        }
971                        try {
972                            if (sym.kind == Kinds.PCK)
973                                sym.complete();
974                            if (sym.exists()) {
975                                Name name = names.fromString(nameStr);
976                                if (sym.kind == Kinds.PCK)
977                                    pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
978                                else
979                                    classSymbols = classSymbols.prepend((ClassSymbol)sym);
980                                continue;
981                            }
982                            assert sym.kind == Kinds.PCK;
983                            log.warning("proc.package.does.not.exist", nameStr);
984                            pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
985                        } catch (CompletionFailure e) {
986                            log.error("proc.cant.find.class", nameStr);
987                            errors = true;
988                            continue;
989                        }
990                    }
991                    if (errors)
992                        return this;
993                }
994            }
995            JavaCompiler c = procEnvImpl.doProcessing(context, roots, classSymbols, pckSymbols);
996            if (c != this)
997                annotationProcessingOccurred = c.annotationProcessingOccurred = true;
998            return c;
999        } catch (CompletionFailure ex) {
1000            log.error("cant.access", ex.sym, ex.errmsg);
1001            return this;
1002 
1003        }
1004    }
1005 
1006    boolean explicitAnnotationProcessingRequested() {
1007        Options options = Options.instance(context);
1008        return
1009            explicitAnnotationProcessingRequested ||
1010            options.get("-processor") != null ||
1011            options.get("-processorpath") != null ||
1012            options.get("-proc:only") != null ||
1013            options.get("-Xprint") != null;
1014    }
1015 
1016    /**
1017     * Attribute a list of parse trees, such as found on the "todo" list.
1018     * Note that attributing classes may cause additional files to be
1019     * parsed and entered via the SourceCompleter.
1020     * Attribution of the entries in the list does not stop if any errors occur.
1021     * @returns a list of environments for attributd classes.
1022     */
1023    public List<Env<AttrContext>> attribute(ListBuffer<Env<AttrContext>> envs) {
1024        ListBuffer<Env<AttrContext>> results = lb();
1025        while (envs.nonEmpty())
1026            results.append(attribute(envs.next()));
1027        return results.toList();
1028    }
1029 
1030    /**
1031     * Attribute a parse tree.
1032     * @returns the attributed parse tree
1033     */
1034    public Env<AttrContext> attribute(Env<AttrContext> env) {
1035        if (verboseCompilePolicy)
1036            log.printLines(log.noticeWriter, "[attribute " + env.enclClass.sym + "]");
1037        if (verbose)
1038            printVerbose("checking.attribution", env.enclClass.sym);
1039 
1040        if (taskListener != null) {
1041            TaskEvent e = new TaskEvent(TaskEvent.Kind.ANALYZE, env.toplevel, env.enclClass.sym);
1042            taskListener.started(e);
1043        }
1044 
1045        JavaFileObject prev = log.useSource(
1046                                  env.enclClass.sym.sourcefile != null ?
1047                                  env.enclClass.sym.sourcefile :
1048                                  env.toplevel.sourcefile);
1049        try {
1050            attr.attribClass(env.tree.pos(), env.enclClass.sym);
1051        }
1052        finally {
1053            log.useSource(prev);
1054        }
1055 
1056        return env;
1057    }
1058 
1059    /**
1060     * Perform dataflow checks on attributed parse trees.
1061     * These include checks for definite assignment and unreachable statements.
1062     * If any errors occur, an empty list will be returned.
1063     * @returns the list of attributed parse trees
1064     */
1065    public List<Env<AttrContext>> flow(List<Env<AttrContext>> envs) {
1066        ListBuffer<Env<AttrContext>> results = lb();
1067        for (List<Env<AttrContext>> l = envs; l.nonEmpty(); l = l.tail) {
1068            flow(l.head, results);
1069        }
1070        return stopIfError(results);
1071    }
1072 
1073    /**
1074     * Perform dataflow checks on an attributed parse tree.
1075     */
1076    public List<Env<AttrContext>> flow(Env<AttrContext> env) {
1077        ListBuffer<Env<AttrContext>> results = lb();
1078        flow(env, results);
1079        return stopIfError(results);
1080    }
1081 
1082    /**
1083     * Perform dataflow checks on an attributed parse tree.
1084     */
1085    protected void flow(Env<AttrContext> env, ListBuffer<Env<AttrContext>> results) {
1086        try {
1087            if (errorCount() > 0)
1088                return;
1089 
1090            if (relax || deferredSugar.contains(env)) {
1091                results.append(env);
1092                return;
1093            }
1094 
1095            if (verboseCompilePolicy)
1096                log.printLines(log.noticeWriter, "[flow " + env.enclClass.sym + "]");
1097            JavaFileObject prev = log.useSource(
1098                                                env.enclClass.sym.sourcefile != null ?
1099                                                env.enclClass.sym.sourcefile :
1100                                                env.toplevel.sourcefile);
1101            try {
1102                make.at(Position.FIRSTPOS);
1103                TreeMaker localMake = make.forToplevel(env.toplevel);
1104                flow.analyzeTree(env.tree, localMake);
1105 
1106                if (errorCount() > 0)
1107                    return;
1108 
1109                results.append(env);
1110            }
1111            finally {
1112                log.useSource(prev);
1113            }
1114        }
1115        finally {
1116            if (taskListener != null) {
1117                TaskEvent e = new TaskEvent(TaskEvent.Kind.ANALYZE, env.toplevel, env.enclClass.sym);
1118                taskListener.finished(e);
1119            }
1120        }
1121    }
1122 
1123    /**
1124     * Prepare attributed parse trees, in conjunction with their attribution contexts,
1125     * for source or code generation.
1126     * If any errors occur, an empty list will be returned.
1127     * @returns a list containing the classes to be generated
1128     */
1129    public List<Pair<Env<AttrContext>, JCClassDecl>> desugar(List<Env<AttrContext>> envs) {
1130        ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = lb();
1131        for (List<Env<AttrContext>> l = envs; l.nonEmpty(); l = l.tail)
1132            desugar(l.head, results);
1133        return stopIfError(results);
1134    }
1135 
1136    /**
1137     * Prepare attributed parse trees, in conjunction with their attribution contexts,
1138     * for source or code generation. If the file was not listed on the command line,
1139     * the current implicitSourcePolicy is taken into account.
1140     * The preparation stops as soon as an error is found.
1141     */
1142    protected void desugar(Env<AttrContext> env, ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results) {
1143        if (errorCount() > 0)
1144            return;
1145 
1146        if (implicitSourcePolicy == ImplicitSourcePolicy.NONE
1147                && !inputFiles.contains(env.toplevel.sourcefile)) {
1148            return;
1149        }
1150 
1151        if (desugarLater(env)) {
1152            if (verboseCompilePolicy)
1153                log.printLines(log.noticeWriter, "[defer " + env.enclClass.sym + "]");
1154            todo.append(env);
1155            return;
1156        }
1157        deferredSugar.remove(env);
1158 
1159        if (verboseCompilePolicy)
1160            log.printLines(log.noticeWriter, "[desugar " + env.enclClass.sym + "]");
1161 
1162        JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ?
1163                                  env.enclClass.sym.sourcefile :
1164                                  env.toplevel.sourcefile);
1165        try {
1166            //save tree prior to rewriting
1167            JCTree untranslated = env.tree;
1168 
1169            make.at(Position.FIRSTPOS);
1170            TreeMaker localMake = make.forToplevel(env.toplevel);
1171 
1172            if (env.tree instanceof JCCompilationUnit) {
1173                if (!(stubOutput || sourceOutput || printFlat)) {
1174                    List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake);
1175                    if (pdef.head != null) {
1176                        assert pdef.tail.isEmpty();
1177                        results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, (JCClassDecl)pdef.head));
1178                    }
1179                }
1180                return;
1181            }
1182 
1183            if (stubOutput) {
1184                //emit stub Java source file, only for compilation
1185                //units enumerated explicitly on the command line
1186                JCClassDecl cdef = (JCClassDecl)env.tree;
1187                if (untranslated instanceof JCClassDecl &&
1188                    rootClasses.contains((JCClassDecl)untranslated) &&
1189                    ((cdef.mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1190                     cdef.sym.packge().getQualifiedName() == names.java_lang)) {
1191                    results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, removeMethodBodies(cdef)));
1192                }
1193                return;
1194            }
1195 
1196            env.tree = transTypes.translateTopLevelClass(env.tree, localMake);
1197 
1198            if (errorCount() != 0)
1199                return;
1200 
1201            if (sourceOutput) {
1202                //emit standard Java source file, only for compilation
1203                //units enumerated explicitly on the command line
1204                JCClassDecl cdef = (JCClassDecl)env.tree;
1205                if (untranslated instanceof JCClassDecl &&
1206                    rootClasses.contains((JCClassDecl)untranslated)) {
1207                    results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, cdef));
1208                }
1209                return;
1210            }
1211 
1212            //translate out inner classes
1213            List<JCTree> cdefs = lower.translateTopLevelClass(env, env.tree, localMake);
1214 
1215            if (errorCount() != 0)
1216                return;
1217 
1218            //generate code for each class
1219            for (List<JCTree> l = cdefs; l.nonEmpty(); l = l.tail) {
1220                JCClassDecl cdef = (JCClassDecl)l.head;
1221                results.append(new Pair<Env<AttrContext>, JCClassDecl>(env, cdef));
1222            }
1223        }
1224        finally {
1225            log.useSource(prev);
1226        }
1227 
1228    }
1229 
1230    /**
1231     * Determine if a class needs to be desugared later.  As erasure
1232     * (TransTypes) destroys information needed in flow analysis, we
1233     * need to ensure that supertypes are translated before derived
1234     * types are translated.
1235     */
1236    public boolean desugarLater(final Env<AttrContext> env) {
1237        if (compilePolicy == CompilePolicy.BY_FILE)
1238            return false;
1239        if (!devVerbose && deferredSugar.contains(env))
1240            // guarantee that compiler terminates
1241            return false;
1242        class ScanNested extends TreeScanner {
1243            Set<Symbol> externalSupers = new HashSet<Symbol>();
1244            public void visitClassDef(JCClassDecl node) {
1245                Type st = types.supertype(node.sym.type);
1246                if (st.tag == TypeTags.CLASS) {
1247                    ClassSymbol c = st.tsym.outermostClass();
1248                    Env<AttrContext> stEnv = enter.getEnv(c);
1249                    if (stEnv != null && env != stEnv)
1250                        externalSupers.add(st.tsym);
1251                }
1252                super.visitClassDef(node);
1253            }
1254        }
1255        ScanNested scanner = new ScanNested();
1256        scanner.scan(env.tree);
1257        if (scanner.externalSupers.isEmpty())
1258            return false;
1259        if (!deferredSugar.add(env) && devVerbose) {
1260            throw new AssertionError(env.enclClass.sym + " was deferred, " +
1261                                     "second time has these external super types " +
1262                                     scanner.externalSupers);
1263        }
1264        return true;
1265    }
1266 
1267    /** Generates the source or class file for a list of classes.
1268     * The decision to generate a source file or a class file is
1269     * based upon the compiler's options.
1270     * Generation stops if an error occurs while writing files.
1271     */
1272    public void generate(List<Pair<Env<AttrContext>, JCClassDecl>> list) {
1273        generate(list, null);
1274    }
1275 
1276    public void generate(List<Pair<Env<AttrContext>, JCClassDecl>> list, ListBuffer<JavaFileObject> results) {
1277        boolean usePrintSource = (stubOutput || sourceOutput || printFlat);
1278 
1279        for (List<Pair<Env<AttrContext>, JCClassDecl>> l = list; l.nonEmpty(); l = l.tail) {
1280            Pair<Env<AttrContext>, JCClassDecl> x = l.head;
1281            Env<AttrContext> env = x.fst;
1282            JCClassDecl cdef = x.snd;
1283 
1284            if (verboseCompilePolicy) {
1285                log.printLines(log.noticeWriter, "[generate "
1286                               + (usePrintSource ? " source" : "code")
1287                               + " " + env.enclClass.sym + "]");
1288            }
1289 
1290            if (taskListener != null) {
1291                TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym);
1292                taskListener.started(e);
1293            }
1294 
1295            JavaFileObject prev = log.useSource(env.enclClass.sym.sourcefile != null ?
1296                                      env.enclClass.sym.sourcefile :
1297                                      env.toplevel.sourcefile);
1298            try {
1299                JavaFileObject file;
1300                if (usePrintSource)
1301                    file = printSource(env, cdef);
1302                else
1303                    file = genCode(env, cdef);
1304                if (results != null && file != null)
1305                    results.append(file);
1306            } catch (IOException ex) {
1307                log.error(cdef.pos(), "class.cant.write",
1308                          cdef.sym, ex.getMessage());
1309                return;
1310            } finally {
1311                log.useSource(prev);
1312            }
1313 
1314            if (taskListener != null) {
1315                TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym);
1316                taskListener.finished(e);
1317            }
1318        }
1319    }
1320 
1321        // where
1322        Map<JCCompilationUnit, List<Env<AttrContext>>> groupByFile(List<Env<AttrContext>> list) {
1323            // use a LinkedHashMap to preserve the order of the original list as much as possible
1324            Map<JCCompilationUnit, List<Env<AttrContext>>> map = new LinkedHashMap<JCCompilationUnit, List<Env<AttrContext>>>();
1325            Set<JCCompilationUnit> fixupSet = new HashSet<JCTree.JCCompilationUnit>();
1326            for (List<Env<AttrContext>> l = list; l.nonEmpty(); l = l.tail) {
1327                Env<AttrContext> env = l.head;
1328                List<Env<AttrContext>> sublist = map.get(env.toplevel);
1329                if (sublist == null)
1330                    sublist = List.of(env);
1331                else {
1332                    // this builds the list for the file in reverse order, so make a note
1333                    // to reverse the list before returning.
1334                    sublist = sublist.prepend(env);
1335                    fixupSet.add(env.toplevel);
1336                }
1337                map.put(env.toplevel, sublist);
1338            }
1339            // fixup any lists that need reversing back to the correct order
1340            for (JCTree.JCCompilationUnit tree: fixupSet)
1341                map.put(tree, map.get(tree).reverse());
1342            return map;
1343        }
1344 
1345        JCClassDecl removeMethodBodies(JCClassDecl cdef) {
1346            final boolean isInterface = (cdef.mods.flags & Flags.INTERFACE) != 0;
1347            class MethodBodyRemover extends TreeTranslator {
1348                public void visitMethodDef(JCMethodDecl tree) {
1349                    tree.mods.flags &= ~Flags.SYNCHRONIZED;
1350                    for (JCVariableDecl vd : tree.params)
1351                        vd.mods.flags &= ~Flags.FINAL;
1352                    tree.body = null;
1353                    super.visitMethodDef(tree);
1354                }
1355                public void visitVarDef(JCVariableDecl tree) {
1356                    if (tree.init != null && tree.init.type.constValue() == null)
1357                        tree.init = null;
1358                    super.visitVarDef(tree);
1359                }
1360                public void visitClassDef(JCClassDecl tree) {
1361                    ListBuffer<JCTree> newdefs = lb();
1362                    for (List<JCTree> it = tree.defs; it.tail != null; it = it.tail) {
1363                        JCTree t = it.head;
1364                        switch (t.getTag()) {
1365                        case JCTree.CLASSDEF:
1366                            if (isInterface ||
1367                                (((JCClassDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1368                                (((JCClassDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCClassDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1369                                newdefs.append(t);
1370                            break;
1371                        case JCTree.METHODDEF:
1372                            if (isInterface ||
1373                                (((JCMethodDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1374                                ((JCMethodDecl) t).sym.name == names.init ||
1375                                (((JCMethodDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCMethodDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1376                                newdefs.append(t);
1377                            break;
1378                        case JCTree.VARDEF:
1379                            if (isInterface || (((JCVariableDecl) t).mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
1380                                (((JCVariableDecl) t).mods.flags & (Flags.PRIVATE)) == 0 && ((JCVariableDecl) t).sym.packge().getQualifiedName() == names.java_lang)
1381                                newdefs.append(t);
1382                            break;
1383                        default:
1384                            break;
1385                        }
1386                    }
1387                    tree.defs = newdefs.toList();
1388                    super.visitClassDef(tree);
1389                }
1390            }
1391            MethodBodyRemover r = new MethodBodyRemover();
1392            return r.translate(cdef);
1393        }
1394 
1395    public void reportDeferredDiagnostics() {
1396        if (annotationProcessingOccurred
1397                && implicitSourceFilesRead
1398                && implicitSourcePolicy == ImplicitSourcePolicy.UNSET) {
1399            if (explicitAnnotationProcessingRequested())
1400                log.warning("proc.use.implicit");
1401            else
1402                log.warning("proc.use.proc.or.implicit");
1403        }
1404        chk.reportDeferredDiagnostics();
1405    }
1406 
1407    /** Close the compiler, flushing the logs
1408     */
1409    public void close() {
1410        close(true);
1411    }
1412 
1413    private void close(boolean disposeNames) {
1414        rootClasses = null;
1415        reader = null;
1416        make = null;
1417        writer = null;
1418        enter = null;
1419        if (todo != null)
1420            todo.clear();
1421        todo = null;
1422        parserFactory = null;
1423        syms = null;
1424        source = null;
1425        attr = null;
1426        chk = null;
1427        gen = null;
1428        flow = null;
1429        transTypes = null;
1430        lower = null;
1431        annotate = null;
1432        types = null;
1433 
1434        log.flush();
1435        try {
1436            fileManager.flush();
1437        } catch (IOException e) {
1438            throw new Abort(e);
1439        } finally {
1440            if (names != null && disposeNames)
1441                names.dispose();
1442            names = null;
1443        }
1444    }
1445 
1446    /** Output for "-verbose" option.
1447     *  @param key The key to look up the correct internationalized string.
1448     *  @param arg An argument for substitution into the output string.
1449     */
1450    protected void printVerbose(String key, Object arg) {
1451        Log.printLines(log.noticeWriter, log.getLocalizedString("verbose." + key, arg));
1452    }
1453 
1454    /** Print numbers of errors and warnings.
1455     */
1456    protected void printCount(String kind, int count) {
1457        if (count != 0) {
1458            String text;
1459            if (count == 1)
1460                text = log.getLocalizedString("count." + kind, String.valueOf(count));
1461            else
1462                text = log.getLocalizedString("count." + kind + ".plural", String.valueOf(count));
1463            Log.printLines(log.errWriter, text);
1464            log.errWriter.flush();
1465        }
1466    }
1467 
1468    private static long now() {
1469        return System.currentTimeMillis();
1470    }
1471 
1472    private static long elapsed(long then) {
1473        return now() - then;
1474    }
1475 
1476    public void initRound(JavaCompiler prev) {
1477        keepComments = prev.keepComments;
1478        start_msec = prev.start_msec;
1479        hasBeenUsed = true;
1480    }
1481 
1482    public static void enableLogging() {
1483        Logger logger = Logger.getLogger(com.sun.tools.javac.Main.class.getPackage().getName());
1484        logger.setLevel(Level.ALL);
1485        for (Handler h : logger.getParent().getHandlers()) {
1486            h.setLevel(Level.ALL);
1487       }
1488 
1489    }
1490}

[all classes][com.sun.tools.javac.main]
EMMA 2.0.5312 (C) Vladimir Roubtsov