EMMA Coverage Report (generated Thu Dec 06 15:24:05 GMT 2007)
[all classes][com.sun.tools.javac.api]

COVERAGE SUMMARY FOR SOURCE FILE [JavacTaskImpl.java]

nameclass, %method, %block, %line, %
JavacTaskImpl.java20%  (1/5)18%  (7/39)17%  (178/1052)20%  (44.8/220)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JavacTaskImpl$10%   (0/1)0%   (0/3)0%   (0/33)0%   (0/11)
JavacTaskImpl$1 (JavacTaskImpl, TaskListener): void 0%   (0/1)0%   (0/9)0%   (0/1)
finished (TaskEvent): void 0%   (0/1)0%   (0/12)0%   (0/5)
started (TaskEvent): void 0%   (0/1)0%   (0/12)0%   (0/5)
     
class JavacTaskImpl$20%   (0/1)0%   (0/2)0%   (0/25)0%   (0/3)
JavacTaskImpl$2 (JavacTaskImpl, ListBuffer): void 0%   (0/1)0%   (0/10)0%   (0/1)
process (Env): void 0%   (0/1)0%   (0/15)0%   (0/2)
     
class JavacTaskImpl$30%   (0/1)0%   (0/2)0%   (0/23)0%   (0/3)
JavacTaskImpl$3 (JavacTaskImpl, ListBuffer): void 0%   (0/1)0%   (0/10)0%   (0/1)
process (Env): void 0%   (0/1)0%   (0/13)0%   (0/2)
     
class JavacTaskImpl$Filter0%   (0/1)0%   (0/2)0%   (0/69)0%   (0/15)
JavacTaskImpl$Filter (JavacTaskImpl): void 0%   (0/1)0%   (0/6)0%   (0/1)
run (ListBuffer, Iterable): void 0%   (0/1)0%   (0/63)0%   (0/14)
     
class JavacTaskImpl100% (1/1)23%  (7/30)20%  (178/902)23%  (44.8/191)
access$000 (JavacTaskImpl): JavaCompiler 0%   (0/1)0%   (0/3)0%   (0/1)
access$100 (JavacTaskImpl, List, ListBuffer): void 0%   (0/1)0%   (0/5)0%   (0/1)
analyze (): Iterable 0%   (0/1)0%   (0/4)0%   (0/1)
analyze (Iterable): Iterable 0%   (0/1)0%   (0/49)0%   (0/9)
asJavaFileObject (File): JavaFileObject 0%   (0/1)0%   (0/10)0%   (0/2)
enter (): Iterable 0%   (0/1)0%   (0/4)0%   (0/1)
enter (Iterable): Iterable 0%   (0/1)0%   (0/161)0%   (0/33)
generate (): Iterable 0%   (0/1)0%   (0/4)0%   (0/1)
generate (Iterable): Iterable 0%   (0/1)0%   (0/62)0%   (0/14)
getContext (): Context 0%   (0/1)0%   (0/3)0%   (0/1)
getElements (): JavacElements 0%   (0/1)0%   (0/11)0%   (0/3)
getTypeMirror (Iterable): TypeMirror 0%   (0/1)0%   (0/19)0%   (0/4)
getTypes (): JavacTypes 0%   (0/1)0%   (0/11)0%   (0/3)
handleFlowResults (List, ListBuffer): void 0%   (0/1)0%   (0/46)0%   (0/11)
parse (): Iterable 0%   (0/1)0%   (0/68)0%   (0/11)
parseType (String, TypeElement): Type 0%   (0/1)0%   (0/79)0%   (0/12)
pathFor (CompilationUnitTree, Tree): Iterable 0%   (0/1)0%   (0/7)0%   (0/1)
prepareCompiler (): void 0%   (0/1)0%   (0/96)0%   (0/18)
setLocale (Locale): void 0%   (0/1)0%   (0/9)0%   (0/3)
setProcessors (Iterable): void 0%   (0/1)0%   (0/15)0%   (0/5)
setTaskListener (TaskListener): void 0%   (0/1)0%   (0/4)0%   (0/2)
updateContext (Context): void 0%   (0/1)0%   (0/4)0%   (0/2)
wrap (TaskListener): TaskListener 0%   (0/1)0%   (0/9)0%   (0/2)
beginContext (): void 100% (1/1)58%  (19/33)71%  (5/7)
toArray (Iterable, Iterable): String [] 100% (1/1)67%  (30/45)75%  (6/8)
call (): Boolean 100% (1/1)83%  (49/59)90%  (10.8/12)
toList (Iterable): List 100% (1/1)92%  (24/26)83%  (5/6)
JavacTaskImpl (JavacTool, Main, Iterable, Context, Iterable, Iterable): void 100% (1/1)100% (11/11)100% (2/2)
JavacTaskImpl (JavacTool, Main, String [], Context, List): void 100% (1/1)100% (41/41)100% (14/14)
endContext (): void 100% (1/1)100% (4/4)100% (2/2)

