changeset 59688:3bbe266345ea

8246712: doclint incorrectly reports some HTML elements as empty Reviewed-by: prappo
author jjg
date Tue, 09 Jun 2020 19:34:18 -0700
parents cd5fe7734a4d
children 2187231a23ab
files src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java test/langtools/tools/doclint/EmptyHtmlTest.java
diffstat 2 files changed, 155 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java	Wed Jun 10 09:32:27 2020 +0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java	Tue Jun 09 19:34:18 2020 -0700
@@ -803,6 +803,7 @@
 
     @Override @DefinedBy(Api.COMPILER_TREE)
     public Void visitIndex(IndexTree tree, Void ignore) {
+        markEnclosingTag(Flag.HAS_INLINE_TAG);
         for (TagStackItem tsi : tagStack) {
             if (tsi.tag == HtmlTag.A) {
                 env.messages.warning(HTML, tree, "dc.tag.a.within.a",
@@ -956,6 +957,7 @@
 
     @Override @DefinedBy(Api.COMPILER_TREE)
     public Void visitSummary(SummaryTree node, Void aVoid) {
+        markEnclosingTag(Flag.HAS_INLINE_TAG);
         int idx = env.currDocComment.getFullBody().indexOf(node);
         // Warn if the node is preceded by non-whitespace characters,
         // or other non-text nodes.
@@ -967,6 +969,7 @@
 
     @Override @DefinedBy(Api.COMPILER_TREE)
     public Void visitSystemProperty(SystemPropertyTree tree, Void ignore) {
+        markEnclosingTag(Flag.HAS_INLINE_TAG);
         for (TagStackItem tsi : tagStack) {
             if (tsi.tag == HtmlTag.A) {
                 env.messages.warning(HTML, tree, "dc.tag.a.within.a",
@@ -1041,6 +1044,7 @@
 
     @Override @DefinedBy(Api.COMPILER_TREE)
     public Void visitUnknownInlineTag(UnknownInlineTagTree tree, Void ignore) {
+        markEnclosingTag(Flag.HAS_INLINE_TAG);
         checkUnknownTag(tree, tree.getTagName());
         return super.visitUnknownInlineTag(tree, ignore);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/doclint/EmptyHtmlTest.java	Tue Jun 09 19:34:18 2020 -0700
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2020, 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 8246712
+ * @summary doclint incorrectly reports some HTML elements as empty
+ * @modules jdk.compiler/com.sun.tools.doclint
+ * @library /tools/lib
+ * @build toolbox.TestRunner toolbox.ToolBox
+ * @run main EmptyHtmlTest
+ */
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+import com.sun.source.doctree.DocTreeVisitor;
+import com.sun.source.doctree.InlineTagTree;
+import com.sun.tools.doclint.DocLint;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+public class EmptyHtmlTest extends TestRunner {
+
+    public static void main(String... args) throws Exception {
+        EmptyHtmlTest t = new EmptyHtmlTest();
+        t.runTests(m -> new Object[] { Path.of(m.getName()) });
+    }
+
+    public EmptyHtmlTest() {
+        super(System.err);
+    }
+
+    ToolBox tb = new ToolBox();
+
+    /**
+     * This test is intended to be future-proof, and hence detect any
+     * problems in any inline tags added in the future.
+     * Since there is not yet any mapping between DocTree.Kind and
+     * the corresponding subtype DocTree (see javac Tree.Kind, Tree)
+     * the list of all current inline tag classes is determined by
+     * scanning DocTreeVisitor.
+     *
+     * @param base working directory for the test case
+     * @throws Exception if an error occurs
+     */
+    @Test
+    public void testInlines(Path base) throws Exception {
+        Class<DocTreeVisitor> c = DocTreeVisitor.class;
+        for (Method m : c.getDeclaredMethods()) {
+            if (m.getName().startsWith("visit") && m.getParameterCount() == 2) {
+                Class<?>[] paramTypes = m.getParameterTypes();
+                Class<?> firstParamType = paramTypes[0];
+                if (InlineTagTree.class.isAssignableFrom(firstParamType)) {
+                    testInline(base, firstParamType);
+                }
+            }
+        }
+    }
+
+    void testInline(Path base, Class<?> type) throws Exception {
+        // the following can eventually be converted to instanceof pattern switch
+        Path d = Files.createDirectories(base.resolve(type.getSimpleName()));
+        switch (type.getSimpleName()) {
+            case "DocRootTree" ->
+                    test(d, type, "{@docRoot}");
+
+            case "IndexTree" ->
+                    test(d, type, "{@index Object}");
+
+            case "InheritDocTree" ->
+                    test(d, type, "{@inheritDoc}");
+
+            case "LinkTree" ->
+                    test(d, type, "{@link Object}");
+
+            case "LiteralTree" ->
+                    test(d, type, "{@literal abc}");
+
+            case "SummaryTree" ->
+                    test(d, type, "{@summary First sentence.}");
+
+            case "SystemPropertyTree" ->
+                    test(d, type, "{@systemProperty file.separator}");
+
+            case "UnknownInlineTagTree" ->
+                    test(d, type, "{@unknown}");
+
+            case "ValueTree" ->
+                    test(d, type, "{@value Math.PI}");
+
+            default ->
+                error("no test case provided for " + type);
+        }
+    }
+
+    void test(Path base, Class<?> type, String tag) throws Exception {
+        System.err.println("test " + type.getSimpleName() + " " + tag);
+        Path src = base.resolve("src");
+        String text = """
+                /**
+                 * This is a comment.
+                 * <b>INSERT</b>
+                 */
+                 public class C {  }
+                """.replace("INSERT", tag);
+        tb.writeJavaFiles(src, text);
+
+        List<String> cmdArgs = List.of(
+                "-Xmsgs:html",
+                "-XcustomTags:unknown",
+                src.resolve("C.java").toString()
+        );
+
+        StringWriter sw = new StringWriter();
+        try (PrintWriter pw = new PrintWriter(sw)) {
+            new DocLint().run(pw, cmdArgs.toArray(new String[0]));
+        }
+        String log = sw.toString();
+        if (!log.isEmpty()) {
+            System.err.println("output:");
+            log.lines().forEach(System.err::println);
+            error("Unexpected output from doclint");
+        }
+    }
+}