8340565: Create separate index page for terms defined by the index tag
Reviewed-by: prappo
This commit is contained in:
parent
baabfbba3e
commit
cfe719fbde
@ -172,6 +172,7 @@ public class Contents {
|
|||||||
public final Content relatedPackages;
|
public final Content relatedPackages;
|
||||||
public final Content returns;
|
public final Content returns;
|
||||||
public final Content searchLabel;
|
public final Content searchLabel;
|
||||||
|
public final Content searchTagsLabel;
|
||||||
public final Content seeAlso;
|
public final Content seeAlso;
|
||||||
public final Content serializedForm;
|
public final Content serializedForm;
|
||||||
public final Content servicesLabel;
|
public final Content servicesLabel;
|
||||||
@ -325,6 +326,7 @@ public class Contents {
|
|||||||
relatedPackages = getContent("doclet.Related_Packages");
|
relatedPackages = getContent("doclet.Related_Packages");
|
||||||
returns = getContent("doclet.Returns");
|
returns = getContent("doclet.Returns");
|
||||||
searchLabel = getContent("doclet.search");
|
searchLabel = getContent("doclet.search");
|
||||||
|
searchTagsLabel = getContent("doclet.searchTags");
|
||||||
seeAlso = getContent("doclet.See_Also");
|
seeAlso = getContent("doclet.See_Also");
|
||||||
serializedForm = getContent("doclet.Serialized_Form");
|
serializedForm = getContent("doclet.Serialized_Form");
|
||||||
servicesLabel = getContent("doclet.Services");
|
servicesLabel = getContent("doclet.Services");
|
||||||
|
@ -183,7 +183,7 @@ public class HelpWriter extends HtmlDocletWriter {
|
|||||||
* <li>Declaration pages: module, package, classes
|
* <li>Declaration pages: module, package, classes
|
||||||
* <li>Derived info for declarations: use and tree
|
* <li>Derived info for declarations: use and tree
|
||||||
* <li>General summary info: deprecated, preview
|
* <li>General summary info: deprecated, preview
|
||||||
* <li>Detailed summary info: constant values, serialized form, system properties
|
* <li>Detailed summary info: constant values, search tags, serialized form, system properties
|
||||||
* <li>Index info: all packages, all classes, full index
|
* <li>Index info: all packages, all classes, full index
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
@ -346,6 +346,15 @@ public class HelpWriter extends HtmlDocletWriter {
|
|||||||
pageKindsSection.add(section);
|
pageKindsSection.add(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search Tags
|
||||||
|
if (configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.SEARCH_TAGS)) {
|
||||||
|
section = newHelpSection(contents.searchTagsLabel, PageMode.SEARCH_TAGS);
|
||||||
|
Content searchTagsBody = getContent("doclet.help.searchTags.body",
|
||||||
|
links.createLink(DocPaths.SEARCH_TAGS, resources.getText("doclet.searchTags")));
|
||||||
|
section.add(HtmlTree.P(searchTagsBody));
|
||||||
|
pageKindsSection.add(section);
|
||||||
|
}
|
||||||
|
|
||||||
// Serialized Form
|
// Serialized Form
|
||||||
if (configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.SERIALIZED_FORM)) {
|
if (configuration.conditionalPages.contains(HtmlConfiguration.ConditionalPage.SERIALIZED_FORM)) {
|
||||||
section = newHelpSection(contents.serializedForm, PageMode.SERIALIZED_FORM)
|
section = newHelpSection(contents.serializedForm, PageMode.SERIALIZED_FORM)
|
||||||
|
@ -177,7 +177,7 @@ public class HtmlConfiguration extends BaseConfiguration {
|
|||||||
// which performs a somewhat similar role
|
// which performs a somewhat similar role
|
||||||
public enum ConditionalPage {
|
public enum ConditionalPage {
|
||||||
CONSTANT_VALUES, DEPRECATED, EXTERNAL_SPECS, PREVIEW, RESTRICTED,
|
CONSTANT_VALUES, DEPRECATED, EXTERNAL_SPECS, PREVIEW, RESTRICTED,
|
||||||
SERIALIZED_FORM, SYSTEM_PROPERTIES, NEW
|
SEARCH_TAGS, SERIALIZED_FORM, SYSTEM_PROPERTIES, NEW
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -283,6 +283,7 @@ public class HtmlDoclet extends AbstractDoclet {
|
|||||||
if (!options.noExternalSpecsPage()){
|
if (!options.noExternalSpecsPage()){
|
||||||
writerFactory.newExternalSpecsWriter().buildPage();
|
writerFactory.newExternalSpecsWriter().buildPage();
|
||||||
}
|
}
|
||||||
|
writerFactory.newSearchTagsWriter().buildPage();
|
||||||
writerFactory.newSystemPropertiesWriter().buildPage();
|
writerFactory.newSystemPropertiesWriter().buildPage();
|
||||||
|
|
||||||
configuration.indexBuilder.addElements();
|
configuration.indexBuilder.addElements();
|
||||||
|
@ -0,0 +1,286 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 2024, 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jdk.javadoc.internal.doclets.formats.html;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.sun.source.doctree.DocTree;
|
||||||
|
|
||||||
|
import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode;
|
||||||
|
import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
|
||||||
|
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyles;
|
||||||
|
import jdk.javadoc.internal.doclets.toolkit.DocFileElement;
|
||||||
|
import jdk.javadoc.internal.doclets.toolkit.OverviewElement;
|
||||||
|
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
|
||||||
|
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
|
||||||
|
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
|
||||||
|
import jdk.javadoc.internal.doclets.toolkit.util.IndexItem;
|
||||||
|
import jdk.javadoc.internal.html.Content;
|
||||||
|
import jdk.javadoc.internal.html.ContentBuilder;
|
||||||
|
import jdk.javadoc.internal.html.HtmlTree;
|
||||||
|
import jdk.javadoc.internal.html.Text;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.groupingBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates summary files for tags represented by {@code IndexItem}.
|
||||||
|
* Supported items are search tags and system properties.
|
||||||
|
*/
|
||||||
|
public abstract class IndexItemListWriter extends HtmlDocletWriter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached contents of {@code <title>...</title>} tags of the HTML pages.
|
||||||
|
*/
|
||||||
|
final Map<DocFileElement, String> titles = new WeakHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a IndexItemListWriter object.
|
||||||
|
*
|
||||||
|
* @param configuration The current configuration
|
||||||
|
* @param path the doc path of the file to write
|
||||||
|
*/
|
||||||
|
protected IndexItemListWriter(HtmlConfiguration configuration, DocPath path) {
|
||||||
|
super(configuration, path, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildPage() throws DocFileIOException {
|
||||||
|
boolean hasTags = configuration.indexBuilder != null
|
||||||
|
&& !configuration.indexBuilder.getItems(getKind()).isEmpty();
|
||||||
|
if (!hasTags) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeGenerating();
|
||||||
|
configuration.conditionalPages.add(getConditionalPage());
|
||||||
|
|
||||||
|
String title = getPageLabel().toString();
|
||||||
|
HtmlTree body = getBody(getWindowTitle(title));
|
||||||
|
Content mainContent = new ContentBuilder();
|
||||||
|
addIndexItems(mainContent);
|
||||||
|
body.add(new BodyContents()
|
||||||
|
.setHeader(getHeader(getPageMode()))
|
||||||
|
.addMainContent(HtmlTree.DIV(HtmlStyles.header,
|
||||||
|
HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, getPageLabel())))
|
||||||
|
.addMainContent(mainContent)
|
||||||
|
.setFooter(getFooter()));
|
||||||
|
printHtmlDocument(null, title.toLowerCase(Locale.ROOT), body);
|
||||||
|
|
||||||
|
if (configuration.indexBuilder != null) {
|
||||||
|
configuration.indexBuilder.add(IndexItem.of(IndexItem.Category.TAGS, title, path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String, List<IndexItem>> groupTags() {
|
||||||
|
return configuration.indexBuilder.getItems(getKind()).stream()
|
||||||
|
.collect(groupingBy(IndexItem::getLabel, TreeMap::new, Collectors.toCollection(ArrayList::new)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Content createLink(IndexItem i) {
|
||||||
|
assert i.getDocTree().getKind() == getKind() : i;
|
||||||
|
var element = i.getElement();
|
||||||
|
if (element instanceof OverviewElement) {
|
||||||
|
return links.createLink(pathToRoot.resolve(i.getUrl()),
|
||||||
|
resources.getText("doclet.Overview"));
|
||||||
|
} else if (element instanceof DocFileElement e) {
|
||||||
|
var fo = e.getFileObject();
|
||||||
|
var t = titles.computeIfAbsent(e, this::getFileTitle);
|
||||||
|
if (t.isBlank()) {
|
||||||
|
// The user should probably be notified (a warning?) that this
|
||||||
|
// file does not have a title
|
||||||
|
var p = Path.of(fo.toUri());
|
||||||
|
t = p.getFileName().toString();
|
||||||
|
}
|
||||||
|
var b = new ContentBuilder()
|
||||||
|
.add(HtmlTree.CODE(Text.of(i.getHolder() + ": ")))
|
||||||
|
.add(t);
|
||||||
|
return links.createLink(pathToRoot.resolve(i.getUrl()), b);
|
||||||
|
} else {
|
||||||
|
// program elements should be displayed using a code font
|
||||||
|
var link = links.createLink(pathToRoot.resolve(i.getUrl()), i.getHolder());
|
||||||
|
return HtmlTree.CODE(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a table with the included index items to the content.
|
||||||
|
*
|
||||||
|
* @param target the content to which the table will be added
|
||||||
|
*/
|
||||||
|
protected abstract void addIndexItems(Content target);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the kind of index item to list in this page}
|
||||||
|
*/
|
||||||
|
protected abstract DocTree.Kind getKind();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the conditional page value}
|
||||||
|
*/
|
||||||
|
protected abstract HtmlConfiguration.ConditionalPage getConditionalPage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the label for the page heading}
|
||||||
|
*/
|
||||||
|
protected abstract Content getPageLabel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the Navigation.PageMode value}
|
||||||
|
*/
|
||||||
|
protected abstract Navigation.PageMode getPageMode();
|
||||||
|
|
||||||
|
// Note: The reason we can't use anonymous classes below is that HtmlDocletWriter.getBodyStyle()
|
||||||
|
// uses the writer's class name to deduce the CSS body style name.
|
||||||
|
|
||||||
|
public static IndexItemListWriter createSystemPropertiesWriter(HtmlConfiguration configuration) {
|
||||||
|
return new SystemPropertiesWriter(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IndexItemListWriter createSearchTagsWriter(HtmlConfiguration configuration) {
|
||||||
|
return new SearchTagsWriter(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SystemPropertiesWriter extends IndexItemListWriter {
|
||||||
|
SystemPropertiesWriter(HtmlConfiguration configuration) {
|
||||||
|
super(configuration, DocPaths.SYSTEM_PROPERTIES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DocTree.Kind getKind() {
|
||||||
|
return DocTree.Kind.SYSTEM_PROPERTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HtmlConfiguration.ConditionalPage getConditionalPage() {
|
||||||
|
return HtmlConfiguration.ConditionalPage.SYSTEM_PROPERTIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Content getPageLabel() {
|
||||||
|
return contents.systemPropertiesLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Navigation.PageMode getPageMode() {
|
||||||
|
return PageMode.SYSTEM_PROPERTIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 2-column table containing system properties.
|
||||||
|
*
|
||||||
|
* @param target the content to which the links will be added
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void addIndexItems(Content target) {
|
||||||
|
Map<String, List<IndexItem>> searchIndexMap = groupTags();
|
||||||
|
Content separator = Text.of(", ");
|
||||||
|
var table = new Table<Void>(HtmlStyles.summaryTable)
|
||||||
|
.setCaption(contents.systemPropertiesSummaryLabel)
|
||||||
|
.setHeader(new TableHeader(contents.propertyLabel, contents.referencedIn))
|
||||||
|
.setColumnStyles(HtmlStyles.colFirst, HtmlStyles.colLast);
|
||||||
|
searchIndexMap.forEach((key, searchIndexItems) -> {
|
||||||
|
Content propertyName = Text.of(key);
|
||||||
|
Content referenceLinks = new ContentBuilder();
|
||||||
|
for (IndexItem searchIndexItem : searchIndexItems) {
|
||||||
|
if (!referenceLinks.isEmpty()) {
|
||||||
|
referenceLinks.add(separator);
|
||||||
|
}
|
||||||
|
referenceLinks.add(createLink(searchIndexItem));
|
||||||
|
}
|
||||||
|
table.addRow(propertyName, HtmlTree.DIV(HtmlStyles.block, referenceLinks));
|
||||||
|
});
|
||||||
|
target.add(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SearchTagsWriter extends IndexItemListWriter {
|
||||||
|
SearchTagsWriter(HtmlConfiguration configuration) {
|
||||||
|
super(configuration, DocPaths.SEARCH_TAGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DocTree.Kind getKind() {
|
||||||
|
return DocTree.Kind.INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HtmlConfiguration.ConditionalPage getConditionalPage() {
|
||||||
|
return HtmlConfiguration.ConditionalPage.SEARCH_TAGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Content getPageLabel() {
|
||||||
|
return contents.searchTagsLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Navigation.PageMode getPageMode() {
|
||||||
|
return PageMode.SEARCH_TAGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 3-column table containing search tags.
|
||||||
|
*
|
||||||
|
* @param target the content to which the links will be added
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void addIndexItems(Content target) {
|
||||||
|
Map<String, List<IndexItem>> searchIndexMap = groupTags();
|
||||||
|
Content separator = Text.of(", ");
|
||||||
|
var table = new Table<Void>(HtmlStyles.summaryTable)
|
||||||
|
.setCaption(contents.getContent("doclet.searchTagsSummary"))
|
||||||
|
.setHeader(new TableHeader(contents.getContent("doclet.searchTag"),
|
||||||
|
contents.descriptionLabel,
|
||||||
|
contents.getContent("doclet.DefinedIn")))
|
||||||
|
.setColumnStyles(HtmlStyles.colFirst, HtmlStyles.colSecond, HtmlStyles.colLast);
|
||||||
|
searchIndexMap.forEach((key, searchIndexItems) -> {
|
||||||
|
Content propertyName = Text.of(key);
|
||||||
|
Content referenceLinks = new ContentBuilder();
|
||||||
|
String description = "";
|
||||||
|
for (IndexItem searchIndexItem : searchIndexItems) {
|
||||||
|
if (!referenceLinks.isEmpty()) {
|
||||||
|
referenceLinks.add(separator);
|
||||||
|
}
|
||||||
|
referenceLinks.add(createLink(searchIndexItem));
|
||||||
|
if (description.isEmpty()) {
|
||||||
|
description = searchIndexItem.getDescription();
|
||||||
|
Objects.requireNonNull(description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.addRow(propertyName, Text.of(description), HtmlTree.DIV(HtmlStyles.block, referenceLinks));
|
||||||
|
});
|
||||||
|
target.add(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -87,8 +87,9 @@ public class Navigation {
|
|||||||
PACKAGE,
|
PACKAGE,
|
||||||
PREVIEW,
|
PREVIEW,
|
||||||
RESTRICTED,
|
RESTRICTED,
|
||||||
SERIALIZED_FORM,
|
|
||||||
SEARCH,
|
SEARCH,
|
||||||
|
SEARCH_TAGS,
|
||||||
|
SERIALIZED_FORM,
|
||||||
SYSTEM_PROPERTIES,
|
SYSTEM_PROPERTIES,
|
||||||
TREE,
|
TREE,
|
||||||
USE
|
USE
|
||||||
@ -274,6 +275,7 @@ public class Navigation {
|
|||||||
case CONSTANT_VALUES:
|
case CONSTANT_VALUES:
|
||||||
case EXTERNAL_SPECS:
|
case EXTERNAL_SPECS:
|
||||||
case RESTRICTED:
|
case RESTRICTED:
|
||||||
|
case SEARCH_TAGS:
|
||||||
case SERIALIZED_FORM:
|
case SERIALIZED_FORM:
|
||||||
case SYSTEM_PROPERTIES:
|
case SYSTEM_PROPERTIES:
|
||||||
addOverviewLink(target);
|
addOverviewLink(target);
|
||||||
|
@ -1,158 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, 2024, 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jdk.javadoc.internal.doclets.formats.html;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.WeakHashMap;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.sun.source.doctree.DocTree;
|
|
||||||
|
|
||||||
import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode;
|
|
||||||
import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
|
|
||||||
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyles;
|
|
||||||
import jdk.javadoc.internal.doclets.toolkit.DocFileElement;
|
|
||||||
import jdk.javadoc.internal.doclets.toolkit.OverviewElement;
|
|
||||||
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
|
|
||||||
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
|
|
||||||
import jdk.javadoc.internal.doclets.toolkit.util.IndexItem;
|
|
||||||
import jdk.javadoc.internal.html.Content;
|
|
||||||
import jdk.javadoc.internal.html.ContentBuilder;
|
|
||||||
import jdk.javadoc.internal.html.HtmlTree;
|
|
||||||
import jdk.javadoc.internal.html.Text;
|
|
||||||
|
|
||||||
import static java.util.stream.Collectors.groupingBy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the file with the summary of all the system properties.
|
|
||||||
*/
|
|
||||||
public class SystemPropertiesWriter extends HtmlDocletWriter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cached contents of {@code <title>...</title>} tags of the HTML pages.
|
|
||||||
*/
|
|
||||||
final Map<DocFileElement, String> titles = new WeakHashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs SystemPropertiesWriter object.
|
|
||||||
*
|
|
||||||
* @param configuration The current configuration
|
|
||||||
*/
|
|
||||||
public SystemPropertiesWriter(HtmlConfiguration configuration) {
|
|
||||||
super(configuration, DocPaths.SYSTEM_PROPERTIES, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void buildPage() throws DocFileIOException {
|
|
||||||
boolean hasSystemProperties = configuration.indexBuilder != null
|
|
||||||
&& !configuration.indexBuilder.getItems(DocTree.Kind.SYSTEM_PROPERTY).isEmpty();
|
|
||||||
if (!hasSystemProperties) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeGenerating();
|
|
||||||
configuration.conditionalPages.add(HtmlConfiguration.ConditionalPage.SYSTEM_PROPERTIES);
|
|
||||||
|
|
||||||
String title = resources.getText("doclet.systemProperties");
|
|
||||||
HtmlTree body = getBody(getWindowTitle(title));
|
|
||||||
Content mainContent = new ContentBuilder();
|
|
||||||
addSystemProperties(mainContent);
|
|
||||||
body.add(new BodyContents()
|
|
||||||
.setHeader(getHeader(PageMode.SYSTEM_PROPERTIES))
|
|
||||||
.addMainContent(HtmlTree.DIV(HtmlStyles.header,
|
|
||||||
HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
|
|
||||||
contents.getContent("doclet.systemProperties"))))
|
|
||||||
.addMainContent(mainContent)
|
|
||||||
.setFooter(getFooter()));
|
|
||||||
printHtmlDocument(null, "system properties", body);
|
|
||||||
|
|
||||||
if (configuration.indexBuilder != null) {
|
|
||||||
configuration.indexBuilder.add(IndexItem.of(IndexItem.Category.TAGS, title, path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds all the system properties to the content.
|
|
||||||
*
|
|
||||||
* @param target the content to which the links will be added
|
|
||||||
*/
|
|
||||||
protected void addSystemProperties(Content target) {
|
|
||||||
Map<String, List<IndexItem>> searchIndexMap = groupSystemProperties();
|
|
||||||
Content separator = Text.of(", ");
|
|
||||||
var table = new Table<Void>(HtmlStyles.summaryTable)
|
|
||||||
.setCaption(contents.systemPropertiesSummaryLabel)
|
|
||||||
.setHeader(new TableHeader(contents.propertyLabel, contents.referencedIn))
|
|
||||||
.setColumnStyles(HtmlStyles.colFirst, HtmlStyles.colLast);
|
|
||||||
for (Entry<String, List<IndexItem>> entry : searchIndexMap.entrySet()) {
|
|
||||||
Content propertyName = Text.of(entry.getKey());
|
|
||||||
List<IndexItem> searchIndexItems = entry.getValue();
|
|
||||||
Content separatedReferenceLinks = new ContentBuilder();
|
|
||||||
separatedReferenceLinks.add(createLink(searchIndexItems.get(0)));
|
|
||||||
for (int i = 1; i < searchIndexItems.size(); i++) {
|
|
||||||
separatedReferenceLinks.add(separator);
|
|
||||||
separatedReferenceLinks.add(createLink(searchIndexItems.get(i)));
|
|
||||||
}
|
|
||||||
table.addRow(propertyName, HtmlTree.DIV(HtmlStyles.block, separatedReferenceLinks));
|
|
||||||
}
|
|
||||||
target.add(table);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, List<IndexItem>> groupSystemProperties() {
|
|
||||||
return configuration.indexBuilder.getItems(DocTree.Kind.SYSTEM_PROPERTY).stream()
|
|
||||||
.collect(groupingBy(IndexItem::getLabel, TreeMap::new, Collectors.toCollection(ArrayList::new)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Content createLink(IndexItem i) {
|
|
||||||
assert i.getDocTree().getKind() == DocTree.Kind.SYSTEM_PROPERTY : i;
|
|
||||||
var element = i.getElement();
|
|
||||||
if (element instanceof OverviewElement) {
|
|
||||||
return links.createLink(pathToRoot.resolve(i.getUrl()),
|
|
||||||
resources.getText("doclet.Overview"));
|
|
||||||
} else if (element instanceof DocFileElement e) {
|
|
||||||
var fo = e.getFileObject();
|
|
||||||
var t = titles.computeIfAbsent(e, this::getFileTitle);
|
|
||||||
if (t.isBlank()) {
|
|
||||||
// The user should probably be notified (a warning?) that this
|
|
||||||
// file does not have a title
|
|
||||||
var p = Path.of(fo.toUri());
|
|
||||||
t = p.getFileName().toString();
|
|
||||||
}
|
|
||||||
var b = new ContentBuilder()
|
|
||||||
.add(HtmlTree.CODE(Text.of(i.getHolder() + ": ")))
|
|
||||||
.add(t);
|
|
||||||
return links.createLink(pathToRoot.resolve(i.getUrl()), b);
|
|
||||||
} else {
|
|
||||||
// program elements should be displayed using a code font
|
|
||||||
var link = links.createLink(pathToRoot.resolve(i.getUrl()), i.getHolder());
|
|
||||||
return HtmlTree.CODE(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -37,7 +37,6 @@ import jdk.javadoc.internal.doclets.toolkit.DocFileElement;
|
|||||||
import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
|
import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
|
||||||
import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper;
|
import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper;
|
||||||
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
|
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
|
||||||
import jdk.javadoc.internal.doclets.toolkit.util.IndexBuilder;
|
|
||||||
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
|
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -184,6 +183,13 @@ public class WriterFactory {
|
|||||||
return new SearchWriter(configuration);
|
return new SearchWriter(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return a new writer for the page listing search tags defined in the API}
|
||||||
|
*/
|
||||||
|
public HtmlDocletWriter newSearchTagsWriter() {
|
||||||
|
return IndexItemListWriter.createSearchTagsWriter(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@return a new writer for the page giving the serialized forms of classes and other type elements}
|
* {@return a new writer for the page giving the serialized forms of classes and other type elements}
|
||||||
*/
|
*/
|
||||||
@ -195,7 +201,7 @@ public class WriterFactory {
|
|||||||
* {@return a new writer for the page listing system properties referenced in the API}
|
* {@return a new writer for the page listing system properties referenced in the API}
|
||||||
*/
|
*/
|
||||||
public HtmlDocletWriter newSystemPropertiesWriter() {
|
public HtmlDocletWriter newSystemPropertiesWriter() {
|
||||||
return new SystemPropertiesWriter(configuration);
|
return IndexItemListWriter.createSystemPropertiesWriter(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -857,6 +857,11 @@ public enum HtmlStyles implements HtmlStyle {
|
|||||||
*/
|
*/
|
||||||
searchPage,
|
searchPage,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class of the {@code body} element for the search tags page.
|
||||||
|
*/
|
||||||
|
searchTagsPage,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class of the {@code body} element for the serialized-forms page.
|
* The class of the {@code body} element for the serialized-forms page.
|
||||||
*/
|
*/
|
||||||
|
@ -135,6 +135,9 @@ doclet.Preview_Label=Preview
|
|||||||
doclet.Preview_Mark=PREVIEW
|
doclet.Preview_Mark=PREVIEW
|
||||||
doclet.Restricted_Methods=Restricted Methods
|
doclet.Restricted_Methods=Restricted Methods
|
||||||
doclet.Restricted_Mark=RESTRICTED
|
doclet.Restricted_Mark=RESTRICTED
|
||||||
|
doclet.searchTag=Search Tag
|
||||||
|
doclet.searchTags=Search Tags
|
||||||
|
doclet.searchTagsSummary=Search Tags Summary
|
||||||
doclet.Terminally_Deprecated=Terminally Deprecated
|
doclet.Terminally_Deprecated=Terminally Deprecated
|
||||||
doclet.Terminally_Deprecated_Elements=Terminally Deprecated Elements
|
doclet.Terminally_Deprecated_Elements=Terminally Deprecated Elements
|
||||||
doclet.Terminally_Deprecated_In_Release=Terminally Deprecated in {0}
|
doclet.Terminally_Deprecated_In_Release=Terminally Deprecated in {0}
|
||||||
@ -171,6 +174,7 @@ doclet.Interfaces=Interfaces
|
|||||||
doclet.Enclosing_Class=Enclosing class:
|
doclet.Enclosing_Class=Enclosing class:
|
||||||
doclet.Enclosing_Interface=Enclosing interface:
|
doclet.Enclosing_Interface=Enclosing interface:
|
||||||
doclet.Inheritance_Tree=Inheritance Tree
|
doclet.Inheritance_Tree=Inheritance Tree
|
||||||
|
doclet.DefinedIn=Defined In
|
||||||
doclet.ReferencedIn=Referenced In
|
doclet.ReferencedIn=Referenced In
|
||||||
doclet.Section=Section
|
doclet.Section=Section
|
||||||
doclet.External_Specification=External Specification
|
doclet.External_Specification=External Specification
|
||||||
@ -340,6 +344,9 @@ doclet.help.serial_form.body=\
|
|||||||
# 0: link to Constant Values page
|
# 0: link to Constant Values page
|
||||||
doclet.help.constants.body=\
|
doclet.help.constants.body=\
|
||||||
The {0} page lists the static final fields and their values.
|
The {0} page lists the static final fields and their values.
|
||||||
|
# 0: link to Search Tags page
|
||||||
|
doclet.help.searchTags.body=\
|
||||||
|
The {0} page lists search tags defined in the documentation.
|
||||||
# 0: link to System Properties page
|
# 0: link to System Properties page
|
||||||
doclet.help.systemProperties.body=\
|
doclet.help.systemProperties.body=\
|
||||||
The {0} page lists references to system properties.
|
The {0} page lists references to system properties.
|
||||||
|
@ -175,6 +175,9 @@ public class DocPaths {
|
|||||||
/** The name of the file for search page. */
|
/** The name of the file for search page. */
|
||||||
public static final DocPath SEARCH_PAGE = DocPath.create("search.html");
|
public static final DocPath SEARCH_PAGE = DocPath.create("search.html");
|
||||||
|
|
||||||
|
/** The name of the file for search tags index page. */
|
||||||
|
public static final DocPath SEARCH_TAGS = DocPath.create("search-tags.html");
|
||||||
|
|
||||||
/** The name of the file for all system properties. */
|
/** The name of the file for all system properties. */
|
||||||
public static final DocPath SYSTEM_PROPERTIES = DocPath.create("system-properties.html");
|
public static final DocPath SYSTEM_PROPERTIES = DocPath.create("system-properties.html");
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8213957 8213958
|
* @bug 8213957 8213958 8340565
|
||||||
* @summary Test use of at-index in package-iinfo and doc-files
|
* @summary Test use of at-index in package-iinfo and doc-files
|
||||||
* @library /tools/lib ../../lib
|
* @library /tools/lib ../../lib
|
||||||
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
||||||
@ -121,6 +121,23 @@ public class TestIndexInPackageFiles extends JavadocTester {
|
|||||||
<a href="p/q/package-summary.html#test.property.1" class="search-tag-link">test.property.1</a>""",
|
<a href="p/q/package-summary.html#test.property.1" class="search-tag-link">test.property.1</a>""",
|
||||||
"""
|
"""
|
||||||
<a href="p/q/doc-files/extra.html#test.property.2" class="search-tag-link">test.property.2</a>""");
|
<a href="p/q/doc-files/extra.html#test.property.2" class="search-tag-link">test.property.2</a>""");
|
||||||
|
|
||||||
|
checkOrder("search-tags.html",
|
||||||
|
"""
|
||||||
|
<div class="col-first even-row-color">test.name.1</div>
|
||||||
|
<div class="col-second even-row-color">additional info</div>
|
||||||
|
<div class="col-last even-row-color">
|
||||||
|
<div class="block"><code><a href="p/q/package-summary.html#test.name.1">package p.q</a></code></div>""",
|
||||||
|
"""
|
||||||
|
<div class="col-first odd-row-color">test.name.2</div>
|
||||||
|
<div class="col-second odd-row-color">additional info</div>
|
||||||
|
<div class="col-last odd-row-color">
|
||||||
|
<div class="block"><a href="p/q/doc-files/extra.html#test.name.2"><code>package p.q: </code>Extra</a></div>""",
|
||||||
|
"""
|
||||||
|
<div class="col-first even-row-color">test.name.3</div>
|
||||||
|
<div class="col-second even-row-color">additional info</div>
|
||||||
|
<div class="col-last even-row-color">
|
||||||
|
<div class="block"><a href="index.html#test.name.3">Overview</a></div>""");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8202462
|
* @bug 8202462 8340565
|
||||||
* @summary {@index} may cause duplicate labels
|
* @summary {@index} may cause duplicate labels
|
||||||
* @library /tools/lib ../../lib
|
* @library /tools/lib ../../lib
|
||||||
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
||||||
@ -33,7 +33,6 @@
|
|||||||
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
import builder.ClassBuilder;
|
import builder.ClassBuilder;
|
||||||
import builder.ClassBuilder.MethodBuilder;
|
import builder.ClassBuilder.MethodBuilder;
|
||||||
@ -84,6 +83,21 @@ public class TestIndexTaglet extends JavadocTester {
|
|||||||
"<h2>Method Summary</h2>\n",
|
"<h2>Method Summary</h2>\n",
|
||||||
"""
|
"""
|
||||||
<div class="block">test description with search_phrase_a</div>""");
|
<div class="block">test description with search_phrase_a</div>""");
|
||||||
|
|
||||||
|
checkOrder("search-tags.html",
|
||||||
|
"""
|
||||||
|
<h1>Search Tags</h1>""",
|
||||||
|
"""
|
||||||
|
<div class="caption"><span>Search Tags Summary</span></div>
|
||||||
|
<div class="summary-table three-column-summary">
|
||||||
|
<div class="table-header col-first">Search Tag</div>
|
||||||
|
<div class="table-header col-second">Description</div>
|
||||||
|
<div class="table-header col-last">Defined In</div>""",
|
||||||
|
"""
|
||||||
|
<div class="col-first even-row-color">search_phrase_a</div>
|
||||||
|
<div class="col-second even-row-color">class a</div>
|
||||||
|
<div class="col-last even-row-color">
|
||||||
|
<div class="block"><code><a href="pkg/A.html#search_phrase_a">pkg.A.func(A)</a></code></div>""");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -130,5 +144,13 @@ public class TestIndexTaglet extends JavadocTester {
|
|||||||
This is a class. Here is <span id="foo" class="search-tag-result">foo</span>.""",
|
This is a class. Here is <span id="foo" class="search-tag-result">foo</span>.""",
|
||||||
"""
|
"""
|
||||||
This is a method. Here is <span id="foo-1" class="search-tag-result">foo</span>.""");
|
This is a method. Here is <span id="foo-1" class="search-tag-result">foo</span>.""");
|
||||||
|
|
||||||
|
checkOrder("search-tags.html",
|
||||||
|
"""
|
||||||
|
<div class="col-first even-row-color">foo</div>
|
||||||
|
<div class="col-second even-row-color">first</div>
|
||||||
|
<div class="col-last even-row-color">
|
||||||
|
<div class="block"><code><a href="pkg/A.html#foo">class pkg.A</a></code>, <code\
|
||||||
|
><a href="pkg/A.html#foo-1">pkg.A.m()</a></code></div>""");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user