Option.java revision 2599:50b448c5be54
117680Spst/* 298527Sfenner * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. 398527Sfenner * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 498527Sfenner * 598527Sfenner * This code is free software; you can redistribute it and/or modify it 698527Sfenner * under the terms of the GNU General Public License version 2 only, as 798527Sfenner * published by the Free Software Foundation. Oracle designates this 898527Sfenner * particular file as subject to the "Classpath" exception as provided 998527Sfenner * by Oracle in the LICENSE file that accompanied this code. 1098527Sfenner * 1198527Sfenner * This code is distributed in the hope that it will be useful, but WITHOUT 1298527Sfenner * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1398527Sfenner * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1498527Sfenner * version 2 for more details (a copy is included in the LICENSE file that 1598527Sfenner * accompanied this code). 1698527Sfenner * 1798527Sfenner * You should have received a copy of the GNU General Public License version 1898527Sfenner * 2 along with this work; if not, write to the Free Software Foundation, 1998527Sfenner * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2098527Sfenner * 2198527Sfenner * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2298527Sfenner * or visit www.oracle.com if you need additional information or have any 2398527Sfenner * questions. 2498527Sfenner */ 2598527Sfenner 2698527Sfennerpackage com.sun.tools.javac.main; 2798527Sfenner 2898527Sfennerimport java.io.File; 2998527Sfennerimport java.io.FileWriter; 3098527Sfennerimport java.io.PrintWriter; 3198527Sfennerimport java.util.Collections; 3298527Sfennerimport java.util.EnumSet; 3398527Sfennerimport java.util.LinkedHashMap; 3498527Sfennerimport java.util.Map; 3517680Spstimport java.util.Set; 3617680Spst 3717680Spstimport javax.lang.model.SourceVersion; 3817680Spst 3917680Spstimport com.sun.tools.doclint.DocLint; 4017680Spstimport com.sun.tools.javac.code.Lint; 4156896Sfennerimport com.sun.tools.javac.code.Lint.LintCategory; 4256896Sfennerimport com.sun.tools.javac.code.Source; 4317680Spstimport com.sun.tools.javac.code.Type; 4417680Spstimport com.sun.tools.javac.jvm.Profile; 4526183Sfennerimport com.sun.tools.javac.jvm.Target; 4626183Sfennerimport com.sun.tools.javac.processing.JavacProcessingEnvironment; 4798527Sfennerimport com.sun.tools.javac.util.Log; 4826183Sfennerimport com.sun.tools.javac.util.Log.PrefixKind; 4926183Sfennerimport com.sun.tools.javac.util.Log.WriterKind; 5056896Sfennerimport com.sun.tools.javac.util.Options; 5156896Sfennerimport com.sun.tools.javac.util.StringUtils; 5256896Sfennerimport static com.sun.tools.javac.main.Option.ChoiceKind.*; 5356896Sfennerimport static com.sun.tools.javac.main.Option.OptionGroup.*; 5417680Spstimport static com.sun.tools.javac.main.Option.OptionKind.*; 5517680Spst 5617680Spst/** 5717680Spst * Options for javac. The specific Option to handle a command-line option 5817680Spst * is identified by searching the members of this enum in order, looking for 5917680Spst * the first {@link #matches match}. The action for an Option is performed 6017680Spst * by calling {@link #process process}, and by providing a suitable 6117680Spst * {@link OptionHelper} to provide access the compiler state. 6217680Spst * 6317680Spst * <p><b>This is NOT part of any supported API. 6417680Spst * If you write code that depends on this, you do so at your own 6517680Spst * risk. This code and its internal interfaces are subject to change 6617680Spst * or deletion without notice.</b></p> 6717680Spst */ 6817680Spstpublic enum Option { 6917680Spst G("-g", "opt.g", STANDARD, BASIC), 7017680Spst 7117680Spst G_NONE("-g:none", "opt.g.none", STANDARD, BASIC) { 7217680Spst @Override 7317680Spst public boolean process(OptionHelper helper, String option) { 7417680Spst helper.put("-g:", "none"); 7517680Spst return false; 7617680Spst } 7717680Spst }, 7817680Spst 7917680Spst G_CUSTOM("-g:", "opt.g.lines.vars.source", 8017680Spst STANDARD, BASIC, ANYOF, "lines", "vars", "source"), 8117680Spst 8217680Spst XLINT("-Xlint", "opt.Xlint", EXTENDED, BASIC), 8317680Spst 8417680Spst XLINT_CUSTOM("-Xlint:", EXTENDED, BASIC, ANYOF, getXLintChoices()) { 8517680Spst private static final String LINT_KEY_FORMAT = " %-19s %s"; 8617680Spst @Override 8717680Spst void help(Log log, OptionKind kind) { 8817680Spst if (this.kind != kind) 8917680Spst return; 9017680Spst 9117680Spst log.printRawLines(WriterKind.NOTICE, 9217680Spst String.format(HELP_LINE_FORMAT, 9317680Spst log.localize(PrefixKind.JAVAC, "opt.Xlint.subopts"), 9417680Spst log.localize(PrefixKind.JAVAC, "opt.Xlint.suboptlist"))); 9517680Spst log.printRawLines(WriterKind.NOTICE, 9617680Spst String.format(LINT_KEY_FORMAT, 9717680Spst "all", 9817680Spst log.localize(PrefixKind.JAVAC, "opt.Xlint.all"))); 9917680Spst for (LintCategory lc : LintCategory.values()) { 10017680Spst if (lc.hidden) continue; 10117680Spst log.printRawLines(WriterKind.NOTICE, 10217680Spst String.format(LINT_KEY_FORMAT, 10317680Spst lc.option, 10417680Spst log.localize(PrefixKind.JAVAC, 10517680Spst "opt.Xlint.desc." + lc.option))); 10617680Spst } 10717680Spst log.printRawLines(WriterKind.NOTICE, 10817680Spst String.format(LINT_KEY_FORMAT, 10917680Spst "none", 11017680Spst log.localize(PrefixKind.JAVAC, "opt.Xlint.none"))); 11117680Spst } 11217680Spst }, 11317680Spst 11417680Spst XDOCLINT("-Xdoclint", "opt.Xdoclint", EXTENDED, BASIC), 11517680Spst 11618976Sdfr XDOCLINT_CUSTOM("-Xdoclint:", "opt.Xdoclint.subopts", "opt.Xdoclint.custom", EXTENDED, BASIC) { 11717680Spst @Override 11818976Sdfr public boolean matches(String option) { 11917680Spst return DocLint.isValidOption( 12017680Spst option.replace(XDOCLINT_CUSTOM.text, DocLint.XMSGS_CUSTOM_PREFIX)); 12198527Sfenner } 12298527Sfenner 12317680Spst @Override 12417680Spst public boolean process(OptionHelper helper, String option) { 12517680Spst String prev = helper.get(XDOCLINT_CUSTOM); 12617680Spst String next = (prev == null) ? option : (prev + " " + option); 12717680Spst helper.put(XDOCLINT_CUSTOM.text, next); 12875118Sfenner return false; 12917680Spst } 13017680Spst }, 13117680Spst 13217680Spst // -nowarn is retained for command-line backward compatibility 13317680Spst NOWARN("-nowarn", "opt.nowarn", STANDARD, BASIC) { 13417680Spst @Override 13517680Spst public boolean process(OptionHelper helper, String option) { 13617680Spst helper.put("-Xlint:none", option); 13717680Spst return false; 13817680Spst } 13917680Spst }, 14017680Spst 14117680Spst VERBOSE("-verbose", "opt.verbose", STANDARD, BASIC), 14217680Spst 14317680Spst // -deprecation is retained for command-line backward compatibility 14417680Spst DEPRECATION("-deprecation", "opt.deprecation", STANDARD, BASIC) { 14517680Spst @Override 14617680Spst public boolean process(OptionHelper helper, String option) { 14717680Spst helper.put("-Xlint:deprecation", option); 14817680Spst return false; 14917680Spst } 15017680Spst }, 15117680Spst 15217680Spst CLASSPATH("-classpath", "opt.arg.path", "opt.classpath", STANDARD, FILEMANAGER), 15317680Spst 15417680Spst CP("-cp", "opt.arg.path", "opt.classpath", STANDARD, FILEMANAGER) { 15517680Spst @Override 15617680Spst public boolean process(OptionHelper helper, String option, String arg) { 15717680Spst return super.process(helper, "-classpath", arg); 15817680Spst } 15917680Spst }, 16017680Spst 16117680Spst SOURCEPATH("-sourcepath", "opt.arg.path", "opt.sourcepath", STANDARD, FILEMANAGER), 16217680Spst 16317680Spst BOOTCLASSPATH("-bootclasspath", "opt.arg.path", "opt.bootclasspath", STANDARD, FILEMANAGER) { 16417680Spst @Override 16517680Spst public boolean process(OptionHelper helper, String option, String arg) { 16617680Spst helper.remove("-Xbootclasspath/p:"); 16717680Spst helper.remove("-Xbootclasspath/a:"); 16817680Spst return super.process(helper, option, arg); 16917680Spst } 17017680Spst }, 17117680Spst 17217680Spst XBOOTCLASSPATH_PREPEND("-Xbootclasspath/p:", "opt.arg.path", "opt.Xbootclasspath.p", EXTENDED, FILEMANAGER), 17317680Spst 17417680Spst XBOOTCLASSPATH_APPEND("-Xbootclasspath/a:", "opt.arg.path", "opt.Xbootclasspath.a", EXTENDED, FILEMANAGER), 17517680Spst 17617680Spst XBOOTCLASSPATH("-Xbootclasspath:", "opt.arg.path", "opt.bootclasspath", EXTENDED, FILEMANAGER) { 17717680Spst @Override 17817680Spst public boolean process(OptionHelper helper, String option, String arg) { 17917680Spst helper.remove("-Xbootclasspath/p:"); 18017680Spst helper.remove("-Xbootclasspath/a:"); 18117680Spst return super.process(helper, "-bootclasspath", arg); 18217680Spst } 18317680Spst }, 18417680Spst 18517680Spst EXTDIRS("-extdirs", "opt.arg.dirs", "opt.extdirs", STANDARD, FILEMANAGER), 18617680Spst 18717680Spst DJAVA_EXT_DIRS("-Djava.ext.dirs=", "opt.arg.dirs", "opt.extdirs", EXTENDED, FILEMANAGER) { 18817680Spst @Override 18917680Spst public boolean process(OptionHelper helper, String option, String arg) { 19017680Spst return super.process(helper, "-extdirs", arg); 19117680Spst } 19217680Spst }, 19317680Spst 19417680Spst ENDORSEDDIRS("-endorseddirs", "opt.arg.dirs", "opt.endorseddirs", STANDARD, FILEMANAGER), 19517680Spst 19617680Spst DJAVA_ENDORSED_DIRS("-Djava.endorsed.dirs=", "opt.arg.dirs", "opt.endorseddirs", EXTENDED, FILEMANAGER) { 19717680Spst @Override 19817680Spst public boolean process(OptionHelper helper, String option, String arg) { 19917680Spst return super.process(helper, "-endorseddirs", arg); 20017680Spst } 20117680Spst }, 20217680Spst 20317680Spst PROC("-proc:", "opt.proc.none.only", STANDARD, BASIC, ONEOF, "none", "only"), 20417680Spst 20517680Spst PROCESSOR("-processor", "opt.arg.class.list", "opt.processor", STANDARD, BASIC), 20617680Spst 20717680Spst PROCESSORPATH("-processorpath", "opt.arg.path", "opt.processorpath", STANDARD, FILEMANAGER), 20817680Spst 20917680Spst PARAMETERS("-parameters","opt.parameters", STANDARD, BASIC), 21017680Spst 21117680Spst D("-d", "opt.arg.directory", "opt.d", STANDARD, FILEMANAGER), 21217680Spst 21317680Spst S("-s", "opt.arg.directory", "opt.sourceDest", STANDARD, FILEMANAGER), 21417680Spst 21517680Spst H("-h", "opt.arg.directory", "opt.headerDest", STANDARD, FILEMANAGER), 21617680Spst 21717680Spst IMPLICIT("-implicit:", "opt.implicit", STANDARD, BASIC, ONEOF, "none", "class"), 21817680Spst 21917680Spst ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER) { 22017680Spst @Override 22117680Spst public boolean process(OptionHelper helper, String option, String operand) { 22217680Spst return super.process(helper, option, operand); 22317680Spst } 22417680Spst 22517680Spst }, 22617680Spst 22717680Spst SOURCE("-source", "opt.arg.release", "opt.source", STANDARD, BASIC) { 22817680Spst @Override 22917680Spst public boolean process(OptionHelper helper, String option, String operand) { 23017680Spst Source source = Source.lookup(operand); 23117680Spst if (source == null) { 23217680Spst helper.error("err.invalid.source", operand); 23317680Spst return true; 23417680Spst } 23517680Spst return super.process(helper, option, operand); 23617680Spst } 23717680Spst }, 23817680Spst 23917680Spst TARGET("-target", "opt.arg.release", "opt.target", STANDARD, BASIC) { 24017680Spst @Override 24117680Spst public boolean process(OptionHelper helper, String option, String operand) { 24217680Spst Target target = Target.lookup(operand); 24317680Spst if (target == null) { 24417680Spst helper.error("err.invalid.target", operand); 24517680Spst return true; 24617680Spst } 24717680Spst return super.process(helper, option, operand); 24817680Spst } 24917680Spst }, 25017680Spst 25117680Spst PROFILE("-profile", "opt.arg.profile", "opt.profile", STANDARD, BASIC) { 25217680Spst @Override 25317680Spst public boolean process(OptionHelper helper, String option, String operand) { 25417680Spst Profile profile = Profile.lookup(operand); 25517680Spst if (profile == null) { 25617680Spst helper.error("err.invalid.profile", operand); 25717680Spst return true; 25817680Spst } 25926183Sfenner return super.process(helper, option, operand); 26026183Sfenner } 26117680Spst }, 26217680Spst 26317680Spst VERSION("-version", "opt.version", STANDARD, INFO) { 26417680Spst @Override 26517680Spst public boolean process(OptionHelper helper, String option) { 26617680Spst Log log = helper.getLog(); 26717680Spst String ownName = helper.getOwnName(); 26817680Spst log.printLines(PrefixKind.JAVAC, "version", ownName, JavaCompiler.version()); 26917680Spst return super.process(helper, option); 27017680Spst } 27117680Spst }, 27217680Spst 27317680Spst FULLVERSION("-fullversion", null, HIDDEN, INFO) { 27417680Spst @Override 27526183Sfenner public boolean process(OptionHelper helper, String option) { 27626183Sfenner Log log = helper.getLog(); 27717680Spst String ownName = helper.getOwnName(); 27817680Spst log.printLines(PrefixKind.JAVAC, "fullVersion", ownName, JavaCompiler.fullVersion()); 27917680Spst return super.process(helper, option); 28017680Spst } 28117680Spst }, 28217680Spst 28317680Spst DIAGS("-XDdiags=", null, HIDDEN, INFO) { 28417680Spst @Override 28526183Sfenner public boolean process(OptionHelper helper, String option) { 28626183Sfenner option = option.substring(option.indexOf('=') + 1); 28717680Spst String diagsOption = option.contains("%") ? 28817680Spst "-XDdiagsFormat=" : 28917680Spst "-XDdiags="; 29017680Spst diagsOption += option; 29117680Spst if (XD.matches(diagsOption)) 29217680Spst return XD.process(helper, diagsOption); 29317680Spst else 29417680Spst return false; 29517680Spst } 29617680Spst }, 29726183Sfenner 29826183Sfenner HELP("-help", "opt.help", STANDARD, INFO) { 29917680Spst @Override 30017680Spst public boolean process(OptionHelper helper, String option) { 30117680Spst Log log = helper.getLog(); 30217680Spst String ownName = helper.getOwnName(); 30317680Spst log.printLines(PrefixKind.JAVAC, "msg.usage.header", ownName); 30417680Spst for (Option o: getJavaCompilerOptions()) { 30517680Spst o.help(log, OptionKind.STANDARD); 30617680Spst } 30717680Spst log.printNewline(); 30817680Spst return super.process(helper, option); 30917680Spst } 31017680Spst }, 31117680Spst 31217680Spst A("-A", "opt.arg.key.equals.value", "opt.A", STANDARD, BASIC, true) { 31317680Spst @Override 31426183Sfenner public boolean matches(String arg) { 31526183Sfenner return arg.startsWith("-A"); 31617680Spst } 31717680Spst 31817680Spst @Override 31917680Spst public boolean hasArg() { 32017680Spst return false; 32117680Spst } 32217680Spst // Mapping for processor options created in 32317680Spst // JavacProcessingEnvironment 32417680Spst @Override 32517680Spst public boolean process(OptionHelper helper, String option) { 32617680Spst int argLength = option.length(); 32726183Sfenner if (argLength == 2) { 32817680Spst helper.error("err.empty.A.argument"); 32926183Sfenner return true; 33017680Spst } 33117680Spst int sepIndex = option.indexOf('='); 33217680Spst String key = option.substring(2, (sepIndex != -1 ? sepIndex : argLength) ); 33317680Spst if (!JavacProcessingEnvironment.isValidOptionName(key)) { 33417680Spst helper.error("err.invalid.A.key", option); 33517680Spst return true; 33617680Spst } 33717680Spst return process(helper, option, option); 33817680Spst } 33917680Spst }, 34017680Spst 34126183Sfenner X("-X", "opt.X", STANDARD, INFO) { 34226183Sfenner @Override 34317680Spst public boolean process(OptionHelper helper, String option) { 34417680Spst Log log = helper.getLog(); 34517680Spst for (Option o: getJavaCompilerOptions()) { 34617680Spst o.help(log, OptionKind.EXTENDED); 34717680Spst } 34817680Spst log.printNewline(); 34917680Spst log.printLines(PrefixKind.JAVAC, "msg.usage.nonstandard.footer"); 35017680Spst return super.process(helper, option); 35117680Spst } 35217680Spst }, 35317680Spst 35417680Spst // This option exists only for the purpose of documenting itself. 35539300Sfenner // It's actually implemented by the launcher. 35639300Sfenner J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO, true) { 35717680Spst @Override 35817680Spst public boolean process(OptionHelper helper, String option) { 35917680Spst throw new AssertionError 36017680Spst ("the -J flag should be caught by the launcher."); 36117680Spst } 36239300Sfenner }, 36326183Sfenner 36426183Sfenner MOREINFO("-moreinfo", null, HIDDEN, BASIC) { 36517680Spst @Override 36617680Spst public boolean process(OptionHelper helper, String option) { 36717680Spst Type.moreInfo = true; 36817680Spst return super.process(helper, option); 36917680Spst } 37017680Spst }, 37117680Spst 37217680Spst // treat warnings as errors 37317680Spst WERROR("-Werror", "opt.Werror", STANDARD, BASIC), 37417680Spst 37517680Spst // prompt after each error 37617680Spst // new Option("-prompt", "opt.prompt"), 37717680Spst PROMPT("-prompt", null, HIDDEN, BASIC), 37817680Spst 37917680Spst // dump stack on error 38026183Sfenner DOE("-doe", null, HIDDEN, BASIC), 38126183Sfenner 38217680Spst // output source after type erasure 38317680Spst PRINTSOURCE("-printsource", null, HIDDEN, BASIC), 38417680Spst 38517680Spst // display warnings for generic unchecked operations 38617680Spst WARNUNCHECKED("-warnunchecked", null, HIDDEN, BASIC) { 38717680Spst @Override 38817680Spst public boolean process(OptionHelper helper, String option) { 38917680Spst helper.put("-Xlint:unchecked", option); 39017680Spst return false; 39117680Spst } 39226183Sfenner }, 39317680Spst 39426183Sfenner XMAXERRS("-Xmaxerrs", "opt.arg.number", "opt.maxerrs", EXTENDED, BASIC), 39517680Spst 39617680Spst XMAXWARNS("-Xmaxwarns", "opt.arg.number", "opt.maxwarns", EXTENDED, BASIC), 39717680Spst 39817680Spst XSTDOUT("-Xstdout", "opt.arg.file", "opt.Xstdout", EXTENDED, INFO) { 39917680Spst @Override 40017680Spst public boolean process(OptionHelper helper, String option, String arg) { 40117680Spst try { 40217680Spst Log log = helper.getLog(); 40317680Spst log.setWriters(new PrintWriter(new FileWriter(arg), true)); 40417680Spst } catch (java.io.IOException e) { 40517680Spst helper.error("err.error.writing.file", arg, e); 40675118Sfenner return true; 40775118Sfenner } 40875118Sfenner return super.process(helper, option, arg); 40975118Sfenner } 41017680Spst }, 41175118Sfenner 41275118Sfenner XPRINT("-Xprint", "opt.print", EXTENDED, BASIC), 41398527Sfenner 41475118Sfenner XPRINTROUNDS("-XprintRounds", "opt.printRounds", EXTENDED, BASIC), 41598527Sfenner 41617680Spst XPRINTPROCESSORINFO("-XprintProcessorInfo", "opt.printProcessorInfo", EXTENDED, BASIC), 41726183Sfenner 41826183Sfenner XPREFER("-Xprefer:", "opt.prefer", EXTENDED, BASIC, ONEOF, "source", "newer"), 41917680Spst 42017680Spst XXUSERPATHSFIRST("-XXuserPathsFirst", "opt.userpathsfirst", HIDDEN, BASIC), 42117680Spst 42217680Spst // see enum PkgInfo 42317680Spst XPKGINFO("-Xpkginfo:", "opt.pkginfo", EXTENDED, BASIC, ONEOF, "always", "legacy", "nonempty"), 42417680Spst 42517680Spst /* -O is a no-op, accepted for backward compatibility. */ 42617680Spst O("-O", null, HIDDEN, BASIC), 42717680Spst 42817680Spst /* -Xjcov produces tables to support the code coverage tool jcov. */ 42917680Spst XJCOV("-Xjcov", null, HIDDEN, BASIC), 43017680Spst 43117680Spst PLUGIN("-Xplugin:", "opt.arg.plugin", "opt.plugin", EXTENDED, BASIC) { 43217680Spst @Override 43317680Spst public boolean process(OptionHelper helper, String option) { 43417680Spst String p = option.substring(option.indexOf(':') + 1); 43517680Spst String prev = helper.get(PLUGIN); 43617680Spst helper.put(PLUGIN.text, (prev == null) ? p : prev + '\0' + p.trim()); 43717680Spst return false; 43817680Spst } 43917680Spst }, 44017680Spst 44117680Spst XDIAGS("-Xdiags:", "opt.diags", EXTENDED, BASIC, ONEOF, "compact", "verbose"), 44217680Spst 44317680Spst /* This is a back door to the compiler's option table. 44417680Spst * -XDx=y sets the option x to the value y. 44517680Spst * -XDx sets the option x to the value x. 44617680Spst */ 44717680Spst XD("-XD", null, HIDDEN, BASIC) { 44817680Spst @Override 44917680Spst public boolean matches(String s) { 45017680Spst return s.startsWith(text); 45117680Spst } 45217680Spst @Override 45317680Spst public boolean process(OptionHelper helper, String option) { 45417680Spst option = option.substring(text.length()); 45517680Spst int eq = option.indexOf('='); 45617680Spst String key = (eq < 0) ? option : option.substring(0, eq); 45717680Spst String value = (eq < 0) ? option : option.substring(eq+1); 45817680Spst helper.put(key, value); 45917680Spst return false; 46017680Spst } 46117680Spst }, 46217680Spst 463 // This option exists only for the purpose of documenting itself. 464 // It's actually implemented by the CommandLine class. 465 AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO, true) { 466 @Override 467 public boolean process(OptionHelper helper, String option) { 468 throw new AssertionError("the @ flag should be caught by CommandLine."); 469 } 470 }, 471 472 /* 473 * TODO: With apt, the matches method accepts anything if 474 * -XclassAsDecls is used; code elsewhere does the lookup to 475 * see if the class name is both legal and found. 476 * 477 * In apt, the process method adds the candidate class file 478 * name to a separate list. 479 */ 480 SOURCEFILE("sourcefile", null, HIDDEN, INFO) { 481 @Override 482 public boolean matches(String s) { 483 return s.endsWith(".java") // Java source file 484 || SourceVersion.isName(s); // Legal type name 485 } 486 @Override 487 public boolean process(OptionHelper helper, String option) { 488 if (option.endsWith(".java") ) { 489 File f = new File(option); 490 if (!f.exists()) { 491 helper.error("err.file.not.found", f); 492 return true; 493 } 494 if (!f.isFile()) { 495 helper.error("err.file.not.file", f); 496 return true; 497 } 498 helper.addFile(f); 499 } else { 500 helper.addClassName(option); 501 } 502 return false; 503 } 504 }; 505 506 /** The kind of an Option. This is used by the -help and -X options. */ 507 public enum OptionKind { 508 /** A standard option, documented by -help. */ 509 STANDARD, 510 /** An extended option, documented by -X. */ 511 EXTENDED, 512 /** A hidden option, not documented. */ 513 HIDDEN, 514 } 515 516 /** The group for an Option. This determines the situations in which the 517 * option is applicable. */ 518 enum OptionGroup { 519 /** A basic option, available for use on the command line or via the 520 * Compiler API. */ 521 BASIC, 522 /** An option for javac's standard JavaFileManager. Other file managers 523 * may or may not support these options. */ 524 FILEMANAGER, 525 /** A command-line option that requests information, such as -help. */ 526 INFO, 527 /** A command-line "option" representing a file or class name. */ 528 OPERAND 529 } 530 531 /** The kind of choice for "choice" options. */ 532 enum ChoiceKind { 533 /** The expected value is exactly one of the set of choices. */ 534 ONEOF, 535 /** The expected value is one of more of the set of choices. */ 536 ANYOF 537 } 538 539 public final String text; 540 541 final OptionKind kind; 542 543 final OptionGroup group; 544 545 /** Documentation key for arguments. 546 */ 547 final String argsNameKey; 548 549 /** Documentation key for description. 550 */ 551 final String descrKey; 552 553 /** Suffix option (-foo=bar or -foo:bar) 554 */ 555 final boolean hasSuffix; 556 557 /** The kind of choices for this option, if any. 558 */ 559 final ChoiceKind choiceKind; 560 561 /** The choices for this option, if any, and whether or not the choices 562 * are hidden 563 */ 564 final Map<String,Boolean> choices; 565 566 567 Option(String text, String descrKey, 568 OptionKind kind, OptionGroup group) { 569 this(text, null, descrKey, kind, group, null, null, false); 570 } 571 572 Option(String text, String argsNameKey, String descrKey, 573 OptionKind kind, OptionGroup group) { 574 this(text, argsNameKey, descrKey, kind, group, null, null, false); 575 } 576 577 Option(String text, String argsNameKey, String descrKey, 578 OptionKind kind, OptionGroup group, boolean doHasSuffix) { 579 this(text, argsNameKey, descrKey, kind, group, null, null, doHasSuffix); 580 } 581 582 Option(String text, OptionKind kind, OptionGroup group, 583 ChoiceKind choiceKind, Map<String,Boolean> choices) { 584 this(text, null, null, kind, group, choiceKind, choices, false); 585 } 586 587 Option(String text, String descrKey, 588 OptionKind kind, OptionGroup group, 589 ChoiceKind choiceKind, String... choices) { 590 this(text, null, descrKey, kind, group, choiceKind, 591 createChoices(choices), false); 592 } 593 // where 594 private static Map<String,Boolean> createChoices(String... choices) { 595 Map<String,Boolean> map = new LinkedHashMap<>(); 596 for (String c: choices) 597 map.put(c, false); 598 return map; 599 } 600 601 private Option(String text, String argsNameKey, String descrKey, 602 OptionKind kind, OptionGroup group, 603 ChoiceKind choiceKind, Map<String,Boolean> choices, 604 boolean doHasSuffix) { 605 this.text = text; 606 this.argsNameKey = argsNameKey; 607 this.descrKey = descrKey; 608 this.kind = kind; 609 this.group = group; 610 this.choiceKind = choiceKind; 611 this.choices = choices; 612 char lastChar = text.charAt(text.length()-1); 613 this.hasSuffix = doHasSuffix || lastChar == ':' || lastChar == '='; 614 } 615 616 public String getText() { 617 return text; 618 } 619 620 public OptionKind getKind() { 621 return kind; 622 } 623 624 public boolean hasArg() { 625 return argsNameKey != null && !hasSuffix; 626 } 627 628 public boolean matches(String option) { 629 if (!hasSuffix) 630 return option.equals(text); 631 632 if (!option.startsWith(text)) 633 return false; 634 635 if (choices != null) { 636 String arg = option.substring(text.length()); 637 if (choiceKind == ChoiceKind.ONEOF) 638 return choices.keySet().contains(arg); 639 else { 640 for (String a: arg.split(",+")) { 641 if (!choices.keySet().contains(a)) 642 return false; 643 } 644 } 645 } 646 647 return true; 648 } 649 650 public boolean process(OptionHelper helper, String option, String arg) { 651 if (choices != null) { 652 if (choiceKind == ChoiceKind.ONEOF) { 653 // some clients like to see just one of option+choice set 654 for (String s: choices.keySet()) 655 helper.remove(option + s); 656 String opt = option + arg; 657 helper.put(opt, opt); 658 // some clients like to see option (without trailing ":") 659 // set to arg 660 String nm = option.substring(0, option.length() - 1); 661 helper.put(nm, arg); 662 } else { 663 // set option+word for each word in arg 664 for (String a: arg.split(",+")) { 665 String opt = option + a; 666 helper.put(opt, opt); 667 } 668 } 669 } 670 helper.put(option, arg); 671 if (group == OptionGroup.FILEMANAGER) 672 helper.handleFileManagerOption(this, arg); 673 return false; 674 } 675 676 public boolean process(OptionHelper helper, String option) { 677 if (hasSuffix) 678 return process(helper, text, option.substring(text.length())); 679 else 680 return process(helper, option, option); 681 } 682 683 private static final String HELP_LINE_FORMAT = " %-26s %s"; 684 685 void help(Log log, OptionKind kind) { 686 if (this.kind != kind) 687 return; 688 689 log.printRawLines(WriterKind.NOTICE, 690 String.format(HELP_LINE_FORMAT, 691 helpSynopsis(log), 692 log.localize(PrefixKind.JAVAC, descrKey))); 693 694 } 695 696 private String helpSynopsis(Log log) { 697 StringBuilder sb = new StringBuilder(); 698 sb.append(text); 699 if (argsNameKey == null) { 700 if (choices != null) { 701 String sep = "{"; 702 for (Map.Entry<String,Boolean> e: choices.entrySet()) { 703 if (!e.getValue()) { 704 sb.append(sep); 705 sb.append(e.getKey()); 706 sep = ","; 707 } 708 } 709 sb.append("}"); 710 } 711 } else { 712 if (!hasSuffix) 713 sb.append(" "); 714 sb.append(log.localize(PrefixKind.JAVAC, argsNameKey)); 715 716 } 717 718 return sb.toString(); 719 } 720 721 // For -XpkgInfo:value 722 public enum PkgInfo { 723 /** 724 * Always generate package-info.class for every package-info.java file. 725 * The file may be empty if there annotations with a RetentionPolicy 726 * of CLASS or RUNTIME. This option may be useful in conjunction with 727 * build systems (such as Ant) that expect javac to generate at least 728 * one .class file for every .java file. 729 */ 730 ALWAYS, 731 /** 732 * Generate a package-info.class file if package-info.java contains 733 * annotations. The file may be empty if all the annotations have 734 * a RetentionPolicy of SOURCE. 735 * This value is just for backwards compatibility with earlier behavior. 736 * Either of the other two values are to be preferred to using this one. 737 */ 738 LEGACY, 739 /** 740 * Generate a package-info.class file if and only if there are annotations 741 * in package-info.java to be written into it. 742 */ 743 NONEMPTY; 744 745 public static PkgInfo get(Options options) { 746 String v = options.get(XPKGINFO); 747 return (v == null 748 ? PkgInfo.LEGACY 749 : PkgInfo.valueOf(StringUtils.toUpperCase(v))); 750 } 751 } 752 753 private static Map<String,Boolean> getXLintChoices() { 754 Map<String,Boolean> choices = new LinkedHashMap<>(); 755 choices.put("all", false); 756 for (Lint.LintCategory c : Lint.LintCategory.values()) 757 choices.put(c.option, c.hidden); 758 for (Lint.LintCategory c : Lint.LintCategory.values()) 759 choices.put("-" + c.option, c.hidden); 760 choices.put("none", false); 761 return choices; 762 } 763 764 static Set<Option> getJavaCompilerOptions() { 765 return EnumSet.allOf(Option.class); 766 } 767 768 public static Set<Option> getJavacFileManagerOptions() { 769 return getOptions(EnumSet.of(FILEMANAGER)); 770 } 771 772 public static Set<Option> getJavacToolOptions() { 773 return getOptions(EnumSet.of(BASIC)); 774 } 775 776 static Set<Option> getOptions(Set<OptionGroup> desired) { 777 Set<Option> options = EnumSet.noneOf(Option.class); 778 for (Option option : Option.values()) 779 if (desired.contains(option.group)) 780 options.add(option); 781 return Collections.unmodifiableSet(options); 782 } 783 784} 785