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