8239487: Better links generation for system properties found in HTML files

8239485: Define behavior of the System Properties page when no system properties are available

Reviewed-by: jjg
This commit is contained in:
Pavel Rappo 2020-03-11 17:09:10 +00:00
parent 5b323a8656
commit 8c6649dea0
21 changed files with 504 additions and 161 deletions

View file

@ -27,11 +27,12 @@ package jdk.javadoc.internal.doclets.formats.html;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
@ -41,6 +42,7 @@ import javax.lang.model.element.TypeElement;
import javax.lang.model.util.SimpleElementVisitor14;
import com.sun.source.doctree.DocTree;
import jdk.javadoc.internal.doclets.formats.html.SearchIndexItem.Category;
import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@ -92,8 +94,9 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
super(configuration, path);
this.indexBuilder = indexBuilder;
this.navBar = new Navigation(null, configuration, PageMode.INDEX, path);
Collection<SearchIndexItem> items =
searchItems.get(SearchIndexItem.Category.SEARCH_TAGS);
Stream<SearchIndexItem> items =
searchItems.itemsOfCategories(Category.INDEX, Category.SYSTEM_PROPERTY)
.sorted(utils.makeGenericSearchIndexComparator());
this.tagSearchIndexMap = buildSearchTagIndex(items);
}
@ -229,7 +232,7 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
String moduleName = utils.getFullyQualifiedName(mdle);
Content link = getModuleLink(mdle, new StringContent(moduleName));
si.setLabel(moduleName);
si.setCategory(SearchIndexItem.Category.MODULES);
si.setCategory(Category.MODULES);
Content dt = HtmlTree.DT(link);
dt.add(" - ");
dt.add(contents.module_);
@ -253,7 +256,7 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
si.setContainingModule(utils.getFullyQualifiedName(utils.containingModule(pkg)));
}
si.setLabel(utils.getPackageName(pkg));
si.setCategory(SearchIndexItem.Category.PACKAGES);
si.setCategory(Category.PACKAGES);
Content dt = HtmlTree.DT(link);
dt.add(" - ");
dt.add(contents.package_);
@ -276,7 +279,7 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
LinkInfoImpl.Kind.INDEX, typeElement).strong(true));
si.setContainingPackage(utils.getPackageName(utils.containingPackage(typeElement)));
si.setLabel(utils.getSimpleName(typeElement));
si.setCategory(SearchIndexItem.Category.TYPES);
si.setCategory(Category.TYPES);
Content dt = HtmlTree.DT(link);
dt.add(" - ");
addClassInfo(typeElement, dt);
@ -324,7 +327,7 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
} else {
si.setLabel(name);
}
si.setCategory(SearchIndexItem.Category.MEMBERS);
si.setCategory(Category.MEMBERS);
Content span = HtmlTree.SPAN(HtmlStyle.memberNameLink,
getDocLink(LinkInfoImpl.Kind.INDEX, member, name));
Content dt = HtmlTree.DT(span);
@ -431,32 +434,32 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
protected void createSearchIndexFiles() throws DocFileIOException {
if (configuration.showModules) {
createSearchIndexFile(DocPaths.MODULE_SEARCH_INDEX_JS,
searchItems.get(SearchIndexItem.Category.MODULES),
searchItems.itemsOfCategories(Category.MODULES),
"moduleSearchIndex");
}
if (!configuration.packages.isEmpty()) {
SearchIndexItem si = new SearchIndexItem();
si.setCategory(SearchIndexItem.Category.PACKAGES);
si.setCategory(Category.PACKAGES);
si.setLabel(resources.getText("doclet.All_Packages"));
si.setUrl(DocPaths.ALLPACKAGES_INDEX.getPath());
searchItems.add(si);
}
createSearchIndexFile(DocPaths.PACKAGE_SEARCH_INDEX_JS,
searchItems.get(SearchIndexItem.Category.PACKAGES),
searchItems.itemsOfCategories(Category.PACKAGES),
"packageSearchIndex");
SearchIndexItem si = new SearchIndexItem();
si.setCategory(SearchIndexItem.Category.TYPES);
si.setCategory(Category.TYPES);
si.setLabel(resources.getText("doclet.All_Classes"));
si.setUrl(DocPaths.ALLCLASSES_INDEX.getPath());
searchItems.add(si);
createSearchIndexFile(DocPaths.TYPE_SEARCH_INDEX_JS,
searchItems.get(SearchIndexItem.Category.TYPES),
searchItems.itemsOfCategories(Category.TYPES),
"typeSearchIndex");
createSearchIndexFile(DocPaths.MEMBER_SEARCH_INDEX_JS,
searchItems.get(SearchIndexItem.Category.MEMBERS),
searchItems.itemsOfCategories(Category.MEMBERS),
"memberSearchIndex");
createSearchIndexFile(DocPaths.TAG_SEARCH_INDEX_JS,
searchItems.get(SearchIndexItem.Category.SEARCH_TAGS),
searchItems.itemsOfCategories(Category.INDEX, Category.SYSTEM_PROPERTY),
"tagSearchIndex");
}
@ -469,16 +472,18 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
* @throws DocFileIOException if there is a problem creating the search index file
*/
protected void createSearchIndexFile(DocPath searchIndexJS,
Collection<SearchIndexItem> searchIndex,
Stream<SearchIndexItem> searchIndex,
String varName)
throws DocFileIOException
{
// The file needs to be created even if there are no searchIndex items
// File could be written straight-through, without an intermediate StringBuilder
if (!searchIndex.isEmpty()) {
Iterator<SearchIndexItem> index = searchIndex.iterator();
if (index.hasNext()) {
StringBuilder searchVar = new StringBuilder("[");
boolean first = true;
for (SearchIndexItem item : searchIndex) {
while (index.hasNext()) {
SearchIndexItem item = index.next();
if (first) {
searchVar.append(item.toString());
first = false;
@ -498,17 +503,13 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
}
}
protected static Map<Character, List<SearchIndexItem>> buildSearchTagIndex(
Collection<? extends SearchIndexItem> searchItems)
private static Map<Character, List<SearchIndexItem>> buildSearchTagIndex(
Stream<? extends SearchIndexItem> searchItems)
{
Map<Character, List<SearchIndexItem>> map = new HashMap<>();
for (SearchIndexItem sii : searchItems) {
String tagLabel = sii.getLabel();
Character unicode = (tagLabel.length() == 0)
? '*'
: Character.toUpperCase(tagLabel.charAt(0));
map.computeIfAbsent(unicode, k -> new ArrayList<>()).add(sii);
}
return map;
return searchItems.collect(Collectors.groupingBy(i -> keyCharacter(i.getLabel())));
}
protected static Character keyCharacter(String s) {
return s.isEmpty() ? '*' : Character.toUpperCase(s.charAt(0));
}
}

View file

@ -28,7 +28,6 @@ package jdk.javadoc.internal.doclets.formats.html;
import com.sun.source.doctree.DocTree;
import com.sun.source.doctree.EndElementTree;
import com.sun.source.doctree.StartElementTree;
import com.sun.source.doctree.TextTree;
import com.sun.source.util.DocTreeFactory;
import com.sun.tools.doclint.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
@ -266,37 +265,8 @@ public class DocFilesHandlerImpl implements DocFilesHandler {
}
private String getWindowTitle(HtmlDocletWriter docletWriter, Element element) {
List<? extends DocTree> preamble = configuration.utils.getPreamble(element);
StringBuilder sb = new StringBuilder();
boolean titleFound = false;
loop:
for (DocTree dt : preamble) {
switch (dt.getKind()) {
case START_ELEMENT:
StartElementTree nodeStart = (StartElementTree)dt;
if (Utils.toLowerCase(nodeStart.getName().toString()).equals("title")) {
titleFound = true;
}
break;
case END_ELEMENT:
EndElementTree nodeEnd = (EndElementTree)dt;
if (Utils.toLowerCase(nodeEnd.getName().toString()).equals("title")) {
break loop;
}
break;
case TEXT:
TextTree nodeText = (TextTree)dt;
if (titleFound)
sb.append(nodeText.getBody());
break;
default:
// do nothing
}
}
return docletWriter.getWindowTitle(sb.toString().trim());
String t = configuration.utils.getHTMLTitle(element);
return docletWriter.getWindowTitle(t);
}
private static class DocFileWriter extends HtmlDocletWriter {

View file

@ -25,6 +25,8 @@
package jdk.javadoc.internal.doclets.formats.html;
import javax.lang.model.element.Element;
/**
* Index item for search.
*
@ -40,7 +42,14 @@ public class SearchIndexItem {
PACKAGES,
TYPES,
MEMBERS,
SEARCH_TAGS
/**
* The category of items corresponding to {@code {@index}} tags.
*/
INDEX,
/**
* The category of items corresponding to {@code {@systemProperty}} tags.
*/
SYSTEM_PROPERTY
}
private Category category;
@ -51,7 +60,7 @@ public class SearchIndexItem {
private String containingClass = "";
private String holder = "";
private String description = "";
private boolean systemProperty;
private Element element;
public void setLabel(String l) {
label = l;
@ -105,12 +114,12 @@ public class SearchIndexItem {
return category;
}
public void setSystemProperty(boolean value) {
systemProperty = value;
public void setElement(Element element) {
this.element = element;
}
public boolean isSystemProperty() {
return systemProperty;
public Element getElement() {
return element;
}
@Override
@ -155,7 +164,8 @@ public class SearchIndexItem {
}
item.append("}");
break;
case SEARCH_TAGS:
case INDEX:
case SYSTEM_PROPERTY:
item.append("{")
.append("\"l\":\"").append(label).append("\",")
.append("\"h\":\"").append(holder).append("\",");

View file

@ -25,20 +25,20 @@
package jdk.javadoc.internal.doclets.formats.html;
import jdk.javadoc.internal.doclets.formats.html.SearchIndexItem.Category;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Stream;
/**
* A container for organizing {@linkplain SearchIndexItem search items}
* by {@linkplain SearchIndexItem.Category category}.
* by {@linkplain Category category}.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
@ -47,7 +47,7 @@ import java.util.TreeSet;
*/
public final class SearchIndexItems {
private final Map<SearchIndexItem.Category, Set<SearchIndexItem>> items = new HashMap<>();
private final Map<Category, Set<SearchIndexItem>> items = new HashMap<>();
private final Utils utils;
public SearchIndexItems(Utils utils) {
@ -66,9 +66,9 @@ public final class SearchIndexItems {
.add(item);
}
private Set<SearchIndexItem> newSetForCategory(SearchIndexItem.Category category) {
private Set<SearchIndexItem> newSetForCategory(Category category) {
final Comparator<SearchIndexItem> cmp;
if (category == SearchIndexItem.Category.TYPES) {
if (category == Category.TYPES) {
cmp = utils.makeTypeSearchIndexComparator();
} else {
cmp = utils.makeGenericSearchIndexComparator();
@ -77,21 +77,82 @@ public final class SearchIndexItems {
}
/**
* Retrieves the items of the specified category from this container.
* Checks if there are items of any of the specified categories
* in this container.
*
* <p> The returned collection is either empty, if there are no items
* of the specified category, or contains only items {@code i} such that
* {@code i.getCategory().equals(cat)}. In any case, the returned collection
* is unmodifiable.
* <p> Iff there exists an item {@code i} for which there is a category
* {@code c} from the specified categories such that
* {@code i.getCategory().equals(c)}, then {@code true} is returned.
*
* @param cat
* the category of the items to retrieve
* @param firstCategory
* the first category
* @param otherCategories
* other categories (optional)
*
* @return a collection of items of the specified category
* @return {@code true} if there are items of any of the specified categories,
* {@code false} otherwise
*
* @throws NullPointerException
* if there are {@code null} categories
*/
public Collection<SearchIndexItem> get(SearchIndexItem.Category cat) {
public boolean containsAnyOfCategories(Category firstCategory,
Category... otherCategories)
{
return itemsOfCategories(firstCategory, otherCategories)
.findAny()
.isPresent();
}
/**
* Returns a stream of items of any of the specified categories
* from this container.
*
* <p> The returned stream consists of all items {@code i} for which there
* is a category {@code c} from the specified categories such that
* {@code i.getCategory().equals(c)}. The stream may be empty.
*
* @param firstCategory
* the first category
* @param otherCategories
* other categories (optional)
*
* @return a stream of items of the specified categories
*
* @throws NullPointerException
* if there are {@code null} categories
*/
public Stream<SearchIndexItem> itemsOfCategories(Category firstCategory,
Category... otherCategories)
{
return concatenatedStreamOf(firstCategory, otherCategories)
.distinct()
.flatMap(this::itemsOf);
}
private Stream<SearchIndexItem> itemsOf(Category cat) {
Objects.requireNonNull(cat);
Set<SearchIndexItem> col = items.getOrDefault(cat, Set.of());
return Collections.unmodifiableCollection(col);
return items.getOrDefault(cat, Set.of()).stream();
}
/**
* Returns a concatenated stream of elements.
*
* <p> The elements of the returned stream are encountered in the following order:
* {@code first, remaining[0], remaining[1], ..., remaining[remaining.length - 1]}.
*
* @param first
* the first element
* @param remaining
* the remaining elements, if any
* @param <T>
* the type of elements
*
* @return the stream of elements
*
* @throws NullPointerException
* if {@code remaining} is {@code null}
*/
private static <T> Stream<T> concatenatedStreamOf(T first, T[] remaining) {
return Stream.concat(Stream.of(first), Stream.of(remaining));
}
}

View file

@ -28,6 +28,7 @@ package jdk.javadoc.internal.doclets.formats.html;
import java.util.Set;
import java.util.TreeSet;
import jdk.javadoc.internal.doclets.formats.html.SearchIndexItem.Category;
import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
@ -150,7 +151,7 @@ public class SingleIndexWriter extends AbstractIndexWriter {
contentTree.add(links.createLink(DocPaths.ALLPACKAGES_INDEX,
contents.allPackagesLabel));
}
if (!searchItems.get(SearchIndexItem.Category.SEARCH_TAGS).isEmpty()) {
if (searchItems.containsAnyOfCategories(Category.SYSTEM_PROPERTY)) {
contentTree.add(getVerticalSeparator());
contentTree.add(links.createLink(DocPaths.SYSTEM_PROPERTIES, contents.systemPropertiesLabel));
}

View file

@ -27,13 +27,14 @@ package jdk.javadoc.internal.doclets.formats.html;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collectors;
import jdk.javadoc.internal.doclets.formats.html.SearchIndexItem.Category;
import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
@ -47,7 +48,6 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.IndexBuilder;
/**
* Generate Separate Index Files for all the member names with Indexing in
* Unicode Order. This will create "index-files" directory in the current or
@ -90,12 +90,15 @@ public class SplitIndexWriter extends AbstractIndexWriter {
* @throws DocFileIOException if there is a problem generating the index files
*/
public static void generate(HtmlConfiguration configuration,
IndexBuilder indexBuilder) throws DocFileIOException {
IndexBuilder indexBuilder) throws DocFileIOException
{
DocPath path = DocPaths.INDEX_FILES;
SortedSet<Character> keys = new TreeSet<>(indexBuilder.asMap().keySet());
Collection<SearchIndexItem> searchItems =
configuration.searchItems.get(SearchIndexItem.Category.SEARCH_TAGS);
keys.addAll(buildSearchTagIndex(searchItems).keySet());
Set<Character> searchItemsKeys = configuration.searchItems
.itemsOfCategories(Category.INDEX, Category.SYSTEM_PROPERTY)
.map(i -> keyCharacter(i.getLabel()))
.collect(Collectors.toSet());
keys.addAll(searchItemsKeys);
ListIterator<Character> li = new ArrayList<>(keys).listIterator();
while (li.hasNext()) {
Character ch = li.next();
@ -174,7 +177,7 @@ public class SplitIndexWriter extends AbstractIndexWriter {
contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.ALLPACKAGES_INDEX),
contents.allPackagesLabel));
}
if (!searchItems.get(SearchIndexItem.Category.SEARCH_TAGS).isEmpty()) {
if (searchItems.containsAnyOfCategories(Category.SYSTEM_PROPERTY)) {
contentTree.add(getVerticalSeparator());
contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.SYSTEM_PROPERTIES),
contents.systemPropertiesLabel));

View file

@ -24,7 +24,9 @@
*/
package jdk.javadoc.internal.doclets.formats.html;
import jdk.javadoc.internal.doclets.formats.html.SearchIndexItem.Category;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.FixedStringContent;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode;
@ -32,15 +34,22 @@ import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.formats.html.markup.Table;
import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletElement;
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 java.util.ArrayList;
import javax.lang.model.element.Element;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.WeakHashMap;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
/**
* Generates the file with the summary of all the system properties.
@ -59,6 +68,11 @@ public class SystemPropertiesWriter extends HtmlDocletWriter {
private final Navigation navBar;
/**
* Cached contents of {@code <title>...</title>} tags of the HTML pages.
*/
final Map<Element, String> titles = new WeakHashMap<>();
/**
* Constructs SystemPropertiesWriter object.
*
@ -70,17 +84,22 @@ public class SystemPropertiesWriter extends HtmlDocletWriter {
this.navBar = new Navigation(null, configuration, PageMode.SYSTEM_PROPERTIES, path);
}
/**
* Creates SystemPropertiesWriter object.
*
* @param configuration The current configuration
* @throws DocFileIOException
*/
public static void generate(HtmlConfiguration configuration) throws DocFileIOException {
generate(configuration, DocPaths.SYSTEM_PROPERTIES);
}
private static void generate(HtmlConfiguration configuration, DocPath fileName) throws DocFileIOException {
boolean hasSystemProperties = configuration.searchItems
.containsAnyOfCategories(Category.SYSTEM_PROPERTY);
if (!hasSystemProperties) {
// Cannot defer this check any further, because of the super() call
// that prints out notices on creating files, etc.
//
// There is probably a better place for this kind of checks (see how
// this is achieved in other "optional" pages, like Constant Values
// and Serialized Form).
return;
}
SystemPropertiesWriter systemPropertiesGen = new SystemPropertiesWriter(configuration, fileName);
systemPropertiesGen.buildSystemPropertiesPage();
}
@ -114,7 +133,7 @@ public class SystemPropertiesWriter extends HtmlDocletWriter {
}
/**
* Add all the system properties to the content tree.
* Adds all the system properties to the content tree.
*
* @param content HtmlTree content to which the links will be added
*/
@ -129,41 +148,49 @@ public class SystemPropertiesWriter extends HtmlDocletWriter {
Content propertyName = new StringContent(entry.getKey());
List<SearchIndexItem> searchIndexItems = entry.getValue();
Content separatedReferenceLinks = new ContentBuilder();
separatedReferenceLinks.add(links.createLink(
pathToRoot.resolve(searchIndexItems.get(0).getUrl()),
getLinkLabel(searchIndexItems.get(0))));
separatedReferenceLinks.add(createLink(searchIndexItems.get(0)));
for (int i = 1; i < searchIndexItems.size(); i++) {
separatedReferenceLinks.add(separator);
separatedReferenceLinks.add(links.createLink(
pathToRoot.resolve(searchIndexItems.get(i).getUrl()),
getLinkLabel(searchIndexItems.get(i))));
separatedReferenceLinks.add(createLink(searchIndexItems.get(i)));
}
table.addRow(propertyName, separatedReferenceLinks);
table.addRow(propertyName, HtmlTree.DIV(HtmlStyle.block, separatedReferenceLinks));
}
content.add(table);
}
private Map<String, List<SearchIndexItem>> groupSystemProperties() {
Map<String, List<SearchIndexItem>> searchIndexMap = new TreeMap<>();
for (SearchIndexItem searchIndex : searchItems.get(SearchIndexItem.Category.SEARCH_TAGS)) {
if (searchIndex.isSystemProperty()) {
List<SearchIndexItem> list = searchIndexMap
.computeIfAbsent(searchIndex.getLabel(), k -> new ArrayList<>());
list.add(searchIndex);
}
}
return searchIndexMap;
return searchItems
.itemsOfCategories(Category.SYSTEM_PROPERTY)
.collect(groupingBy(SearchIndexItem::getLabel, TreeMap::new, toList()));
}
private String getLinkLabel(SearchIndexItem searchIndexItem) {
String holder = searchIndexItem.getHolder();
String url = searchIndexItem.getUrl();
final String docFiles = "/doc-files/";
if (url.contains(docFiles)) {
final int idx = url.indexOf(docFiles);
final int len = docFiles.length();
return url.substring(idx + len, url.indexOf("#", idx));
private Content createLink(SearchIndexItem i) {
assert i.getCategory() == Category.SYSTEM_PROPERTY : i;
if (i.getElement() != null) {
if (i.getElement() instanceof OverviewElement) {
return links.createLink(pathToRoot.resolve(i.getUrl()),
resources.getText("doclet.Overview"));
}
DocletElement e = ((DocletElement) i.getElement());
// Implementations of DocletElement do not override equals and
// hashCode; putting instances of DocletElement in a map is not
// incorrect, but might well be inefficient
String t = titles.computeIfAbsent(i.getElement(), utils::getHTMLTitle);
if (t.isBlank()) {
// The user should probably be notified (a warning?) that this
// file does not have a title
Path p = Path.of(e.getFileObject().toUri());
t = p.getFileName().toString();
}
ContentBuilder b = new ContentBuilder();
b.add(HtmlTree.CODE(new FixedStringContent(i.getHolder() + ": ")));
// non-program elements should be displayed using a normal font
b.add(t);
return links.createLink(pathToRoot.resolve(i.getUrl()), b);
} else {
// program elements should be displayed using a code font
Content link = links.createLink(pathToRoot.resolve(i.getUrl()), i.getHolder());
return HtmlTree.CODE(link);
}
return holder;
}
}

View file

@ -41,6 +41,7 @@ import com.sun.source.doctree.DocTree;
import com.sun.source.doctree.IndexTree;
import com.sun.source.doctree.ParamTree;
import com.sun.source.doctree.SystemPropertyTree;
import jdk.javadoc.internal.doclets.formats.html.SearchIndexItem.Category;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@ -48,6 +49,7 @@ import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocFileElement;
import jdk.javadoc.internal.doclets.toolkit.DocletElement;
import jdk.javadoc.internal.doclets.toolkit.Resources;
import jdk.javadoc.internal.doclets.toolkit.builders.SerializedFormBuilder;
@ -401,7 +403,6 @@ public class TagletWriterImpl extends TagletWriter {
result = HtmlTree.SPAN(anchorName, HtmlStyle.searchTagResult, new StringContent(tagText));
if (options.createIndex() && !tagText.isEmpty()) {
SearchIndexItem si = new SearchIndexItem();
si.setSystemProperty(isSystemProperty);
si.setLabel(tagText);
si.setDescription(desc);
si.setUrl(htmlWriter.path.getPath() + "#" + anchorName);
@ -446,6 +447,7 @@ public class TagletWriterImpl extends TagletWriter {
public Void visitUnknown(Element e, Void p) {
if (e instanceof DocletElement) {
DocletElement de = (DocletElement) e;
si.setElement(de);
switch (de.getSubKind()) {
case OVERVIEW:
si.setHolder(resources.getText("doclet.Overview"));
@ -468,7 +470,7 @@ public class TagletWriterImpl extends TagletWriter {
return null;
}
}.visit(element);
si.setCategory(SearchIndexItem.Category.SEARCH_TAGS);
si.setCategory(isSystemProperty ? Category.SYSTEM_PROPERTY : Category.INDEX);
configuration.searchItems.add(si);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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
@ -33,8 +33,8 @@ import javax.tools.FileObject;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
/**
* This is a pseudo element wrapper for doc-files html contents, essentially to
* associate the doc-file's html documentation's DocCommentTree to an element.
* This is a pseudo-element wrapper for doc-files html contents, essentially to
* associate the doc-files' html documentation's {@code DocCommentTree} to an element.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.

View file

@ -95,8 +95,11 @@ import javax.tools.StandardLocation;
import com.sun.source.doctree.DocCommentTree;
import com.sun.source.doctree.DocTree;
import com.sun.source.doctree.DocTree.Kind;
import com.sun.source.doctree.EndElementTree;
import com.sun.source.doctree.ParamTree;
import com.sun.source.doctree.SerialFieldTree;
import com.sun.source.doctree.StartElementTree;
import com.sun.source.doctree.TextTree;
import com.sun.source.doctree.UnknownBlockTagTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.LineMap;
@ -1654,6 +1657,40 @@ public class Utils {
return secondaryCollator.compare(s1, s2);
}
public String getHTMLTitle(Element element) {
List<? extends DocTree> preamble = getPreamble(element);
StringBuilder sb = new StringBuilder();
boolean titleFound = false;
loop:
for (DocTree dt : preamble) {
switch (dt.getKind()) {
case START_ELEMENT:
StartElementTree nodeStart = (StartElementTree)dt;
if (Utils.toLowerCase(nodeStart.getName().toString()).equals("title")) {
titleFound = true;
}
break;
case END_ELEMENT:
EndElementTree nodeEnd = (EndElementTree)dt;
if (Utils.toLowerCase(nodeEnd.getName().toString()).equals("title")) {
break loop;
}
break;
case TEXT:
TextTree nodeText = (TextTree)dt;
if (titleFound)
sb.append(nodeText.getBody());
break;
default:
// do nothing
}
}
return sb.toString().trim();
}
private static class DocCollator {
private final Map<String, CollationKey> keys;
private final Collator instance;