# HG changeset patch # User ksrini # Date 1489715450 25200 # Node ID 2f97c71f06f40bbac0c279c93b97fe6e2465eb4f # Parent 4bd6416db3deab6eceb729e43b0c08aadde45a82 8175346: javadoc does not handle Locations correctly with --patch-module Reviewed-by: jjg diff -r 4bd6416db3de -r 2f97c71f06f4 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java Thu Mar 16 17:13:10 2017 -0700 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java Thu Mar 16 18:50:50 2017 -0700 @@ -53,6 +53,7 @@ import javax.tools.StandardLocation; import com.sun.tools.javac.code.Kinds.Kind; +import com.sun.tools.javac.code.Source; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.CompletionFailure; @@ -60,8 +61,11 @@ import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.comp.Modules; +import com.sun.tools.javac.main.JavaCompiler; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCModuleDecl; +import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; @@ -70,7 +74,9 @@ import jdk.javadoc.doclet.DocletEnvironment.ModuleMode; import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; + import static javax.tools.JavaFileObject.Kind.*; + import static jdk.javadoc.internal.tool.Main.Result.*; import static jdk.javadoc.internal.tool.JavadocTool.isValidClassName; @@ -153,10 +159,11 @@ private final Symtab syms; private final Names names; private final JavaFileManager fm; - private final Location location; + private final List locations; private final Modules modules; private final Map opts; private final Messager messager; + private final JavaCompiler compiler; private final Map entries = new LinkedHashMap<>(); @@ -201,12 +208,22 @@ this.modules = Modules.instance(context); this.opts = opts; this.messager = Messager.instance0(context); + this.compiler = JavaCompiler.instance(context); + Source source = Source.instance(context); - this.location = modules.multiModuleMode - ? StandardLocation.MODULE_SOURCE_PATH - : toolEnv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) - ? StandardLocation.SOURCE_PATH - : StandardLocation.CLASS_PATH; + List locs = new ArrayList<>(); + if (modules.multiModuleMode) { + locs.add(StandardLocation.MODULE_SOURCE_PATH); + } else { + if (toolEnv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)) + locs.add(StandardLocation.SOURCE_PATH); + else + locs.add(StandardLocation.CLASS_PATH); + } + if (source.allowModules() && toolEnv.fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) + locs.add(StandardLocation.PATCH_MODULE_PATH); + this.locations = Collections.unmodifiableList(locs); + getEntry("").excluded = false; accessFilter = new ModifierFilter(opts); @@ -341,6 +358,52 @@ return this; } + /* + * This method sanity checks the following cases: + * a. a source-path containing a single module and many modules specified with --module + * b. no modules on source-path + * c. mismatched source-path and many modules specified with --module + */ + void sanityCheckSourcePathModules(List moduleNames) throws ToolException { + if (!haveSourceLocationWithModule) + return; + + if (moduleNames.size() > 1) { + String text = messager.getText("main.cannot_use_sourcepath_for_modules", + String.join(", ", moduleNames)); + throw new ToolException(CMDERR, text); + } + + String foundModule = getModuleName(StandardLocation.SOURCE_PATH); + if (foundModule == null) { + String text = messager.getText("main.module_not_found_on_sourcepath", moduleNames.get(0)); + throw new ToolException(CMDERR, text); + } + + if (!moduleNames.get(0).equals(foundModule)) { + String text = messager.getText("main.sourcepath_does_not_contain_module", moduleNames.get(0)); + throw new ToolException(CMDERR, text); + } + } + + private String getModuleName(Location location) throws ToolException { + try { + JavaFileObject jfo = fm.getJavaFileForInput(location, + "module-info", JavaFileObject.Kind.SOURCE); + if (jfo != null) { + JCCompilationUnit jcu = compiler.parse(jfo); + JCModuleDecl module = TreeInfo.getModule(jcu); + if (module != null) { + return module.getName().toString(); + } + } + } catch (IOException ioe) { + String text = messager.getText("main.file.manager.list", location); + throw new ToolException(SYSERR, text, ioe); + } + return null; + } + @SuppressWarnings("unchecked") ElementsTable scanSpecifiedItems() throws ToolException { @@ -349,15 +412,17 @@ s -> Collections.EMPTY_LIST); List mlist = new ArrayList<>(); for (String m : moduleNames) { - Location moduleLoc = getModuleLocation(location, m); - if (moduleLoc == null) { + List moduleLocations = getModuleLocation(locations, m); + if (moduleLocations.isEmpty()) { String text = messager.getText("main.module_not_found", m); throw new ToolException(CMDERR, text); - } else { - mlist.add(m); - ModuleSymbol msym = syms.enterModule(names.fromString(m)); - specifiedModuleElements.add((ModuleElement) msym); + } + if (moduleLocations.contains(StandardLocation.SOURCE_PATH)) { + sanityCheckSourcePathModules(moduleNames); } + mlist.add(m); + ModuleSymbol msym = syms.enterModule(names.fromString(m)); + specifiedModuleElements.add((ModuleElement) msym); } // scan for modules with qualified packages @@ -448,35 +513,41 @@ }); for (ModulePackage modpkg : subPackages) { - Location packageLocn = getLocation(modpkg); - Iterable list = null; - try { - list = fm.list(packageLocn, modpkg.packageName, sourceKinds, true); - } catch (IOException ioe) { - String text = messager.getText("main.file.manager.list", modpkg.packageName); - throw new ToolException(SYSERR, text, ioe); + List locs = getLocation(modpkg); + for (Location loc : locs) { + addPackagesFromLocations(loc, modpkg); } - for (JavaFileObject fo : list) { - String binaryName = fm.inferBinaryName(packageLocn, fo); - String pn = getPackageName(binaryName); - String simpleName = getSimpleName(binaryName); - Entry e = getEntry(pn); - if (!e.isExcluded() && isValidClassName(simpleName)) { - ModuleSymbol msym = (modpkg.hasModule()) - ? syms.getModule(names.fromString(modpkg.moduleName)) - : findModuleOfPackageName(modpkg.packageName); + } + } - if (msym != null && !msym.isUnnamed()) { - syms.enterPackage(msym, names.fromString(pn)); - ModulePackage npkg = new ModulePackage(msym.toString(), pn); - cmdLinePackages.add(npkg); - } else { - cmdLinePackages.add(e.modpkg); - } - e.files = (e.files == null - ? com.sun.tools.javac.util.List.of(fo) - : e.files.prepend(fo)); + private void addPackagesFromLocations(Location packageLocn, ModulePackage modpkg) throws ToolException { + Iterable list = null; + try { + list = fm.list(packageLocn, modpkg.packageName, sourceKinds, true); + } catch (IOException ioe) { + String text = messager.getText("main.file.manager.list", modpkg.packageName); + throw new ToolException(SYSERR, text, ioe); + } + for (JavaFileObject fo : list) { + String binaryName = fm.inferBinaryName(packageLocn, fo); + String pn = getPackageName(binaryName); + String simpleName = getSimpleName(binaryName); + Entry e = getEntry(pn); + if (!e.isExcluded() && isValidClassName(simpleName)) { + ModuleSymbol msym = (modpkg.hasModule()) + ? syms.getModule(names.fromString(modpkg.moduleName)) + : findModuleOfPackageName(modpkg.packageName); + + if (msym != null && !msym.isUnnamed()) { + syms.enterPackage(msym, names.fromString(pn)); + ModulePackage npkg = new ModulePackage(msym.toString(), pn); + cmdLinePackages.add(npkg); + } else { + cmdLinePackages.add(e.modpkg); } + e.files = (e.files == null + ? com.sun.tools.javac.util.List.of(fo) + : e.files.prepend(fo)); } } } @@ -544,20 +615,23 @@ private Set getAllModulePackages(ModuleElement mdle) throws ToolException { Set result = new HashSet<>(); ModuleSymbol msym = (ModuleSymbol) mdle; - Location msymloc = getModuleLocation(location, msym.name.toString()); - try { - for (JavaFileObject fo : fm.list(msymloc, "", sourceKinds, true)) { - if (fo.getName().endsWith("module-info.java")) - continue; - String binaryName = fm.inferBinaryName(msymloc, fo); - String pn = getPackageName(binaryName); - PackageSymbol psym = syms.enterPackage(msym, names.fromString(pn)); - result.add((PackageElement) psym); + List msymlocs = getModuleLocation(locations, msym.name.toString()); + for (Location msymloc : msymlocs) { + try { + for (JavaFileObject fo : fm.list(msymloc, "", sourceKinds, true)) { + if (fo.getName().endsWith("module-info.java")) { + continue; + } + String binaryName = fm.inferBinaryName(msymloc, fo); + String pn = getPackageName(binaryName); + PackageSymbol psym = syms.enterPackage(msym, names.fromString(pn)); + result.add((PackageElement) psym); + } + + } catch (IOException ioe) { + String text = messager.getText("main.file.manager.list", msymloc.getName()); + throw new ToolException(SYSERR, text, ioe); } - - } catch (IOException ioe) { - String text = messager.getText("main.file.manager.list", msymloc.getName()); - throw new ToolException(SYSERR, text, ioe); } return result; } @@ -741,25 +815,25 @@ } ListBuffer lb = new ListBuffer<>(); - Location packageLocn = getLocation(modpkg); - if (packageLocn == null) { + List locs = getLocation(modpkg); + if (locs.isEmpty()) { return Collections.emptyList(); } String pname = modpkg.packageName; - - try { - for (JavaFileObject fo : fm.list(packageLocn, pname, sourceKinds, recurse)) { - String binaryName = fm.inferBinaryName(packageLocn, fo); - String simpleName = getSimpleName(binaryName); - if (isValidClassName(simpleName)) { - lb.append(fo); + for (Location packageLocn : locs) { + try { + for (JavaFileObject fo : fm.list(packageLocn, pname, sourceKinds, recurse)) { + String binaryName = fm.inferBinaryName(packageLocn, fo); + String simpleName = getSimpleName(binaryName); + if (isValidClassName(simpleName)) { + lb.append(fo); + } } + } catch (IOException ioe) { + String text = messager.getText("main.file.manager.list", pname); + throw new ToolException(SYSERR, text, ioe); } - } catch (IOException ioe) { - String text = messager.getText("main.file.manager.list", pname); - throw new ToolException(SYSERR, text, ioe); } - return lb.toList(); } @@ -774,24 +848,49 @@ return null; } - private Location getLocation(ModulePackage modpkg) throws ToolException { - if (location != StandardLocation.MODULE_SOURCE_PATH) { - return location; + private List getLocation(ModulePackage modpkg) throws ToolException { + if (locations.size() == 1 && !locations.contains(StandardLocation.MODULE_SOURCE_PATH)) { + return Collections.singletonList(locations.get(0)); } if (modpkg.hasModule()) { - return getModuleLocation(location, modpkg.moduleName); + return getModuleLocation(locations, modpkg.moduleName); } // TODO: handle invalid results better. ModuleSymbol msym = findModuleOfPackageName(modpkg.packageName); if (msym == null) { - return null; + return Collections.emptyList(); } - return getModuleLocation(location, msym.name.toString()); + return getModuleLocation(locations, msym.name.toString()); } - private Location getModuleLocation(Location location, String msymName) - throws ToolException { + boolean haveSourceLocationWithModule = false; + + private List getModuleLocation(List locations, String msymName) throws ToolException { + List out = new ArrayList<>(); + // search in the patch module first, this overrides others + if (locations.contains(StandardLocation.PATCH_MODULE_PATH)) { + Location loc = getModuleLocation(StandardLocation.PATCH_MODULE_PATH, msymName); + if (loc != null) + out.add(loc); + } + for (Location location : locations) { + // skip patch module, already done + if (location == StandardLocation.PATCH_MODULE_PATH) { + continue; + } else if (location == StandardLocation.MODULE_SOURCE_PATH) { + Location loc = getModuleLocation(location, msymName); + if (loc != null) + out.add(loc); + } else if (location == StandardLocation.SOURCE_PATH) { + haveSourceLocationWithModule = true; + out.add(StandardLocation.SOURCE_PATH); + } + } + return out; + } + + private Location getModuleLocation(Location location, String msymName) throws ToolException { try { return fm.getLocationForModule(location, msymName); } catch (IOException ioe) { diff -r 4bd6416db3de -r 2f97c71f06f4 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties Thu Mar 16 17:13:10 2017 -0700 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties Thu Mar 16 18:50:50 2017 -0700 @@ -258,6 +258,9 @@ main.invalid_flag=invalid flag: {0} main.No_modules_packages_or_classes_specified=No modules, packages or classes specified. main.module_not_found=module {0} not found.\n +main.cannot_use_sourcepath_for_modules=cannot use source path for multiple modules {0} +main.module_not_found_on_sourcepath=module {0} not found on source path +main.sourcepath_does_not_contain_module=source path does not contain module {0} main.cant.read=cannot read {0} main.Loading_source_files_for_package=Loading source files for package {0}... main.Loading_source_file=Loading source file {0}... diff -r 4bd6416db3de -r 2f97c71f06f4 langtools/test/jdk/javadoc/tool/modules/ModuleTestBase.java --- a/langtools/test/jdk/javadoc/tool/modules/ModuleTestBase.java Thu Mar 16 17:13:10 2017 -0700 +++ b/langtools/test/jdk/javadoc/tool/modules/ModuleTestBase.java Thu Mar 16 18:50:50 2017 -0700 @@ -27,7 +27,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; -import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; @@ -158,6 +158,12 @@ } } + void checkTypesSelected(String... args) throws Exception { + for (String arg : args) { + checkDocletOutputPresent("Selected", ElementKind.CLASS, arg); + } + } + void checkMembersSelected(String... args) throws Exception { for (String arg : args) { checkDocletOutputPresent("Selected", ElementKind.METHOD, arg); @@ -280,6 +286,17 @@ StringWriter sw = new StringWriter(); PrintWriter ps = new PrintWriter(sw); + DocletEnvironment docEnv = null; + + boolean hasDocComments = false; + + String hasDocComments(Element e) { + String comment = docEnv.getElementUtils().getDocComment(e); + return comment != null && !comment.isEmpty() + ? "hasDocComments" + : "noDocComments"; + } + // csv style output, for simple regex verification void printDataSet(String header, Set set) { for (Element e : set) { @@ -290,7 +307,12 @@ ps.print(FS); ps.print(e.getKind()); ps.print(FS); - ps.println(e.getQualifiedName()); + ps.print(e.getQualifiedName()); + if (hasDocComments) { + ps.print(FS); + ps.print(hasDocComments(e)); + } + ps.println(); return null; } @@ -299,7 +321,12 @@ ps.print(FS); ps.print(e.getKind()); ps.print(FS); - ps.println(e.getQualifiedName()); + ps.print(e.getQualifiedName()); + if (hasDocComments) { + ps.print(FS); + ps.print(hasDocComments(e)); + } + ps.println(); return null; } @@ -308,7 +335,12 @@ ps.print(FS); ps.print(ElementKind.CLASS); ps.print(FS); - ps.println(e.getQualifiedName()); + ps.print(e.getQualifiedName()); + if (hasDocComments) { + ps.print(FS); + ps.print(hasDocComments(e)); + } + ps.println(); return null; } @@ -338,7 +370,12 @@ ps.print(FS); ps.print(fqn); ps.print("."); - ps.println(e.getSimpleName()); + ps.print(e.getSimpleName()); + if (hasDocComments) { + ps.print(FS); + ps.print(hasDocComments(e)); + } + ps.println(); return null; } }.visit(e); @@ -347,6 +384,7 @@ @Override public boolean run(DocletEnvironment docenv) { + this.docEnv = docenv; ps.println("ModuleMode" + FS + docenv.getModuleMode()); printDataSet("Specified", docenv.getSpecifiedElements()); printDataSet("Included", docenv.getIncludedElements()); @@ -369,7 +407,9 @@ addEnclosedElements(docenv, result, me); } for (PackageElement pe : ElementFilter.packagesIn(elements)) { - addEnclosedElements(docenv, result, docenv.getElementUtils().getModuleOf(pe)); + ModuleElement mdle = docenv.getElementUtils().getModuleOf(pe); + if (mdle != null) + addEnclosedElements(docenv, result, mdle); addEnclosedElements(docenv, result, pe); } for (TypeElement te : ElementFilter.typesIn(elements)) { @@ -390,7 +430,45 @@ @Override public Set getSupportedOptions() { - return Collections.emptySet(); + Option[] options = { + new Option() { + private final List someOption = Arrays.asList( + "-hasDocComments" + ); + + @Override + public int getArgumentCount() { + return 0; + } + + @Override + public String getDescription() { + return "print disposition of doc comments on an element"; + } + + @Override + public Option.Kind getKind() { + return Option.Kind.STANDARD; + } + + @Override + public List getNames() { + return someOption; + } + + @Override + public String getParameters() { + return "flag"; + } + + @Override + public boolean process(String opt, List arguments) { + hasDocComments = true; + return true; + } + } + }; + return new HashSet<>(Arrays.asList(options)); } @Override diff -r 4bd6416db3de -r 2f97c71f06f4 langtools/test/jdk/javadoc/tool/modules/Modules.java --- a/langtools/test/jdk/javadoc/tool/modules/Modules.java Thu Mar 16 17:13:10 2017 -0700 +++ b/langtools/test/jdk/javadoc/tool/modules/Modules.java Thu Mar 16 18:50:50 2017 -0700 @@ -35,6 +35,7 @@ * @run main Modules */ +import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -321,38 +322,6 @@ } @Test - public void testPatchModuleOption(Path base) throws Exception { - Path src = base.resolve("src"); - Path modulePath = base.resolve("modules"); - Path patchPath = base.resolve("patch"); - - ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); - mb1.comment("Module on module path.") - .exports("pkg1") - .classes("package pkg1; /** Class A */ public class A { }") - .build(modulePath); - - tb.writeJavaFiles(patchPath, "package pkg1; /** Class A */ public class A { public static int k; }"); - new JavacTask(tb) - .files(patchPath.resolve("pkg1/A.java")) - .run(); - - ModuleBuilder mb2 = new ModuleBuilder(tb, "m2"); - mb2.comment("The second module.") - .exports("pkg2") - .requires("m1") - .classes("package pkg2; /** Class B */ public class B { /** Field f */ public int f = pkg1.A.k; }") - .write(src); - execTask("--module-source-path", src.toString(), - "--patch-module", "m1=" + patchPath.toString(), - "--module-path", modulePath.toString(), - "--module", "m2"); - checkModulesSpecified("m2"); - checkPackagesIncluded("pkg2"); - checkMembersSelected("pkg2.B.f"); - } - - @Test public void testAddReadsOption(Path base) throws Exception { Path src = base.resolve("src"); Path modulePath = base.resolve("modules"); @@ -550,6 +519,52 @@ assertMessagePresent("javadoc: error - module MIA not found"); } + @Test + public void testSingleModuleOptionWithSourcePath(Path base) throws Exception { + Path src = base.resolve("src"); + Path mod = createSimpleModule(src, "m1"); + execTask("--source-path", mod.toString(), + "--module", "m1"); + checkModulesSpecified("m1"); + checkPackagesIncluded("p"); + checkTypesIncluded("p.C"); + } + + @Test + public void testSingleModuleOptionWithMissingModuleInSourcePath(Path base) throws Exception { + Path src = base.resolve("src"); + Path mod = createSimpleModule(src, "m1"); + execNegativeTask("--source-path", mod.toString(), + "--module", "m2"); + assertMessagePresent("source path does not contain module m2"); + } + + @Test + public void testMultipleModuleOptionWithSourcePath(Path base) throws Exception { + Path src = base.resolve("src"); + Path mod = createSimpleModule(src, "m1"); + execNegativeTask("--source-path", mod.toString(), + "--module", "m1,m2,m3"); + assertMessagePresent("cannot use source path for multiple modules m1, m2, m3"); + } + + @Test + public void testSingleModuleOptionWithNoModuleOnSourcePath(Path base) throws Exception { + Path src = base.resolve("src"); + Path mod1 = Paths.get(src.toString(), "m1"); + execNegativeTask("--source-path", mod1.toString(), + "--module", "m1"); + assertMessagePresent("module m1 not found on source path"); + } + + Path createSimpleModule(Path src, String mname) throws IOException { + Path mpath = Paths.get(src.toString(), mname); + tb.writeJavaFiles(mpath, + "module " + mname + " { exports p; }", + "package p; public class C { }"); + return mpath; + } + void createAuxiliaryModules(Path src) throws IOException { new ModuleBuilder(tb, "J") diff -r 4bd6416db3de -r 2f97c71f06f4 langtools/test/jdk/javadoc/tool/modules/PatchModules.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/jdk/javadoc/tool/modules/PatchModules.java Thu Mar 16 18:50:50 2017 -0700 @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2017, 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 8175346 + * @summary Test patch module options + * @modules + * jdk.javadoc/jdk.javadoc.internal.api + * jdk.javadoc/jdk.javadoc.internal.tool + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @library /tools/lib + * @build toolbox.ToolBox toolbox.TestRunner + * @run main PatchModules + */ + +import java.nio.file.Path; +import java.nio.file.Paths; + +import toolbox.*; + +public class PatchModules extends ModuleTestBase { + + public static void main(String... args) throws Exception { + new PatchModules().runTests(); + } + + // Case A.1, m2 augmenting m1 + @Test + public void testPatchModuleOption(Path base) throws Exception { + Path src = base.resolve("src"); + Path modulePath = base.resolve("modules"); + Path patchPath = base.resolve("patch"); + + ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); + mb1.comment("Module on module path.") + .exports("pkg1") + .classes("package pkg1; /** Class A */ public class A { }") + .build(modulePath); + + tb.writeJavaFiles(patchPath, "package pkg1; /** Class A */ public class A { public static int k; }"); + new JavacTask(tb) + .files(patchPath.resolve("pkg1/A.java")) + .run(); + + ModuleBuilder mb2 = new ModuleBuilder(tb, "m2"); + mb2.comment("The second module.") + .exports("pkg2") + .requires("m1") + .classes("package pkg2; /** Class B */ public class B { /** Field f */ public int f = pkg1.A.k; }") + .write(src); + execTask("--module-source-path", src.toString(), + "--patch-module", "m1=" + patchPath.toString(), + "--module-path", modulePath.toString(), + "--module", "m2"); + checkModulesSpecified("m2"); + checkPackagesIncluded("pkg2"); + checkMembersSelected("pkg2.B.f"); + } + + // Case A.2: use package, source form of m1 augmenting binary form of m1 + @Test + public void testPatchModuleWithPackage(Path base) throws Exception { + Path modulePath = base.resolve("modules"); + Path moduleSrcPath = base.resolve("modulesSrc"); + + Path mpath = Paths.get(moduleSrcPath.toString(), "m1"); + + ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); + mb1.comment("Module m1.") + .exports("pkg1") + .classes("package pkg1; /** Class A */ public class A { }") + .classes("package pkg1.pkg2; /** Class B */ public class B { }") + .build(modulePath); + + execTask("-hasDocComments", + "--module-path", modulePath.toString(), + "--add-modules", "m1", + "--patch-module", "m1=" + mpath.toString(), + "pkg1"); + checkTypesIncluded("pkg1.A hasDocComments"); + } + + // Case A.2: use subpackages, source form of m1 augmenting binary form of m1 + @Test + public void testPatchModuleWithSubPackages(Path base) throws Exception { + Path modulePath = base.resolve("modules"); + Path moduleSrcPath = base.resolve("modulesSrc"); + + Path mpath = Paths.get(moduleSrcPath.toString(), "m1"); + + ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); + mb1.comment("Module m1.") + .exports("pkg1") + .classes("package pkg1; /** Class A */ public class A { }") + .classes("package pkg1.pkg2; /** Class B */ public class B { }") + .build(modulePath); + + execTask("-hasDocComments", + "--module-path", modulePath.toString(), + "--add-modules", "m1", + "--patch-module", "m1=" + mpath.toString(), + "-subpackages", "pkg1"); + checkTypesIncluded("pkg1.A hasDocComments"); + checkTypesIncluded("pkg1.pkg2.B hasDocComments"); + } + + // Case B.1: (jsr166) augment and override system module + @Test + public void testPatchModuleModifyingSystemModule(Path base) throws Exception { + Path src = base.resolve("src"); + Path patchSrc = base.resolve("patch"); + + // build the patching sources + tb.writeJavaFiles(patchSrc, "package java.util;\n" + + "/** Class Collection */\n" + + "public interface Collection {}"); + + tb.writeJavaFiles(patchSrc, "package java.util;\n" + + "/** Class MyCollection */\n" + + "public interface MyCollection extends Collection {}"); + + execTask("-hasDocComments", "--patch-module", "java.base=" + patchSrc.toString(), + "java.util"); + + checkPackagesSpecified("java.util"); + checkTypesIncluded("java.util.Collection hasDocComments", + "java.util.MyCollection hasDocComments"); + } + + // Case C.1: patch a user module's sources using source path + @Test + public void testPatchModuleUsingSourcePath(Path base) throws Exception { + Path src = base.resolve("src"); + Path patchSrc = base.resolve("patch"); + + ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); + mb1.comment("Module m1.") + .exports("pkg1") + .classes("package pkg1; /** Class A */ public class A { }") + .write(src); + + // build the patching module + tb.writeJavaFiles(patchSrc, "package pkg1;\n" + + "/** Class A */ public class A extends java.util.ArrayList { }"); + tb.writeJavaFiles(patchSrc, "package pkg1;\n" + + "/** Class B */ public class B { }"); + + Path m1src = Paths.get(src.toString(), "m1"); + + execTask("--source-path", m1src.toString(), + "--patch-module", "m1=" + patchSrc.toString(), + "pkg1"); + + checkPackagesSpecified("pkg1"); + checkModulesIncluded("m1"); + checkTypesIncluded("pkg1.A", "pkg1.B"); + } + + // Case C.2: patch a user module's sources using module source path + @Test + public void testPatchModuleWithModuleSourcePath(Path base) throws Exception { + Path src = base.resolve("src"); + Path patchSrc = base.resolve("patch"); + + ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); + mb1.comment("Module on module-source-path.") + .exports("pkg1") + .classes("package pkg1; /** Class A */ public class A { }") + .write(src); + + // build the patching module + tb.writeJavaFiles(patchSrc, "package pkg1;\n" + + "/** Class A */ public class A extends java.util.ArrayList { }"); + tb.writeJavaFiles(patchSrc, "package pkg1;\n" + + "/** Class B */ public class B { }"); + + + execTask("--module-source-path", src.toString(), + "--add-modules", "m1", + "--patch-module", "m1=" + patchSrc.toString(), + "pkg1"); + + checkPackagesSpecified("pkg1"); + checkModulesIncluded("m1"); + checkTypesIncluded("pkg1.A", "pkg1.B"); + } + +} diff -r 4bd6416db3de -r 2f97c71f06f4 langtools/test/jdk/javadoc/tool/modules/ReleaseOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/jdk/javadoc/tool/modules/ReleaseOptions.java Thu Mar 16 18:50:50 2017 -0700 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2017, 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 8175346 + * @summary Test release option interactions + * @modules + * jdk.javadoc/jdk.javadoc.internal.api + * jdk.javadoc/jdk.javadoc.internal.tool + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @library /tools/lib + * @build toolbox.ToolBox toolbox.TestRunner + * @run main ReleaseOptions + */ + +import java.nio.file.Path; +import java.nio.file.Paths; + +import toolbox.*; + +public class ReleaseOptions extends ModuleTestBase { + + public static void main(String... args) throws Exception { + new ReleaseOptions().runTests(); + } + + @Test + public void testReleaseWithPatchModule(Path base) throws Exception { + Path src = Paths.get(base.toString(), "src"); + Path mpath = Paths.get(src. toString(), "m"); + + tb.writeJavaFiles(mpath, + "module m { exports p; }", + "package p; public class C { }"); + + Task.Result result = execNegativeTask("--release", "8", + "--patch-module", "m=" + mpath.toString(), + "p"); + assertMessagePresent(".*No source files for package p.*"); + assertMessageNotPresent(".*Exception*"); + assertMessageNotPresent(".java.lang.AssertionError.*"); + } + + @Test + public void testReleaseWithSourcepath(Path base) throws Exception { + Path src = Paths.get(base.toString(), "src"); + Path mpath = Paths.get(src. toString(), "m"); + + tb.writeJavaFiles(mpath, + "module m { exports p; }", + "package p; public class C { }"); + + Task.Result result = execNegativeTask("--release", "8", + "--source-path", mpath.toString(), + "--module", "m"); + assertMessagePresent(".*(use -source 9 or higher to enable modules).*"); + assertMessageNotPresent(".*Exception*"); + assertMessageNotPresent(".java.lang.AssertionError.*"); + } + +// @Test TBD, JDK-8175277, argument validation should fail on this +// public void testReleaseWithModuleSourcepath(Path base) throws Exception { +// Path src = Paths.get(base.toString(), "src"); +// Path mpath = Paths.get(src.toString(), "m"); +// +// tb.writeJavaFiles(mpath, +// "module m { exports p; }", +// "package p; public class C { }"); +// +// Task.Result result = execNegativeTask("--release", "8", +// "--module-source-path", src.toString(), +// "--module", "m"); +// assertMessagePresent(".*(use -source 9 or higher to enable modules).*"); +// assertMessageNotPresent(".*Exception*"); +// assertMessageNotPresent(".java.lang.AssertionError.*"); +// } +}