# HG changeset patch # User jjg # Date 1205266495 25200 # Node ID b66d15dfd001506b8d7a13c83d0405d1ffb0f812 # Parent 508c019990477aaa69ac13290397c3c77784dbe0 6307187: clean up code for -Xlint:options Summary: introduce common code for handling one-of and any-of options Reviewed-by: mcimadamore diff -r 508c01999047 -r b66d15dfd001 src/share/classes/com/sun/tools/javac/code/Lint.java --- a/src/share/classes/com/sun/tools/javac/code/Lint.java Thu Mar 06 10:25:04 2008 -0800 +++ b/src/share/classes/com/sun/tools/javac/code/Lint.java Tue Mar 11 13:14:55 2008 -0700 @@ -194,7 +194,7 @@ return map.get(option); } - private final String option; + public final String option; }; /** diff -r 508c01999047 -r b66d15dfd001 src/share/classes/com/sun/tools/javac/main/JavacOption.java --- a/src/share/classes/com/sun/tools/javac/main/JavacOption.java Thu Mar 06 10:25:04 2008 -0800 +++ b/src/share/classes/com/sun/tools/javac/main/JavacOption.java Tue Mar 11 13:14:55 2008 -0700 @@ -28,6 +28,8 @@ import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Options; import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Collection; /** * TODO: describe com.sun.tools.javac.main.JavacOption @@ -41,19 +43,29 @@ OptionKind getKind(); - /** Does this option take a (separate) operand? */ + /** Does this option take a (separate) operand? + * @return true if this option takes a separate operand + */ boolean hasArg(); /** Does argument string match option pattern? - * @param arg The command line argument string. + * @param arg the command line argument string + * @return true if {@code arg} matches this option */ boolean matches(String arg); - /** Process the option (with arg). Return true if error detected. + /** Process an option with an argument. + * @param options the accumulated set of analyzed options + * @param option the option to be processed + * @param arg the arg for the option to be processed + * @return true if an error was detected */ boolean process(Options options, String option, String arg); - /** Process the option (without arg). Return true if error detected. + /** Process the option with no argument. + * @param options the accumulated set of analyzed options + * @param option the option to be processed + * @return true if an error was detected */ boolean process(Options options, String option); @@ -65,6 +77,11 @@ HIDDEN, } + enum ChoiceKind { + ONEOF, + ANYOF + } + /** This class represents an option recognized by the main program */ static class Option implements JavacOption { @@ -85,6 +102,14 @@ */ boolean hasSuffix; + /** The kind of choices for this option, if any. + */ + ChoiceKind choiceKind; + + /** The choices for this option, if any. + */ + Collection choices; + Option(OptionName name, String argsNameKey, String descrKey) { this.name = name; this.argsNameKey = argsNameKey; @@ -92,51 +117,116 @@ char lastChar = name.optionName.charAt(name.optionName.length()-1); hasSuffix = lastChar == ':' || lastChar == '='; } + Option(OptionName name, String descrKey) { this(name, null, descrKey); } + Option(OptionName name, String descrKey, ChoiceKind choiceKind, String... choices) { + this(name, descrKey, choiceKind, Arrays.asList(choices)); + } + + Option(OptionName name, String descrKey, ChoiceKind choiceKind, Collection choices) { + this(name, null, descrKey); + if (choiceKind == null || choices == null) + throw new NullPointerException(); + this.choiceKind = choiceKind; + this.choices = choices; + } + + @Override public String toString() { return name.optionName; } - /** Does this option take a (separate) operand? - */ public boolean hasArg() { return argsNameKey != null && !hasSuffix; } - /** Does argument string match option pattern? - * @param arg The command line argument string. - */ - public boolean matches(String arg) { - return hasSuffix ? arg.startsWith(name.optionName) : arg.equals(name.optionName); + public boolean matches(String option) { + if (!hasSuffix) + return option.equals(name.optionName); + + if (!option.startsWith(name.optionName)) + return false; + + if (choices != null) { + String arg = option.substring(name.optionName.length()); + if (choiceKind == ChoiceKind.ONEOF) + return choices.contains(arg); + else { + for (String a: arg.split(",+")) { + if (!choices.contains(a)) + return false; + } + } + } + + return true; } /** Print a line of documentation describing this option, if standard. + * @param out the stream to which to write the documentation */ void help(PrintWriter out) { String s = " " + helpSynopsis(); out.print(s); - for (int j = s.length(); j < 29; j++) out.print(" "); + for (int j = Math.min(s.length(), 28); j < 29; j++) out.print(" "); Log.printLines(out, Main.getLocalizedString(descrKey)); } + String helpSynopsis() { - return name + - (argsNameKey == null ? "" : - ((hasSuffix ? "" : " ") + - Main.getLocalizedString(argsNameKey))); + StringBuilder sb = new StringBuilder(); + sb.append(name); + if (argsNameKey == null) { + if (choices != null) { + String sep = "{"; + for (String c: choices) { + sb.append(sep); + sb.append(c); + sep = ","; + } + sb.append("}"); + } + } else { + if (!hasSuffix) + sb.append(" "); + sb.append(Main.getLocalizedString(argsNameKey)); + } + + return sb.toString(); } /** Print a line of documentation describing this option, if non-standard. + * @param out the stream to which to write the documentation */ void xhelp(PrintWriter out) {} /** Process the option (with arg). Return true if error detected. */ public boolean process(Options options, String option, String arg) { - if (options != null) + if (options != null) { + if (choices != null) { + if (choiceKind == ChoiceKind.ONEOF) { + // some clients like to see just one of option+choice set + for (String c: choices) + options.remove(option + c); + String opt = option + arg; + options.put(opt, opt); + // some clients like to see option (without trailing ":") + // set to arg + String nm = option.substring(0, option.length() - 1); + options.put(nm, arg); + } else { + // set option+word for each word in arg + for (String a: arg.split(",+")) { + String opt = option + a; + options.put(opt, opt); + } + } + } options.put(option, arg); + } return false; } @@ -163,8 +253,17 @@ XOption(OptionName name, String descrKey) { this(name, null, descrKey); } + XOption(OptionName name, String descrKey, ChoiceKind kind, String... choices) { + super(name, descrKey, kind, choices); + } + XOption(OptionName name, String descrKey, ChoiceKind kind, Collection choices) { + super(name, descrKey, kind, choices); + } + @Override void help(PrintWriter out) {} + @Override void xhelp(PrintWriter out) { super.help(out); } + @Override public OptionKind getKind() { return OptionKind.EXTENDED; } }; @@ -177,8 +276,11 @@ HiddenOption(OptionName name, String argsNameKey) { super(name, argsNameKey, null); } + @Override void help(PrintWriter out) {} + @Override void xhelp(PrintWriter out) {} + @Override public OptionKind getKind() { return OptionKind.HIDDEN; } }; diff -r 508c01999047 -r b66d15dfd001 src/share/classes/com/sun/tools/javac/main/OptionName.java --- a/src/share/classes/com/sun/tools/javac/main/OptionName.java Thu Mar 06 10:25:04 2008 -0800 +++ b/src/share/classes/com/sun/tools/javac/main/OptionName.java Tue Mar 11 13:14:55 2008 -0700 @@ -37,13 +37,9 @@ public enum OptionName { G("-g"), G_NONE("-g:none"), - G_CUSTOM("-g:{lines,vars,source}"), + G_CUSTOM("-g:"), XLINT("-Xlint"), - XLINT_CUSTOM("-Xlint:{" - + "all," - + "cast,deprecation,divzero,empty,unchecked,fallthrough,path,serial,finally,overrides," - + "-cast,-deprecation,-divzero,-empty,-unchecked,-fallthrough,-path,-serial,-finally,-overrides," - + "none}"), + XLINT_CUSTOM("-Xlint:"), NOWARN("-nowarn"), VERBOSE("-verbose"), DEPRECATION("-deprecation"), @@ -58,12 +54,12 @@ DJAVA_EXT_DIRS("-Djava.ext.dirs="), ENDORSEDDIRS("-endorseddirs"), DJAVA_ENDORSED_DIRS("-Djava.endorsed.dirs="), - PROC_CUSTOM("-proc:{none,only}"), + PROC("-proc:"), PROCESSOR("-processor"), PROCESSORPATH("-processorpath"), D("-d"), S("-s"), - IMPLICIT("-implicit:{none,class}"), + IMPLICIT("-implicit:"), ENCODING("-encoding"), SOURCE("-source"), TARGET("-target"), @@ -86,7 +82,7 @@ XPRINT("-Xprint"), XPRINTROUNDS("-XprintRounds"), XPRINTPROCESSORINFO("-XprintProcessorInfo"), - XPREFER("-Xprefer:{source,newer}"), + XPREFER("-Xprefer:"), O("-O"), XJCOV("-Xjcov"), XD("-XD"), diff -r 508c01999047 -r b66d15dfd001 src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java --- a/src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java Thu Mar 06 10:25:04 2008 -0800 +++ b/src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java Tue Mar 11 13:14:55 2008 -0700 @@ -25,21 +25,23 @@ package com.sun.tools.javac.main; +import com.sun.tools.javac.code.Lint; import com.sun.tools.javac.code.Source; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.main.JavacOption.HiddenOption; import com.sun.tools.javac.main.JavacOption.Option; import com.sun.tools.javac.main.JavacOption.XOption; -import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; -import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Options; import com.sun.tools.javac.processing.JavacProcessingEnvironment; import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Collection; import java.util.EnumSet; +import java.util.LinkedHashSet; import java.util.Set; import java.util.StringTokenizer; import javax.lang.model.SourceVersion; @@ -134,7 +136,7 @@ DJAVA_EXT_DIRS, ENDORSEDDIRS, DJAVA_ENDORSED_DIRS, - PROC_CUSTOM, + PROC, PROCESSOR, PROCESSORPATH, D, @@ -195,7 +197,7 @@ NOWARN, VERBOSE, DEPRECATION, - PROC_CUSTOM, + PROC, PROCESSOR, IMPLICIT, SOURCE, @@ -245,79 +247,58 @@ } /** - * @param out the writer to use for diagnostic output + * Get all the recognized options. + * @param helper an {@code OptionHelper} to help when processing options + * @return an array of options */ public static Option[] getAll(final OptionHelper helper) { - return new Option[]{ + return new Option[] { new Option(G, "opt.g"), new Option(G_NONE, "opt.g.none") { + @Override public boolean process(Options options, String option) { options.put("-g:", "none"); return false; } }, - new Option(G_CUSTOM, "opt.g.lines.vars.source") { - public boolean matches(String s) { - return s.startsWith("-g:"); - } + new Option(G_CUSTOM, "opt.g.lines.vars.source", + Option.ChoiceKind.ANYOF, "lines", "vars", "source"), + + new XOption(XLINT, "opt.Xlint"), + new XOption(XLINT_CUSTOM, "opt.Xlint.suboptlist", + Option.ChoiceKind.ANYOF, getXLintChoices()), + + // -nowarn is retained for command-line backward compatibility + new Option(NOWARN, "opt.nowarn") { + @Override public boolean process(Options options, String option) { - String suboptions = option.substring(3); - options.put("-g:", suboptions); - // enter all the -g suboptions as "-g:suboption" - for (StringTokenizer t = new StringTokenizer(suboptions, ","); t.hasMoreTokens(); ) { - String tok = t.nextToken(); - String opt = "-g:" + tok; - options.put(opt, opt); - } + options.put("-Xlint:none", option); return false; } }, - new XOption(XLINT, "opt.Xlint"), - new XOption(XLINT_CUSTOM, "opt.Xlint.suboptlist") { - public boolean matches(String s) { - return s.startsWith("-Xlint:"); - } - public boolean process(Options options, String option) { - String suboptions = option.substring(7); - options.put("-Xlint:", suboptions); - // enter all the -Xlint suboptions as "-Xlint:suboption" - for (StringTokenizer t = new StringTokenizer(suboptions, ","); t.hasMoreTokens(); ) { - String tok = t.nextToken(); - String opt = "-Xlint:" + tok; - options.put(opt, opt); - } - return false; - } - }, - - // -nowarn is retained for command-line backward compatibility - new Option(NOWARN, "opt.nowarn") { - public boolean process(Options options, String option) { - options.put("-Xlint:none", option); - return false; - } - }, - new Option(VERBOSE, "opt.verbose"), // -deprecation is retained for command-line backward compatibility new Option(DEPRECATION, "opt.deprecation") { - public boolean process(Options options, String option) { - options.put("-Xlint:deprecation", option); - return false; - } - }, + @Override + public boolean process(Options options, String option) { + options.put("-Xlint:deprecation", option); + return false; + } + }, new Option(CLASSPATH, "opt.arg.path", "opt.classpath"), new Option(CP, "opt.arg.path", "opt.classpath") { + @Override public boolean process(Options options, String option, String arg) { return super.process(options, "-classpath", arg); } }, new Option(SOURCEPATH, "opt.arg.path", "opt.sourcepath"), new Option(BOOTCLASSPATH, "opt.arg.path", "opt.bootclasspath") { + @Override public boolean process(Options options, String option, String arg) { options.remove("-Xbootclasspath/p:"); options.remove("-Xbootclasspath/a:"); @@ -327,6 +308,7 @@ new XOption(XBOOTCLASSPATH_PREPEND,"opt.arg.path", "opt.Xbootclasspath.p"), new XOption(XBOOTCLASSPATH_APPEND, "opt.arg.path", "opt.Xbootclasspath.a"), new XOption(XBOOTCLASSPATH, "opt.arg.path", "opt.bootclasspath") { + @Override public boolean process(Options options, String option, String arg) { options.remove("-Xbootclasspath/p:"); options.remove("-Xbootclasspath/a:"); @@ -335,48 +317,29 @@ }, new Option(EXTDIRS, "opt.arg.dirs", "opt.extdirs"), new XOption(DJAVA_EXT_DIRS, "opt.arg.dirs", "opt.extdirs") { + @Override public boolean process(Options options, String option, String arg) { return super.process(options, "-extdirs", arg); } }, new Option(ENDORSEDDIRS, "opt.arg.dirs", "opt.endorseddirs"), new XOption(DJAVA_ENDORSED_DIRS, "opt.arg.dirs", "opt.endorseddirs") { + @Override public boolean process(Options options, String option, String arg) { return super.process(options, "-endorseddirs", arg); } }, - new Option(PROC_CUSTOM, "opt.proc.none.only") { - public boolean matches(String s) { - return s.equals("-proc:none") || s.equals("-proc:only"); - } - - public boolean process(Options options, String option) { - if (option.equals("-proc:none")) { - options.remove("-proc:only"); - } else { - options.remove("-proc:none"); - } - options.put(option, option); - return false; - } - }, + new Option(PROC, "opt.proc.none.only", + Option.ChoiceKind.ONEOF, "none", "only"), new Option(PROCESSOR, "opt.arg.class.list", "opt.processor"), new Option(PROCESSORPATH, "opt.arg.path", "opt.processorpath"), new Option(D, "opt.arg.directory", "opt.d"), new Option(S, "opt.arg.directory", "opt.sourceDest"), - new Option(IMPLICIT, "opt.implicit") { - public boolean matches(String s) { - return s.equals("-implicit:none") || s.equals("-implicit:class"); - } - public boolean process(Options options, String option, String operand) { - int sep = option.indexOf(":"); - options.put(option.substring(0, sep), option.substring(sep+1)); - options.put(option,option); - return false; - } - }, + new Option(IMPLICIT, "opt.implicit", + Option.ChoiceKind.ONEOF, "none", "class"), new Option(ENCODING, "opt.arg.encoding", "opt.encoding"), new Option(SOURCE, "opt.arg.release", "opt.source") { + @Override public boolean process(Options options, String option, String operand) { Source source = Source.lookup(operand); if (source == null) { @@ -387,6 +350,7 @@ } }, new Option(TARGET, "opt.arg.release", "opt.target") { + @Override public boolean process(Options options, String option, String operand) { Target target = Target.lookup(operand); if (target == null) { @@ -397,54 +361,62 @@ } }, new Option(VERSION, "opt.version") { + @Override public boolean process(Options options, String option) { helper.printVersion(); return super.process(options, option); } }, new HiddenOption(FULLVERSION) { + @Override public boolean process(Options options, String option) { helper.printFullVersion(); return super.process(options, option); } }, new Option(HELP, "opt.help") { + @Override public boolean process(Options options, String option) { helper.printHelp(); return super.process(options, option); } }, new Option(A, "opt.arg.key.equals.value","opt.A") { - String helpSynopsis() { - hasSuffix = true; - return super.helpSynopsis(); + @Override + String helpSynopsis() { + hasSuffix = true; + return super.helpSynopsis(); + } + + @Override + public boolean matches(String arg) { + return arg.startsWith("-A"); + } + + @Override + public boolean hasArg() { + return false; + } + // Mapping for processor options created in + // JavacProcessingEnvironment + @Override + public boolean process(Options options, String option) { + int argLength = option.length(); + if (argLength == 2) { + helper.error("err.empty.A.argument"); + return true; } - - public boolean matches(String arg) { - return arg.startsWith("-A"); + int sepIndex = option.indexOf('='); + String key = option.substring(2, (sepIndex != -1 ? sepIndex : argLength) ); + if (!JavacProcessingEnvironment.isValidOptionName(key)) { + helper.error("err.invalid.A.key", option); + return true; } - - public boolean hasArg() { - return false; - } - // Mapping for processor options created in - // JavacProcessingEnvironment - public boolean process(Options options, String option) { - int argLength = option.length(); - if (argLength == 2) { - helper.error("err.empty.A.argument"); - return true; - } - int sepIndex = option.indexOf('='); - String key = option.substring(2, (sepIndex != -1 ? sepIndex : argLength) ); - if (!JavacProcessingEnvironment.isValidOptionName(key)) { - helper.error("err.invalid.A.key", option); - return true; - } - return process(options, option, option); - } + return process(options, option, option); + } }, new Option(X, "opt.X") { + @Override public boolean process(Options options, String option) { helper.printXhelp(); return super.process(options, option); @@ -454,10 +426,12 @@ // This option exists only for the purpose of documenting itself. // It's actually implemented by the launcher. new Option(J, "opt.arg.flag", "opt.J") { + @Override String helpSynopsis() { hasSuffix = true; return super.helpSynopsis(); } + @Override public boolean process(Options options, String option) { throw new AssertionError ("the -J flag should be caught by the launcher."); @@ -469,6 +443,7 @@ // new Option("-moreinfo", "opt.moreinfo") { new HiddenOption(MOREINFO) { + @Override public boolean process(Options options, String option) { Type.moreInfo = true; return super.process(options, option); @@ -512,6 +487,7 @@ // display warnings for generic unchecked operations new HiddenOption(WARNUNCHECKED) { + @Override public boolean process(Options options, String option) { options.put("-Xlint:unchecked", option); return false; @@ -521,6 +497,7 @@ new XOption(XMAXERRS, "opt.arg.number", "opt.maxerrs"), new XOption(XMAXWARNS, "opt.arg.number", "opt.maxwarns"), new XOption(XSTDOUT, "opt.arg.file", "opt.Xstdout") { + @Override public boolean process(Options options, String option, String arg) { try { helper.setOut(new PrintWriter(new FileWriter(arg), true)); @@ -538,17 +515,8 @@ new XOption(XPRINTPROCESSORINFO, "opt.printProcessorInfo"), - new XOption(XPREFER, "opt.prefer") { - public boolean matches(String s) { - return s.equals("-Xprefer:source") || s.equals("-Xprefer:newer"); - } - public boolean process(Options options, String option, String operand) { - int sep = option.indexOf(":"); - options.put(option.substring(0, sep), option.substring(sep+1)); - options.put(option,option); - return false; - } - }, + new XOption(XPREFER, "opt.prefer", + Option.ChoiceKind.ONEOF, "source", "newer"), /* -O is a no-op, accepted for backward compatibility. */ new HiddenOption(O), @@ -562,10 +530,12 @@ */ new HiddenOption(XD) { String s; + @Override public boolean matches(String s) { this.s = s; return s.startsWith(name.optionName); } + @Override public boolean process(Options options, String option) { s = s.substring(name.optionName.length()); int eq = s.indexOf('='); @@ -586,11 +556,13 @@ */ new HiddenOption(SOURCEFILE) { String s; + @Override public boolean matches(String s) { this.s = s; return s.endsWith(".java") // Java source file || SourceVersion.isName(s); // Legal type name } + @Override public boolean process(Options options, String option) { if (s.endsWith(".java") ) { File f = new File(s); @@ -612,4 +584,15 @@ }; } + private static Collection getXLintChoices() { + Collection choices = new LinkedHashSet(); + choices.add("all"); + for (Lint.LintCategory c : Lint.LintCategory.values()) + choices.add(c.option); + for (Lint.LintCategory c : Lint.LintCategory.values()) + choices.add("-" + c.option); + choices.add("none"); + return choices; + } + } diff -r 508c01999047 -r b66d15dfd001 test/tools/javac/6341866/T6341866.java --- a/test/tools/javac/6341866/T6341866.java Thu Mar 06 10:25:04 2008 -0800 +++ b/test/tools/javac/6341866/T6341866.java Tue Mar 11 13:14:55 2008 -0700 @@ -186,7 +186,7 @@ } static void error(String msg) { - System.err.println(msg); + System.err.println("ERROR: " + msg); } static File services(Class service) {