# HG changeset patch # User jjg # Date 1547579125 28800 # Node ID 8ce4083fc831b1142b2eaeaed334b08f81b6d049 # Parent 314c5b5d9369c3dbef9b4fa70e97d6d6901dea94 8212233: javadoc fails on jdk12 with "The code being documented uses modules but the packages defined in $URL are in the unnamed module." Reviewed-by: hannesw, pmuthuswamy diff -r 314c5b5d9369 -r 8ce4083fc831 src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java Tue Jan 15 10:40:32 2019 -0800 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java Tue Jan 15 11:05:25 2019 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, 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 @@ -40,6 +40,8 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocPath; import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import java.util.Collections; + /** * Writes a file that tries to redirect to an alternate page. * The redirect uses JavaScript, if enabled, falling back on diff -r 314c5b5d9369 -r 8ce4083fc831 src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java Tue Jan 15 10:40:32 2019 -0800 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java Tue Jan 15 11:05:25 2019 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, 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 @@ -45,6 +45,8 @@ import javax.tools.Diagnostic.Kind; import javax.tools.DocumentationTool; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Symbol.ModuleSymbol; import jdk.javadoc.doclet.Reporter; import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration; import jdk.javadoc.internal.doclets.toolkit.Resources; @@ -276,6 +278,12 @@ ModuleElement moduleElement = utils.containingModule(packageElement); Map pkgMap = packageItems.get(utils.getModuleName(moduleElement)); item = (pkgMap != null) ? pkgMap.get(utils.getPackageName(packageElement)) : null; + if (item == null && isAutomaticModule(moduleElement)) { + pkgMap = packageItems.get(utils.getModuleName(null)); + if (pkgMap != null) { + item = pkgMap.get(utils.getPackageName(packageElement)); + } + } } return item; } @@ -420,12 +428,25 @@ path), null); } } else if (moduleName == null) { - throw new Fault(resources.getText("doclet.linkMismatch_ModuleLinkedtoPackage", - path), null); + // suppress the error message in the case of automatic modules + if (!isAutomaticModule(me)) { + throw new Fault(resources.getText("doclet.linkMismatch_ModuleLinkedtoPackage", + path), null); + } } } } + // The following should be replaced by a new method such as Elements.isAutomaticModule + private boolean isAutomaticModule(ModuleElement me) { + if (me == null) { + return false; + } else { + ModuleSymbol msym = (ModuleSymbol) me; + return (msym.flags() & Flags.AUTOMATIC_MODULE) != 0; + } + } + public boolean isUrl (String urlCandidate) { try { new URL(urlCandidate); diff -r 314c5b5d9369 -r 8ce4083fc831 test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithAutomaticModule.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithAutomaticModule.java Tue Jan 15 11:05:25 2019 -0800 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2019, 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 8212233 + * @summary The code being documented uses modules but the packages defined in $URL are in the unnamed module. + * @library /tools/lib ../lib + * @modules + * jdk.javadoc/jdk.javadoc.internal.tool + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build JavadocTester toolbox.JarTask toolbox.JavacTask toolbox.ModuleBuilder toolbox.ToolBox + * @run main TestLinkOptionWithAutomaticModule + */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import toolbox.JarTask; +import toolbox.JavacTask; +import toolbox.ModuleBuilder; +import toolbox.ToolBox; + +public class TestLinkOptionWithAutomaticModule extends JavadocTester { + + public static void main(String... args) throws Exception { + TestLinkOptionWithAutomaticModule tester = new TestLinkOptionWithAutomaticModule(); + tester.runTests(m -> new Object[]{ Path.of(m.getName()) }); + } + + final ToolBox tb = new ToolBox(); + private Path libJar; + private Path libAPI; + + TestLinkOptionWithAutomaticModule() throws IOException { + initLib(); + } + + private void initLib() throws IOException { + // create library: write source, compile it, jar it + Path lib = Path.of("lib"); + Path libSrc = lib.resolve("src"); + tb.writeJavaFiles(libSrc, "package lib; public class LibClass { }"); + Path libClasses = Files.createDirectories(lib.resolve("classes")); + + new JavacTask(tb) + .outdir(libClasses) + .files(tb.findJavaFiles(libSrc)) + .run() + .writeAll(); + + libJar = lib.resolve("MyLib.jar"); + new JarTask(tb, libJar) + .baseDir(libClasses) + .files(".") + .run(); + + libAPI = lib.resolve("api"); + javadoc("-d", libAPI.toString(), + "-sourcepath", libSrc.toString(), + "lib"); + checkExit(Exit.OK); + } + + @Test + public void testLinkUnnamedToAutomaticModule(Path base) throws IOException { + + // create API referring to library + Path src = base.resolve("src"); + tb.writeJavaFiles(src, "package p; public class MyClass extends lib.LibClass { }"); + + // run javadoc with library as automatic module + Path api = base.resolve("api"); + javadoc("-d", api.toString(), + "-sourcepath", src.toString(), + "--add-modules", "MyLib", + "--module-path", libJar.toString(), + "-linkoffline", "http://myWebsite", libAPI.toAbsolutePath().toString(), + "p"); + checkExit(Exit.OK); + checkOutput("p/MyClass.html", true, + "extends LibClass"); + } + + @Test + public void testLinkNamedToAutomaticModule(Path base) throws IOException { + + // create API referring to library + Path src = base.resolve("src"); + new ModuleBuilder(tb, "my.module") + .exports("p") + .requires("MyLib") + .classes("package p; public class MyClass extends lib.LibClass { }") + .write(src); + + // run javadoc with library as automatic module + Path api = base.resolve("api"); + javadoc("-d", api.toString(), + "--module-source-path", src.toString(), + "--module-path", libJar.toString(), + "-linkoffline", "http://myWebsite", libAPI.toAbsolutePath().toString(), + "--module", "my.module"); + checkExit(Exit.OK); + checkOutput("my.module/p/MyClass.html", true, + "extends LibClass"); + } + + @Test + public void testLinkNamedToUnnamedModule(Path base) throws IOException { + + // create API referring to library + Path src = base.resolve("src"); + new ModuleBuilder(tb, "my.module") + .exports("p") + .classes("package p; public class MyClass extends lib.LibClass { }") + .write(src); + + // run javadoc with library as unnamed module + Path api = base.resolve("api"); + javadoc("-d", api.toString(), + "--module-source-path", src.toString(), + "--add-reads", "my.module=ALL-UNNAMED", + "--class-path", libJar.toString(), + "-linkoffline", "http://myWebsite", libAPI.toAbsolutePath().toString(), + "--module", "my.module"); + checkExit(Exit.OK); + checkOutput("my.module/p/MyClass.html", true, + "extends LibClass"); + } +}