8178339: javadoc includes qualified opens in "Additional Opened Packages" section
authorksrini
Tue, 18 Apr 2017 06:29:53 -0700
changeset 44807 47e09e3f1829
parent 44806 d6bdff2ad6f2
child 44808 702854495934
8178339: javadoc includes qualified opens in "Additional Opened Packages" section Reviewed-by: jjg
langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
langtools/test/jdk/javadoc/doclet/testModules/TestIndirectExportsOpens.java
langtools/test/jdk/javadoc/doclet/testModules/TestModules.java
langtools/test/tools/lib/toolbox/ModuleBuilder.java
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Mon Apr 17 17:03:19 2017 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Tue Apr 18 06:29:53 2017 -0700
@@ -336,26 +336,32 @@
         // Get all the exported and opened packages, for the transitive closure of the module, to be displayed in
         // the indirect packages tables.
         dependentModules.forEach((module, mod) -> {
-            SortedSet<PackageElement> pkgList = new TreeSet<>(utils.makePackageComparator());
+            SortedSet<PackageElement> exportPkgList = new TreeSet<>(utils.makePackageComparator());
             (ElementFilter.exportsIn(module.getDirectives())).forEach((directive) -> {
                 PackageElement pkg = directive.getPackage();
                 if (shouldDocument(pkg)) {
-                    pkgList.add(pkg);
+                    // Qualified exports are not displayed in API mode
+                    if (moduleMode == ModuleMode.ALL || directive.getTargetModules() == null) {
+                        exportPkgList.add(pkg);
+                    }
                 }
             });
-            // If none of the transitive modules have exported packages to be displayed, we should not be
+            // If none of the indirect modules have exported packages to be displayed, we should not be
             // displaying the table and so it should not be added to the map.
-            if (!pkgList.isEmpty()) {
-                indirectPackages.put(module, pkgList);
+            if (!exportPkgList.isEmpty()) {
+                indirectPackages.put(module, exportPkgList);
             }
             SortedSet<PackageElement> openPkgList = new TreeSet<>(utils.makePackageComparator());
             (ElementFilter.opensIn(module.getDirectives())).forEach((directive) -> {
                 PackageElement pkg = directive.getPackage();
                 if (shouldDocument(pkg)) {
-                    openPkgList.add(pkg);
+                    // Qualified opens are not displayed in API mode
+                    if (moduleMode == ModuleMode.ALL || directive.getTargetModules() == null) {
+                        openPkgList.add(pkg);
+                    }
                 }
             });
-            // If none of the transitive modules have opened packages to be displayed, we should not be
+            // If none of the indirect modules have opened packages to be displayed, we should not be
             // displaying the table and so it should not be added to the map.
             if (!openPkgList.isEmpty()) {
                 indirectOpenPackages.put(module, openPkgList);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/TestIndirectExportsOpens.java	Tue Apr 18 06:29:53 2017 -0700
@@ -0,0 +1,209 @@
+/*
+ * 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 8178339
+ * @summary Tests indirect exports and opens in the module summary page
+ * @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 ../lib /tools/lib
+ * @build toolbox.ToolBox toolbox.ModuleBuilder JavadocTester
+ * @run main TestIndirectExportsOpens
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import toolbox.*;
+
+public class TestIndirectExportsOpens extends JavadocTester {
+
+    public final ToolBox tb;
+    public static void main(String... args) throws Exception {
+        TestIndirectExportsOpens tester = new TestIndirectExportsOpens();
+        tester.runTests(m -> new Object[] { Paths.get(m.getName()) });
+    }
+
+    public TestIndirectExportsOpens() {
+        tb = new ToolBox();
+    }
+
+    @Test
+    public void checkNoIndirects(Path base) throws Exception {
+
+        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
+                .classes("package pm; public class A {}");
+        Path p0 = mb0.write(base);
+
+        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
+                .requiresTransitive("m", p0)
+                .classes("package pa; public class NoOp {}")
+                .exports("pa");
+        mb1.write(base);
+
+        javadoc("-d", base.resolve("out-api").toString(),
+                "-quiet",
+                "--module-source-path", base.toString(),
+                "--expand-requires", "transitive",
+                "--module", "a");
+        checkExit(Exit.OK);
+        verifyIndirectExports(false);
+        verifyIndirectOpens(false);
+    }
+
+    @Test
+    public void checkExportsOpens(Path base) throws Exception {
+
+        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
+                .classes("package pm; public class A {}")
+                .exports("pm")
+                .opens("pm");
+
+        Path p0 = mb0.write(base);
+
+        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
+                .requiresTransitive("m", p0)
+                .classes("package pa ; public class NoOp {}")
+                .exports("pa");
+        mb1.write(base);
+
+        javadoc("-d", base.resolve("out-api").toString(),
+                "-quiet",
+                "--module-source-path", base.toString(),
+                "--expand-requires", "transitive",
+                "--module", "a");
+        checkExit(Exit.OK);
+        verifyIndirectExports(true);
+        verifyIndirectOpens(true);
+    }
+
+    @Test
+    public void checkExportsToOpensTo(Path base) throws Exception {
+
+        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
+                .classes("package pm; public class A {}")
+                .exportsTo("pm", "x")
+                .opensTo("pm", "x");
+
+        Path p0 = mb0.write(base);
+
+        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
+                .requiresTransitive("m", p0)
+                .classes("package pa ; public class NoOp {}")
+                .exports("pa");
+        mb1.write(base);
+
+        javadoc("-d", base.resolve("out-api").toString(),
+                "-quiet",
+                "--module-source-path", base.toString(),
+                "--expand-requires", "transitive",
+                "--module", "a");
+
+        checkExit(Exit.OK);
+        verifyIndirectExports(false);
+        verifyIndirectOpens(false);
+    }
+
+    @Test
+    public void checkExportsToOpensToDetailMode(Path base) throws Exception {
+
+        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
+                .classes("package exportsto; public class A {}")
+                .classes("package opensto; public class A {}")
+                .exportsTo("exportsto", "x")
+                .opensTo("opensto", "x");
+
+        Path p0 = mb0.write(base);
+
+        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
+                .requiresTransitive("m", p0)
+                .classes("package pa ; public class NoOp {}")
+                .exports("pa");
+        mb1.write(base);
+
+        javadoc("-d", base.resolve("out-detail").toString(),
+                "-quiet",
+                "--module-source-path", base.toString(),
+                "--expand-requires", "transitive",
+                "--show-module-contents", "all",
+                "--module", "a");
+
+        checkExit(Exit.OK);
+
+        // In details mode all kinds of packages from java.base,
+        // could be listed in the indirects section, so just
+        // check for minimal expected strings.
+        checkOutput("a-summary.html", true,
+                "Indirect Exports table",
+                "<tr class=\"rowColor\">\n"
+                + "<th class=\"colFirst\" scope=\"row\"><a href=\"m-summary.html\">m</a></th>\n"
+                + "<td class=\"colLast\"><a href=\"exportsto/package-summary.html\">exportsto</a></td>\n"
+                + "</tr>\n");
+
+        checkOutput("a-summary.html", true,
+                "Indirect Opens table",
+                "<tr class=\"altColor\">\n"
+                + "<th class=\"colFirst\" scope=\"row\"><a href=\"m-summary.html\">m</a></th>\n"
+                + "<td class=\"colLast\">opensto</td>\n"
+                + "</tr>\n");
+    }
+
+    void verifyIndirectExports(boolean present) {
+        verifyIndirects(present, false);
+    }
+
+    void verifyIndirectOpens(boolean present) {
+        verifyIndirects(present, true);
+    }
+
+    void verifyIndirects(boolean present, boolean opens) {
+
+        String typeString = opens ? "Indirect Opens" : "Indirect Exports";
+
+        // Avoid false positives, just check for primary string absence.
+        if (!present) {
+            checkOutput("a-summary.html", false, typeString);
+            return;
+        }
+
+        checkOutput("a-summary.html", present,
+                "<table class=\"packagesSummary\" summary=\"" + typeString + " table, listing modules, and packages\">\n"
+                + "<caption><span>" + typeString + "</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<tr>\n"
+                + "<th class=\"colFirst\" scope=\"col\">From</th>\n"
+                + "<th class=\"colLast\" scope=\"col\">Packages</th>\n"
+                + "</tr>\n"
+                + "<tbody>\n"
+                + "<tr class=\"altColor\">\n"
+                + "<th class=\"colFirst\" scope=\"row\"><a href=\"m-summary.html\">m</a></th>\n"
+                + "<td class=\"colLast\"><a href=\"pm/package-summary.html\">pm</a></td>\n"
+                + "</tr>\n"
+                + "</tbody>\n"
+                + "</table>\n");
+    }
+
+}
+
--- a/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java	Mon Apr 17 17:03:19 2017 -0700
+++ b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java	Tue Apr 18 06:29:53 2017 -0700
@@ -752,14 +752,6 @@
         checkOutput("moduleA-summary.html", true,
                 "<li><a href=\"#module.description\">Description</a>&nbsp;|&nbsp;<a href=\"#modules.summary\">"
                 + "Modules</a>&nbsp;|&nbsp;<a href=\"#packages.summary\">Packages</a>&nbsp;|&nbsp;Services</li>",
-                "<table class=\"packagesSummary\" summary=\"Indirect Exports table, listing modules, and packages\">\n"
-                + "<caption><span>Indirect Exports</span><span class=\"tabEnd\">&nbsp;</span></caption>",
-                "<table class=\"packagesSummary\" summary=\"Indirect Opens table, listing modules, and packages\">\n"
-                + "<caption><span>Indirect Opens</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
-                + "<tr>\n"
-                + "<th class=\"colFirst\" scope=\"col\">From</th>\n"
-                + "<th class=\"colLast\" scope=\"col\">Packages</th>\n"
-                + "</tr>\n",
                 "<th class=\"colFirst\" scope=\"row\"><a href=\"moduleB-summary.html\">moduleB</a></th>\n"
                 + "<td class=\"colLast\"><a href=\"testpkgmdlB/package-summary.html\">testpkgmdlB</a></td>\n");
         checkOutput("moduleB-summary.html", true,
--- a/langtools/test/tools/lib/toolbox/ModuleBuilder.java	Mon Apr 17 17:03:19 2017 -0700
+++ b/langtools/test/tools/lib/toolbox/ModuleBuilder.java	Tue Apr 18 06:29:53 2017 -0700
@@ -45,6 +45,7 @@
     private String comment = "";
     private List<String> requires = new ArrayList<>();
     private List<String> exports = new ArrayList<>();
+    private List<String> opens = new ArrayList<>();
     private List<String> uses = new ArrayList<>();
     private List<String> provides = new ArrayList<>();
     private List<String> content = new ArrayList<>();
@@ -134,33 +135,6 @@
     }
 
     /**
-     * Adds an unqualified "exports dynamic" directive to the declaration.
-     * @param pkg the name of the package to be exported
-     * @return this builder
-     */
-    public ModuleBuilder exportsDynamic(String pkg) {
-        return addDirective(exports, "exports dynamic " + pkg + ";");
-    }
-
-    /**
-     * Adds an unqualified "exports private" directive to the declaration.
-     * @param pkg the name of the package to be exported
-     * @return this builder
-     */
-    public ModuleBuilder exportsPrivate(String pkg) {
-        return addDirective(exports, "exports private " + pkg + ";");
-    }
-
-    /**
-     * Adds an unqualified "exports dynamic private" directive to the declaration.
-     * @param pkg the name of the package to be exported
-     * @return this builder
-     */
-    public ModuleBuilder exportsDynamicPrivate(String pkg) {
-        return addDirective(exports, "exports dynamic private " + pkg + ";");
-    }
-
-    /**
      * Adds a qualified "exports" directive to the declaration.
      * @param pkg the name of the package to be exported
      * @param module the name of the module to which it is to be exported
@@ -171,33 +145,22 @@
     }
 
     /**
-     * Adds a qualified "exports dynamic" directive to the declaration.
-     * @param pkg the name of the package to be exported
-     * @param module the name of the module to which it is to be exported
+     * Adds an unqualified "opens" directive to the declaration.
+     * @param pkg the name of the package to be opened
      * @return this builder
      */
-    public ModuleBuilder exportsDynamicTo(String pkg, String module) {
-        return addDirective(exports, "exports dynamic " + pkg + " to " + module + ";");
+    public ModuleBuilder opens(String pkg) {
+        return addDirective(opens, "opens " + pkg + ";");
     }
 
     /**
-     * Adds a qualified "exports private" directive to the declaration.
-     * @param pkg the name of the package to be exported
-     * @param module the name of the module to which it is to be exported
+     * Adds a qualified "opens" directive to the declaration.
+     * @param pkg the name of the package to be opened
+     * @param module the name of the module to which it is to be opened
      * @return this builder
      */
-    public ModuleBuilder exportsPrivateTo(String pkg, String module) {
-        return addDirective(exports, "exports private " + pkg + " to " + module + ";");
-    }
-
-    /**
-     * Adds a qualified "exports dynamic private" directive to the declaration.
-     * @param pkg the name of the package to be exported
-     * @param module the name of the module to which it is to be exported
-     * @return this builder
-     */
-    public ModuleBuilder exportsDynamicPrivateTo(String pkg, String module) {
-        return addDirective(exports, "exports dynamic private " + pkg + " to " + module + ";");
+    public ModuleBuilder opensTo(String pkg, String module) {
+        return addDirective(opens, "opens " + pkg + " to " + module + ";");
     }
 
     /**
@@ -254,6 +217,7 @@
         sb.append("module ").append(name).append(" {\n");
         requires.forEach(r -> sb.append("    " + r + "\n"));
         exports.forEach(e -> sb.append("    " + e + "\n"));
+        opens.forEach(o -> sb.append("    " + o + "\n"));
         uses.forEach(u -> sb.append("    " + u + "\n"));
         provides.forEach(p -> sb.append("    " + p + "\n"));
         sb.append("}");