< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java

Print this page

        

*** 28,40 **** --- 28,45 ---- import java.io.FileWriter; import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; + import java.text.Collator; + import java.util.Arrays; import java.util.Collections; + import java.util.Comparator; import java.util.EnumSet; + import java.util.Iterator; import java.util.LinkedHashMap; + import java.util.Locale; import java.util.Map; import java.util.ServiceLoader; import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors;
*** 49,58 **** --- 54,66 ---- import com.sun.tools.javac.code.Type; import com.sun.tools.javac.jvm.Profile; import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.platform.PlatformProvider; import com.sun.tools.javac.processing.JavacProcessingEnvironment; + import com.sun.tools.javac.resources.CompilerProperties.Errors; + import com.sun.tools.javac.util.Assert; + import com.sun.tools.javac.util.JDK9Wrappers; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Log.PrefixKind; import com.sun.tools.javac.util.Log.WriterKind; import com.sun.tools.javac.util.Options; import com.sun.tools.javac.util.StringUtils;
*** 60,73 **** import static com.sun.tools.javac.main.Option.ChoiceKind.*; import static com.sun.tools.javac.main.Option.OptionGroup.*; import static com.sun.tools.javac.main.Option.OptionKind.*; /** ! * Options for javac. The specific Option to handle a command-line option ! * is identified by searching the members of this enum in order, looking for ! * the first {@link #matches match}. The action for an Option is performed ! * by calling {@link #process process}, and by providing a suitable * {@link OptionHelper} to provide access the compiler state. * * <p><b>This is NOT part of any supported API. * If you write code that depends on this, you do so at your own * risk. This code and its internal interfaces are subject to change --- 68,84 ---- import static com.sun.tools.javac.main.Option.ChoiceKind.*; import static com.sun.tools.javac.main.Option.OptionGroup.*; import static com.sun.tools.javac.main.Option.OptionKind.*; /** ! * Options for javac. ! * The specific Option to handle a command-line option can be found by calling ! * {@link #lookup}, which search some or all of the members of this enum in order, ! * looking for the first {@link #matches match}. ! * The action for an Option is performed {@link #handleOption}, which determines ! * whether an argument is needed and where to find it; ! * {@code handleOption} then calls {@link #process process} providing a suitable * {@link OptionHelper} to provide access the compiler state. * * <p><b>This is NOT part of any supported API. * If you write code that depends on this, you do so at your own * risk. This code and its internal interfaces are subject to change
*** 87,107 **** G_CUSTOM("-g:", "opt.g.lines.vars.source", STANDARD, BASIC, ANYOF, "lines", "vars", "source"), XLINT("-Xlint", "opt.Xlint", EXTENDED, BASIC), ! XLINT_CUSTOM("-Xlint:", EXTENDED, BASIC, ANYOF, getXLintChoices()) { ! private static final String LINT_KEY_FORMAT = " %-19s %s"; @Override ! void help(Log log, OptionKind kind) { ! if (this.kind != kind) ! return; ! ! log.printRawLines(WriterKind.STDOUT, ! String.format(HELP_LINE_FORMAT, ! log.localize(PrefixKind.JAVAC, "opt.Xlint.subopts"), ! log.localize(PrefixKind.JAVAC, "opt.Xlint.suboptlist"))); log.printRawLines(WriterKind.STDOUT, String.format(LINT_KEY_FORMAT, "all", log.localize(PrefixKind.JAVAC, "opt.Xlint.all"))); for (LintCategory lc : LintCategory.values()) { --- 98,113 ---- G_CUSTOM("-g:", "opt.g.lines.vars.source", STANDARD, BASIC, ANYOF, "lines", "vars", "source"), XLINT("-Xlint", "opt.Xlint", EXTENDED, BASIC), ! XLINT_CUSTOM("-Xlint:", "opt.arg.Xlint", "opt.Xlint.custom", EXTENDED, BASIC, ANYOF, getXLintChoices()) { ! private final String LINT_KEY_FORMAT = LARGE_INDENT + " %-" + ! (DEFAULT_SYNOPSIS_WIDTH + SMALL_INDENT.length() - LARGE_INDENT.length() - 2) + "s %s"; @Override ! protected void help(Log log) { ! super.help(log); log.printRawLines(WriterKind.STDOUT, String.format(LINT_KEY_FORMAT, "all", log.localize(PrefixKind.JAVAC, "opt.Xlint.all"))); for (LintCategory lc : LintCategory.values()) {
*** 123,156 **** XDOCLINT_CUSTOM("-Xdoclint:", "opt.Xdoclint.subopts", "opt.Xdoclint.custom", EXTENDED, BASIC) { @Override public boolean matches(String option) { return DocLint.isValidOption( ! option.replace(XDOCLINT_CUSTOM.text, DocLint.XMSGS_CUSTOM_PREFIX)); } @Override public boolean process(OptionHelper helper, String option) { String prev = helper.get(XDOCLINT_CUSTOM); String next = (prev == null) ? option : (prev + " " + option); ! helper.put(XDOCLINT_CUSTOM.text, next); return false; } }, XDOCLINT_PACKAGE("-Xdoclint/package:", "opt.Xdoclint.package.args", "opt.Xdoclint.package.desc", EXTENDED, BASIC) { @Override public boolean matches(String option) { return DocLint.isValidOption( ! option.replace(XDOCLINT_PACKAGE.text, DocLint.XCHECK_PACKAGE)); } @Override public boolean process(OptionHelper helper, String option) { String prev = helper.get(XDOCLINT_PACKAGE); String next = (prev == null) ? option : (prev + " " + option); ! helper.put(XDOCLINT_PACKAGE.text, next); return false; } }, // -nowarn is retained for command-line backward compatibility --- 129,162 ---- XDOCLINT_CUSTOM("-Xdoclint:", "opt.Xdoclint.subopts", "opt.Xdoclint.custom", EXTENDED, BASIC) { @Override public boolean matches(String option) { return DocLint.isValidOption( ! option.replace(XDOCLINT_CUSTOM.primaryName, DocLint.XMSGS_CUSTOM_PREFIX)); } @Override public boolean process(OptionHelper helper, String option) { String prev = helper.get(XDOCLINT_CUSTOM); String next = (prev == null) ? option : (prev + " " + option); ! helper.put(XDOCLINT_CUSTOM.primaryName, next); return false; } }, XDOCLINT_PACKAGE("-Xdoclint/package:", "opt.Xdoclint.package.args", "opt.Xdoclint.package.desc", EXTENDED, BASIC) { @Override public boolean matches(String option) { return DocLint.isValidOption( ! option.replace(XDOCLINT_PACKAGE.primaryName, DocLint.XCHECK_PACKAGE)); } @Override public boolean process(OptionHelper helper, String option) { String prev = helper.get(XDOCLINT_PACKAGE); String next = (prev == null) ? option : (prev + " " + option); ! helper.put(XDOCLINT_PACKAGE.primaryName, next); return false; } }, // -nowarn is retained for command-line backward compatibility
*** 171,209 **** helper.put("-Xlint:deprecation", option); return false; } }, ! CLASSPATH("-classpath", "opt.arg.path", "opt.classpath", STANDARD, FILEMANAGER), ! CP("-cp", "opt.arg.path", "opt.classpath", STANDARD, FILEMANAGER) { ! @Override ! public boolean process(OptionHelper helper, String option, String arg) { ! return super.process(helper, "-classpath", arg); ! } ! }, ! SOURCEPATH("-sourcepath", "opt.arg.path", "opt.sourcepath", STANDARD, FILEMANAGER), ! MODULESOURCEPATH("-modulesourcepath", "opt.arg.mspath", "opt.modulesourcepath", STANDARD, FILEMANAGER), ! MODULEPATH("-modulepath", "opt.arg.path", "opt.modulepath", STANDARD, FILEMANAGER), ! MP("-mp", "opt.arg.path", "opt.modulepath", STANDARD, FILEMANAGER) { @Override public boolean process(OptionHelper helper, String option, String arg) { ! return super.process(helper, "-modulepath", arg); } - }, ! UPGRADEMODULEPATH("-upgrademodulepath", "opt.arg.path", "opt.upgrademodulepath", STANDARD, FILEMANAGER), ! SYSTEM("-system", "opt.arg.jdk", "opt.system", STANDARD, FILEMANAGER), ! XPATCH("-Xpatch:", "opt.arg.patch", "opt.patch", EXTENDED, FILEMANAGER), ! BOOTCLASSPATH("-bootclasspath", "opt.arg.path", "opt.bootclasspath", STANDARD, FILEMANAGER) { @Override public boolean process(OptionHelper helper, String option, String arg) { helper.remove("-Xbootclasspath/p:"); helper.remove("-Xbootclasspath/a:"); return super.process(helper, option, arg); --- 177,235 ---- helper.put("-Xlint:deprecation", option); return false; } }, ! CLASS_PATH("--class-path -classpath -cp", "opt.arg.path", "opt.classpath", STANDARD, FILEMANAGER), ! SOURCE_PATH("--source-path -sourcepath", "opt.arg.path", "opt.sourcepath", STANDARD, FILEMANAGER), ! MODULE_SOURCE_PATH("--module-source-path -modulesourcepath", "opt.arg.mspath", "opt.modulesourcepath", STANDARD, FILEMANAGER), ! MODULE_PATH("--module-path -p -modulepath -mp", "opt.arg.path", "opt.modulepath", STANDARD, FILEMANAGER), ! UPGRADE_MODULE_PATH("--upgrade-module-path -upgrademodulepath", "opt.arg.path", "opt.upgrademodulepath", STANDARD, FILEMANAGER), ! SYSTEM("--system -system", "opt.arg.jdk", "opt.system", STANDARD, FILEMANAGER), ! ! PATCH_MODULE("--patch-module -Xpatch:", "opt.arg.patch", "opt.patch", EXTENDED, FILEMANAGER) { ! // The deferred filemanager diagnostics mechanism assumes a single value per option, ! // but --patch-module can be used multiple times, once per module. Therefore we compose ! // a value for the option containing the last value specified for each module, and separate ! // the the module=path pairs by an invalid path character, NULL. ! // The standard file manager code knows to split apart the NULL-separated components. @Override public boolean process(OptionHelper helper, String option, String arg) { ! if (!arg.contains("=")) { // could be more strict regeex, e.g. "(?i)[a-z0-9_.]+=.*" ! helper.error(Errors.LocnInvalidArgForXpatch(arg)); } ! String previous = helper.get(this); ! if (previous == null) { ! return super.process(helper, option, arg); ! } ! ! Map<String,String> map = new LinkedHashMap<>(); ! for (String s : previous.split("\0")) { ! int sep = s.indexOf('='); ! map.put(s.substring(0, sep), s.substring(sep + 1)); ! } ! int sep = arg.indexOf('='); ! map.put(arg.substring(0, sep), arg.substring(sep + 1)); ! StringBuilder sb = new StringBuilder(); ! map.forEach((m, p) -> { ! if (sb.length() > 0) ! sb.append('\0'); ! sb.append(m).append('=').append(p); ! }); ! return super.process(helper, option, sb.toString()); ! } ! }, ! BOOT_CLASS_PATH("--boot-class-path -bootclasspath", "opt.arg.path", "opt.bootclasspath", STANDARD, FILEMANAGER) { @Override public boolean process(OptionHelper helper, String option, String arg) { helper.remove("-Xbootclasspath/p:"); helper.remove("-Xbootclasspath/a:"); return super.process(helper, option, arg);
*** 226,255 **** EXTDIRS("-extdirs", "opt.arg.dirs", "opt.extdirs", STANDARD, FILEMANAGER), DJAVA_EXT_DIRS("-Djava.ext.dirs=", "opt.arg.dirs", "opt.extdirs", EXTENDED, FILEMANAGER) { @Override public boolean process(OptionHelper helper, String option, String arg) { ! return super.process(helper, "-extdirs", arg); } }, ENDORSEDDIRS("-endorseddirs", "opt.arg.dirs", "opt.endorseddirs", STANDARD, FILEMANAGER), DJAVA_ENDORSED_DIRS("-Djava.endorsed.dirs=", "opt.arg.dirs", "opt.endorseddirs", EXTENDED, FILEMANAGER) { @Override public boolean process(OptionHelper helper, String option, String arg) { ! return super.process(helper, "-endorseddirs", arg); } }, PROC("-proc:", "opt.proc.none.only", STANDARD, BASIC, ONEOF, "none", "only"), PROCESSOR("-processor", "opt.arg.class.list", "opt.processor", STANDARD, BASIC), ! PROCESSORPATH("-processorpath", "opt.arg.path", "opt.processorpath", STANDARD, FILEMANAGER), ! PROCESSORMODULEPATH("-processormodulepath", "opt.arg.path", "opt.processormodulepath", STANDARD, FILEMANAGER), PARAMETERS("-parameters","opt.parameters", STANDARD, BASIC), D("-d", "opt.arg.directory", "opt.d", STANDARD, FILEMANAGER), --- 252,281 ---- EXTDIRS("-extdirs", "opt.arg.dirs", "opt.extdirs", STANDARD, FILEMANAGER), DJAVA_EXT_DIRS("-Djava.ext.dirs=", "opt.arg.dirs", "opt.extdirs", EXTENDED, FILEMANAGER) { @Override public boolean process(OptionHelper helper, String option, String arg) { ! return EXTDIRS.process(helper, "-extdirs", arg); } }, ENDORSEDDIRS("-endorseddirs", "opt.arg.dirs", "opt.endorseddirs", STANDARD, FILEMANAGER), DJAVA_ENDORSED_DIRS("-Djava.endorsed.dirs=", "opt.arg.dirs", "opt.endorseddirs", EXTENDED, FILEMANAGER) { @Override public boolean process(OptionHelper helper, String option, String arg) { ! return ENDORSEDDIRS.process(helper, "-endorseddirs", arg); } }, PROC("-proc:", "opt.proc.none.only", STANDARD, BASIC, ONEOF, "none", "only"), PROCESSOR("-processor", "opt.arg.class.list", "opt.processor", STANDARD, BASIC), ! PROCESSOR_PATH("--processor-path -processorpath", "opt.arg.path", "opt.processorpath", STANDARD, FILEMANAGER), ! PROCESSOR_MODULE_PATH("--processor-module-path -processormodulepath", "opt.arg.path", "opt.processormodulepath", STANDARD, FILEMANAGER), PARAMETERS("-parameters","opt.parameters", STANDARD, BASIC), D("-d", "opt.arg.directory", "opt.d", STANDARD, FILEMANAGER),
*** 283,298 **** } return super.process(helper, option, operand); } }, ! RELEASE("-release", "opt.arg.release", "opt.release", STANDARD, BASIC) { @Override ! void help(Log log, OptionKind kind) { ! if (this.kind != kind) ! return; ! Iterable<PlatformProvider> providers = ServiceLoader.load(PlatformProvider.class, Arguments.class.getClassLoader()); Set<String> platforms = StreamSupport.stream(providers.spliterator(), false) .flatMap(provider -> StreamSupport.stream(provider.getSupportedPlatformNames() .spliterator(), --- 309,321 ---- } return super.process(helper, option, operand); } }, ! RELEASE("--release -release", "opt.arg.release", "opt.release", STANDARD, BASIC) { @Override ! protected void help(Log log) { Iterable<PlatformProvider> providers = ServiceLoader.load(PlatformProvider.class, Arguments.class.getClassLoader()); Set<String> platforms = StreamSupport.stream(providers.spliterator(), false) .flatMap(provider -> StreamSupport.stream(provider.getSupportedPlatformNames() .spliterator(),
*** 305,318 **** targets.append(delim); targets.append(platform); delim = ", "; } ! log.printRawLines(WriterKind.STDOUT, ! String.format(HELP_LINE_FORMAT, ! super.helpSynopsis(log), ! log.localize(PrefixKind.JAVAC, descrKey, targets.toString()))); } }, PROFILE("-profile", "opt.arg.profile", "opt.profile", STANDARD, BASIC) { @Override --- 328,338 ---- targets.append(delim); targets.append(platform); delim = ", "; } ! super.help(log, log.localize(PrefixKind.JAVAC, descrKey, targets.toString())); } }, PROFILE("-profile", "opt.arg.profile", "opt.profile", STANDARD, BASIC) { @Override
*** 344,368 **** log.printLines(WriterKind.STDOUT, PrefixKind.JAVAC, "fullVersion", ownName, JavaCompiler.fullVersion()); return super.process(helper, option); } }, ! HELP("-help", "opt.help", STANDARD, INFO) { @Override public boolean process(OptionHelper helper, String option) { Log log = helper.getLog(); String ownName = helper.getOwnName(); log.printLines(WriterKind.STDOUT, PrefixKind.JAVAC, "msg.usage.header", ownName); ! for (Option o: getJavaCompilerOptions()) { ! o.help(log, OptionKind.STANDARD); ! } log.printNewline(WriterKind.STDOUT); return super.process(helper, option); } }, ! A("-A", "opt.arg.key.equals.value", "opt.A", STANDARD, BASIC, true) { @Override public boolean matches(String arg) { return arg.startsWith("-A"); } --- 364,387 ---- log.printLines(WriterKind.STDOUT, PrefixKind.JAVAC, "fullVersion", ownName, JavaCompiler.fullVersion()); return super.process(helper, option); } }, ! // Note: -h is already taken for "native header output directory". ! HELP("--help -help", "opt.help", STANDARD, INFO) { @Override public boolean process(OptionHelper helper, String option) { Log log = helper.getLog(); String ownName = helper.getOwnName(); log.printLines(WriterKind.STDOUT, PrefixKind.JAVAC, "msg.usage.header", ownName); ! showHelp(log, OptionKind.STANDARD); log.printNewline(WriterKind.STDOUT); return super.process(helper, option); } }, ! A("-A", "opt.arg.key.equals.value", "opt.A", STANDARD, BASIC, ArgKind.ADJACENT) { @Override public boolean matches(String arg) { return arg.startsWith("-A"); }
*** 383,412 **** String key = option.substring(2, (sepIndex != -1 ? sepIndex : argLength) ); if (!JavacProcessingEnvironment.isValidOptionName(key)) { helper.error("err.invalid.A.key", option); return true; } ! return process(helper, option, option); } }, X("-X", "opt.X", STANDARD, INFO) { @Override public boolean process(OptionHelper helper, String option) { Log log = helper.getLog(); ! for (Option o: getJavaCompilerOptions()) { ! o.help(log, OptionKind.EXTENDED); ! } log.printNewline(WriterKind.STDOUT); log.printLines(WriterKind.STDOUT, PrefixKind.JAVAC, "msg.usage.nonstandard.footer"); return super.process(helper, option); } }, // This option exists only for the purpose of documenting itself. // It's actually implemented by the launcher. ! J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO, true) { @Override public boolean process(OptionHelper helper, String option) { throw new AssertionError ("the -J flag should be caught by the launcher."); } --- 402,430 ---- String key = option.substring(2, (sepIndex != -1 ? sepIndex : argLength) ); if (!JavacProcessingEnvironment.isValidOptionName(key)) { helper.error("err.invalid.A.key", option); return true; } ! helper.put(option, option); ! return false; } }, X("-X", "opt.X", STANDARD, INFO) { @Override public boolean process(OptionHelper helper, String option) { Log log = helper.getLog(); ! showHelp(log, OptionKind.EXTENDED); log.printNewline(WriterKind.STDOUT); log.printLines(WriterKind.STDOUT, PrefixKind.JAVAC, "msg.usage.nonstandard.footer"); return super.process(helper, option); } }, // This option exists only for the purpose of documenting itself. // It's actually implemented by the launcher. ! J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO, ArgKind.ADJACENT) { @Override public boolean process(OptionHelper helper, String option) { throw new AssertionError ("the -J flag should be caught by the launcher."); }
*** 482,492 **** PLUGIN("-Xplugin:", "opt.arg.plugin", "opt.plugin", EXTENDED, BASIC) { @Override public boolean process(OptionHelper helper, String option) { String p = option.substring(option.indexOf(':') + 1).trim(); String prev = helper.get(PLUGIN); ! helper.put(PLUGIN.text, (prev == null) ? p : prev + '\0' + p); return false; } }, XDIAGS("-Xdiags:", "opt.diags", EXTENDED, BASIC, ONEOF, "compact", "verbose"), --- 500,510 ---- PLUGIN("-Xplugin:", "opt.arg.plugin", "opt.plugin", EXTENDED, BASIC) { @Override public boolean process(OptionHelper helper, String option) { String p = option.substring(option.indexOf(':') + 1).trim(); String prev = helper.get(PLUGIN); ! helper.put(PLUGIN.primaryName, (prev == null) ? p : prev + '\0' + p); return false; } }, XDIAGS("-Xdiags:", "opt.diags", EXTENDED, BASIC, ONEOF, "compact", "verbose"),
*** 515,525 **** } return false; } }, ! DIAGS("-diags:", null, HIDDEN, BASIC, true) { @Override public boolean process(OptionHelper helper, String option) { return HiddenGroup.DIAGS.process(helper, option); } }, --- 533,543 ---- } return false; } }, ! DIAGS("-diags:", null, HIDDEN, BASIC) { @Override public boolean process(OptionHelper helper, String option) { return HiddenGroup.DIAGS.process(helper, option); } },
*** 529,543 **** * -XDx sets the option x to the value x. */ XD("-XD", null, HIDDEN, BASIC) { @Override public boolean matches(String s) { ! return s.startsWith(text); } @Override public boolean process(OptionHelper helper, String option) { ! return process(helper, option, option.substring(text.length())); } @Override public boolean process(OptionHelper helper, String option, String arg) { int eq = arg.indexOf('='); --- 547,561 ---- * -XDx sets the option x to the value x. */ XD("-XD", null, HIDDEN, BASIC) { @Override public boolean matches(String s) { ! return s.startsWith(primaryName); } @Override public boolean process(OptionHelper helper, String option) { ! return process(helper, option, option.substring(primaryName.length())); } @Override public boolean process(OptionHelper helper, String option, String arg) { int eq = arg.indexOf('=');
*** 546,596 **** helper.put(key, value); return false; } }, ! XADDEXPORTS("-XaddExports:", "opt.arg.addExports", "opt.addExports", EXTENDED, BASIC) { @Override ! public boolean process(OptionHelper helper, String option) { ! String p = option.substring(option.indexOf(':') + 1).trim(); ! String prev = helper.get(XADDEXPORTS); ! helper.put(XADDEXPORTS.text, (prev == null) ? p : prev + '\0' + p); return false; } }, ! XADDREADS("-XaddReads:", "opt.arg.addReads", "opt.addReads", EXTENDED, BASIC) { @Override ! public boolean process(OptionHelper helper, String option) { ! String p = option.substring(option.indexOf(':') + 1).trim(); ! String prev = helper.get(XADDREADS); ! helper.put(XADDREADS.text, (prev == null) ? p : prev + '\0' + p); return false; } }, XMODULE("-Xmodule:", "opt.arg.module", "opt.module", EXTENDED, BASIC) { @Override ! public boolean process(OptionHelper helper, String option) { String prev = helper.get(XMODULE); if (prev != null) { ! helper.error("err.option.too.many", XMODULE.text); } ! String p = option.substring(option.indexOf(':') + 1); ! helper.put(XMODULE.text, p); return false; } }, ! M("-m", "opt.arg.m", "opt.m", STANDARD, BASIC), ! ADDMODS("-addmods", "opt.arg.addmods", "opt.addmods", STANDARD, BASIC), ! LIMITMODS("-limitmods", "opt.arg.limitmods", "opt.limitmods", STANDARD, BASIC), // This option exists only for the purpose of documenting itself. // It's actually implemented by the CommandLine class. ! AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO, true) { @Override public boolean process(OptionHelper helper, String option) { throw new AssertionError("the @ flag should be caught by CommandLine."); } }, --- 564,612 ---- helper.put(key, value); return false; } }, ! ADD_EXPORTS("--add-exports -XaddExports:", "opt.arg.addExports", "opt.addExports", EXTENDED, BASIC) { @Override ! public boolean process(OptionHelper helper, String option, String arg) { ! String prev = helper.get(ADD_EXPORTS); ! helper.put(ADD_EXPORTS.primaryName, (prev == null) ? arg : prev + '\0' + arg); return false; } }, ! ADD_READS("--add-reads -XaddReads:", "opt.arg.addReads", "opt.addReads", EXTENDED, BASIC) { @Override ! public boolean process(OptionHelper helper, String option, String arg) { ! String prev = helper.get(ADD_READS); ! helper.put(ADD_READS.primaryName, (prev == null) ? arg : prev + '\0' + arg); return false; } }, XMODULE("-Xmodule:", "opt.arg.module", "opt.module", EXTENDED, BASIC) { @Override ! public boolean process(OptionHelper helper, String option, String arg) { String prev = helper.get(XMODULE); if (prev != null) { ! helper.error("err.option.too.many", XMODULE.primaryName); } ! helper.put(XMODULE.primaryName, arg); return false; } }, ! MODULE("--module -m", "opt.arg.m", "opt.m", STANDARD, BASIC), ! ADD_MODULES("--add-modules -addmods", "opt.arg.addmods", "opt.addmods", STANDARD, BASIC), ! ! LIMIT_MODULES("--limit-modules -limitmods", "opt.arg.limitmods", "opt.limitmods", STANDARD, BASIC), // This option exists only for the purpose of documenting itself. // It's actually implemented by the CommandLine class. ! AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO, ArgKind.ADJACENT) { @Override public boolean process(OptionHelper helper, String option) { throw new AssertionError("the @ flag should be caught by CommandLine."); } },
*** 627,650 **** } return false; } }, ! MULTIRELEASE("-multi-release", "opt.arg.multi-release", "opt.multi-release", HIDDEN, FILEMANAGER); ! /** The kind of an Option. This is used by the -help and -X options. */ public enum OptionKind { /** A standard option, documented by -help. */ STANDARD, /** An extended option, documented by -X. */ EXTENDED, /** A hidden option, not documented. */ HIDDEN, } ! /** The group for an Option. This determines the situations in which the ! * option is applicable. */ enum OptionGroup { /** A basic option, available for use on the command line or via the * Compiler API. */ BASIC, /** An option for javac's standard JavaFileManager. Other file managers --- 643,737 ---- } return false; } }, ! MULTIRELEASE("--multi-release -multi-release", "opt.arg.multi-release", "opt.multi-release", HIDDEN, FILEMANAGER), ! INHERIT_RUNTIME_ENVIRONMENT("--inherit-runtime-environment", "opt.inherit_runtime_environment", ! EXTENDED, BASIC) { ! @Override ! public boolean process(OptionHelper helper, String option) { ! try { ! Class.forName(JDK9Wrappers.VMHelper.VM_CLASSNAME); ! String[] runtimeArgs = JDK9Wrappers.VMHelper.getRuntimeArguments(); ! for (String arg : runtimeArgs) { ! // Handle any supported runtime options; ignore all others. ! // The runtime arguments always use the single token form, e.g. "--name=value". ! for (Option o : getSupportedRuntimeOptions()) { ! if (o.matches(arg)) { ! o.handleOption(helper, arg, Collections.emptyIterator()); ! break; ! } ! } ! } ! } catch (ClassNotFoundException | SecurityException e) { ! helper.error("err.cannot.access.runtime.env"); ! } ! return false; ! } ! ! private Option[] getSupportedRuntimeOptions() { ! Option[] supportedRuntimeOptions = { ! ADD_EXPORTS, ! ADD_MODULES, ! LIMIT_MODULES, ! MODULE_PATH, ! UPGRADE_MODULE_PATH, ! PATCH_MODULE ! }; ! return supportedRuntimeOptions; ! } ! }; ! ! /** ! * The kind of argument, if any, accepted by this option. The kind is augmented ! * by characters in the name of the option. ! */ ! public enum ArgKind { ! /** This option does not take any argument. */ ! NONE, ! ! // Not currently supported ! // /** ! // * This option takes an optional argument, which may be provided directly after an '=' ! // * separator, or in the following argument position if that word does not itself appear ! // * to be the name of an option. ! // */ ! // OPTIONAL, ! ! /** ! * This option takes an argument. ! * If the name of option ends with ':' or '=', the argument must be provided directly ! * after that separator. ! * Otherwise, if may appear after an '=' or in the following argument position. ! */ ! REQUIRED, ! ! /** ! * This option takes an argument immediately after the option name, with no separator ! * character. ! */ ! ADJACENT ! } ! ! /** ! * The kind of an Option. This is used by the -help and -X options. ! */ public enum OptionKind { /** A standard option, documented by -help. */ STANDARD, /** An extended option, documented by -X. */ EXTENDED, /** A hidden option, not documented. */ HIDDEN, } ! /** ! * The group for an Option. This determines the situations in which the ! * option is applicable. ! */ enum OptionGroup { /** A basic option, available for use on the command line or via the * Compiler API. */ BASIC, /** An option for javac's standard JavaFileManager. Other file managers
*** 654,664 **** INFO, /** A command-line "option" representing a file or class name. */ OPERAND } ! /** The kind of choice for "choice" options. */ enum ChoiceKind { /** The expected value is exactly one of the set of choices. */ ONEOF, /** The expected value is one of more of the set of choices. */ ANYOF --- 741,753 ---- INFO, /** A command-line "option" representing a file or class name. */ OPERAND } ! /** ! * The kind of choice for "choice" options. ! */ enum ChoiceKind { /** The expected value is exactly one of the set of choices. */ ONEOF, /** The expected value is one of more of the set of choices. */ ANYOF
*** 682,750 **** } return false; } } ! public final String text; ! ! final OptionKind kind; ! ! final OptionGroup group; ! /** Documentation key for arguments. */ ! final String argsNameKey; /** Documentation key for description. */ ! final String descrKey; ! /** Suffix option (-foo=bar or -foo:bar) ! */ ! final boolean hasSuffix; ! /** The kind of choices for this option, if any. ! */ ! final ChoiceKind choiceKind; ! /** The choices for this option, if any, and whether or not the choices ! * are hidden */ ! final Map<String,Boolean> choices; ! Option(String text, String descrKey, ! OptionKind kind, OptionGroup group) { ! this(text, null, descrKey, kind, group, null, null, false); } Option(String text, String descrKey, ! OptionKind kind, OptionGroup group, ! boolean doHasSuffix) { ! this(text, null, descrKey, kind, group, null, null, doHasSuffix); } Option(String text, String argsNameKey, String descrKey, OptionKind kind, OptionGroup group) { ! this(text, argsNameKey, descrKey, kind, group, null, null, false); } Option(String text, String argsNameKey, String descrKey, ! OptionKind kind, OptionGroup group, boolean doHasSuffix) { ! this(text, argsNameKey, descrKey, kind, group, null, null, doHasSuffix); } ! Option(String text, OptionKind kind, OptionGroup group, ChoiceKind choiceKind, Map<String,Boolean> choices) { ! this(text, null, null, kind, group, choiceKind, choices, false); } Option(String text, String descrKey, OptionKind kind, OptionGroup group, ChoiceKind choiceKind, String... choices) { this(text, null, descrKey, kind, group, choiceKind, ! createChoices(choices), false); } // where private static Map<String,Boolean> createChoices(String... choices) { Map<String,Boolean> map = new LinkedHashMap<>(); for (String c: choices) --- 771,887 ---- } return false; } } ! /** ! * The "primary name" for this option. ! * This is the name that is used to put values in the {@link Options} table. ! */ ! public final String primaryName; ! /** ! * The set of names (primary name and aliases) for this option. ! * Note that some names may end in a separator, to indicate that an argument must immediately ! * follow the separator (and cannot appear in the following argument position. */ ! public final String[] names; ! ! /** Documentation key for arguments. */ ! protected final String argsNameKey; /** Documentation key for description. */ ! protected final String descrKey; ! /** The kind of this option. */ ! private final OptionKind kind; ! /** The group for this option. */ ! private final OptionGroup group; ! /** The kind of argument for this option. */ ! private final ArgKind argKind; ! ! /** The kind of choices for this option, if any. */ ! private final ChoiceKind choiceKind; ! ! /** The choices for this option, if any, and whether or not the choices are hidden. */ ! private final Map<String,Boolean> choices; ! ! /** ! * Looks up the first option matching the given argument in the full set of options. ! * @param arg the argument to be matches ! * @return the first option that matches, or null if none. */ ! public static Option lookup(String arg) { ! return lookup(arg, EnumSet.allOf(Option.class)); ! } + /** + * Looks up the first option matching the given argument within a set of options. + * @param arg the argument to be matches + * @return the first option that matches, or null if none. + */ + public static Option lookup(String arg, Set<Option> options) { + for (Option option: options) { + if (option.matches(arg)) + return option; + } + return null; + } ! /** ! * Writes the "command line help" for given kind of option to the log. ! * @param log the log ! * @param kind the kind of options to select ! */ ! private static void showHelp(Log log, OptionKind kind) { ! Comparator<Option> comp = new Comparator<Option>() { ! final Collator collator = Collator.getInstance(Locale.US); ! { collator.setStrength(Collator.PRIMARY); } ! ! @Override ! public int compare(Option o1, Option o2) { ! return collator.compare(o1.primaryName, o2.primaryName); ! } ! }; ! ! getJavaCompilerOptions() ! .stream() ! .filter(o -> o.kind == kind) ! .sorted(comp) ! .forEach(o -> { ! o.help(log); ! }); } Option(String text, String descrKey, ! OptionKind kind, OptionGroup group) { ! this(text, null, descrKey, kind, group, null, null, ArgKind.NONE); } Option(String text, String argsNameKey, String descrKey, OptionKind kind, OptionGroup group) { ! this(text, argsNameKey, descrKey, kind, group, null, null, ArgKind.REQUIRED); } Option(String text, String argsNameKey, String descrKey, ! OptionKind kind, OptionGroup group, ArgKind ak) { ! this(text, argsNameKey, descrKey, kind, group, null, null, ak); } ! Option(String text, String argsNameKey, String descrKey, OptionKind kind, OptionGroup group, ChoiceKind choiceKind, Map<String,Boolean> choices) { ! this(text, argsNameKey, descrKey, kind, group, choiceKind, choices, ArgKind.REQUIRED); } Option(String text, String descrKey, OptionKind kind, OptionGroup group, ChoiceKind choiceKind, String... choices) { this(text, null, descrKey, kind, group, choiceKind, ! createChoices(choices), ArgKind.REQUIRED); } // where private static Map<String,Boolean> createChoices(String... choices) { Map<String,Boolean> map = new LinkedHashMap<>(); for (String c: choices)
*** 753,795 **** } private Option(String text, String argsNameKey, String descrKey, OptionKind kind, OptionGroup group, ChoiceKind choiceKind, Map<String,Boolean> choices, ! boolean doHasSuffix) { ! this.text = text; this.argsNameKey = argsNameKey; this.descrKey = descrKey; this.kind = kind; this.group = group; this.choiceKind = choiceKind; this.choices = choices; ! char lastChar = text.charAt(text.length()-1); ! this.hasSuffix = doHasSuffix || lastChar == ':' || lastChar == '='; } ! public String getText() { ! return text; } public OptionKind getKind() { return kind; } public boolean hasArg() { ! return argsNameKey != null && !hasSuffix; } public boolean matches(String option) { if (!hasSuffix) ! return option.equals(text); ! if (!option.startsWith(text)) return false; if (choices != null) { ! String arg = option.substring(text.length()); if (choiceKind == ChoiceKind.ONEOF) return choices.keySet().contains(arg); else { for (String a: arg.split(",+")) { if (!choices.keySet().contains(a)) --- 890,954 ---- } private Option(String text, String argsNameKey, String descrKey, OptionKind kind, OptionGroup group, ChoiceKind choiceKind, Map<String,Boolean> choices, ! ArgKind argKind) { ! this.names = text.trim().split("\\s+"); ! Assert.check(names.length >= 1); ! this.primaryName = names[0]; this.argsNameKey = argsNameKey; this.descrKey = descrKey; this.kind = kind; this.group = group; this.choiceKind = choiceKind; this.choices = choices; ! this.argKind = argKind; } ! public String getPrimaryName() { ! return primaryName; } public OptionKind getKind() { return kind; } + public ArgKind getArgKind() { + return argKind; + } + public boolean hasArg() { ! // return argsNameKey != null && !hasSuffix; ! return (argKind != ArgKind.NONE); } public boolean matches(String option) { + for (String name: names) { + if (matches(option, name)) + return true; + } + return false; + } + + private boolean matches(String option, String name) { + if (name.startsWith("--")) { + return option.equals(name) + || hasArg() && option.startsWith(name + "="); + } + + boolean hasSuffix = (argKind == ArgKind.ADJACENT) + || name.endsWith(":") || name.endsWith("="); + if (!hasSuffix) ! return option.equals(name); ! if (!option.startsWith(name)) return false; if (choices != null) { ! String arg = option.substring(name.length()); if (choiceKind == ChoiceKind.ONEOF) return choices.keySet().contains(arg); else { for (String a: arg.split(",+")) { if (!choices.keySet().contains(a))
*** 799,857 **** } return true; } public boolean process(OptionHelper helper, String option, String arg) { if (choices != null) { if (choiceKind == ChoiceKind.ONEOF) { // some clients like to see just one of option+choice set for (String s: choices.keySet()) ! helper.remove(option + s); ! String opt = option + arg; helper.put(opt, opt); // some clients like to see option (without trailing ":") // set to arg ! String nm = option.substring(0, option.length() - 1); helper.put(nm, arg); } else { // set option+word for each word in arg for (String a: arg.split(",+")) { ! String opt = option + a; helper.put(opt, opt); } } } ! helper.put(option, arg); if (group == OptionGroup.FILEMANAGER) helper.handleFileManagerOption(this, arg); return false; } ! public boolean process(OptionHelper helper, String option) { ! if (hasSuffix) ! return process(helper, text, option.substring(text.length())); ! else ! return process(helper, option, option); ! } ! private static final String HELP_LINE_FORMAT = " %-26s %s"; ! void help(Log log, OptionKind kind) { ! if (this.kind != kind) return; ! log.printRawLines(WriterKind.STDOUT, ! String.format(HELP_LINE_FORMAT, ! helpSynopsis(log), ! log.localize(PrefixKind.JAVAC, descrKey))); } ! private String helpSynopsis(Log log) { StringBuilder sb = new StringBuilder(); ! sb.append(text); if (argsNameKey == null) { if (choices != null) { String sep = "{"; for (Map.Entry<String,Boolean> e: choices.entrySet()) { if (!e.getValue()) { --- 958,1122 ---- } return true; } + /** + * Handles an option. + * If an argument for the option is required, depending on spec of the option, it will be found + * as part of the current arg (following ':' or '=') or in the following argument. + * This is the recommended way to handle an option directly, instead of calling the underlying + * {@link #process process} methods. + * @param helper a helper to provide access to the environment + * @param arg the arg string that identified this option + * @param rest the remaining strings to be analysed + * @return true if the operation was successful, and false otherwise + * @implNote The return value is the opposite of that used by {@link #process}. + */ + public boolean handleOption(OptionHelper helper, String arg, Iterator<String> rest) { + if (hasArg()) { + String operand; + int sep = findSeparator(arg); + if (getArgKind() == Option.ArgKind.ADJACENT) { + operand = arg.substring(primaryName.length()); + } else if (sep > 0) { + operand = arg.substring(sep + 1); + } else { + if (!rest.hasNext()) { + helper.error("err.req.arg", arg); + return false; + } + operand = rest.next(); + } + return !process(helper, arg, operand); + } else { + return !process(helper, arg); + } + } + + /** + * Processes an option that either does not need an argument, + * or which contains an argument within it, following a separator. + * @param helper a helper to provide access to the environment + * @param option the option to be processed + * @return true if an error occurred + */ + public boolean process(OptionHelper helper, String option) { + if (argKind == ArgKind.NONE) { + return process(helper, primaryName, option); + } else { + int sep = findSeparator(option); + return process(helper, primaryName, option.substring(sep + 1)); + } + } + + /** + * Processes an option by updating the environment via a helper object. + * @param helper a helper to provide access to the environment + * @param option the option to be processed + * @param arg the value to associate with the option, or a default value + * to be used if the option does not otherwise take an argument. + * @return true if an error occurred + */ public boolean process(OptionHelper helper, String option, String arg) { if (choices != null) { if (choiceKind == ChoiceKind.ONEOF) { // some clients like to see just one of option+choice set for (String s: choices.keySet()) ! helper.remove(primaryName + s); ! String opt = primaryName + arg; helper.put(opt, opt); // some clients like to see option (without trailing ":") // set to arg ! String nm = primaryName.substring(0, primaryName.length() - 1); helper.put(nm, arg); } else { // set option+word for each word in arg for (String a: arg.split(",+")) { ! String opt = primaryName + a; helper.put(opt, opt); } } } ! helper.put(primaryName, arg); if (group == OptionGroup.FILEMANAGER) helper.handleFileManagerOption(this, arg); return false; } ! /** ! * Scans a word to find the first separator character, either colon or equals. ! * @param word the word to be scanned ! * @return the position of the first':' or '=' character in the word, ! * or -1 if none found ! */ ! private static int findSeparator(String word) { ! for (int i = 0; i < word.length(); i++) { ! switch (word.charAt(i)) { ! case ':': case '=': ! return i; ! } ! } ! return -1; ! } ! ! /** The indent for the option synopsis. */ ! private static final String SMALL_INDENT = " "; ! /** The automatic indent for the description. */ ! private static final String LARGE_INDENT = " "; ! /** The space allowed for the synopsis, if the description is to be shown on the same line. */ ! private static final int DEFAULT_SYNOPSIS_WIDTH = 28; ! /** The nominal maximum line length, when seeing if text will fit on a line. */ ! private static final int DEFAULT_MAX_LINE_LENGTH = 80; ! /** The format for a single-line help entry. */ ! private static final String COMPACT_FORMAT = SMALL_INDENT + "%-" + DEFAULT_SYNOPSIS_WIDTH + "s %s"; ! /** ! * Writes help text for this option to the log. ! * @param log the log ! */ ! protected void help(Log log) { ! help(log, log.localize(PrefixKind.JAVAC, descrKey)); ! } ! protected void help(Log log, String descr) { ! String synopses = Arrays.stream(names) ! .map(s -> helpSynopsis(s, log)) ! .collect(Collectors.joining(", ")); ! ! // If option synopses and description fit on a single line of reasonable length, ! // display using COMPACT_FORMAT ! if (synopses.length() < DEFAULT_SYNOPSIS_WIDTH ! && !descr.contains("\n") ! && (SMALL_INDENT.length() + DEFAULT_SYNOPSIS_WIDTH + 1 + descr.length() <= DEFAULT_MAX_LINE_LENGTH)) { ! log.printRawLines(WriterKind.STDOUT, String.format(COMPACT_FORMAT, synopses, descr)); return; + } ! // If option synopses fit on a single line of reasonable length, show that; ! // otherwise, show 1 per line ! if (synopses.length() <= DEFAULT_MAX_LINE_LENGTH) { ! log.printRawLines(WriterKind.STDOUT, SMALL_INDENT + synopses); ! } else { ! for (String name: names) { ! log.printRawLines(WriterKind.STDOUT, SMALL_INDENT + helpSynopsis(name, log)); ! } ! } + // Finally, show the description + log.printRawLines(WriterKind.STDOUT, LARGE_INDENT + descr.replace("\n", "\n" + LARGE_INDENT)); } ! /** ! * Composes the initial synopsis of one of the forms for this option. ! * @param name the name of this form of the option ! * @param log the log used to localize the description of the arguments ! * @return the synopsis ! */ ! private String helpSynopsis(String name, Log log) { StringBuilder sb = new StringBuilder(); ! sb.append(name); if (argsNameKey == null) { if (choices != null) { String sep = "{"; for (Map.Entry<String,Boolean> e: choices.entrySet()) { if (!e.getValue()) {
*** 861,874 **** } } sb.append("}"); } } else { ! if (!hasSuffix) sb.append(" "); sb.append(log.localize(PrefixKind.JAVAC, argsNameKey)); - } return sb.toString(); } --- 1126,1138 ---- } } sb.append("}"); } } else { ! if (!name.matches(".*[=:]$") && argKind != ArgKind.ADJACENT) sb.append(" "); sb.append(log.localize(PrefixKind.JAVAC, argsNameKey)); } return sb.toString(); }
*** 913,938 **** choices.put("-" + c.option, c.hidden); choices.put("none", false); return choices; } static Set<Option> getJavaCompilerOptions() { return EnumSet.allOf(Option.class); } public static Set<Option> getJavacFileManagerOptions() { ! return getOptions(EnumSet.of(FILEMANAGER)); } public static Set<Option> getJavacToolOptions() { ! return getOptions(EnumSet.of(BASIC)); } ! static Set<Option> getOptions(Set<OptionGroup> desired) { ! Set<Option> options = EnumSet.noneOf(Option.class); ! for (Option option : Option.values()) ! if (desired.contains(option.group)) ! options.add(option); ! return Collections.unmodifiableSet(options); } } --- 1177,1213 ---- choices.put("-" + c.option, c.hidden); choices.put("none", false); return choices; } + /** + * Returns the set of options supported by the command line tool. + * @return the set of options. + */ static Set<Option> getJavaCompilerOptions() { return EnumSet.allOf(Option.class); } + /** + * Returns the set of options supported by the built-in file manager. + * @return the set of options. + */ public static Set<Option> getJavacFileManagerOptions() { ! return getOptions(FILEMANAGER); } + /** + * Returns the set of options supported by this implementation of + * the JavaCompiler API, via {@link JavaCompiler#getTask}. + * @return the set of options. + */ public static Set<Option> getJavacToolOptions() { ! return getOptions(BASIC); } ! private static Set<Option> getOptions(OptionGroup group) { ! return Arrays.stream(Option.values()) ! .filter(o -> o.group == group) ! .collect(Collectors.toCollection(() -> EnumSet.noneOf(Option.class))); } }
< prev index next >