8175346: javadoc does not handle Locations correctly with --patch-module

Reviewed-by: jjg
This commit is contained in:
Kumar Srinivasan 2017-03-16 18:50:50 -07:00
parent 833ecc754c
commit 7feb5d6fb7
6 changed files with 615 additions and 111 deletions

View File

@ -53,6 +53,7 @@ import javax.tools.JavaFileObject;
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.ModuleSymbol;
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;
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 @@ public class ElementsTable {
private final Symtab syms;
private final Names names;
private final JavaFileManager fm;
private final Location location;
private final List<Location> locations;
private final Modules modules;
private final Map<ToolOption, Object> opts;
private final Messager messager;
private final JavaCompiler compiler;
private final Map<String, Entry> entries = new LinkedHashMap<>();
@ -201,12 +208,22 @@ public class ElementsTable {
this.modules = Modules.instance(context);
this.opts = opts;
this.messager = Messager.instance0(context);
this.compiler = JavaCompiler.instance(context);
Source source = Source.instance(context);
List<Location> 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);
this.location = modules.multiModuleMode
? StandardLocation.MODULE_SOURCE_PATH
: toolEnv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
? StandardLocation.SOURCE_PATH
: StandardLocation.CLASS_PATH;
getEntry("").excluded = false;
accessFilter = new ModifierFilter(opts);
@ -341,6 +358,52 @@ public class ElementsTable {
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<String> 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 @@ public class ElementsTable {
s -> Collections.EMPTY_LIST);
List<String> mlist = new ArrayList<>();
for (String m : moduleNames) {
Location moduleLoc = getModuleLocation(location, m);
if (moduleLoc == null) {
List<Location> 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 @@ public class ElementsTable {
});
for (ModulePackage modpkg : subPackages) {
Location packageLocn = getLocation(modpkg);
Iterable<JavaFileObject> 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<Location> 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<JavaFileObject> 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 @@ public class ElementsTable {
private Set<PackageElement> getAllModulePackages(ModuleElement mdle) throws ToolException {
Set<PackageElement> 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<Location> 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 @@ public class ElementsTable {
}
ListBuffer<JavaFileObject> lb = new ListBuffer<>();
Location packageLocn = getLocation(modpkg);
if (packageLocn == null) {
List<Location> 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 @@ public class ElementsTable {
return null;
}
private Location getLocation(ModulePackage modpkg) throws ToolException {
if (location != StandardLocation.MODULE_SOURCE_PATH) {
return location;
private List<Location> 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<Location> getModuleLocation(List<Location> locations, String msymName) throws ToolException {
List<Location> 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) {

View File

@ -258,6 +258,9 @@ main.only_one_argument_with_equals=cannot use ''='' syntax for options that requ
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}...

View File

@ -27,7 +27,7 @@ import java.io.StringWriter;
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 @@ public class ModuleTestBase extends TestRunner {
}
}
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 @@ public class ModuleTestBase extends TestRunner {
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<? extends Element> set) {
for (Element e : set) {
@ -290,7 +307,12 @@ public class ModuleTestBase extends TestRunner {
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 @@ public class ModuleTestBase extends TestRunner {
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 @@ public class ModuleTestBase extends TestRunner {
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 @@ public class ModuleTestBase extends TestRunner {
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 @@ public class ModuleTestBase extends TestRunner {
@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 @@ public class ModuleTestBase extends TestRunner {
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 @@ public class ModuleTestBase extends TestRunner {
@Override
public Set<Doclet.Option> getSupportedOptions() {
return Collections.emptySet();
Option[] options = {
new Option() {
private final List<String> 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<String> getNames() {
return someOption;
}
@Override
public String getParameters() {
return "flag";
}
@Override
public boolean process(String opt, List<String> arguments) {
hasDocComments = true;
return true;
}
}
};
return new HashSet<>(Arrays.asList(options));
}
@Override

View File

@ -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;
@ -320,38 +321,6 @@ public class Modules extends ModuleTestBase {
checkMembersSelected("pkg2.B.f");
}
@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");
@ -550,6 +519,52 @@ public class Modules extends ModuleTestBase {
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")

View File

@ -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<K> {}");
tb.writeJavaFiles(patchSrc, "package java.util;\n"
+ "/** Class MyCollection */\n" +
"public interface MyCollection<K> 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");
}
}

View File

@ -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.*");
// }
}