1/*
2 * Copyright 2005-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.api;
27 
28import java.io.File;
29import java.io.IOException;
30import java.util.*;
31import java.util.concurrent.atomic.AtomicBoolean;
32 
33import javax.annotation.processing.Processor;
34import javax.lang.model.element.Element;
35import javax.lang.model.element.TypeElement;
36import javax.lang.model.type.TypeMirror;
37import javax.tools.*;
38 
39import com.sun.source.tree.Tree;
40import com.sun.source.tree.*;
41import com.sun.source.util.*;
42import com.sun.tools.javac.code.*;
43import com.sun.tools.javac.code.Symbol.*;
44import com.sun.tools.javac.comp.*;
45import com.sun.tools.javac.main.*;
46import com.sun.tools.javac.model.*;
47import com.sun.tools.javac.parser.Parser;
48import com.sun.tools.javac.parser.Scanner;
49import com.sun.tools.javac.tree.*;
50import com.sun.tools.javac.tree.JCTree.*;
51import com.sun.tools.javac.util.*;
52import com.sun.tools.javac.util.List;
53import com.sun.tools.javac.main.JavaCompiler;
54 
55/**
56 * Provides access to functionality specific to the Sun Java Compiler, javac.
57 *
58 * <p><b>This is NOT part of any API supported by Sun Microsystems.
59 * If you write code that depends on this, you do so at your own
60 * risk.  This code and its internal interfaces are subject to change
61 * or deletion without notice.</b></p>
62 *
63 * @author Peter von der Ah&eacute;
64 * @author Jonathan Gibbons
65 */
66public class JavacTaskImpl extends JavacTask {
67    private JavacTool tool;
68    private Main compilerMain;
69    private JavaCompiler compiler;
70    private String[] args;
71    private Context context;
72    private List<JavaFileObject> fileObjects;
73    private Map<JavaFileObject, JCCompilationUnit> notYetEntered;
74    private ListBuffer<Env<AttrContext>> genList;
75    private TaskListener taskListener;
76    private AtomicBoolean used = new AtomicBoolean();
77    private Iterable<? extends Processor> processors;
78 
79    private Integer result = null;
80 
81    JavacTaskImpl(JavacTool tool,
82                Main compilerMain,
83                String[] args,
84                Context context,
85                List<JavaFileObject> fileObjects) {
86        this.tool = tool;
87        this.compilerMain = compilerMain;
88        this.args = args;
89        this.context = context;
90        this.fileObjects = fileObjects;
91        // null checks
92        compilerMain.getClass();
93        args.getClass();
94        context.getClass();
95        fileObjects.getClass();
96    }
97 
98    JavacTaskImpl(JavacTool tool,
99                Main compilerMain,
100                Iterable<String> flags,
101                Context context,
102                Iterable<String> classes,
103                Iterable<? extends JavaFileObject> fileObjects) {
104        this(tool, compilerMain, toArray(flags, classes), context, toList(fileObjects));
105    }
106 
107    static private String[] toArray(Iterable<String> flags, Iterable<String> classes) {
108        ListBuffer<String> result = new ListBuffer<String>();
109        if (flags != null)
110            for (String flag : flags)
111                result.append(flag);
112        if (classes != null)
113            for (String cls : classes)
114                result.append(cls);
115        return result.toArray(new String[result.length()]);
116    }
117 
118    static private List<JavaFileObject> toList(Iterable<? extends JavaFileObject> fileObjects) {
119        if (fileObjects == null)
120            return List.nil();
121        ListBuffer<JavaFileObject> result = new ListBuffer<JavaFileObject>();
122        for (JavaFileObject fo : fileObjects)
123            result.append(fo);
124        return result.toList();
125    }
126 
127    public Boolean call() {
128        if (!used.getAndSet(true)) {
129            beginContext();
130            try {
131                compilerMain.setFatalErrors(true);
132                result = compilerMain.compile(args, context, fileObjects, processors);
133            } finally {
134                endContext();
135            }
136            compilerMain = null;
137            args = null;
138            context = null;
139            fileObjects = null;
140            return result == 0;
141        } else {
142            throw new IllegalStateException("multiple calls to method 'call'");
143        }
144    }
145 
146    public void setProcessors(Iterable<? extends Processor> processors) {
147        processors.getClass(); // null check
148        // not mt-safe
149        if (used.get())
150            throw new IllegalStateException();
151        this.processors = processors;
152    }
153 
154    public void setLocale(Locale locale) {
155        // locale argument is ignored, see RFE 6443132
156        if (used.get())
157            throw new IllegalStateException();
158    }
159 
160    private void prepareCompiler() throws IOException {
161        if (!used.getAndSet(true)) {
162            beginContext();
163            compilerMain.setOptions(Options.instance(context));
164            compilerMain.filenames = new ListBuffer<File>();
165            List<File> filenames = compilerMain.processArgs(CommandLine.parse(args));
166            if (!filenames.isEmpty())
167                throw new IllegalArgumentException("Malformed arguments " + filenames.toString(" "));
168            compiler = JavaCompiler.instance(context);
169            // force the use of the scanner that captures Javadoc comments
170            com.sun.tools.javac.parser.DocCommentScanner.Factory.preRegister(context);
171            compiler.keepComments = true;
172            compiler.genEndPos = true;
173            // NOTE: this value will be updated after annotation processing
174            compiler.initProcessAnnotations(processors);
175            notYetEntered = new HashMap<JavaFileObject, JCCompilationUnit>();
176            for (JavaFileObject file: fileObjects)
177                notYetEntered.put(file, null);
178            genList = new ListBuffer<Env<AttrContext>>();
179            // endContext will be called when all classes have been generated
180            // TODO: should handle the case after each phase if errors have occurred
181            args = null;
182        }
183    }
184 
185    private void beginContext() {
186        context.put(JavacTaskImpl.class, this);
187        if (context.get(TaskListener.class) != null)
188            context.put(TaskListener.class, (TaskListener)null);
189        if (taskListener != null)
190            context.put(TaskListener.class, wrap(taskListener));
191        tool.beginContext(context);
192    }
193    // where
194    private TaskListener wrap(final TaskListener tl) {
195        tl.getClass(); // null check
196        return new TaskListener() {
197            public void started(TaskEvent e) {
198                try {
199                    tl.started(e);
200                } catch (Throwable t) {
201                    throw new ClientCodeException(t);
202                }
203            }
204 
205            public void finished(TaskEvent e) {
206                try {
207                    tl.finished(e);
208                } catch (Throwable t) {
209                    throw new ClientCodeException(t);
210                }
211            }
212 
213        };
214    }
215 
216    private void endContext() {
217        tool.endContext();
218    }
219 
220    /**
221     * Construct a JavaFileObject from the given file.
222     *
223     * <p><b>TODO: this method is useless here</b></p>
224     *
225     * @param file a file
226     * @return a JavaFileObject from the standard file manager.
227     */
228    public JavaFileObject asJavaFileObject(File file) {
229        JavacFileManager fm = (JavacFileManager)context.get(JavaFileManager.class);
230        return fm.getRegularFile(file);
231    }
232 
233    public void setTaskListener(TaskListener taskListener) {
234        this.taskListener = taskListener;
235    }
236 
237    /**
238     * Parse the specified files returning a list of abstract syntax trees.
239     *
240     * @throws java.io.IOException TODO
241     * @return a list of abstract syntax trees
242     */
243    public Iterable<? extends CompilationUnitTree> parse() throws IOException {
244        try {
245            prepareCompiler();
246            List<JCCompilationUnit> units = compiler.parseFiles(fileObjects);
247            for (JCCompilationUnit unit: units) {
248                JavaFileObject file = unit.getSourceFile();
249                if (notYetEntered.containsKey(file))
250                    notYetEntered.put(file, unit);
251            }
252            return units;
253        }
254        finally {
255            parsed = true;
256            if (compiler != null && compiler.log != null)
257                compiler.log.flush();
258        }
259    }
260 
261    private boolean parsed = false;
262 
263    /**
264     * Translate all the abstract syntax trees to elements.
265     *
266     * @throws IOException TODO
267     * @return a list of elements corresponding to the top level
268     * classes in the abstract syntax trees
269     */
270    public Iterable<? extends TypeElement> enter() throws IOException {
271        return enter(null);
272    }
273 
274    /**
275     * Translate the given abstract syntax trees to elements.
276     *
277     * @param trees a list of abstract syntax trees.
278     * @throws java.io.IOException TODO
279     * @return a list of elements corresponding to the top level
280     * classes in the abstract syntax trees
281     */
282    public Iterable<? extends TypeElement> enter(Iterable<? extends CompilationUnitTree> trees)
283        throws IOException
284    {
285        prepareCompiler();
286 
287        ListBuffer<JCCompilationUnit> roots = null;
288 
289        if (trees == null) {
290            // If there are still files which were specified to be compiled
291            // (i.e. in fileObjects) but which have not yet been entered,
292            // then we make sure they have been parsed and add them to the
293            // list to be entered.
294            if (notYetEntered.size() > 0) {
295                if (!parsed)
296                    parse(); // TODO would be nice to specify files needed to be parsed
297                for (JavaFileObject file: fileObjects) {
298                    JCCompilationUnit unit = notYetEntered.remove(file);
299                    if (unit != null) {
300                        if (roots == null)
301                            roots = new ListBuffer<JCCompilationUnit>();
302                        roots.append(unit);
303                    }
304                }
305                notYetEntered.clear();
306            }
307        }
308        else {
309            for (CompilationUnitTree cu : trees) {
310                if (cu instanceof JCCompilationUnit) {
311                    if (roots == null)
312                        roots = new ListBuffer<JCCompilationUnit>();
313                    roots.append((JCCompilationUnit)cu);
314                    notYetEntered.remove(cu.getSourceFile());
315                }
316                else
317                    throw new IllegalArgumentException(cu.toString());
318            }
319        }
320 
321        if (roots == null)
322            return List.nil();
323 
324        try {
325            List<JCCompilationUnit> units = compiler.enterTrees(roots.toList());
326 
327            if (notYetEntered.isEmpty())
328                compiler = compiler.processAnnotations(units);
329 
330            ListBuffer<TypeElement> elements = new ListBuffer<TypeElement>();
331            for (JCCompilationUnit unit : units) {
332                for (JCTree node : unit.defs)
333                    if (node.getTag() == JCTree.CLASSDEF)
334                        elements.append(((JCTree.JCClassDecl) node).sym);
335            }
336            return elements.toList();
337        }
338        finally {
339            compiler.log.flush();
340        }
341    }
342 
343    /**
344     * Complete all analysis.
345     * @throws IOException TODO
346     */
347    @Override
348    public Iterable<? extends Element> analyze() throws IOException {
349        return analyze(null);
350    }
351 
352    /**
353     * Complete all analysis on the given classes.
354     * This can be used to ensure that all compile time errors are reported.
355     * The classes must have previously been returned from {@link #enter}.
356     * If null is specified, all outstanding classes will be analyzed.
357     *
358     * @param classes a list of class elements
359     */
360    // This implementation requires that we open up privileges on JavaCompiler.
361    // An alternative implementation would be to move this code to JavaCompiler and
362    // wrap it here
363    public Iterable<? extends Element> analyze(Iterable<? extends TypeElement> classes) throws IOException {
364        enter(null);  // ensure all classes have been entered
365 
366        final ListBuffer<Element> results = new ListBuffer<Element>();
367        try {
368            if (classes == null) {
369                handleFlowResults(compiler.flow(compiler.attribute(compiler.todo)), results);
370            } else {
371                Filter f = new Filter() {
372                    public void process(Env<AttrContext> env) {
373                        handleFlowResults(compiler.flow(compiler.attribute(env)), results);
374                    }
375                };
376                f.run(compiler.todo, classes);
377            }
378        } finally {
379            compiler.log.flush();
380        }
381        return results;
382    }
383    // where
384        private void handleFlowResults(List<Env<AttrContext>> list, ListBuffer<Element> elems) {
385            for (Env<AttrContext> env: list) {
386                switch (env.tree.getTag()) {
387                    case JCTree.CLASSDEF:
388                        JCClassDecl cdef = (JCClassDecl) env.tree;
389                        if (cdef.sym != null)
390                            elems.append(cdef.sym);
391                        break;
392                    case JCTree.TOPLEVEL:
393                        JCCompilationUnit unit = (JCCompilationUnit) env.tree;
394                        if (unit.packge != null)
395                            elems.append(unit.packge);
396                        break;
397                }
398            }
399            genList.appendList(list);
400        }
401 
402 
403    /**
404     * Generate code.
405     * @throws IOException TODO
406     */
407    @Override
408    public Iterable<? extends JavaFileObject> generate() throws IOException {
409        return generate(null);
410    }
411 
412    /**
413     * Generate code corresponding to the given classes.
414     * The classes must have previously been returned from {@link #enter}.
415     * If there are classes outstanding to be analyzed, that will be done before
416     * any classes are generated.
417     * If null is specified, code will be generated for all outstanding classes.
418     *
419     * @param classes a list of class elements
420     */
421    public Iterable<? extends JavaFileObject> generate(Iterable<? extends TypeElement> classes) throws IOException {
422        final ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>();
423        try {
424            analyze(null);  // ensure all classes have been parsed, entered, and analyzed
425 
426            if (classes == null) {
427                compiler.generate(compiler.desugar(genList.toList()), results);
428                genList.clear();
429            }
430            else {
431                Filter f = new Filter() {
432                        public void process(Env<AttrContext> env) {
433                            compiler.generate(compiler.desugar(List.of(env)), results);
434                        }
435                    };
436                f.run(genList, classes);
437            }
438            if (genList.isEmpty()) {
439                compiler.reportDeferredDiagnostics();
440                compiler.log.flush();
441                endContext();
442            }
443        }
444        finally {
445            compiler.log.flush();
446        }
447        return results;
448    }
449 
450    public TypeMirror getTypeMirror(Iterable<? extends Tree> path) {
451        // TODO: Should complete attribution if necessary
452        Tree last = null;
453        for (Tree node : path)
454            last = node;
455        return ((JCTree)last).type;
456    }
457 
458    public JavacElements getElements() {
459        if (context == null)
460            throw new IllegalStateException();
461        return JavacElements.instance(context);
462    }
463 
464    public JavacTypes getTypes() {
465        if (context == null)
466            throw new IllegalStateException();
467        return JavacTypes.instance(context);
468    }
469 
470    public Iterable<? extends Tree> pathFor(CompilationUnitTree unit, Tree node) {
471        return TreeInfo.pathFor((JCTree) node, (JCTree.JCCompilationUnit) unit).reverse();
472    }
473 
474    abstract class Filter {
475        void run(ListBuffer<Env<AttrContext>> list, Iterable<? extends TypeElement> classes) {
476            Set<TypeElement> set = new HashSet<TypeElement>();
477            for (TypeElement item: classes)
478                set.add(item);
479 
480            List<Env<AttrContext>> defer = List.<Env<AttrContext>>nil();
481            while (list.nonEmpty()) {
482                Env<AttrContext> env = list.next();
483                ClassSymbol csym = env.enclClass.sym;
484                if (csym != null && set.contains(csym.outermostClass()))
485                    process(env);
486                else
487                    defer = defer.prepend(env);
488            }
489 
490            for (List<Env<AttrContext>> l = defer; l.nonEmpty(); l = l.tail)
491                list.prepend(l.head);
492        }
493 
494        abstract void process(Env<AttrContext> env);
495    }
496 
497    /**
498     * For internal use by Sun Microsystems only.  This method will be
499     * removed without warning.
500     */
501    public Context getContext() {
502        return context;
503    }
504 
505    /**
506     * For internal use by Sun Microsystems only.  This method will be
507     * removed without warning.
508     */
509    public void updateContext(Context newContext) {
510        context = newContext;
511    }
512 
513    /**
514     * For internal use by Sun Microsystems only.  This method will be
515     * removed without warning.
516     */
517    public Type parseType(String expr, TypeElement scope) {
518        if (expr == null || expr.equals(""))
519            throw new IllegalArgumentException();
520        compiler = JavaCompiler.instance(context);
521        JavaFileObject prev = compiler.log.useSource(null);
522        Scanner.Factory scannerFactory = Scanner.Factory.instance(context);
523        Parser.Factory parserFactory = Parser.Factory.instance(context);
524        Attr attr = Attr.instance(context);
525        try {
526            Scanner scanner = scannerFactory.newScanner((expr+"\u0000").toCharArray(),
527                                                        expr.length());
528            Parser parser = parserFactory.newParser(scanner, false, false);
529            JCTree tree = parser.type();
530            return attr.attribType(tree, (Symbol.TypeSymbol)scope);
531        } finally {
532            compiler.log.useSource(prev);
533        }
534    }
535 
536}

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