diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java index d46b4c69d82..2d7fb6e9b11 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2023, 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 @@ -113,6 +113,11 @@ public abstract class AbstractOverviewIndexWriter extends HtmlDocletWriter { getDescription(), body); } + @Override + public boolean isIndexable() { + return true; + } + /** * Adds the index to the documentation. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java index 364619065a5..dcbc78f7107 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java @@ -769,4 +769,9 @@ public class ClassWriter extends SubWriterHolderWriter { } return section; } + + @Override + public boolean isIndexable() { + return true; + } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java index 5330b20dcab..5849599a113 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, 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 @@ -301,6 +301,11 @@ public class DocFilesHandler { } return localTags; } + + @Override + public boolean isIndexable() { + return true; + } } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 492743a704b..c1f2f8d7a63 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -411,6 +411,20 @@ public abstract class HtmlDocletWriter { return new TagletWriter(this, context); } + /** + * {@return true if the page written by this writer should be indexed, + * false otherwise} + * + * Some pages merely aggregate filtered information available on other pages + * and, thus, have no indexing value. In fact, if indexed, they would + * clutter the index and mislead the reader. + * + * @implSpec The default implementation returns {@code false}. + */ + public boolean isIndexable() { + return false; + } + /** * Generates the HTML document tree and prints it out. * @@ -1369,7 +1383,8 @@ public abstract class HtmlDocletWriter { @Override public Boolean visitStartElement(StartElementTree node, Content content) { Content attrs = new ContentBuilder(); - if (node.getName().toString().matches("(?i)h[1-6]")) { + if (node.getName().toString().matches("(?i)h[1-6]") + && isIndexable()) { createSectionIdAndIndex(node, trees, attrs, element, context); } for (DocTree dt : node.getAttributes()) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java index d37e1334eb4..c9e1f4afaaf 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java @@ -923,4 +923,9 @@ public class ModuleWriter extends HtmlDocletWriter { li.add(deprDiv); } } + + @Override + public boolean isIndexable() { + return true; + } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java index e960b2e59ba..55be119f350 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java @@ -455,4 +455,9 @@ public class PackageWriter extends HtmlDocletWriter { .filter(p -> p != packageElement && filter.test(p)) .collect(Collectors.toList()); } + + @Override + public boolean isIndexable() { + return true; + } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletWriter.java index 2288369d45b..b977951f2fa 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletWriter.java @@ -49,6 +49,8 @@ import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration; import jdk.javadoc.internal.doclets.formats.html.HtmlDocletWriter; import jdk.javadoc.internal.doclets.formats.html.HtmlIds; import jdk.javadoc.internal.doclets.formats.html.HtmlOptions; +import jdk.javadoc.internal.doclets.formats.html.IndexWriter; +import jdk.javadoc.internal.doclets.formats.html.SummaryListWriter; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlId; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; @@ -370,7 +372,8 @@ public class TagletWriter { @SuppressWarnings("preview") Content createAnchorAndSearchIndex(Element element, String tagText, Content tagContent, String desc, DocTree tree) { Content result; - if (context.isFirstSentence && context.inSummary || context.inTags.contains(DocTree.Kind.INDEX)) { + if (context.isFirstSentence && context.inSummary || context.inTags.contains(DocTree.Kind.INDEX) + || !htmlWriter.isIndexable()) { result = tagContent; } else { HtmlId id = HtmlIds.forText(tagText, htmlWriter.indexAnchorTable); diff --git a/test/langtools/jdk/javadoc/doclet/testIndex/TestSelfIndexing.java b/test/langtools/jdk/javadoc/doclet/testIndex/TestSelfIndexing.java new file mode 100644 index 00000000000..9d1d146d54d --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testIndex/TestSelfIndexing.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2023, 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. + */ + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Optional; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.regex.Pattern; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import javadoc.tester.JavadocTester; +import toolbox.ToolBox; + +/* + * @test + * @bug 8318082 + * @library /tools/lib ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.ToolBox javadoc.tester.* + * @run main TestSelfIndexing + */ +public class TestSelfIndexing extends JavadocTester { + + public static void main(String... args) throws Exception { + new TestSelfIndexing().runTests(); + } + + private final ToolBox tb = new ToolBox(); + + /* + * Pages derived from other pages must not be indexed and may not + * cross-reference each other except for navigation ergonomics. + * + * For example, it's okay for all-index.html to reference deprecated-list.html; + * but it is not okay, for all-index.html to reference an anchor, such as + * deprecated-list.html#java.lang.Object.finalize() + */ + @Test + public void test(Path base) throws Exception { + Path src = base.resolve("src"); + int i = 0; + // try to start a search tag (i) with the same letter, H, + // as the class, Hello, and (ii) with some other letter, P + for (var l : List.of("H", "P")) { + // try all markup constructs that cause indexing + for (var t : List.of("