View Javadoc
1   /*
2    * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.tools.javac.main;
27  
28  import java.io.File;
29  import java.io.FileWriter;
30  import java.io.PrintWriter;
31  import java.util.Collections;
32  import java.util.EnumSet;
33  import java.util.LinkedHashMap;
34  import java.util.Map;
35  import java.util.Set;
36  
37  import javax.lang.model.SourceVersion;
38  
39  import com.sun.tools.doclint.DocLint;
40  import com.sun.tools.javac.code.Lint;
41  import com.sun.tools.javac.code.Source;
42  import com.sun.tools.javac.code.Type;
43  import com.sun.tools.javac.jvm.Profile;
44  import com.sun.tools.javac.jvm.Target;
45  import com.sun.tools.javac.processing.JavacProcessingEnvironment;
46  import com.sun.tools.javac.util.Log;
47  import com.sun.tools.javac.util.Log.PrefixKind;
48  import com.sun.tools.javac.util.Log.WriterKind;
49  import com.sun.tools.javac.util.Options;
50  import static com.sun.tools.javac.main.Option.ChoiceKind.*;
51  import static com.sun.tools.javac.main.Option.OptionGroup.*;
52  import static com.sun.tools.javac.main.Option.OptionKind.*;
53  
54  /**
55   * Options for javac. The specific Option to handle a command-line option
56   * is identified by searching the members of this enum in order, looking
57   * the first {@link #matches match}. The action for an Option is performed
58   * by calling {@link #process process}, and by providing a suitable
59   * {@link OptionHelper} to provide access the compiler state.
60   *
61   * <p><b>This is NOT part of any supported API.
62   * If you write code that depends on this, you do so at your own
63   * risk.  This code and its internal interfaces are subject to change
64   * or deletion without notice.</b></p>
65   */
66  public enum Option {
67      G("-g", "opt.g", STANDARD, BASIC),
68  
69      G_NONE("-g:none", "opt.g.none", STANDARD, BASIC) {
70          @Override
71          public boolean process(OptionHelper helper, String option) {
72              helper.put("-g:", "none");
73              return false;
74          }
75      },
76  
77      G_CUSTOM("-g:",  "opt.g.lines.vars.source",
78              STANDARD, BASIC, ANYOF, "lines", "vars", "source"),
79  
80      XLINT("-Xlint", "opt.Xlint", EXTENDED, BASIC),
81  
82      XLINT_CUSTOM("-Xlint:", "opt.Xlint.suboptlist",
83              EXTENDED,   BASIC, ANYOF, getXLintChoices()),
84  
85      XDOCLINT("-Xdoclint", "opt.Xdoclint", EXTENDED, BASIC),
86  
87      XDOCLINT_CUSTOM("-Xdoclint:", "opt.Xdoclint.subopts", "opt.Xdoclint.custom", EXTENDED, BASIC) {
88          @Override
89          public boolean matches(String option) {
90              return DocLint.isValidOption(
91                      option.replace(XDOCLINT_CUSTOM.text, DocLint.XMSGS_CUSTOM_PREFIX));
92          }
93  
94          @Override
95          public boolean process(OptionHelper helper, String option) {
96              String prev = helper.get(XDOCLINT_CUSTOM);
97              String next = (prev == null) ? option : (prev + " " + option);
98              helper.put(XDOCLINT_CUSTOM.text, next);
99              return false;
100         }
101     },
102 
103     // -nowarn is retained for command-line backward compatibility
104     NOWARN("-nowarn", "opt.nowarn", STANDARD, BASIC) {
105         @Override
106         public boolean process(OptionHelper helper, String option) {
107             helper.put("-Xlint:none", option);
108             return false;
109         }
110     },
111 
112     VERBOSE("-verbose", "opt.verbose", STANDARD, BASIC),
113 
114     // -deprecation is retained for command-line backward compatibility
115     DEPRECATION("-deprecation", "opt.deprecation", STANDARD, BASIC) {
116         @Override
117         public boolean process(OptionHelper helper, String option) {
118             helper.put("-Xlint:deprecation", option);
119             return false;
120         }
121     },
122 
123     CLASSPATH("-classpath", "opt.arg.path", "opt.classpath", STANDARD, FILEMANAGER),
124 
125     CP("-cp", "opt.arg.path", "opt.classpath", STANDARD, FILEMANAGER) {
126         @Override
127         public boolean process(OptionHelper helper, String option, String arg) {
128             return super.process(helper, "-classpath", arg);
129         }
130     },
131 
132     SOURCEPATH("-sourcepath", "opt.arg.path", "opt.sourcepath", STANDARD, FILEMANAGER),
133 
134     BOOTCLASSPATH("-bootclasspath", "opt.arg.path", "opt.bootclasspath", STANDARD, FILEMANAGER) {
135         @Override
136         public boolean process(OptionHelper helper, String option, String arg) {
137             helper.remove("-Xbootclasspath/p:");
138             helper.remove("-Xbootclasspath/a:");
139             return super.process(helper, option, arg);
140         }
141     },
142 
143     XBOOTCLASSPATH_PREPEND("-Xbootclasspath/p:", "opt.arg.path", "opt.Xbootclasspath.p", EXTENDED, FILEMANAGER),
144 
145     XBOOTCLASSPATH_APPEND("-Xbootclasspath/a:", "opt.arg.path", "opt.Xbootclasspath.a", EXTENDED, FILEMANAGER),
146 
147     XBOOTCLASSPATH("-Xbootclasspath:", "opt.arg.path", "opt.bootclasspath", EXTENDED, FILEMANAGER) {
148         @Override
149         public boolean process(OptionHelper helper, String option, String arg) {
150             helper.remove("-Xbootclasspath/p:");
151             helper.remove("-Xbootclasspath/a:");
152             return super.process(helper, "-bootclasspath", arg);
153         }
154     },
155 
156     EXTDIRS("-extdirs", "opt.arg.dirs", "opt.extdirs", STANDARD, FILEMANAGER),
157 
158     DJAVA_EXT_DIRS("-Djava.ext.dirs=", "opt.arg.dirs", "opt.extdirs", EXTENDED, FILEMANAGER) {
159         @Override
160         public boolean process(OptionHelper helper, String option, String arg) {
161             return super.process(helper, "-extdirs", arg);
162         }
163     },
164 
165     ENDORSEDDIRS("-endorseddirs", "opt.arg.dirs", "opt.endorseddirs", STANDARD, FILEMANAGER),
166 
167     DJAVA_ENDORSED_DIRS("-Djava.endorsed.dirs=", "opt.arg.dirs", "opt.endorseddirs", EXTENDED, FILEMANAGER) {
168         @Override
169         public boolean process(OptionHelper helper, String option, String arg) {
170             return super.process(helper, "-endorseddirs", arg);
171         }
172     },
173 
174     PROC("-proc:", "opt.proc.none.only", STANDARD, BASIC,  ONEOF, "none", "only"),
175 
176     PROCESSOR("-processor", "opt.arg.class.list", "opt.processor", STANDARD, BASIC),
177 
178     PROCESSORPATH("-processorpath", "opt.arg.path", "opt.processorpath", STANDARD, FILEMANAGER),
179 
180     PARAMETERS("-parameters","opt.parameters", STANDARD, BASIC),
181 
182     D("-d", "opt.arg.directory", "opt.d", STANDARD, FILEMANAGER),
183 
184     S("-s", "opt.arg.directory", "opt.sourceDest", STANDARD, FILEMANAGER),
185 
186     H("-h", "opt.arg.directory", "opt.headerDest", STANDARD, FILEMANAGER),
187 
188     IMPLICIT("-implicit:", "opt.implicit", STANDARD, BASIC, ONEOF, "none", "class"),
189 
190     ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER) {
191         @Override
192         public boolean process(OptionHelper helper, String option, String operand) {
193             return super.process(helper, option, operand);
194         }
195 
196     },
197 
198     SOURCE("-source", "opt.arg.release", "opt.source", STANDARD, BASIC) {
199         @Override
200         public boolean process(OptionHelper helper, String option, String operand) {
201             Source source = Source.lookup(operand);
202             if (source == null) {
203                 helper.error("err.invalid.source", operand);
204                 return true;
205             }
206             return super.process(helper, option, operand);
207         }
208     },
209 
210     TARGET("-target", "opt.arg.release", "opt.target", STANDARD, BASIC) {
211         @Override
212         public boolean process(OptionHelper helper, String option, String operand) {
213             Target target = Target.lookup(operand);
214             if (target == null) {
215                 helper.error("err.invalid.target", operand);
216                 return true;
217             }
218             return super.process(helper, option, operand);
219         }
220     },
221 
222     PROFILE("-profile", "opt.arg.profile", "opt.profile", STANDARD, BASIC) {
223         @Override
224         public boolean process(OptionHelper helper, String option, String operand) {
225             Profile profile = Profile.lookup(operand);
226             if (profile == null) {
227                 helper.error("err.invalid.profile", operand);
228                 return true;
229             }
230             return super.process(helper, option, operand);
231         }
232     },
233 
234     VERSION("-version", "opt.version", STANDARD, INFO) {
235         @Override
236         public boolean process(OptionHelper helper, String option) {
237             Log log = helper.getLog();
238             String ownName = helper.getOwnName();
239             log.printLines(PrefixKind.JAVAC, "version", ownName,  JavaCompiler.version());
240             return super.process(helper, option);
241         }
242     },
243 
244     FULLVERSION("-fullversion", null, HIDDEN, INFO) {
245         @Override
246         public boolean process(OptionHelper helper, String option) {
247             Log log = helper.getLog();
248             String ownName = helper.getOwnName();
249             log.printLines(PrefixKind.JAVAC, "fullVersion", ownName,  JavaCompiler.fullVersion());
250             return super.process(helper, option);
251         }
252     },
253 
254     DIAGS("-XDdiags=", null, HIDDEN, INFO) {
255         @Override
256         public boolean process(OptionHelper helper, String option) {
257             option = option.substring(option.indexOf('=') + 1);
258             String diagsOption = option.contains("%") ?
259                 "-XDdiagsFormat=" :
260                 "-XDdiags=";
261             diagsOption += option;
262             if (XD.matches(diagsOption))
263                 return XD.process(helper, diagsOption);
264             else
265                 return false;
266         }
267     },
268 
269     HELP("-help", "opt.help", STANDARD, INFO) {
270         @Override
271         public boolean process(OptionHelper helper, String option) {
272             Log log = helper.getLog();
273             String ownName = helper.getOwnName();
274             log.printLines(PrefixKind.JAVAC, "msg.usage.header", ownName);
275             for (Option o: getJavaCompilerOptions()) {
276                 o.help(log, OptionKind.STANDARD);
277             }
278             log.printNewline();
279             return super.process(helper, option);
280         }
281     },
282 
283     A("-A", "opt.arg.key.equals.value", "opt.A", STANDARD, BASIC, true) {
284         @Override
285         public boolean matches(String arg) {
286             return arg.startsWith("-A");
287         }
288 
289         @Override
290         public boolean hasArg() {
291             return false;
292         }
293         // Mapping for processor options created in
294         // JavacProcessingEnvironment
295         @Override
296         public boolean process(OptionHelper helper, String option) {
297             int argLength = option.length();
298             if (argLength == 2) {
299                 helper.error("err.empty.A.argument");
300                 return true;
301             }
302             int sepIndex = option.indexOf('=');
303             String key = option.substring(2, (sepIndex != -1 ? sepIndex : argLength) );
304             if (!JavacProcessingEnvironment.isValidOptionName(key)) {
305                 helper.error("err.invalid.A.key", option);
306                 return true;
307             }
308             return process(helper, option, option);
309         }
310     },
311 
312     X("-X", "opt.X", STANDARD, INFO) {
313         @Override
314         public boolean process(OptionHelper helper, String option) {
315             Log log = helper.getLog();
316             for (Option o: getJavaCompilerOptions()) {
317                 o.help(log, OptionKind.EXTENDED);
318             }
319             log.printNewline();
320             log.printLines(PrefixKind.JAVAC, "msg.usage.nonstandard.footer");
321             return super.process(helper, option);
322         }
323     },
324 
325     // This option exists only for the purpose of documenting itself.
326     // It's actually implemented by the launcher.
327     J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO, true) {
328         @Override
329         public boolean process(OptionHelper helper, String option) {
330             throw new AssertionError
331                 ("the -J flag should be caught by the launcher.");
332         }
333     },
334 
335     MOREINFO("-moreinfo", null, HIDDEN, BASIC) {
336         @Override
337         public boolean process(OptionHelper helper, String option) {
338             Type.moreInfo = true;
339             return super.process(helper, option);
340         }
341     },
342 
343     // treat warnings as errors
344     WERROR("-Werror", "opt.Werror", STANDARD, BASIC),
345 
346     // prompt after each error
347     // new Option("-prompt",                                        "opt.prompt"),
348     PROMPT("-prompt", null, HIDDEN, BASIC),
349 
350     // dump stack on error
351     DOE("-doe", null, HIDDEN, BASIC),
352 
353     // output source after type erasure
354     PRINTSOURCE("-printsource", null, HIDDEN, BASIC),
355 
356     // display warnings for generic unchecked operations
357     WARNUNCHECKED("-warnunchecked", null, HIDDEN, BASIC) {
358         @Override
359         public boolean process(OptionHelper helper, String option) {
360             helper.put("-Xlint:unchecked", option);
361             return false;
362         }
363     },
364 
365     XMAXERRS("-Xmaxerrs", "opt.arg.number", "opt.maxerrs", EXTENDED, BASIC),
366 
367     XMAXWARNS("-Xmaxwarns", "opt.arg.number", "opt.maxwarns", EXTENDED, BASIC),
368 
369     XSTDOUT("-Xstdout", "opt.arg.file", "opt.Xstdout", EXTENDED, INFO) {
370         @Override
371         public boolean process(OptionHelper helper, String option, String arg) {
372             try {
373                 Log log = helper.getLog();
374                 // TODO: this file should be closed at the end of compilation
375                 log.setWriters(new PrintWriter(new FileWriter(arg), true));
376             } catch (java.io.IOException e) {
377                 helper.error("err.error.writing.file", arg, e);
378                 return true;
379             }
380             return super.process(helper, option, arg);
381         }
382     },
383 
384     XPRINT("-Xprint", "opt.print", EXTENDED, BASIC),
385 
386     XPRINTROUNDS("-XprintRounds", "opt.printRounds", EXTENDED, BASIC),
387 
388     XPRINTPROCESSORINFO("-XprintProcessorInfo", "opt.printProcessorInfo", EXTENDED, BASIC),
389 
390     XPREFER("-Xprefer:", "opt.prefer", EXTENDED, BASIC, ONEOF, "source", "newer"),
391 
392     // see enum PkgInfo
393     XPKGINFO("-Xpkginfo:", "opt.pkginfo", EXTENDED, BASIC, ONEOF, "always", "legacy", "nonempty"),
394 
395     /* -O is a no-op, accepted for backward compatibility. */
396     O("-O", null, HIDDEN, BASIC),
397 
398     /* -Xjcov produces tables to support the code coverage tool jcov. */
399     XJCOV("-Xjcov", null, HIDDEN, BASIC),
400 
401     PLUGIN("-Xplugin:", "opt.arg.plugin", "opt.plugin", EXTENDED, BASIC) {
402         @Override
403         public boolean process(OptionHelper helper, String option) {
404             String p = option.substring(option.indexOf(':') + 1);
405             String prev = helper.get(PLUGIN);
406             helper.put(PLUGIN.text, (prev == null) ? p : prev + '\0' + p.trim());
407             return false;
408         }
409     },
410 
411     XDIAGS("-Xdiags:", "opt.diags", EXTENDED, BASIC, ONEOF, "compact", "verbose"),
412 
413     /* This is a back door to the compiler's option table.
414      * -XDx=y sets the option x to the value y.
415      * -XDx sets the option x to the value x.
416      */
417     XD("-XD", null, HIDDEN, BASIC) {
418         @Override
419         public boolean matches(String s) {
420             return s.startsWith(text);
421         }
422         @Override
423         public boolean process(OptionHelper helper, String option) {
424             option = option.substring(text.length());
425             int eq = option.indexOf('=');
426             String key = (eq < 0) ? option : option.substring(0, eq);
427             String value = (eq < 0) ? option : option.substring(eq+1);
428             helper.put(key, value);
429             return false;
430         }
431     },
432 
433     // This option exists only for the purpose of documenting itself.
434     // It's actually implemented by the CommandLine class.
435     AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO, true) {
436         @Override
437         public boolean process(OptionHelper helper, String option) {
438             throw new AssertionError("the @ flag should be caught by CommandLine.");
439         }
440     },
441 
442     /*
443      * TODO: With apt, the matches method accepts anything if
444      * -XclassAsDecls is used; code elsewhere does the lookup to
445      * see if the class name is both legal and found.
446      *
447      * In apt, the process method adds the candidate class file
448      * name to a separate list.
449      */
450     SOURCEFILE("sourcefile", null, HIDDEN, INFO) {
451         @Override
452         public boolean matches(String s) {
453             return s.endsWith(".java")  // Java source file
454                 || SourceVersion.isName(s);   // Legal type name
455         }
456         @Override
457         public boolean process(OptionHelper helper, String option) {
458             if (option.endsWith(".java") ) {
459                 File f = new File(option);
460                 if (!f.exists()) {
461                     helper.error("err.file.not.found", f);
462                     return true;
463                 }
464                 if (!f.isFile()) {
465                     helper.error("err.file.not.file", f);
466                     return true;
467                 }
468                 helper.addFile(f);
469             } else {
470                 helper.addClassName(option);
471             }
472             return false;
473         }
474     };
475 
476     /** The kind of an Option. This is used by the -help and -X options. */
477     public enum OptionKind {
478         /** A standard option, documented by -help. */
479         STANDARD,
480         /** An extended option, documented by -X. */
481         EXTENDED,
482         /** A hidden option, not documented. */
483         HIDDEN,
484     }
485 
486     /** The group for an Option. This determines the situations in which the
487      *  option is applicable. */
488     enum OptionGroup {
489         /** A basic option, available for use on the command line or via the
490          *  Compiler API. */
491         BASIC,
492         /** An option for javac's standard JavaFileManager. Other file managers
493          *  may or may not support these options. */
494         FILEMANAGER,
495         /** A command-line option that requests information, such as -help. */
496         INFO,
497         /** A command-line "option" representing a file or class name. */
498         OPERAND
499     }
500 
501     /** The kind of choice for "choice" options. */
502     enum ChoiceKind {
503         /** The expected value is exactly one of the set of choices. */
504         ONEOF,
505         /** The expected value is one of more of the set of choices. */
506         ANYOF
507     }
508 
509     public final String text;
510 
511     final OptionKind kind;
512 
513     final OptionGroup group;
514 
515     /** Documentation key for arguments.
516      */
517     final String argsNameKey;
518 
519     /** Documentation key for description.
520      */
521     final String descrKey;
522 
523     /** Suffix option (-foo=bar or -foo:bar)
524      */
525     final boolean hasSuffix;
526 
527     /** The kind of choices for this option, if any.
528      */
529     final ChoiceKind choiceKind;
530 
531     /** The choices for this option, if any, and whether or not the choices
532      *  are hidden
533      */
534     final Map<String,Boolean> choices;
535 
536 
537     Option(String text, String descrKey,
538             OptionKind kind, OptionGroup group) {
539         this(text, null, descrKey, kind, group, null, null, false);
540     }
541 
542     Option(String text, String argsNameKey, String descrKey,
543             OptionKind kind, OptionGroup group) {
544         this(text, argsNameKey, descrKey, kind, group, null, null, false);
545     }
546 
547     Option(String text, String argsNameKey, String descrKey,
548             OptionKind kind, OptionGroup group, boolean doHasSuffix) {
549         this(text, argsNameKey, descrKey, kind, group, null, null, doHasSuffix);
550     }
551 
552     Option(String text, String descrKey,
553             OptionKind kind, OptionGroup group,
554             ChoiceKind choiceKind, Map<String,Boolean> choices) {
555         this(text, null, descrKey, kind, group, choiceKind, choices, false);
556     }
557 
558     Option(String text, String descrKey,
559             OptionKind kind, OptionGroup group,
560             ChoiceKind choiceKind, String... choices) {
561         this(text, null, descrKey, kind, group, choiceKind,
562                 createChoices(choices), false);
563     }
564     // where
565         private static Map<String,Boolean> createChoices(String... choices) {
566             Map<String,Boolean> map = new LinkedHashMap<String,Boolean>();
567             for (String c: choices)
568                 map.put(c, false);
569             return map;
570         }
571 
572     private Option(String text, String argsNameKey, String descrKey,
573             OptionKind kind, OptionGroup group,
574             ChoiceKind choiceKind, Map<String,Boolean> choices,
575             boolean doHasSuffix) {
576         this.text = text;
577         this.argsNameKey = argsNameKey;
578         this.descrKey = descrKey;
579         this.kind = kind;
580         this.group = group;
581         this.choiceKind = choiceKind;
582         this.choices = choices;
583         char lastChar = text.charAt(text.length()-1);
584         this.hasSuffix = doHasSuffix || lastChar == ':' || lastChar == '=';
585     }
586 
587     public String getText() {
588         return text;
589     }
590 
591     public OptionKind getKind() {
592         return kind;
593     }
594 
595     public boolean hasArg() {
596         return argsNameKey != null && !hasSuffix;
597     }
598 
599     public boolean matches(String option) {
600         if (!hasSuffix)
601             return option.equals(text);
602 
603         if (!option.startsWith(text))
604             return false;
605 
606         if (choices != null) {
607             String arg = option.substring(text.length());
608             if (choiceKind == ChoiceKind.ONEOF)
609                 return choices.keySet().contains(arg);
610             else {
611                 for (String a: arg.split(",+")) {
612                     if (!choices.keySet().contains(a))
613                         return false;
614                 }
615             }
616         }
617 
618         return true;
619     }
620 
621     public boolean process(OptionHelper helper, String option, String arg) {
622         if (choices != null) {
623             if (choiceKind == ChoiceKind.ONEOF) {
624                 // some clients like to see just one of option+choice set
625                 for (String s: choices.keySet())
626                     helper.remove(option + s);
627                 String opt = option + arg;
628                 helper.put(opt, opt);
629                 // some clients like to see option (without trailing ":")
630                 // set to arg
631                 String nm = option.substring(0, option.length() - 1);
632                 helper.put(nm, arg);
633             } else {
634                 // set option+word for each word in arg
635                 for (String a: arg.split(",+")) {
636                     String opt = option + a;
637                     helper.put(opt, opt);
638                 }
639             }
640         }
641         helper.put(option, arg);
642         return false;
643     }
644 
645     public boolean process(OptionHelper helper, String option) {
646         if (hasSuffix)
647             return process(helper, text, option.substring(text.length()));
648         else
649             return process(helper, option, option);
650     }
651 
652     void help(Log log, OptionKind kind) {
653         if (this.kind != kind)
654             return;
655 
656         log.printRawLines(WriterKind.NOTICE,
657                 String.format("  %-26s %s",
658                     helpSynopsis(log),
659                     log.localize(PrefixKind.JAVAC, descrKey)));
660 
661     }
662 
663     private String helpSynopsis(Log log) {
664         StringBuilder sb = new StringBuilder();
665         sb.append(text);
666         if (argsNameKey == null) {
667             if (choices != null) {
668                 String sep = "{";
669                 for (Map.Entry<String,Boolean> e: choices.entrySet()) {
670                     if (!e.getValue()) {
671                         sb.append(sep);
672                         sb.append(e.getKey());
673                         sep = ",";
674                     }
675                 }
676                 sb.append("}");
677             }
678         } else {
679             if (!hasSuffix)
680                 sb.append(" ");
681             sb.append(log.localize(PrefixKind.JAVAC, argsNameKey));
682 
683         }
684 
685         return sb.toString();
686     }
687 
688     // For -XpkgInfo:value
689     public enum PkgInfo {
690         /**
691          * Always generate package-info.class for every package-info.java file.
692          * The file may be empty if there annotations with a RetentionPolicy
693          * of CLASS or RUNTIME.  This option may be useful in conjunction with
694          * build systems (such as Ant) that expect javac to generate at least
695          * one .class file for every .java file.
696          */
697         ALWAYS,
698         /**
699          * Generate a package-info.class file if package-info.java contains
700          * annotations. The file may be empty if all the annotations have
701          * a RetentionPolicy of SOURCE.
702          * This value is just for backwards compatibility with earlier behavior.
703          * Either of the other two values are to be preferred to using this one.
704          */
705         LEGACY,
706         /**
707          * Generate a package-info.class file if and only if there are annotations
708          * in package-info.java to be written into it.
709          */
710         NONEMPTY;
711 
712         public static PkgInfo get(Options options) {
713             String v = options.get(XPKGINFO);
714             return (v == null
715                     ? PkgInfo.LEGACY
716                     : PkgInfo.valueOf(v.toUpperCase()));
717         }
718     }
719 
720     private static Map<String,Boolean> getXLintChoices() {
721         Map<String,Boolean> choices = new LinkedHashMap<String,Boolean>();
722         choices.put("all", false);
723         for (Lint.LintCategory c : Lint.LintCategory.values())
724             choices.put(c.option, c.hidden);
725         for (Lint.LintCategory c : Lint.LintCategory.values())
726             choices.put("-" + c.option, c.hidden);
727         choices.put("none", false);
728         return choices;
729     }
730 
731     static Set<Option> getJavaCompilerOptions() {
732         return EnumSet.allOf(Option.class);
733     }
734 
735     public static Set<Option> getJavacFileManagerOptions() {
736         return getOptions(EnumSet.of(FILEMANAGER));
737     }
738 
739     public static Set<Option> getJavacToolOptions() {
740         return getOptions(EnumSet.of(BASIC));
741     }
742 
743     static Set<Option> getOptions(Set<OptionGroup> desired) {
744         Set<Option> options = EnumSet.noneOf(Option.class);
745         for (Option option : Option.values())
746             if (desired.contains(option.group))
747                 options.add(option);
748         return Collections.unmodifiableSet(options);
749     }
750 
751 }