mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
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:
parent
5b323a8656
commit
8c6649dea0
21 changed files with 504 additions and 161 deletions
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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("\",");
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue