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

COVERAGE SUMMARY FOR SOURCE FILE [Main.java]

nameclass, %method, %block, %line, %
Main.java67%  (2/3)22%  (7/32)25%  (272/1100)31%  (65.1/209)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Main$20%   (0/1)0%   (0/2)0%   (0/6)0%   (0/2)
Main$2 (String): void 0%   (0/1)0%   (0/4)0%   (0/1)
getLocalizedString (String, Object []): String 0%   (0/1)0%   (0/2)0%   (0/1)
     
class Main$1100% (1/1)11%  (1/9)7%   (6/83)6%   (1/18)
addClassName (String): void 0%   (0/1)0%   (0/7)0%   (0/2)
addFile (File): void 0%   (0/1)0%   (0/13)0%   (0/3)
error (String, Object []): void 0%   (0/1)0%   (0/6)0%   (0/2)
printFullVersion (): void 0%   (0/1)0%   (0/19)0%   (0/2)
printHelp (): void 0%   (0/1)0%   (0/4)0%   (0/2)
printVersion (): void 0%   (0/1)0%   (0/19)0%   (0/2)
printXhelp (): void 0%   (0/1)0%   (0/4)0%   (0/2)
setOut (PrintWriter): void 0%   (0/1)0%   (0/5)0%   (0/2)
Main$1 (Main): void 100% (1/1)100% (6/6)100% (1/1)
     
