# HG changeset patch # User jjg # Date 1478206755 25200 # Node ID 8e66bf10fcec5c67aa87ecd87417ebc01a2d2c51 # Parent 1313399705e9b62042a6748f549b28e27431cac9 8167975: align javac --add-* modules options with launcher Reviewed-by: jlahoda diff -r 1313399705e9 -r 8e66bf10fcec langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Thu Nov 03 13:59:15 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -101,6 +101,8 @@ @Override public Main.Result call() throws Exception { prepareCompiler(false); + if (compiler.errorCount() > 0) + return Main.Result.ERROR; compiler.compile(args.getFileObjects(), args.getClassNames(), processors); return (compiler.errorCount() > 0) ? Main.Result.ERROR : Main.Result.OK; // FIXME? } diff -r 1313399705e9 -r 8e66bf10fcec langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Thu Nov 03 13:59:15 2016 -0700 @@ -36,7 +36,6 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import java.util.function.Consumer; import java.util.function.Predicate; @@ -59,6 +58,7 @@ import com.sun.tools.javac.code.Directive.UsesDirective; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Kinds; +import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.ModuleFinder; import com.sun.tools.javac.code.Source; import com.sun.tools.javac.code.Symbol; @@ -131,6 +131,7 @@ private final Types types; private final JavaFileManager fileManager; private final ModuleFinder moduleFinder; + private final Source source; private final boolean allowModules; public final boolean multiModuleMode; @@ -151,6 +152,8 @@ private final String limitModsOpt; private final Set extraLimitMods = new HashSet<>(); + private final boolean lintOptions; + private Set rootModules = null; public static Modules instance(Context context) { @@ -170,9 +173,12 @@ moduleFinder = ModuleFinder.instance(context); types = Types.instance(context); fileManager = context.get(JavaFileManager.class); - allowModules = Source.instance(context).allowModules(); + source = Source.instance(context); + allowModules = source.allowModules(); Options options = Options.instance(context); + lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option); + moduleOverride = options.get(Option.XMODULE); multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH); @@ -487,7 +493,7 @@ ModuleSymbol msym = moduleFinder.findModule((ModuleSymbol) sym); if (msym.kind == Kinds.Kind.ERR) { - log.error(Errors.CantFindModule(msym)); + log.error(Errors.ModuleNotFound(msym)); //make sure the module is initialized: msym.directives = List.nil(); msym.exports = List.nil(); @@ -684,15 +690,10 @@ } private ModuleSymbol lookupModule(JCExpression moduleName) { - try { Name name = TreeInfo.fullName(moduleName); ModuleSymbol msym = moduleFinder.findModule(name); TreeInfo.setSymbol(moduleName, msym); return msym; - } catch (Throwable t) { - System.err.println("Module " + sym + "; lookup export " + moduleName); - throw t; - } } } @@ -884,6 +885,8 @@ Set limitMods = new HashSet<>(); if (limitModsOpt != null) { for (String limit : limitModsOpt.split(",")) { + if (!isValidName(limit)) + continue; limitMods.add(syms.enterModule(names.fromString(limit))); } } @@ -892,6 +895,14 @@ } observable = computeTransitiveClosure(limitMods, null); observable.addAll(rootModules); + if (lintOptions) { + for (ModuleSymbol msym : limitMods) { + if (!observable.contains(msym)) { + log.warning(LintCategory.OPTIONS, + Warnings.ModuleForOptionNotFound(Option.LIMIT_MODULES, msym)); + } + } + } } Predicate observablePred = sym -> observable == null || observable.contains(sym); @@ -944,6 +955,8 @@ .filter(systemModulePred.negate().and(observablePred)); break; default: + if (!isValidName(added)) + continue; modules = Stream.of(syms.enterModule(names.fromString(added))); break; } @@ -1141,8 +1154,9 @@ addVisiblePackages(msym, seen, rm, rm.exports); } - for (Entry> addExportsEntry : addExports.entrySet()) - addVisiblePackages(msym, seen, addExportsEntry.getKey(), addExportsEntry.getValue()); + addExports.forEach((exportsFrom, exports) -> { + addVisiblePackages(msym, seen, exportsFrom, exports); + }); } private void addVisiblePackages(ModuleSymbol msym, @@ -1180,12 +1194,11 @@ return; addExports = new LinkedHashMap<>(); + Set unknownModules = new HashSet<>(); if (addExportsOpt == null) return; -// System.err.println("Modules.addExports:\n " + addExportsOpt.replace("\0", "\n ")); - Pattern ep = Pattern.compile("([^/]+)/([^=]+)=(.*)"); for (String s: addExportsOpt.split("\0+")) { if (s.isEmpty()) @@ -1203,7 +1216,15 @@ String packageName = em.group(2); String targetNames = em.group(3); + if (!isValidName(moduleName)) + continue; + ModuleSymbol msym = syms.enterModule(names.fromString(moduleName)); + if (!isKnownModule(msym, unknownModules)) + continue; + + if (!isValidName(packageName)) + continue; PackageSymbol p = syms.enterPackage(msym, names.fromString(packageName)); p.modle = msym; // TODO: do we need this? @@ -1213,11 +1234,11 @@ if (toModule.equals("ALL-UNNAMED")) { m = syms.unnamedModule; } else { - if (!SourceVersion.isName(toModule)) { - // TODO: error: invalid module name + if (!isValidName(toModule)) continue; - } m = syms.enterModule(names.fromString(toModule)); + if (!isKnownModule(m, unknownModules)) + continue; } targetModules = targetModules.prepend(m); } @@ -1228,6 +1249,21 @@ } } + private boolean isKnownModule(ModuleSymbol msym, Set unknownModules) { + if (allModules.contains(msym)) { + return true; + } + + if (!unknownModules.contains(msym)) { + if (lintOptions) { + log.warning(LintCategory.OPTIONS, + Warnings.ModuleForOptionNotFound(Option.ADD_EXPORTS, msym)); + } + unknownModules.add(msym); + } + return false; + } + private void initAddReads() { if (addReads != null) return; @@ -1237,8 +1273,6 @@ if (addReadsOpt == null) return; -// System.err.println("Modules.addReads:\n " + addReadsOpt.replace("\0", "\n ")); - Pattern rp = Pattern.compile("([^=]+)=(.*)"); for (String s : addReadsOpt.split("\0+")) { if (s.isEmpty()) @@ -1249,26 +1283,40 @@ } // Terminology comes from - // --add-reads target-module=source-module,... + // --add-reads source-module=target-module,... // Compare to - // module target-module { requires source-module; ... } - String targetName = rm.group(1); - String sources = rm.group(2); + // module source-module { requires target-module; ... } + String sourceName = rm.group(1); + String targetNames = rm.group(2); + + if (!isValidName(sourceName)) + continue; - ModuleSymbol msym = syms.enterModule(names.fromString(targetName)); - for (String source : sources.split("[ ,]+")) { - ModuleSymbol sourceModule; - if (source.equals("ALL-UNNAMED")) { - sourceModule = syms.unnamedModule; + ModuleSymbol msym = syms.enterModule(names.fromString(sourceName)); + if (!allModules.contains(msym)) { + if (lintOptions) { + log.warning(Warnings.ModuleForOptionNotFound(Option.ADD_READS, msym)); + } + continue; + } + + for (String targetName : targetNames.split("[ ,]+", -1)) { + ModuleSymbol targetModule; + if (targetName.equals("ALL-UNNAMED")) { + targetModule = syms.unnamedModule; } else { - if (!SourceVersion.isName(source)) { - // TODO: error: invalid module name + if (!isValidName(targetName)) + continue; + targetModule = syms.enterModule(names.fromString(targetName)); + if (!allModules.contains(targetModule)) { + if (lintOptions) { + log.warning(LintCategory.OPTIONS, Warnings.ModuleForOptionNotFound(Option.ADD_READS, targetModule)); + } continue; } - sourceModule = syms.enterModule(names.fromString(source)); } addReads.computeIfAbsent(msym, m -> new HashSet<>()) - .add(new RequiresDirective(sourceModule, EnumSet.of(RequiresFlag.EXTRA))); + .add(new RequiresDirective(targetModule, EnumSet.of(RequiresFlag.EXTRA))); } } } @@ -1301,6 +1349,10 @@ } } + private boolean isValidName(CharSequence name) { + return SourceVersion.isName(name, Source.toSourceVersion(source)); + } + // DEBUG private String toString(ModuleSymbol msym) { return msym.name + "[" diff -r 1313399705e9 -r 8e66bf10fcec langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Thu Nov 03 13:59:15 2016 -0700 @@ -43,6 +43,7 @@ import java.util.regex.Pattern; import java.util.stream.Stream; +import javax.lang.model.SourceVersion; import javax.tools.JavaFileManager; import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; @@ -400,7 +401,7 @@ /** * Validates the overall consistency of the options and operands * processed by processOptions. - * @return true if all args are successfully validating; false otherwise. + * @return true if all args are successfully validated; false otherwise. * @throws IllegalStateException if a problem is found and errorMode is set to * ILLEGAL_STATE */ @@ -610,62 +611,143 @@ if (obsoleteOptionFound) log.warning(LintCategory.OPTIONS, "option.obsolete.suppression"); + SourceVersion sv = Source.toSourceVersion(source); + validateAddExports(sv); + validateAddModules(sv); + validateAddReads(sv); + validateLimitModules(sv); + + return !errors && (log.nerrors == 0); + } + + private void validateAddExports(SourceVersion sv) { String addExports = options.get(Option.ADD_EXPORTS); if (addExports != null) { - // Each entry must be of the form module/package=target-list where target-list is a - // comma-separated list of module or ALL-UNNAMED. - // All module/package pairs must be unique. - Pattern p = Pattern.compile("([^/]+)/([^=]+)=(.*)"); - Map> map = new LinkedHashMap<>(); - for (String e: addExports.split("\0")) { + // Each entry must be of the form sourceModule/sourcePackage=target-list where + // target-list is a comma separated list of module or ALL-UNNAMED. + // Empty items in the target-list are ignored. + // There must be at least one item in the list; this is handled in Option.ADD_EXPORTS. + Pattern p = Option.ADD_EXPORTS.getPattern(); + for (String e : addExports.split("\0")) { Matcher m = p.matcher(e); - if (!m.matches()) { - log.error(Errors.XaddexportsMalformedEntry(e)); - continue; + if (m.matches()) { + String sourceModuleName = m.group(1); + if (!SourceVersion.isName(sourceModuleName, sv)) { + // syntactically invalid source name: e.g. --add-exports m!/p1=m2 + log.warning(Warnings.BadNameForOption(Option.ADD_EXPORTS, sourceModuleName)); + } + String sourcePackageName = m.group(2); + if (!SourceVersion.isName(sourcePackageName, sv)) { + // syntactically invalid source name: e.g. --add-exports m1/p!=m2 + log.warning(Warnings.BadNameForOption(Option.ADD_EXPORTS, sourcePackageName)); + } + + String targetNames = m.group(3); + for (String targetName : targetNames.split(",")) { + switch (targetName) { + case "": + case "ALL-UNNAMED": + break; + + default: + if (!SourceVersion.isName(targetName, sv)) { + // syntactically invalid target name: e.g. --add-exports m1/p1=m! + log.warning(Warnings.BadNameForOption(Option.ADD_EXPORTS, targetName)); + } + break; + } + } } - String eModule = m.group(1); // TODO: check a valid dotted identifier - String ePackage = m.group(2); // TODO: check a valid dotted identifier - String eTargets = m.group(3); // TODO: check a valid list of dotted identifier or ALL-UNNAMED - String eModPkg = eModule + '/' + ePackage; - List l = map.get(eModPkg); - map.put(eModPkg, (l == null) ? List.of(eTargets) : l.prepend(eTargets)); } - map.forEach((key, value) -> { - if (value.size() > 1) { - log.error(Errors.XaddexportsTooMany(key)); - // TODO: consider adding diag fragments for the entries - } - }); } + } + private void validateAddReads(SourceVersion sv) { String addReads = options.get(Option.ADD_READS); if (addReads != null) { - // Each entry must be of the form module=source-list where source-list is a - // comma separated list of module or ALL-UNNAMED. - // All target modules (i.e. on left of '=') must be unique. - Pattern p = Pattern.compile("([^=]+)=(.*)"); - Map> map = new LinkedHashMap<>(); - for (String e: addReads.split("\0")) { + // Each entry must be of the form source=target-list where target-list is a + // comma-separated list of module or ALL-UNNAMED. + // Empty items in the target list are ignored. + // There must be at least one item in the list; this is handled in Option.ADD_READS. + Pattern p = Option.ADD_READS.getPattern(); + for (String e : addReads.split("\0")) { Matcher m = p.matcher(e); - if (!m.matches()) { - log.error(Errors.XaddreadsMalformedEntry(e)); - continue; + if (m.matches()) { + String sourceName = m.group(1); + if (!SourceVersion.isName(sourceName, sv)) { + // syntactically invalid source name: e.g. --add-reads m!=m2 + log.warning(Warnings.BadNameForOption(Option.ADD_READS, sourceName)); + } + + String targetNames = m.group(2); + for (String targetName : targetNames.split(",", -1)) { + switch (targetName) { + case "": + case "ALL-UNNAMED": + break; + + default: + if (!SourceVersion.isName(targetName, sv)) { + // syntactically invalid target name: e.g. --add-reads m1=m! + log.warning(Warnings.BadNameForOption(Option.ADD_READS, targetName)); + } + break; + } + } } - String eModule = m.group(1); // TODO: check a valid dotted identifier - String eSources = m.group(2); // TODO: check a valid list of dotted identifier or ALL-UNNAMED - List l = map.get(eModule); - map.put(eModule, (l == null) ? List.of(eSources) : l.prepend(eSources)); } - map.forEach((key, value) -> { - if (value.size() > 1) { - log.error(Errors.XaddreadsTooMany(key)); - // TODO: consider adding diag fragments for the entries + } + } + + private void validateAddModules(SourceVersion sv) { + String addModules = options.get(Option.ADD_MODULES); + if (addModules != null) { + // Each entry must be of the form target-list where target-list is a + // comma separated list of module names, or ALL-DEFAULT, ALL-SYSTEM, + // or ALL-MODULE_PATH. + // Empty items in the target list are ignored. + // There must be at least one item in the list; this is handled in Option.ADD_MODULES. + for (String moduleName : addModules.split(",")) { + switch (moduleName) { + case "": + case "ALL-DEFAULT": + case "ALL-SYSTEM": + case "ALL-MODULE-PATH": + break; + + default: + if (!SourceVersion.isName(moduleName, sv)) { + // syntactically invalid module name: e.g. --add-modules m1,m! + log.warning(Warnings.BadNameForOption(Option.ADD_MODULES, moduleName)); + } + break; } - }); + } } + } + private void validateLimitModules(SourceVersion sv) { + String limitModules = options.get(Option.LIMIT_MODULES); + if (limitModules != null) { + // Each entry must be of the form target-list where target-list is a + // comma separated list of module names, or ALL-DEFAULT, ALL-SYSTEM, + // or ALL-MODULE_PATH. + // Empty items in the target list are ignored. + // There must be at least one item in the list; this is handled in Option.LIMIT_EXPORTS. + for (String moduleName : limitModules.split(",")) { + switch (moduleName) { + case "": + break; - return !errors; + default: + if (!SourceVersion.isName(moduleName, sv)) { + // syntactically invalid module name: e.g. --limit-modules m1,m! + log.warning(Warnings.BadNameForOption(Option.LIMIT_MODULES, moduleName)); + } + break; + } + } + } } /** diff -r 1313399705e9 -r 8e66bf10fcec langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Thu Nov 03 13:59:15 2016 -0700 @@ -43,6 +43,7 @@ import java.util.ServiceLoader; import java.util.Set; import java.util.TreeSet; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -556,18 +557,44 @@ ADD_EXPORTS("--add-exports", "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; + if (arg.isEmpty()) { + helper.error("err.no.value.for.option", option); + return true; + } else if (getPattern().matcher(arg).matches()) { + String prev = helper.get(ADD_EXPORTS); + helper.put(ADD_EXPORTS.primaryName, (prev == null) ? arg : prev + '\0' + arg); + return false; + } else { + helper.error("err.bad.value.for.option", option, arg); + return true; + } + } + + @Override + public Pattern getPattern() { + return Pattern.compile("([^/]+)/([^=]+)=(,*[^,].*)"); } }, ADD_READS("--add-reads", "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; + if (arg.isEmpty()) { + helper.error("err.no.value.for.option", option); + return true; + } else if (getPattern().matcher(arg).matches()) { + String prev = helper.get(ADD_READS); + helper.put(ADD_READS.primaryName, (prev == null) ? arg : prev + '\0' + arg); + return false; + } else { + helper.error("err.bad.value.for.option", option, arg); + return true; + } + } + + @Override + public Pattern getPattern() { + return Pattern.compile("([^=]+)=(,*[^,].*)"); } }, @@ -577,6 +604,7 @@ String prev = helper.get(XMODULE); if (prev != null) { helper.error("err.option.too.many", XMODULE.primaryName); + return true; } helper.put(XMODULE.primaryName, arg); return false; @@ -585,9 +613,50 @@ MODULE("--module -m", "opt.arg.m", "opt.m", STANDARD, BASIC), - ADD_MODULES("--add-modules", "opt.arg.addmods", "opt.addmods", STANDARD, BASIC), + ADD_MODULES("--add-modules", "opt.arg.addmods", "opt.addmods", STANDARD, BASIC) { + @Override + public boolean process(OptionHelper helper, String option, String arg) { + if (arg.isEmpty()) { + helper.error("err.no.value.for.option", option); + return true; + } else if (getPattern().matcher(arg).matches()) { + String prev = helper.get(ADD_MODULES); + // since the individual values are simple names, we can simply join the + // values of multiple --add-modules options with ',' + helper.put(ADD_MODULES.primaryName, (prev == null) ? arg : prev + ',' + arg); + return false; + } else { + helper.error("err.bad.value.for.option", option, arg); + return true; + } + } - LIMIT_MODULES("--limit-modules", "opt.arg.limitmods", "opt.limitmods", STANDARD, BASIC), + @Override + public Pattern getPattern() { + return Pattern.compile(",*[^,].*"); + } + }, + + LIMIT_MODULES("--limit-modules", "opt.arg.limitmods", "opt.limitmods", STANDARD, BASIC) { + @Override + public boolean process(OptionHelper helper, String option, String arg) { + if (arg.isEmpty()) { + helper.error("err.no.value.for.option", option); + return true; + } else if (getPattern().matcher(arg).matches()) { + helper.put(LIMIT_MODULES.primaryName, arg); // last one wins + return false; + } else { + helper.error("err.bad.value.for.option", option, arg); + return true; + } + } + + @Override + public Pattern getPattern() { + return Pattern.compile(",*[^,].*"); + } + }, // This option exists only for the purpose of documenting itself. // It's actually implemented by the CommandLine class. @@ -963,20 +1032,24 @@ */ public boolean handleOption(OptionHelper helper, String arg, Iterator rest) { if (hasArg()) { + String option; String operand; int sep = findSeparator(arg); if (getArgKind() == Option.ArgKind.ADJACENT) { + option = primaryName; // aliases not supported operand = arg.substring(primaryName.length()); } else if (sep > 0) { + option = arg.substring(0, sep); operand = arg.substring(sep + 1); } else { if (!rest.hasNext()) { helper.error("err.req.arg", arg); return false; } + option = arg; operand = rest.next(); } - return !process(helper, arg, operand); + return !process(helper, option, operand); } else { return !process(helper, arg); } @@ -1033,6 +1106,15 @@ } /** + * Returns a pattern to analyze the value for an option. + * @return the pattern + * @throws UnsupportedOperationException if an option does not provide a pattern. + */ + public Pattern getPattern() { + throw new UnsupportedOperationException(); + } + + /** * 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, diff -r 1313399705e9 -r 8e66bf10fcec langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Nov 03 13:59:15 2016 -0700 @@ -2844,21 +2844,13 @@ compiler.err.duplicate.module.on.path=\ duplicate module on {0}\nmodule in {1} -# 0: string -compiler.err.xaddexports.malformed.entry=\ - bad value for --add-exports {0} - -# 0: string -compiler.err.xaddexports.too.many=\ - multiple --add-exports options for {0} - -# 0: string -compiler.err.xaddreads.malformed.entry=\ - bad value for --add-reads {0} - -# 0: string -compiler.err.xaddreads.too.many=\ - multiple --add-reads options for {0} +# 0: option name, 1: string +compiler.warn.bad.name.for.option=\ + bad name in value for {0} option: ''{1}'' + +# 0: option name, 1: symbol +compiler.warn.module.for.option.not.found=\ + module name in {0} option not found: {1} compiler.err.addmods.all.module.path.invalid=\ --add-modules ALL-MODULE-PATH can only be used when compiling the unnamed module @@ -2878,10 +2870,6 @@ compiler.misc.cant.resolve.modules=\ cannot resolve modules -# 0: symbol -compiler.err.cant.find.module=\ - cannot find module: {0} - # 0: string compiler.err.invalid.module.specifier=\ module specifier not allowed: {0} diff -r 1313399705e9 -r 8e66bf10fcec langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Thu Nov 03 13:59:15 2016 -0700 @@ -357,6 +357,10 @@ not a file: {0} javac.err.cannot.access.runtime.env=\ cannot access runtime environment +javac.err.bad.value.for.option=\ + bad value for {0} option: ''{1}'' +javac.err.no.value.for.option=\ + no value for {0} option ## messages diff -r 1313399705e9 -r 8e66bf10fcec langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Thu Nov 03 13:59:15 2016 -0700 @@ -48,6 +48,7 @@ import com.sun.tools.javac.code.Type.CapturedType; import com.sun.tools.javac.file.PathFileObject; import com.sun.tools.javac.jvm.Profile; +import com.sun.tools.javac.main.Option; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.Pretty; @@ -204,6 +205,9 @@ else if (arg instanceof Profile) { return ((Profile)arg).name; } + else if (arg instanceof Option) { + return ((Option)arg).primaryName; + } else if (arg instanceof Formattable) { return ((Formattable)arg).toString(l, messages); } diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/doclint/moduleTests/bad/module-info.java --- a/langtools/test/tools/doclint/moduleTests/bad/module-info.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/test/tools/doclint/moduleTests/bad/module-info.java Thu Nov 03 13:59:15 2016 -0700 @@ -6,7 +6,7 @@ * @modules jdk.compiler/com.sun.tools.doclint * @build DocLintTester * @run main DocLintTester -ref module-info.out module-info.java - * @compile/fail/ref=module-info.javac.out -XDrawDiagnostics -Werror -Xdoclint:all module-info.java + * @compile/fail/ref=module-info.javac.out -XDrawDiagnostics -Werror -Xlint:-options -Xdoclint:all module-info.java */ // missing doc comment diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/doclint/moduleTests/good/module-info.java --- a/langtools/test/tools/doclint/moduleTests/good/module-info.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/test/tools/doclint/moduleTests/good/module-info.java Thu Nov 03 13:59:15 2016 -0700 @@ -29,7 +29,7 @@ * @modules jdk.compiler/com.sun.tools.doclint * @build DocLintTester * @run main DocLintTester module-info.java - * @compile -Xdoclint:all -Werror module-info.java + * @compile -Xdoclint:all -Werror -Xlint:-options module-info.java */ /** good module */ diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/T6403466.java --- a/langtools/test/tools/javac/T6403466.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/test/tools/javac/T6403466.java Thu Nov 03 13:59:15 2016 -0700 @@ -58,9 +58,7 @@ fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrcDir, self + ".java"))); Iterable options = Arrays.asList( - "--add-exports", - "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED," - + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", "--processor-path", testClassDir, "-processor", self, "-s", ".", diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/diags/examples/BadNameForOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/examples/BadNameForOption.java Thu Nov 03 13:59:15 2016 -0700 @@ -0,0 +1,28 @@ +/* + * 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. + */ + +// key: compiler.warn.bad.name.for.option +// options: --add-exports Bad!Name/p=java.base + +class BadNameForOption { } + diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/diags/examples/CantFindModule/CantFindModule.java --- a/langtools/test/tools/javac/diags/examples/CantFindModule/CantFindModule.java Thu Nov 03 09:12:02 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * 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. - */ - -// key: compiler.err.cant.find.module -// key: compiler.err.doesnt.exist - -// options: --add-exports undef/undef=ALL-UNNAMED - -import undef.Any; - -class Test {} diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/diags/examples/ModuleForOptionNotFound.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/examples/ModuleForOptionNotFound.java Thu Nov 03 13:59:15 2016 -0700 @@ -0,0 +1,32 @@ +/* + * 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. + */ + +// key: compiler.warn.module.for.option.not.found +// key: compiler.err.doesnt.exist + +// options: --add-exports undefModule/undefPackage=ALL-UNNAMED + +import undefPackage.Any; + +class Test {} + diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/diags/examples/XaddexportsMalformedEntry.java --- a/langtools/test/tools/javac/diags/examples/XaddexportsMalformedEntry.java Thu Nov 03 09:12:02 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * 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. - */ - -// key: compiler.err.xaddexports.malformed.entry -// options: --add-exports jdk.compiler/com.sun.tools.javac.util - -public class XaddexportsMalformedEntry { -} diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/diags/examples/XaddexportsTooMany.java --- a/langtools/test/tools/javac/diags/examples/XaddexportsTooMany.java Thu Nov 03 09:12:02 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * 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. - */ - -// key: compiler.err.xaddexports.too.many -// options: --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED - -public class XaddexportsTooMany { -} diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/diags/examples/XaddreadsMalformedEntry.java --- a/langtools/test/tools/javac/diags/examples/XaddreadsMalformedEntry.java Thu Nov 03 09:12:02 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * 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. - */ - -// key: compiler.err.xaddreads.malformed.entry -// options: --add-reads jdk.compiler - -public class XaddreadsMalformedEntry { -} diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/diags/examples/XaddreadsTooMany.java --- a/langtools/test/tools/javac/diags/examples/XaddreadsTooMany.java Thu Nov 03 09:12:02 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * 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. - */ - -// key: compiler.err.xaddreads.too.many -// options: --add-reads jdk.compiler=ALL-UNNAMED --add-reads jdk.compiler=ALL-UNNAMED - -public class XaddreadsTooMany { -} diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/modules/AddExportsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/modules/AddExportsTest.java Thu Nov 03 13:59:15 2016 -0700 @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2015, 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 + * @summary Test the --add-exports option + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase + * @run main AddExportsTest + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Set; + +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class AddExportsTest extends ModuleTestBase { + + public static void main(String... args) throws Exception { + new AddExportsTest().runTests(); + } + + @Test + public void testEmpty(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "class Dummy { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + testEmpty(src, classes, "--add-exports", ""); + testEmpty(src, classes, "--add-exports="); + } + + private void testEmpty(Path src, Path classes, String... options) throws Exception { + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options(options) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "javac: no value for --add-exports option"); + } + + @Test + public void testEmptyItem(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }", + "package p2; class C2 { p1.C1 c1; }"); + Path src_m3 = src.resolve("m3"); + tb.writeJavaFiles(src_m3, + "module m3 { }", + "package p3; class C3 { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + testEmptyItem(src, classes, "m1/p1=,m2,m3"); + testEmptyItem(src, classes, "m1/p1=m2,,m3"); + testEmptyItem(src, classes, "m1/p1=m2,m3,"); + } + + void testEmptyItem(Path src, Path classes, String option) throws Exception { + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-exports", option) + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testEmptyList(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + testEmptyList(src, classes, "m1/p1="); + testEmptyList(src, classes, "m1/p1=,"); + } + + void testEmptyList(Path src, Path classes, String option) throws Exception { + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("--module-source-path", src.toString(), + "--add-exports", option) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "javac: bad value for --add-exports option: '" + option + "'"); + } + + @Test + public void testMissingSourceParts(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }", + "package p2; class C2 { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + testMissingSourcePart(src, classes, "=m2"); + testMissingSourcePart(src, classes, "/=m2"); + testMissingSourcePart(src, classes, "m1/=m2"); + testMissingSourcePart(src, classes, "/p1=m2"); + testMissingSourcePart(src, classes, "m1p1=m2"); + } + + private void testMissingSourcePart(Path src, Path classes, String option) throws Exception { + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("--module-source-path", src.toString(), + "--add-exports", option) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "javac: bad value for --add-exports option: '" + option + "'"); + } + + @Test + public void testBadSourceParts(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }", + "package p2; class C2 { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + testBadSourcePart(src, classes, "m!/p1=m2", "m!"); + testBadSourcePart(src, classes, "m1/p!=m2", "p!"); + } + + private void testBadSourcePart(Path src, Path classes, String option, String badName) + throws Exception { + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("-XDrawDiagnostics", + "--module-source-path", src.toString(), + "--add-exports", option) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "- compiler.warn.bad.name.for.option: --add-exports, " + badName); + } + + @Test + public void testBadTarget(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("-XDrawDiagnostics", + "--module-source-path", src.toString(), + "--add-exports", "m1/p1=m!") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "- compiler.warn.bad.name.for.option: --add-exports, m!"); + } + + @Test + public void testSourceNotFound(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("-XDrawDiagnostics", + "--module-source-path", src.toString(), + "--add-exports", "DoesNotExist/p=m1") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "- compiler.warn.module.for.option.not.found: --add-exports, DoesNotExist"); + } + + @Test + public void testTargetNotFound(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { }", + "package p1; class C1 { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("-XDrawDiagnostics", + "--module-source-path", src.toString(), + "--add-exports", "m1/p1=DoesNotExist") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "- compiler.warn.module.for.option.not.found: --add-exports, DoesNotExist"); + } + + @Test + public void testDuplicate(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }", + "package p2; class C2 { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-exports", "m1/p1=m2,m2") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testRepeated_SameTarget(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }", + "package p2; class C2 { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-exports", "m1/p1=m2", + "--add-exports", "m1/p1=m2") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testRepeated_DifferentTarget(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }", + "package p2; class C2 { p1.C1 c1; }"); + Path src_m3 = src.resolve("m3"); + tb.writeJavaFiles(src_m3, + "module m3 { }", + "package p3; class C3 { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-exports", "m1/p1=m2", + "--add-exports", "m1/p1=m3") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } +} diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/modules/AddModulesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/modules/AddModulesTest.java Thu Nov 03 13:59:15 2016 -0700 @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2015, 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 + * @summary Test the --add-modules option + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase + * @run main AddModulesTest + */ + + +import java.nio.file.Path; + +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class AddModulesTest extends ModuleTestBase { + public static void main(String... args) throws Exception { + new AddModulesTest().runTests(); + } + + @Test + public void testEmpty(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "class Dummy { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + testEmpty(src, classes, "--add-modules", ""); + testEmpty(src, classes, "--add-modules="); + } + + private void testEmpty(Path src, Path classes, String... options) throws Exception { + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options(options) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "javac: no value for --add-modules option"); + } + + @Test + public void testEmptyItem(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + testEmptyItem(src, classes, ",m1"); + testEmptyItem(src, classes, "m1,,m2"); + testEmptyItem(src, classes, "m1,"); + } + + private void testEmptyItem(Path src, Path classes, String option) throws Exception { + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-modules", option) + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testEmptyList(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "class Dummy { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("--module-source-path", src.toString(), + "--add-modules", ",") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "javac: bad value for --add-modules option"); + } + + @Test + public void testInvalidName(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "class Dummy { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--add-modules", "BadModule!") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "- compiler.warn.bad.name.for.option: --add-modules, BadModule!"); + } + + @Test + public void testUnknownName(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "class Dummy { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--add-modules", "DoesNotExist") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "- compiler.err.module.not.found: DoesNotExist"); + } + + @Test + public void testDuplicate(Path base) throws Exception { + Path src = base.resolve("src"); + + // setup a utility module + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path modules = base.resolve("modules"); + tb.createDirectories(modules); + + new JavacTask(tb) + .options("--module-source-path", src.toString()) + .outdir(modules) + .files(findJavaFiles(src)) + .run() + .writeAll(); + + // now test access to the module + Path src2 = base.resolve("src2"); + tb.writeJavaFiles(src2, + "class Dummy { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-path", modules.toString(), + "--add-modules", "m1,m1") + .outdir(classes) + .files(findJavaFiles(src2)) + .run() + .writeAll(); + } + + @Test + public void testRepeatable(Path base) throws Exception { + Path src = base.resolve("src"); + + // setup some utility modules + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { exports p2; }", + "package p2; public class C2 { }"); + Path modules = base.resolve("modules"); + tb.createDirectories(modules); + + new JavacTask(tb) + .options("--module-source-path", src.toString()) + .outdir(modules) + .files(findJavaFiles(src)) + .run() + .writeAll(); + + // now test access to the modules + Path src2 = base.resolve("src2"); + tb.writeJavaFiles(src2, + "class Dummy { p1.C1 c1; p2.C2 c2; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-path", modules.toString(), + "--add-modules", "m1", + "--add-modules", "m2") + .outdir(classes) + .files(findJavaFiles(src2)) + .run() + .writeAll(); + } +} + diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/modules/AddReadsTest.java --- a/langtools/test/tools/javac/modules/AddReadsTest.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/test/tools/javac/modules/AddReadsTest.java Thu Nov 03 13:59:15 2016 -0700 @@ -28,6 +28,7 @@ * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main * jdk.jdeps/com.sun.tools.javap + * java.desktop * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavapTask ModuleTestBase * @run main AddReadsTest */ @@ -49,7 +50,6 @@ import toolbox.JavacTask; import toolbox.JavapTask; import toolbox.Task; -import toolbox.ToolBox; public class AddReadsTest extends ModuleTestBase { @@ -80,8 +80,8 @@ .writeAll() .getOutput(Task.OutputKind.DIRECT); - if (!log.contains("Test.java:1:44: compiler.err.not.def.access.package.cant.access: api.Api, api")) - throw new Exception("expected output not found"); + checkOutputContains(log, + "Test.java:1:44: compiler.err.not.def.access.package.cant.access: api.Api, api"); //test add dependencies: new JavacTask(tb) @@ -104,7 +104,8 @@ //cyclic dependencies OK when created through addReads: new JavacTask(tb) - .options("--add-reads", "m2=m1,m1=m2", + .options("--add-reads", "m2=m1", + "--add-reads", "m1=m2", "--module-source-path", src.toString()) .outdir(classes) .files(findJavaFiles(src)) @@ -233,7 +234,8 @@ "package impl; public class Impl { javax.swing.JButton b; }"); new JavacTask(tb) - .options("--add-reads", "java.base=java.desktop", + .options("--add-modules", "java.desktop", + "--add-reads", "java.base=java.desktop", "-Xmodule:java.base") .outdir(classes) .files(findJavaFiles(src)) @@ -308,4 +310,356 @@ .run() .writeAll(); } + + @Test + public void testAddSelf(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-reads", "m1=m1") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testEmpty(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "class Dummy { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + testEmpty(src, classes, "--add-reads", ""); + testEmpty(src, classes, "--add-reads="); + } + + private void testEmpty(Path src, Path classes, String... options) throws Exception { + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options(options) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "javac: no value for --add-reads option"); + } + + @Test + public void testEmptyItem(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }", + "package p2; class C2 { }"); + Path src_m3 = src.resolve("m3"); + tb.writeJavaFiles(src_m3, + "module m3 { }", + "package p3; class C3 { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + testEmptyItem(src, classes, "m3=,m1"); + testEmptyItem(src, classes, "m3=m1,,m2"); + testEmptyItem(src, classes, "m3=m1,"); + } + + private void testEmptyItem(Path src, Path classes, String option) throws Exception { + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-reads", option) + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testEmptyList(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }", + "package p2; class C2 { }"); + Path src_m3 = src.resolve("m3"); + tb.writeJavaFiles(src_m3, + "module m3 { }", + "package p3; class C3 { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + testEmptyList(src, classes, "m3="); + testEmptyList(src, classes, "m3=,"); + } + + private void testEmptyList(Path src, Path classes, String option) throws Exception { + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("--module-source-path", src.toString(), + "--add-reads", option) + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "javac: bad value for --add-reads option: '" + option + "'"); + } + + @Test + public void testMultipleAddReads_DifferentModules(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }", + "package p2; class C2 { p1.C1 c1; }"); + Path src_m3 = src.resolve("m3"); + tb.writeJavaFiles(src_m3, + "module m3 { }", + "package p3; class C3 { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-reads", "m2=m1", + "--add-reads", "m3=m1") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testMultipleAddReads_SameModule(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { exports p2; }", + "package p2; public class C2 { }"); + Path src_m3 = src.resolve("m3"); + tb.writeJavaFiles(src_m3, + "module m3 { }", + "package p3; class C3 { p1.C1 c1; p2.C2 c2; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-reads", "m3=m1", + "--add-reads", "m3=m2") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testDuplicateAddReads_SameOption(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { exports p2; }", + "package p2; class C2 { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-reads", "m2=m1,m1") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testDuplicateAddReads_MultipleOptions(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }", + "package p2; class C2 { p1.C1 c1; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-reads", "m2=m1", + "--add-reads", "m2=m1") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testRepeatedAddReads(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { exports p2; }", + "package p2; public class C2 { }"); + Path src_m3 = src.resolve("m3"); + tb.writeJavaFiles(src_m3, + "module m3 { }", + "package p3; class C3 { p1.C1 c1; p2.C2 c2; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--add-reads", "m3=m1", + "--add-reads", "m3=m2") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testNoEquals(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "class Dummy { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("-XDrawDiagnostics", + "--add-reads", "m1:m2") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "javac: bad value for --add-reads option: 'm1:m2'"); + } + + @Test + public void testBadSourceName(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "class Dummy { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--add-reads", "bad*Source=m2") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "- compiler.warn.bad.name.for.option: --add-reads, bad*Source"); + } + + @Test + public void testBadTargetName(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { }", + "package p1; class C1 { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--add-reads", "m1=badTarget!") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "- compiler.warn.bad.name.for.option: --add-reads, badTarget!"); + } + + @Test + public void testSourceNameNotFound(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--add-reads", "missingSource=m1") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "- compiler.warn.module.for.option.not.found: --add-reads, missingSource"); + } + + @Test + public void testTargetNameNotFound(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports p1; }", + "package p1; public class C1 { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--add-reads", "m1=missingTarget") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + checkOutputContains(log, + "- compiler.warn.module.for.option.not.found: --add-reads, missingTarget"); + } } diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java --- a/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java Thu Nov 03 13:59:15 2016 -0700 @@ -230,8 +230,7 @@ .run(Task.Expect.FAIL) .writeAll() .getOutputLines(Task.OutputKind.DIRECT); - if (!log.equals(Arrays.asList("- compiler.err.processorpath.no.processormodulepath", - "1 error"))) { + if (!log.equals(Arrays.asList("- compiler.err.processorpath.no.processormodulepath"))) { throw new AssertionError("Unexpected output: " + log); } } diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/modules/EdgeCases.java --- a/langtools/test/tools/javac/modules/EdgeCases.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/test/tools/javac/modules/EdgeCases.java Thu Nov 03 13:59:15 2016 -0700 @@ -71,21 +71,22 @@ @Test public void testAddExportUndefinedModule(Path base) throws Exception { Path src = base.resolve("src"); - tb.writeJavaFiles(src, "package test; import undef.Any; public class Test {}"); + tb.writeJavaFiles(src, "package test; import undefPackage.Any; public class Test {}"); Path classes = base.resolve("classes"); tb.createDirectories(classes); List log = new JavacTask(tb) - .options("--add-exports", "undef/undef=ALL-UNNAMED", "-XDrawDiagnostics") + .options("--add-exports", "undefModule/undefPackage=ALL-UNNAMED", + "-XDrawDiagnostics") .outdir(classes) .files(findJavaFiles(src)) .run(Task.Expect.FAIL) .writeAll() .getOutputLines(Task.OutputKind.DIRECT); - List expected = Arrays.asList("- compiler.err.cant.find.module: undef", - "Test.java:1:27: compiler.err.doesnt.exist: undef", - "2 errors"); + List expected = Arrays.asList("- compiler.warn.module.for.option.not.found: --add-exports, undefModule", + "Test.java:1:34: compiler.err.doesnt.exist: undefPackage", + "1 error", "1 warning"); if (!expected.equals(log)) throw new Exception("expected output not found: " + log); diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/modules/LimitModulesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/modules/LimitModulesTest.java Thu Nov 03 13:59:15 2016 -0700 @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2015, 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 + * @summary Test the --limit-modules option + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase + * @run main LimitModulesTest + */ + + +import java.nio.file.Path; + +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class LimitModulesTest extends ModuleTestBase { + public static void main(String... args) throws Exception { + new LimitModulesTest().runTests(); + } + + @Test + public void testEmpty(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "class Dummy { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("--module-source-path", src.toString(), + "--limit-modules", "") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + if (!log.contains("javac: no value for --limit-modules option")) + throw new Exception("expected output not found"); + + log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("--module-source-path", src.toString(), + "--limit-modules=") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + if (!log.contains("javac: no value for --limit-modules option")) + throw new Exception("expected output not found"); + } + + @Test + public void testEmptyItem(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { }"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--limit-modules", ",m1") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--limit-modules", "m1,,m2") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + + new JavacTask(tb) + .options("--module-source-path", src.toString(), + "--limit-modules", "m1,") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + } + + @Test + public void testEmptyList(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "class Dummy { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb, Task.Mode.CMDLINE) + .options("--module-source-path", src.toString(), + "--limit-modules", ",") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + if (!log.contains("javac: bad value for --limit-modules option")) + throw new Exception("expected output not found"); + } + + @Test + public void testInvalidName(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "class Dummy { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + String log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--limit-modules", "BadModule!") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + if (!log.contains("- compiler.warn.bad.name.for.option: --limit-modules, BadModule!")) + throw new Exception("expected output not found"); + } + + @Test + public void testLastOneWins(Path base) throws Exception { + Path src = base.resolve("src"); + tb.writeJavaFiles(src, + "package p; class C { com.sun.tools.javac.Main main; }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + System.err.println("case 1:"); + new JavacTask(tb) + .options("-XDrawDiagnostics", + "--limit-modules", "java.base", + "--limit-modules", "jdk.compiler") + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll(); + + System.err.println("case 2:"); + String log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--limit-modules", "jdk.compiler", + "--limit-modules", "java.base") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + if (!log.contains("C.java:1:41: compiler.err.doesnt.exist: com.sun.tools.javac")) + throw new Exception("expected output not found"); + } +} + diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/modules/ModuleTestBase.java --- a/langtools/test/tools/javac/modules/ModuleTestBase.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/test/tools/javac/modules/ModuleTestBase.java Thu Nov 03 13:59:15 2016 -0700 @@ -53,4 +53,12 @@ Path[] findJavaFiles(Path... paths) throws IOException { return tb.findJavaFiles(paths); } + + void checkOutputContains(String log, String... expect) throws Exception { + for (String e : expect) { + if (!log.contains(e)) { + throw new Exception("expected output not found: " + e); + } + } + } } diff -r 1313399705e9 -r 8e66bf10fcec langtools/test/tools/javac/modules/XModuleTest.java --- a/langtools/test/tools/javac/modules/XModuleTest.java Thu Nov 03 09:12:02 2016 -0700 +++ b/langtools/test/tools/javac/modules/XModuleTest.java Thu Nov 03 13:59:15 2016 -0700 @@ -223,8 +223,7 @@ .writeAll() .getOutputLines(Task.OutputKind.DIRECT); - List expected = Arrays.asList("- compiler.err.xmodule.no.module.sourcepath", - "1 error"); + List expected = Arrays.asList("- compiler.err.xmodule.no.module.sourcepath"); if (!expected.equals(log)) throw new Exception("expected output not found: " + log);