8239876: Improve SearchIndexItem

Reviewed-by: jjg
This commit is contained in:
Pavel Rappo 2020-02-26 15:34:04 +00:00
parent 9b12c80e21
commit e8c32ccb2f
10 changed files with 170 additions and 70 deletions

@ -27,8 +27,11 @@ 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.List;
import java.util.Map;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
@ -74,6 +77,8 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
protected Navigation navBar;
protected final Map<Character, List<SearchIndexItem>> tagSearchIndexMap;
/**
* This constructor will be used by {@link SplitIndexWriter}. Initializes
* path to this file and relative path from this file.
@ -88,6 +93,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);
this.tagSearchIndexMap = buildSearchTagIndex(items);
}
/**
@ -182,7 +190,7 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
public Void visitModule(ModuleElement e, Void p) {
if (configuration.showModules) {
addDescription(e, dl, si);
configuration.moduleSearchIndex.add(si);
searchItems.add(si);
}
return null;
}
@ -190,21 +198,21 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
@Override
public Void visitPackage(PackageElement e, Void p) {
addDescription(e, dl, si);
configuration.packageSearchIndex.add(si);
searchItems.add(si);
return null;
}
@Override
public Void visitType(TypeElement e, Void p) {
addDescription(e, dl, si);
configuration.typeSearchIndex.add(si);
searchItems.add(si);
return null;
}
@Override
protected Void defaultAction(Element e, Void p) {
addDescription(e, dl, si);
configuration.memberSearchIndex.add(si);
searchItems.add(si);
return null;
}
@ -424,7 +432,7 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
protected void createSearchIndexFiles() throws DocFileIOException {
if (configuration.showModules) {
createSearchIndexFile(DocPaths.MODULE_SEARCH_INDEX_JS,
configuration.moduleSearchIndex,
searchItems.get(SearchIndexItem.Category.MODULES),
"moduleSearchIndex");
}
if (!configuration.packages.isEmpty()) {
@ -432,24 +440,24 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
si.setCategory(SearchIndexItem.Category.PACKAGES);
si.setLabel(resources.getText("doclet.All_Packages"));
si.setUrl(DocPaths.ALLPACKAGES_INDEX.getPath());
configuration.packageSearchIndex.add(si);
searchItems.add(si);
}
createSearchIndexFile(DocPaths.PACKAGE_SEARCH_INDEX_JS,
configuration.packageSearchIndex,
searchItems.get(SearchIndexItem.Category.PACKAGES),
"packageSearchIndex");
SearchIndexItem si = new SearchIndexItem();
si.setCategory(SearchIndexItem.Category.TYPES);
si.setLabel(resources.getText("doclet.All_Classes"));
si.setUrl(DocPaths.ALLCLASSES_INDEX.getPath());
configuration.typeSearchIndex.add(si);
searchItems.add(si);
createSearchIndexFile(DocPaths.TYPE_SEARCH_INDEX_JS,
configuration.typeSearchIndex,
searchItems.get(SearchIndexItem.Category.TYPES),
"typeSearchIndex");
createSearchIndexFile(DocPaths.MEMBER_SEARCH_INDEX_JS,
configuration.memberSearchIndex,
searchItems.get(SearchIndexItem.Category.MEMBERS),
"memberSearchIndex");
createSearchIndexFile(DocPaths.TAG_SEARCH_INDEX_JS,
configuration.tagSearchIndex,
searchItems.get(SearchIndexItem.Category.SEARCH_TAGS),
"tagSearchIndex");
}
@ -466,6 +474,8 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
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()) {
StringBuilder searchVar = new StringBuilder("[");
boolean first = true;
@ -488,4 +498,18 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
}
}
}
protected static Map<Character, List<SearchIndexItem>> buildSearchTagIndex(
Collection<? 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;
}
}

@ -91,19 +91,7 @@ public class HtmlConfiguration extends BaseConfiguration {
*/
public TypeElement currentTypeElement = null; // Set this TypeElement in the ClassWriter.
protected SortedSet<SearchIndexItem> memberSearchIndex;
protected SortedSet<SearchIndexItem> moduleSearchIndex;
protected SortedSet<SearchIndexItem> packageSearchIndex;
protected SortedSet<SearchIndexItem> tagSearchIndex;
protected SortedSet<SearchIndexItem> typeSearchIndex;
protected Map<Character, List<SearchIndexItem>> tagSearchIndexMap = new HashMap<>();
protected Set<Character> tagSearchIndexKeys;
protected SearchIndexItems searchItems;
public final Contents contents;
@ -349,17 +337,6 @@ public class HtmlConfiguration extends BaseConfiguration {
return (e == null || workArounds.haveDocLint());
}
protected void buildSearchTagIndex() {
for (SearchIndexItem sii : tagSearchIndex) {
String tagLabel = sii.getLabel();
Character unicode = (tagLabel.length() == 0)
? '*'
: Character.toUpperCase(tagLabel.charAt(0));
tagSearchIndexMap.computeIfAbsent(unicode, k -> new ArrayList<>()).add(sii);
}
tagSearchIndexKeys = tagSearchIndexMap.keySet();
}
@Override
protected boolean finishOptionSettings0() throws DocletException {
if (options.docEncoding() == null) {
@ -384,10 +361,6 @@ public class HtmlConfiguration extends BaseConfiguration {
@Override
protected void initConfiguration(DocletEnvironment docEnv) {
super.initConfiguration(docEnv);
memberSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
moduleSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
packageSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
tagSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
typeSearchIndex = new TreeSet<>(utils.makeTypeSearchIndexComparator());
searchItems = new SearchIndexItems(utils);
}
}

@ -169,7 +169,6 @@ public class HtmlDoclet extends AbstractDoclet {
if (options.createIndex()) {
IndexBuilder indexBuilder = new IndexBuilder(configuration, nodeprecated);
configuration.buildSearchTagIndex();
if (options.splitIndex()) {
SplitIndexWriter.generate(configuration, indexBuilder);
} else {

@ -153,6 +153,8 @@ public class HtmlDocletWriter {
*/
public final HtmlConfiguration configuration;
protected final SearchIndexItems searchItems;
protected final HtmlOptions options;
protected final Utils utils;
@ -210,6 +212,7 @@ public class HtmlDocletWriter {
*/
public HtmlDocletWriter(HtmlConfiguration configuration, DocPath path) {
this.configuration = configuration;
this.searchItems = configuration.searchItems;
this.options = configuration.getOptions();
this.contents = configuration.contents;
this.messages = configuration.messages;

@ -101,6 +101,10 @@ public class SearchIndexItem {
return description;
}
protected Category getCategory() {
return category;
}
public void setSystemProperty(boolean value) {
systemProperty = value;
}

@ -0,0 +1,97 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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 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;
/**
* A container for organizing {@linkplain SearchIndexItem search items}
* by {@linkplain SearchIndexItem.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.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public final class SearchIndexItems {
private final Map<SearchIndexItem.Category, Set<SearchIndexItem>> items = new HashMap<>();
private final Utils utils;
public SearchIndexItems(Utils utils) {
this.utils = Objects.requireNonNull(utils);
}
/**
* Adds the specified item to this container.
*
* @param item
* the item to add
*/
public void add(SearchIndexItem item) {
Objects.requireNonNull(item);
items.computeIfAbsent(item.getCategory(), this::newSetForCategory)
.add(item);
}
private Set<SearchIndexItem> newSetForCategory(SearchIndexItem.Category category) {
final Comparator<SearchIndexItem> cmp;
if (category == SearchIndexItem.Category.TYPES) {
cmp = utils.makeTypeSearchIndexComparator();
} else {
cmp = utils.makeGenericSearchIndexComparator();
}
return new TreeSet<>(cmp);
}
/**
* Retrieves the items of the specified category from 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.
*
* @param cat
* the category of the items to retrieve
*
* @return a collection of items of the specified category
*/
public Collection<SearchIndexItem> get(SearchIndexItem.Category cat) {
Objects.requireNonNull(cat);
Set<SearchIndexItem> col = items.getOrDefault(cat, Set.of());
return Collections.unmodifiableCollection(col);
}
}

@ -102,16 +102,16 @@ public class SingleIndexWriter extends AbstractIndexWriter {
HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
divTree.setStyle(HtmlStyle.contentContainer);
elements = new TreeSet<>(indexBuilder.asMap().keySet());
elements.addAll(configuration.tagSearchIndexKeys);
elements.addAll(tagSearchIndexMap.keySet());
addLinksForIndexes(divTree);
for (Character unicode : elements) {
if (configuration.tagSearchIndexMap.get(unicode) == null) {
if (tagSearchIndexMap.get(unicode) == null) {
addContents(unicode, indexBuilder.getMemberList(unicode), divTree);
} else if (indexBuilder.getMemberList(unicode) == null) {
addSearchContents(unicode, configuration.tagSearchIndexMap.get(unicode), divTree);
addSearchContents(unicode, tagSearchIndexMap.get(unicode), divTree);
} else {
addContents(unicode, indexBuilder.getMemberList(unicode),
configuration.tagSearchIndexMap.get(unicode), divTree);
tagSearchIndexMap.get(unicode), divTree);
}
}
addLinksForIndexes(divTree);
@ -137,22 +137,22 @@ public class SingleIndexWriter extends AbstractIndexWriter {
* @param contentTree the content tree to which the links for indexes will be added
*/
protected void addLinksForIndexes(Content contentTree) {
for (Object ch : elements) {
for (Character ch : elements) {
String unicode = ch.toString();
contentTree.add(
links.createLink(getNameForIndex(unicode),
new StringContent(unicode)));
new StringContent(unicode)));
contentTree.add(Entity.NO_BREAK_SPACE);
}
contentTree.add(new HtmlTree(HtmlTag.BR));
contentTree.add(links.createLink(DocPaths.ALLCLASSES_INDEX,
contents.allClassesLabel));
contents.allClassesLabel));
if (!configuration.packages.isEmpty()) {
contentTree.add(getVerticalSeparator());
contentTree.add(links.createLink(DocPaths.ALLPACKAGES_INDEX,
contents.allPackagesLabel));
contents.allPackagesLabel));
}
if (!configuration.tagSearchIndex.isEmpty()) {
if (!searchItems.get(SearchIndexItem.Category.SEARCH_TAGS).isEmpty()) {
contentTree.add(getVerticalSeparator());
contentTree.add(links.createLink(DocPaths.SYSTEM_PROPERTIES, contents.systemPropertiesLabel));
}

@ -27,9 +27,11 @@ 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 jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
@ -90,20 +92,18 @@ public class SplitIndexWriter extends AbstractIndexWriter {
public static void generate(HtmlConfiguration configuration,
IndexBuilder indexBuilder) throws DocFileIOException {
DocPath path = DocPaths.INDEX_FILES;
Set<Character> keys = new TreeSet<>(indexBuilder.asMap().keySet());
keys.addAll(configuration.tagSearchIndexKeys);
SortedSet<Character> keys = new TreeSet<>(indexBuilder.asMap().keySet());
Collection<SearchIndexItem> searchItems =
configuration.searchItems.get(SearchIndexItem.Category.SEARCH_TAGS);
keys.addAll(buildSearchTagIndex(searchItems).keySet());
ListIterator<Character> li = new ArrayList<>(keys).listIterator();
int prev;
int next;
while (li.hasNext()) {
prev = (li.hasPrevious()) ? li.previousIndex() + 1 : -1;
Object ch = li.next();
next = (li.hasNext()) ? li.nextIndex() + 1 : -1;
Character ch = li.next();
DocPath filename = DocPaths.indexN(li.nextIndex());
SplitIndexWriter indexgen = new SplitIndexWriter(configuration,
path.resolve(filename),
indexBuilder, keys);
indexgen.generateIndexFile((Character) ch);
path.resolve(filename),
indexBuilder, keys);
indexgen.generateIndexFile(ch);
if (!li.hasNext()) {
indexgen.createSearchIndexFiles();
}
@ -133,13 +133,13 @@ public class SplitIndexWriter extends AbstractIndexWriter {
HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
divTree.setStyle(HtmlStyle.contentContainer);
addLinksForIndexes(divTree);
if (configuration.tagSearchIndexMap.get(unicode) == null) {
if (tagSearchIndexMap.get(unicode) == null) {
addContents(unicode, indexBuilder.getMemberList(unicode), divTree);
} else if (indexBuilder.getMemberList(unicode) == null) {
addSearchContents(unicode, configuration.tagSearchIndexMap.get(unicode), divTree);
addSearchContents(unicode, tagSearchIndexMap.get(unicode), divTree);
} else {
addContents(unicode, indexBuilder.getMemberList(unicode),
configuration.tagSearchIndexMap.get(unicode), divTree);
tagSearchIndexMap.get(unicode), divTree);
}
addLinksForIndexes(divTree);
main.add(divTree);
@ -170,16 +170,16 @@ public class SplitIndexWriter extends AbstractIndexWriter {
}
contentTree.add(new HtmlTree(HtmlTag.BR));
contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.ALLCLASSES_INDEX),
contents.allClassesLabel));
contents.allClassesLabel));
if (!configuration.packages.isEmpty()) {
contentTree.add(getVerticalSeparator());
contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.ALLPACKAGES_INDEX),
contents.allPackagesLabel));
contents.allPackagesLabel));
}
if (!configuration.tagSearchIndex.isEmpty()) {
if (!searchItems.get(SearchIndexItem.Category.SEARCH_TAGS).isEmpty()) {
contentTree.add(getVerticalSeparator());
contentTree.add(links.createLink(pathToRoot.resolve(DocPaths.SYSTEM_PROPERTIES),
contents.systemPropertiesLabel));
contents.systemPropertiesLabel));
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 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
@ -148,7 +148,7 @@ public class SystemPropertiesWriter extends HtmlDocletWriter {
private Map<String, List<SearchIndexItem>> groupSystemProperties() {
Map<String, List<SearchIndexItem>> searchIndexMap = new TreeMap<>();
for (SearchIndexItem searchIndex : configuration.tagSearchIndex) {
for (SearchIndexItem searchIndex : searchItems.get(SearchIndexItem.Category.SEARCH_TAGS)) {
if (searchIndex.isSystemProperty()) {
List<SearchIndexItem> list = searchIndexMap
.computeIfAbsent(searchIndex.getLabel(), k -> new ArrayList<>());

@ -470,7 +470,7 @@ public class TagletWriterImpl extends TagletWriter {
}
}.visit(element);
si.setCategory(SearchIndexItem.Category.SEARCH_TAGS);
configuration.tagSearchIndex.add(si);
configuration.searchItems.add(si);
}
}
return result;