class Main100% (1/1)29%  (6/21)26%  (266/1011)34%  (65.1/191)
Main (String): void 0%   (0/1)0%   (0/9)0%   (0/2)
apMessage (AnnotationProcessingError): void 0%   (0/1)0%   (0/11)0%   (0/3)
bugMessage (Throwable): void 0%   (0/1)0%   (0/16)0%   (0/3)
compile (String []): int 0%   (0/1)0%   (0/21)0%   (0/6)
compile (String [], Context): int 0%   (0/1)0%   (0/7)0%   (0/1)
error (String, Object []): void 0%   (0/1)0%   (0/32)0%   (0/6)
feMessage (Throwable): void 0%   (0/1)0%   (0/6)0%   (0/2)
getLocalizedString (String, Object []): String 0%   (0/1)0%   (0/26)0%   (0/5)
getOption (String): JavacOption$Option 0%   (0/1)0%   (0/25)0%   (0/4)
help (): void 0%   (0/1)0%   (0/32)0%   (0/5)
ioMessage (Throwable): void 0%   (0/1)0%   (0/12)0%   (0/3)
resourceMessage (Throwable): void 0%   (0/1)0%   (0/12)0%   (0/3)
useRawMessages (boolean): void 0%   (0/1)0%   (0/14)0%   (0/4)
warning (String, Object []): void 0%   (0/1)0%   (0/17)0%   (0/2)
xhelp (): void 0%   (0/1)0%   (0/27)0%   (0/5)
checkDirectory (String): boolean 100% (1/1)20%  (9/44)27%  (3/11)
compile (String [], Context, List, Iterable): int 100% (1/1)24%  (106/448)32%  (21.2/67)
processArgs (String []): List 100% (1/1)54%  (116/213)62%  (27.9/45)
setOptions (Options): void 100% (1/1)60%  (6/10)75%  (3/4)
Main (String, PrintWriter): void 100% (1/1)100% (25/25)100% (8/8)
setFatalErrors (boolean): void 100% (1/1)100% (4/4)100% (2/2)

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 com.sun.tools.javac.util.Options;
29import java.io.File;
30import java.io.IOException;
31import java.io.PrintWriter;
32import java.util.MissingResourceException;
33 
34import com.sun.tools.javac.code.Source;
35import com.sun.tools.javac.jvm.Target;
36import com.sun.tools.javac.main.JavacOption.Option;
37import com.sun.tools.javac.main.RecognizedOptions.OptionHelper;
38import com.sun.tools.javac.util.*;
39import com.sun.tools.javac.processing.AnnotationProcessingError;
40import javax.tools.JavaFileManager;
41import javax.tools.JavaFileObject;
42import javax.annotation.processing.Processor;
43 
44/** This class provides a commandline interface to the GJC compiler.
45 *
46 *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
47 *  you write code that depends on this, you do so at your own risk.
48 *  This code and its internal interfaces are subject to change or
49 *  deletion without notice.</b>
50 */
51public class Main {
52 
53    /** The name of the compiler, for use in diagnostics.
54     */
55    String ownName;
56 
57    /** The writer to use for diagnostic output.
58     */
59    PrintWriter out;
60 
61    /**
62     * If true, any command line arg errors will cause an exception.
63     */
64    boolean fatalErrors;
65 
66    /** Result codes.
67     */
68    static final int
69        EXIT_OK = 0,        // Compilation completed with no errors.
70        EXIT_ERROR = 1,     // Completed but reported errors.
71        EXIT_CMDERR = 2,    // Bad command-line arguments
72        EXIT_SYSERR = 3,    // System error or resource exhaustion.
73        EXIT_ABNORMAL = 4;  // Compiler terminated abnormally
74 
75    private Option[] recognizedOptions = RecognizedOptions.getJavaCompilerOptions(new OptionHelper() {
76 
77        public void setOut(PrintWriter out) {
78            Main.this.out = out;
79        }
80 
81        public void error(String key, Object... args) {
82            Main.this.error(key, args);
83        }
84 
85        public void printVersion() {
86            Log.printLines(out, getLocalizedString("version", ownName,  JavaCompiler.version()));
87        }
88 
89        public void printFullVersion() {
90            Log.printLines(out, getLocalizedString("fullVersion", ownName,  JavaCompiler.fullVersion()));
91        }
92 
93        public void printHelp() {
94            help();
95        }
96 
97        public void printXhelp() {
98            xhelp();
99        }
100 
101        public void addFile(File f) {
102            if (!filenames.contains(f))
103                filenames.append(f);
104        }
105 
106        public void addClassName(String s) {
107            classnames.append(s);
108        }
109 
110    });
111 
112    /**
113     * Construct a compiler instance.
114     */
115    public Main(String name) {
116        this(name, new PrintWriter(System.err, true));
117    }
118 
119    /**
120     * Construct a compiler instance.
121     */
122    public Main(String name, PrintWriter out) {
123        this.ownName = name;
124        this.out = out;
125    }
126    /** A table of all options that's passed to the JavaCompiler constructor.  */
127    private Options options = null;
128 
129    /** The list of source files to process
130     */
131    public ListBuffer<File> filenames = null; // XXX sb protected
132 
133    /** List of class files names passed on the command line
134     */
135    public ListBuffer<String> classnames = null; // XXX sb protected
136 
137    /** Print a string that explains usage.
138     */
139    void help() {
140        Log.printLines(out, getLocalizedString("msg.usage.header", ownName));
141        for (int i=0; i<recognizedOptions.length; i++) {
142            recognizedOptions[i].help(out);
143        }
144        out.println();
145    }
146 
147    /** Print a string that explains usage for X options.
148     */
149    void xhelp() {
150        for (int i=0; i<recognizedOptions.length; i++) {
151            recognizedOptions[i].xhelp(out);
152        }
153        out.println();
154        Log.printLines(out, getLocalizedString("msg.usage.nonstandard.footer"));
155    }
156 
157    /** Report a usage error.
158     */
159    void error(String key, Object... args) {
160        if (fatalErrors) {
161            String msg = getLocalizedString(key, args);
162            throw new PropagatedException(new IllegalStateException(msg));
163        }
164        warning(key, args);
165        Log.printLines(out, getLocalizedString("msg.usage", ownName));
166    }
167 
168    /** Report a warning.
169     */
170    void warning(String key, Object... args) {
171        Log.printLines(out, ownName + ": "
172                       + getLocalizedString(key, args));
173    }
174 
175    public Option getOption(String flag) {
176        for (Option option : recognizedOptions) {
177            if (option.matches(flag))
178                return option;
179        }
180        return null;
181    }
182 
183    public void setOptions(Options options) {
184        if (options == null)
185            throw new NullPointerException();
186        this.options = options;
187    }
188 
189    public void setFatalErrors(boolean fatalErrors) {
190        this.fatalErrors = fatalErrors;
191    }
192 
193    /** Process command line arguments: store all command line options
194     *  in `options' table and return all source filenames.
195     *  @param flags    The array of command line arguments.
196     */
197    public List<File> processArgs(String[] flags) { // XXX sb protected
198        int ac = 0;
199        while (ac < flags.length) {
200            String flag = flags[ac];
201            ac++;
202 
203            Option option = null;
204 
205            if (flag.length() > 0) {
206                // quick hack to speed up file processing:
207                // if the option does not begin with '-', there is no need to check
208                // most of the compiler options.
209                int firstOptionToCheck = flag.charAt(0) == '-' ? 0 : recognizedOptions.length-1;
210                for (int j=firstOptionToCheck; j<recognizedOptions.length; j++) {
211                    if (recognizedOptions[j].matches(flag)) {
212                        option = recognizedOptions[j];
213                        break;
214                    }
215                }
216            }
217 
218            if (option == null) {
219                error("err.invalid.flag", flag);
220                return null;
221            }
222 
223            if (option.hasArg()) {
224                if (ac == flags.length) {
225                    error("err.req.arg", flag);
226                    return null;
227                }
228                String operand = flags[ac];
229                ac++;
230                if (option.process(options, flag, operand))
231                    return null;
232            } else {
233                if (option.process(options, flag))
234                    return null;
235            }
236        }
237 
238        if (!checkDirectory("-d"))
239            return null;
240        if (!checkDirectory("-s"))
241            return null;
242 
243        String sourceString = options.get("-source");
244        Source source = (sourceString != null)
245            ? Source.lookup(sourceString)
246            : Source.DEFAULT;
247        String targetString = options.get("-target");
248        Target target = (targetString != null)
249            ? Target.lookup(targetString)
250            : Target.DEFAULT;
251        // We don't check source/target consistency for CLDC, as J2ME
252        // profiles are not aligned with J2SE targets; moreover, a
253        // single CLDC target may have many profiles.  In addition,
254        // this is needed for the continued functioning of the JSR14
255        // prototype.
256        if (Character.isDigit(target.name.charAt(0))) {
257            if (target.compareTo(source.requiredTarget()) < 0) {
258                if (targetString != null) {
259                    if (sourceString == null) {
260                        warning("warn.target.default.source.conflict",
261                                targetString,
262                                source.requiredTarget().name);
263                    } else {
264                        warning("warn.source.target.conflict",
265                                sourceString,
266                                source.requiredTarget().name);
267                    }
268                    return null;
269                } else {
270                    options.put("-target", source.requiredTarget().name);
271                }
272            } else {
273                if (targetString == null && !source.allowGenerics()) {
274                    options.put("-target", Target.JDK1_4.name);
275                }
276            }
277        }
278        return filenames.toList();
279    }
280    // where
281        private boolean checkDirectory(String optName) {
282            String value = options.get(optName);
283            if (value == null)
284                return true;
285            File file = new File(value);
286            if (!file.exists()) {
287                error("err.dir.not.found", value);
288                return false;
289            }
290            if (!file.isDirectory()) {
291                error("err.file.not.directory", value);
292                return false;
293            }
294            return true;
295        }
296 
297    /** Programmatic interface for main function.
298     * @param args    The command line parameters.
299     */
300    public int compile(String[] args) {
301        Context context = new Context();
302        JavacFileManager.preRegister(context); // can't create it until Log has been set up
303        int result = compile(args, context);
304        if (fileManager instanceof JavacFileManager) {
305            // A fresh context was created above, so jfm must be a JavacFileManager
306            ((JavacFileManager)fileManager).close();
307        }
308        return result;
309    }
310 
311    public int compile(String[] args, Context context) {
312        return compile(args, context, List.<JavaFileObject>nil(), null);
313    }
314 
315    /** Programmatic interface for main function.
316     * @param args    The command line parameters.
317     */
318    public int compile(String[] args,
319                       Context context,
320                       List<JavaFileObject> fileObjects,
321                       Iterable<? extends Processor> processors)
322    {
323        if (options == null)
324            options = Options.instance(context); // creates a new one
325 
326        filenames = new ListBuffer<File>();
327        classnames = new ListBuffer<String>();
328        JavaCompiler comp = null;
329        /*
330         * TODO: Logic below about what is an acceptable command line
331         * should be updated to take annotation processing semantics
332         * into account.
333         */
334        try {
335            if (args.length == 0 && fileObjects.isEmpty()) {
336                help();
337                return EXIT_CMDERR;
338            }
339 
340            List<File> filenames;
341            try {
342                filenames = processArgs(CommandLine.parse(args));
343                if (filenames == null) {
344                    // null signals an error in options, abort
345                    return EXIT_CMDERR;
346                } else if (filenames.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) {
347                    // it is allowed to compile nothing if just asking for help or version info
348                    if (options.get("-help") != null
349                        || options.get("-X") != null
350                        || options.get("-version") != null
351                        || options.get("-fullversion") != null)
352                        return EXIT_OK;
353                    error("err.no.source.files");
354                    return EXIT_CMDERR;
355                }
356            } catch (java.io.FileNotFoundException e) {
357                Log.printLines(out, ownName + ": " +
358                               getLocalizedString("err.file.not.found",
359                                                  e.getMessage()));
360                return EXIT_SYSERR;
361            }
362 
363            boolean forceStdOut = options.get("stdout") != null;
364            if (forceStdOut) {
365                out.flush();
366                out = new PrintWriter(System.out, true);
367            }
368 
369            context.put(Log.outKey, out);
370 
371            fileManager = context.get(JavaFileManager.class);
372 
373            comp = JavaCompiler.instance(context);
374            if (comp == null) return EXIT_SYSERR;
375 
376            if (!filenames.isEmpty()) {
377                // add filenames to fileObjects
378                comp = JavaCompiler.instance(context);
379                List<JavaFileObject> otherFiles = List.nil();
380                JavacFileManager dfm = (JavacFileManager)fileManager;
381                for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(filenames))
382                    otherFiles = otherFiles.prepend(fo);
383                for (JavaFileObject fo : otherFiles)
384                    fileObjects = fileObjects.prepend(fo);
385            }
386            comp.compile(fileObjects,
387                         classnames.toList(),
388                         processors);
389 
390            if (comp.errorCount() != 0 ||
391                options.get("-Werror") != null && comp.warningCount() != 0)
392                return EXIT_ERROR;
393        } catch (IOException ex) {
394            ioMessage(ex);
395            return EXIT_SYSERR;
396        } catch (OutOfMemoryError ex) {
397            resourceMessage(ex);
398            return EXIT_SYSERR;
399        } catch (StackOverflowError ex) {
400            resourceMessage(ex);
401            return EXIT_SYSERR;
402        } catch (FatalError ex) {
403            feMessage(ex);
404            return EXIT_SYSERR;
405        } catch(AnnotationProcessingError ex) {
406            apMessage(ex);
407            return EXIT_SYSERR;
408        } catch (ClientCodeException ex) {
409            // as specified by javax.tools.JavaCompiler#getTask
410            // and javax.tools.JavaCompiler.CompilationTask#call
411            throw new RuntimeException(ex.getCause());
412        } catch (PropagatedException ex) {
413            throw ex.getCause();
414        } catch (Throwable ex) {
415            // Nasty.  If we've already reported an error, compensate
416            // for buggy compiler error recovery by swallowing thrown
417            // exceptions.
418            if (comp == null || comp.errorCount() == 0 ||
419                options == null || options.get("dev") != null)
420                bugMessage(ex);
421            return EXIT_ABNORMAL;
422        } finally {
423            if (comp != null) comp.close();
424            filenames = null;
425            options = null;
426        }
427        return EXIT_OK;
428    }
429 
430    /** Print a message reporting an internal error.
431     */
432    void bugMessage(Throwable ex) {
433        Log.printLines(out, getLocalizedString("msg.bug",
434                                               JavaCompiler.version()));
435        ex.printStackTrace(out);
436    }
437 
438    /** Print a message reporting an fatal error.
439     */
440    void feMessage(Throwable ex) {
441        Log.printLines(out, ex.getMessage());
442    }
443 
444    /** Print a message reporting an input/output error.
445     */
446    void ioMessage(Throwable ex) {
447        Log.printLines(out, getLocalizedString("msg.io"));
448        ex.printStackTrace(out);
449    }
450 
451    /** Print a message reporting an out-of-resources error.
452     */
453    void resourceMessage(Throwable ex) {
454        Log.printLines(out, getLocalizedString("msg.resource"));
455//      System.out.println("(name buffer len = " + Name.names.length + " " + Name.nc);//DEBUG
456        ex.printStackTrace(out);
457    }
458 
459    /** Print a message reporting an uncaught exception from an
460     * annotation processor.
461     */
462    void apMessage(AnnotationProcessingError ex) {
463        Log.printLines(out,
464                       getLocalizedString("msg.proc.annotation.uncaught.exception"));
465        ex.getCause().printStackTrace();
466    }
467 
468    private JavaFileManager fileManager;
469 
470    /* ************************************************************************
471     * Internationalization
472     *************************************************************************/
473 
474    /** Find a localized string in the resource bundle.
475     *  @param key     The key for the localized string.
476     */
477    public static String getLocalizedString(String key, Object... args) { // FIXME sb private
478        try {
479            if (messages == null)
480                messages = new Messages(javacBundleName);
481            return messages.getLocalizedString("javac." + key, args);
482        }
483        catch (MissingResourceException e) {
484            throw new Error("Fatal Error: Resource for javac is missing", e);
485        }
486    }
487 
488    public static void useRawMessages(boolean enable) {
489        if (enable) {
490            messages = new Messages(javacBundleName) {
491                    public String getLocalizedString(String key, Object... args) {
492                        return key;
493                    }
494                };
495        } else {
496            messages = new Messages(javacBundleName);
497        }
498    }
499 
500    private static final String javacBundleName =
501        "com.sun.tools.javac.resources.javac";
502 
503    private static Messages messages;
504}

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