# HG changeset patch # User mchung # Date 1478914341 28800 # Node ID 79da2a8f4274b40d9f947f615c28b255e77a8e7b # Parent 389212e0746c2db28e9dc8aeeecd79470c503c8c 8168386: Fix jdeps verbose options Reviewed-by: dfuchs, lancea diff -r 389212e0746c -r 79da2a8f4274 langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java Fri Nov 11 11:50:11 2016 -0800 +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java Fri Nov 11 17:32:21 2016 -0800 @@ -25,8 +25,10 @@ package com.sun.tools.jdeps; +import com.sun.tools.jdeps.Analyzer.Type; import static com.sun.tools.jdeps.Analyzer.Type.*; import static com.sun.tools.jdeps.JdepsWriter.*; +import static java.util.stream.Collectors.*; import java.io.IOException; import java.io.PrintWriter; @@ -111,6 +113,10 @@ this.aliases = aliases; } + Option(boolean hasArg, CommandOption cmd) { + this(hasArg, cmd.names()); + } + boolean isHidden() { return false; } @@ -144,25 +150,46 @@ } } + enum CommandOption { + ANALYZE_DEPS(""), + GENERATE_DOT_FILE("-dotoutput", "--dot-output"), + GENERATE_MODULE_INFO("--generate-module-info"), + LIST_DEPS("--list-deps"), + LIST_REDUCED_DEPS("--list-reduced-deps"), + CHECK_MODULES("--check"); + + private final String[] names; + CommandOption(String... names) { + this.names = names; + } + + String[] names() { + return names; + } + + @Override + public String toString() { + return names[0]; + } + } + static Option[] recognizedOptions = { new Option(false, "-h", "-?", "-help", "--help") { void process(JdepsTask task, String opt, String arg) { task.options.help = true; } }, - new Option(true, "-dotoutput", "--dot-output") { + new Option(true, CommandOption.GENERATE_DOT_FILE) { void process(JdepsTask task, String opt, String arg) throws BadArgs { - Path p = Paths.get(arg); - if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) { - throw new BadArgs("err.invalid.path", arg); + if (task.command != null) { + throw new BadArgs("err.command.set", task.command, opt); } - task.options.dotOutputDir = Paths.get(arg);; + task.command = task.genDotFile(Paths.get(arg)); } }, new Option(false, "-s", "-summary") { void process(JdepsTask task, String opt, String arg) { task.options.showSummary = true; - task.options.verbose = SUMMARY; } }, new Option(false, "-v", "-verbose", @@ -196,35 +223,48 @@ task.options.apiOnly = true; } }, - new Option(true, "--check") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - Set mods = Set.of(arg.split(",")); - task.options.checkModuleDeps = mods; - task.options.addmods.addAll(mods); - } - }, - new Option(true, "--generate-module-info") { - void process(JdepsTask task, String opt, String arg) throws BadArgs { - Path p = Paths.get(arg); - if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) { - throw new BadArgs("err.invalid.path", arg); - } - task.options.genModuleInfo = Paths.get(arg); - } - }, + new Option(false, "-jdkinternals", "--jdk-internals") { void process(JdepsTask task, String opt, String arg) { task.options.findJDKInternals = true; - task.options.verbose = CLASS; if (task.options.includePattern == null) { task.options.includePattern = Pattern.compile(".*"); } } }, - new Option(false, "--list-deps", "--list-reduced-deps") { - void process(JdepsTask task, String opt, String arg) { - task.options.showModulesAddExports = true; - task.options.reduced = opt.equals("--list-reduced-deps"); + + new Option(true, CommandOption.CHECK_MODULES) { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + if (task.command != null) { + throw new BadArgs("err.command.set", task.command, opt); + } + Set mods = Set.of(arg.split(",")); + task.options.addmods.addAll(mods); + task.command = task.checkModuleDeps(mods); + } + }, + new Option(true, CommandOption.GENERATE_MODULE_INFO) { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + if (task.command != null) { + throw new BadArgs("err.command.set", task.command, opt); + } + task.command = task.genModuleInfo(Paths.get(arg)); + } + }, + new Option(false, CommandOption.LIST_DEPS) { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + if (task.command != null) { + throw new BadArgs("err.command.set", task.command, opt); + } + task.command = task.listModuleDeps(false); + } + }, + new Option(false, CommandOption.LIST_REDUCED_DEPS) { + void process(JdepsTask task, String opt, String arg) throws BadArgs { + if (task.command != null) { + throw new BadArgs("err.command.set", task.command, opt); + } + task.command = task.listModuleDeps(true); } }, @@ -419,6 +459,7 @@ private final Options options = new Options(); private final List inputArgs = new ArrayList<>(); + private Command command; private PrintWriter log; void setLog(PrintWriter out) { log = out; @@ -445,55 +486,30 @@ if (options.version || options.fullVersion) { showVersion(options.fullVersion); } + if (options.help || options.version || options.fullVersion) { + return EXIT_OK; + } + if (!inputArgs.isEmpty() && options.rootModule != null) { reportError("err.invalid.arg.for.option", "-m"); } - if (inputArgs.isEmpty() && options.addmods.isEmpty() && options.includePattern == null - && options.includeSystemModulePattern == null && options.checkModuleDeps == null) { - if (options.help || options.version || options.fullVersion) { - return EXIT_OK; - } else { - showHelp(); - return EXIT_CMDERR; - } - } - if (options.genModuleInfo != null) { - if (options.dotOutputDir != null || options.classpath != null || options.hasFilter()) { - showHelp(); - return EXIT_CMDERR; - } - } if (options.numFilters() > 1) { reportError("err.invalid.filters"); return EXIT_CMDERR; } - if (options.inverse && options.depth != 1) { - reportError("err.invalid.inverse.option", "-R"); - return EXIT_CMDERR; - } - - if (options.inverse && options.numFilters() == 0) { - reportError("err.invalid.filters"); - return EXIT_CMDERR; + // default command to analyze dependences + if (command == null) { + command = analyzeDeps(); } - - if ((options.findJDKInternals) && (options.hasFilter() || options.showSummary)) { - showHelp(); - return EXIT_CMDERR; - } - if (options.showSummary && options.verbose != SUMMARY) { - showHelp(); - return EXIT_CMDERR; - } - if (options.checkModuleDeps != null && !inputArgs.isEmpty()) { - reportError("err.invalid.module.option", inputArgs, "--check"); + if (!command.checkOptions()) { return EXIT_CMDERR; } boolean ok = run(); return ok ? EXIT_OK : EXIT_ERROR; + } catch (BadArgs|UncheckedBadArgs e) { reportError(e.getKey(), e.getArgs()); if (e.showUsage()) { @@ -515,13 +531,14 @@ } boolean run() throws IOException { - try (JdepsConfiguration config = buildConfig()) { + try (JdepsConfiguration config = buildConfig(command.allModules())) { // detect split packages - config.splitPackages().entrySet().stream() + config.splitPackages().entrySet() + .stream() .sorted(Map.Entry.comparingByKey()) .forEach(e -> System.out.format("split package: %s %s%n", e.getKey(), - e.getValue().toString())); + e.getValue().toString())); // check if any module specified in --require is missing Stream.concat(options.addmods.stream(), options.requires.stream()) @@ -529,38 +546,11 @@ .forEach(mn -> config.findModule(mn).orElseThrow(() -> new UncheckedBadArgs(new BadArgs("err.module.not.found", mn)))); - // --generate-module-info - if (options.genModuleInfo != null) { - return genModuleInfo(config); - } - - // --check - if (options.checkModuleDeps != null) { - return new ModuleAnalyzer(config, log, options.checkModuleDeps).run(); - } - - if (options.showModulesAddExports) { - return new ModuleExportsAnalyzer(config, - dependencyFilter(config), - options.reduced, - log).run(); - } - - if (options.dotOutputDir != null && - (options.verbose == SUMMARY || options.verbose == MODULE) && - !options.addmods.isEmpty() && inputArgs.isEmpty()) { - return new ModuleAnalyzer(config, log).genDotFiles(options.dotOutputDir); - } - - if (options.inverse) { - return analyzeInverseDeps(config); - } else { - return analyzeDeps(config); - } + return command.run(config); } } - private JdepsConfiguration buildConfig() throws IOException { + private JdepsConfiguration buildConfig(boolean allModules) throws IOException { JdepsConfiguration.Builder builder = new JdepsConfiguration.Builder(options.systemModulePath); @@ -568,7 +558,7 @@ .appModulePath(options.modulePath) .addmods(options.addmods); - if (options.checkModuleDeps != null || options.showModulesAddExports) { + if (allModules) { // check all system modules in the image builder.allModules(); } @@ -592,148 +582,420 @@ return builder.build(); } - private boolean analyzeDeps(JdepsConfiguration config) throws IOException { - // output result - final JdepsWriter writer; - if (options.dotOutputDir != null) { - writer = new DotFileWriter(options.dotOutputDir, - options.verbose, - options.showProfile, - options.showModule, - options.showLabel); - } else { - writer = new SimpleWriter(log, - options.verbose, - options.showProfile, - options.showModule); + // ---- factory methods to create a Command + + private AnalyzeDeps analyzeDeps() throws BadArgs { + return options.inverse ? new InverseAnalyzeDeps() + : new AnalyzeDeps(); + } + + private GenDotFile genDotFile(Path dir) throws BadArgs { + if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) { + throw new BadArgs("err.invalid.path", dir.toString()); + } + return new GenDotFile(dir); + } + + private GenModuleInfo genModuleInfo(Path dir) throws BadArgs { + if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) { + throw new BadArgs("err.invalid.path", dir.toString()); + } + return new GenModuleInfo(dir); + } + + private ListModuleDeps listModuleDeps(boolean reduced) throws BadArgs { + return reduced ? new ListReducedDeps() + : new ListModuleDeps(); + } + + private CheckModuleDeps checkModuleDeps(Set mods) throws BadArgs { + return new CheckModuleDeps(mods); + } + + abstract class Command { + final CommandOption option; + protected Command(CommandOption option) { + this.option = option; + } + /** + * Returns true if the command-line options are all valid; + * otherwise, returns false. + */ + abstract boolean checkOptions(); + + /** + * Do analysis + */ + abstract boolean run(JdepsConfiguration config) throws IOException; + + /** + * Includes all modules on system module path and application module path + */ + boolean allModules() { + return false; + } + + @Override + public String toString() { + return option.toString(); + } + } + + + /** + * Analyze dependences + */ + class AnalyzeDeps extends Command { + JdepsWriter writer; + AnalyzeDeps() { + this(CommandOption.ANALYZE_DEPS); + } + + AnalyzeDeps(CommandOption option) { + super(option); + } + + @Override + boolean checkOptions() { + if (options.findJDKInternals) { + // cannot set any filter, -verbose and -summary option + if (options.showSummary || options.verbose != null) { + reportError("err.invalid.options", "-summary or -verbose", + "-jdkinternals"); + return false; + } + if (options.hasFilter()) { + reportError("err.invalid.options", "--package, --regex, --require", + "-jdkinternals"); + return false; + } + } + if (options.showSummary) { + // -summary cannot use with -verbose option + if (options.verbose != null) { + reportError("err.invalid.options", "-v, -verbose", "-s, -summary"); + return false; + } + } + if (inputArgs.isEmpty() && !options.hasSourcePath()) { + showHelp(); + return false; + } + return true; + } + + /* + * Default is to show package-level dependencies + */ + Type getAnalyzerType() { + if (options.showSummary) + return Type.SUMMARY; + + if (options.findJDKInternals) + return Type.CLASS; + + // default to package-level verbose + return options.verbose != null ? options.verbose : PACKAGE; + } + + @Override + boolean run(JdepsConfiguration config) throws IOException { + Type type = getAnalyzerType(); + // default to package-level verbose + JdepsWriter writer = new SimpleWriter(log, + type, + options.showProfile, + options.showModule); + + return run(config, writer, type); } - // analyze the dependencies - DepsAnalyzer analyzer = new DepsAnalyzer(config, - dependencyFilter(config), - writer, - options.verbose, - options.apiOnly); + boolean run(JdepsConfiguration config, JdepsWriter writer, Type type) throws IOException { + + + // analyze the dependencies + DepsAnalyzer analyzer = new DepsAnalyzer(config, + dependencyFilter(config), + writer, + type, + options.apiOnly); + + boolean ok = analyzer.run(options.compileTimeView, options.depth); + + // print skipped entries, if any + if (!options.nowarning) { + analyzer.archives() + .forEach(archive -> archive.reader() + .skippedEntries().stream() + .forEach(name -> warning("warn.skipped.entry", name))); + } + + if (options.findJDKInternals && !options.nowarning) { + Map jdkInternals = new TreeMap<>(); + Set deps = analyzer.dependences(); + // find the ones with replacement + deps.forEach(cn -> replacementFor(cn).ifPresent( + repl -> jdkInternals.put(cn, repl)) + ); + + if (!deps.isEmpty()) { + log.println(); + warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url")); + } - boolean ok = analyzer.run(options.compileTimeView, options.depth); + if (!jdkInternals.isEmpty()) { + log.println(); + log.format("%-40s %s%n", "JDK Internal API", "Suggested Replacement"); + log.format("%-40s %s%n", "----------------", "---------------------"); + jdkInternals.entrySet().stream() + .forEach(e -> { + String key = e.getKey(); + String[] lines = e.getValue().split("\\n"); + for (String s : lines) { + log.format("%-40s %s%n", key, s); + key = ""; + } + }); + } + } + return ok; + } + } + - // print skipped entries, if any - if (!options.nowarning) { - analyzer.archives() - .forEach(archive -> archive.reader() - .skippedEntries().stream() - .forEach(name -> warning("warn.skipped.entry", name))); + class InverseAnalyzeDeps extends AnalyzeDeps { + InverseAnalyzeDeps() { + } + + @Override + boolean checkOptions() { + if (options.depth != 1) { + reportError("err.invalid.options", "-R", "--inverse"); + return false; + } + + if (options.numFilters() == 0) { + reportError("err.filter.not.specified"); + return false; + } + + if (!super.checkOptions()) { + return false; + } + + return true; } - if (options.findJDKInternals && !options.nowarning) { - Map jdkInternals = new TreeMap<>(); - Set deps = analyzer.dependences(); - // find the ones with replacement - deps.forEach(cn -> replacementFor(cn).ifPresent( - repl -> jdkInternals.put(cn, repl)) - ); + @Override + boolean run(JdepsConfiguration config) throws IOException { + Type type = getAnalyzerType(); + + InverseDepsAnalyzer analyzer = + new InverseDepsAnalyzer(config, + dependencyFilter(config), + writer, + type, + options.apiOnly); + boolean ok = analyzer.run(); + + log.println(); + if (!options.requires.isEmpty()) + log.format("Inverse transitive dependences on %s%n", options.requires); + else + log.format("Inverse transitive dependences matching %s%n", + options.regex != null + ? options.regex.toString() + : "packages " + options.packageNames); + + analyzer.inverseDependences().stream() + .sorted(Comparator.comparing(this::sortPath)) + .forEach(path -> log.println(path.stream() + .map(Archive::getName) + .collect(joining(" <- ")))); + return ok; + } + + private String sortPath(Deque path) { + return path.peekFirst().getName(); + } + } + - if (!deps.isEmpty()) { - log.println(); - warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url")); + class GenModuleInfo extends Command { + final Path dir; + GenModuleInfo(Path dir) { + super(CommandOption.GENERATE_MODULE_INFO); + this.dir = dir; + } + + @Override + boolean checkOptions() { + if (options.classpath != null) { + reportError("err.invalid.options", "-classpath", + option); + return false; + } + if (options.hasFilter()) { + reportError("err.invalid.options", "--package, --regex, --require", + option); + return false; + } + return true; + } + + @Override + boolean run(JdepsConfiguration config) throws IOException { + // check if any JAR file contains unnamed package + for (String arg : inputArgs) { + try (ClassFileReader reader = ClassFileReader.newInstance(Paths.get(arg))) { + Optional classInUnnamedPackage = + reader.entries().stream() + .filter(n -> n.endsWith(".class")) + .filter(cn -> toPackageName(cn).isEmpty()) + .findFirst(); + + if (classInUnnamedPackage.isPresent()) { + if (classInUnnamedPackage.get().equals("module-info.class")) { + reportError("err.genmoduleinfo.not.jarfile", arg); + } else { + reportError("err.genmoduleinfo.unnamed.package", arg); + } + return false; + } + } } - if (!jdkInternals.isEmpty()) { - log.println(); - log.format("%-40s %s%n", "JDK Internal API", "Suggested Replacement"); - log.format("%-40s %s%n", "----------------", "---------------------"); - jdkInternals.entrySet().stream() - .forEach(e -> { - String key = e.getKey(); - String[] lines = e.getValue().split("\\n"); - for (String s : lines) { - log.format("%-40s %s%n", key, s); - key = ""; + ModuleInfoBuilder builder + = new ModuleInfoBuilder(config, inputArgs, dir); + boolean ok = builder.run(); + + if (!ok && !options.nowarning) { + log.println("ERROR: missing dependencies"); + builder.visitMissingDeps( + new Analyzer.Visitor() { + @Override + public void visitDependence(String origin, Archive originArchive, + String target, Archive targetArchive) { + if (builder.notFound(targetArchive)) + log.format(" %-50s -> %-50s %s%n", + origin, target, targetArchive.getName()); } }); } + return ok; } - return ok; + + private String toPackageName(String name) { + int i = name.lastIndexOf('/'); + return i > 0 ? name.replace('/', '.').substring(0, i) : ""; + } } - private boolean analyzeInverseDeps(JdepsConfiguration config) throws IOException { - JdepsWriter writer = new SimpleWriter(log, - options.verbose, - options.showProfile, - options.showModule); - - InverseDepsAnalyzer analyzer = new InverseDepsAnalyzer(config, - dependencyFilter(config), - writer, - options.verbose, - options.apiOnly); - boolean ok = analyzer.run(); + class CheckModuleDeps extends Command { + final Set modules; + CheckModuleDeps(Set mods) { + super(CommandOption.CHECK_MODULES); + this.modules = mods; + } - log.println(); - if (!options.requires.isEmpty()) - log.format("Inverse transitive dependences on %s%n", options.requires); - else - log.format("Inverse transitive dependences matching %s%n", - options.regex != null - ? options.regex.toString() - : "packages " + options.packageNames); + @Override + boolean checkOptions() { + if (!inputArgs.isEmpty()) { + reportError("err.invalid.options", inputArgs, "--check"); + return false; + } + return true; + } - analyzer.inverseDependences().stream() - .sorted(Comparator.comparing(this::sortPath)) - .forEach(path -> log.println(path.stream() - .map(Archive::getName) - .collect(Collectors.joining(" <- ")))); - return ok; + @Override + boolean run(JdepsConfiguration config) throws IOException { + if (!config.initialArchives().isEmpty()) { + String list = config.initialArchives().stream() + .map(Archive::getPathName).collect(joining(" ")); + throw new UncheckedBadArgs(new BadArgs("err.invalid.options", + list, "--check")); + } + return new ModuleAnalyzer(config, log, modules).run(); + } + + public boolean allModules() { + return true; + } } - private String sortPath(Deque path) { - return path.peekFirst().getName(); + class ListReducedDeps extends ListModuleDeps { + ListReducedDeps() { + super(CommandOption.LIST_REDUCED_DEPS, true); + } } - private boolean genModuleInfo(JdepsConfiguration config) throws IOException { - // check if any JAR file contains unnamed package - for (String arg : inputArgs) { - try (ClassFileReader reader = ClassFileReader.newInstance(Paths.get(arg))) { - Optional classInUnnamedPackage = - reader.entries().stream() - .filter(n -> n.endsWith(".class")) - .filter(cn -> toPackageName(cn).isEmpty()) - .findFirst(); + class ListModuleDeps extends Command { + final boolean reduced; + ListModuleDeps() { + this(CommandOption.LIST_DEPS, false); + } + ListModuleDeps(CommandOption option, boolean reduced) { + super(option); + this.reduced = reduced; + } - if (classInUnnamedPackage.isPresent()) { - if (classInUnnamedPackage.get().equals("module-info.class")) { - reportError("err.genmoduleinfo.not.jarfile", arg); - } else { - reportError("err.genmoduleinfo.unnamed.package", arg); - } - return false; - } + @Override + boolean checkOptions() { + if (options.showSummary || options.verbose != null) { + reportError("err.invalid.options", "-summary or -verbose", + option); + return false; } + if (options.findJDKInternals) { + reportError("err.invalid.options", "-jdkinternals", + option); + return false; + } + if (inputArgs.isEmpty() && !options.hasSourcePath()) { + showHelp(); + return false; + } + return true; } - ModuleInfoBuilder builder - = new ModuleInfoBuilder(config, inputArgs, options.genModuleInfo); - boolean ok = builder.run(); + @Override + boolean run(JdepsConfiguration config) throws IOException { + return new ModuleExportsAnalyzer(config, + dependencyFilter(config), + reduced, + log).run(); + } - if (!ok && !options.nowarning) { - log.println("ERROR: missing dependencies"); - builder.visitMissingDeps( - new Analyzer.Visitor() { - @Override - public void visitDependence(String origin, Archive originArchive, - String target, Archive targetArchive) { - if (builder.notFound(targetArchive)) - log.format(" %-50s -> %-50s %s%n", - origin, target, targetArchive.getName()); - } - }); + public boolean allModules() { + return true; } - return ok; } - private String toPackageName(String name) { - int i = name.lastIndexOf('/'); - return i > 0 ? name.replace('/', '.').substring(0, i) : ""; + + class GenDotFile extends AnalyzeDeps { + final Path dotOutputDir; + GenDotFile(Path dotOutputDir) { + super(CommandOption.GENERATE_DOT_FILE); + + this.dotOutputDir = dotOutputDir; + } + + @Override + boolean run(JdepsConfiguration config) throws IOException { + if ((options.showSummary || options.verbose == MODULE) && + !options.addmods.isEmpty() && inputArgs.isEmpty()) { + // print module descriptor + return new ModuleAnalyzer(config, log).genDotFiles(dotOutputDir); + } + + Type type = getAnalyzerType(); + JdepsWriter writer = new DotFileWriter(dotOutputDir, + type, + options.showProfile, + options.showModule, + options.showLabel); + return run(config, writer, type); + } } /** @@ -875,14 +1137,11 @@ boolean showLabel; boolean findJDKInternals; boolean nowarning = false; - // default is to show package-level dependencies - // and filter references from same package - Analyzer.Type verbose = PACKAGE; + Analyzer.Type verbose; + // default filter references from same package boolean filterSamePackage = true; boolean filterSameArchive = false; Pattern filterRegex; - Path dotOutputDir; - Path genModuleInfo; String classpath; int depth = 1; Set requires = new HashSet<>(); @@ -892,15 +1151,17 @@ Pattern includeSystemModulePattern; boolean inverse = false; boolean compileTimeView = false; - Set checkModuleDeps; String systemModulePath = System.getProperty("java.home"); String upgradeModulePath; String modulePath; String rootModule; Set addmods = new HashSet<>(); Runtime.Version multiRelease; - boolean showModulesAddExports; - boolean reduced; + + boolean hasSourcePath() { + return !addmods.isEmpty() || includePattern != null || + includeSystemModulePattern != null; + } boolean hasFilter() { return numFilters() > 0; diff -r 389212e0746c -r 79da2a8f4274 langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java Fri Nov 11 11:50:11 2016 -0800 +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java Fri Nov 11 17:32:21 2016 -0800 @@ -70,14 +70,6 @@ public ModuleAnalyzer(JdepsConfiguration config, PrintWriter log, Set names) { - - if (!config.initialArchives().isEmpty()) { - String list = config.initialArchives().stream() - .map(Archive::getPathName).collect(joining(" ")); - throw new JdepsTask.UncheckedBadArgs(new BadArgs("err.invalid.module.option", - list, "--check")); - } - this.configuration = config; this.log = log; diff -r 389212e0746c -r 79da2a8f4274 langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties Fri Nov 11 11:50:11 2016 -0800 +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties Fri Nov 11 17:32:21 2016 -0800 @@ -151,7 +151,9 @@ main.opt.list-deps=\ \ --list-deps Lists the dependences and use of JDK internal\n\ -\ APIs.\n\ +\ APIs. + +main.opt.list-reduced-deps=\ \ --list-reduced-deps Same as --list-deps with not listing\n\ \ the implied reads edges from the module graph\n\ \ If module M1 depends on M2 and M3,\n\ @@ -171,6 +173,7 @@ \ multi-release jar files. should\n\ \ be integer >= 9 or base. +err.command.set={0} and {1} options are specified. err.unknown.option=unknown option: {0} err.missing.arg=no value given for {0} err.invalid.arg.for.option=invalid argument for option: {0} @@ -180,11 +183,10 @@ err.profiles.msg=No profile information err.exception.message={0} err.invalid.path=invalid path: {0} -err.invalid.module.option=Cannot set {0} with {1} option. -err.invalid.filters=Only one of --package (-p), --regex (-e), --require option can be set +err.invalid.options={0} cannot be used with {1} option err.module.not.found=module not found: {0} err.root.module.not.set=root module set empty -err.invalid.inverse.option={0} cannot be used with --inverse option +err.filter.not.specified=--package (-p), --regex (-e), --require option must be specified err.multirelease.option.exists={0} is not a multi-release jar file, but the --multi-release option is set err.multirelease.option.notfound={0} is a multi-release jar file, but the --multi-release option is not set err.multirelease.version.associated=class {0} already associated with version {1}, trying to add version {2} diff -r 389212e0746c -r 79da2a8f4274 langtools/test/tools/jdeps/DotFileTest.java --- a/langtools/test/tools/jdeps/DotFileTest.java Fri Nov 11 11:50:11 2016 -0800 +++ b/langtools/test/tools/jdeps/DotFileTest.java Fri Nov 11 17:32:21 2016 -0800 @@ -136,8 +136,6 @@ // with -P option List argsWithDashP = new ArrayList<>(); - argsWithDashP.add("-dotoutput"); - argsWithDashP.add(dotoutput.toString()); argsWithDashP.add("-P"); argsWithDashP.addAll(args); @@ -162,8 +160,6 @@ // with -P option List argsWithDashP = new ArrayList<>(); - argsWithDashP.add("-dotoutput"); - argsWithDashP.add(dotoutput.toString()); argsWithDashP.add("-P"); argsWithDashP.addAll(args); diff -r 389212e0746c -r 79da2a8f4274 langtools/test/tools/jdeps/Options.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/jdeps/Options.java Fri Nov 11 17:32:21 2016 -0800 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8168386 + * @summary Test option validation + * @modules jdk.jdeps + * @library lib + * @build JdepsRunner + * @run testng Options + */ + + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; + +public class Options { + private static final String TEST_CLASSES = System.getProperty("test.classes"); + + @DataProvider(name = "errors") + public Object[][] errors() { + return new Object[][]{ + { + new String[] { "-summary", "-v", TEST_CLASSES }, + "-v, -verbose cannot be used with -s, -summary option" + }, + { + new String[] { "-jdkinternal", "-summary", TEST_CLASSES }, + "-summary or -verbose cannot be used with -jdkinternals option" + }, + { + new String[] { "-jdkinternal", "-p", "java.lang", TEST_CLASSES }, + "--package, --regex, --require cannot be used with -jdkinternals option" + }, + { + new String[] { "--inverse", TEST_CLASSES }, + "--package (-p), --regex (-e), --require option must be specified" + }, + { + new String[] { "--inverse", "-R", TEST_CLASSES }, + "-R cannot be used with --inverse option" + }, + { + new String[] { "--generate-module-info", "dots", "-cp", TEST_CLASSES }, + "-classpath cannot be used with --generate-module-info option" + }, + { + new String[] { "--list-deps", "-summary", TEST_CLASSES }, + "--list-deps and --list-reduced-deps options are specified" + }, + { + new String[] { "--list-deps", "--list-reduced-deps", TEST_CLASSES }, + "--list-deps and --list-reduced-deps options are specified" + }, + }; + } + + @Test(dataProvider = "errors") + public void test(String[] options, String expected) { + jdepsError(options).outputContains(expected); + } + + + public static JdepsRunner jdepsError(String... args) { + JdepsRunner jdeps = new JdepsRunner(args); + assertTrue(jdeps.run(true) != 0); + return jdeps; + } +} diff -r 389212e0746c -r 79da2a8f4274 langtools/test/tools/jdeps/lib/JdepsRunner.java --- a/langtools/test/tools/jdeps/lib/JdepsRunner.java Fri Nov 11 11:50:11 2016 -0800 +++ b/langtools/test/tools/jdeps/lib/JdepsRunner.java Fri Nov 11 17:32:21 2016 -0800 @@ -75,7 +75,7 @@ } public boolean outputContains(String s) { - return stdout.toString().contains(s); + return stdout.toString().contains(s) || stderr.toString().contains(s); } public void printStdout(PrintStream stream) {