8239243: Create index structures only if required

Reviewed-by: hannesw, jjg
This commit is contained in:
Pavel Rappo 2020-02-19 10:34:42 +00:00
parent 7b24bd68c2
commit 9fdcdf4a3e
6 changed files with 131 additions and 155 deletions

View file

@ -70,7 +70,7 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
/**
* The index of all the members with unicode character.
*/
protected IndexBuilder indexbuilder;
protected IndexBuilder indexBuilder;
protected Navigation navBar;
@ -80,13 +80,13 @@ public class AbstractIndexWriter extends HtmlDocletWriter {
*
* @param configuration The current configuration
* @param path Path to the file which is getting generated.
* @param indexbuilder Unicode based Index from {@link IndexBuilder}
* @param indexBuilder Unicode based Index from {@link IndexBuilder}
*/
protected AbstractIndexWriter(HtmlConfiguration configuration,
DocPath path,
IndexBuilder indexbuilder) {
IndexBuilder indexBuilder) {
super(configuration, path);
this.indexbuilder = indexbuilder;
this.indexBuilder = indexBuilder;
this.navBar = new Navigation(null, configuration, PageMode.INDEX, path);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -54,20 +54,20 @@ public class AllClassesIndexWriter extends HtmlDocletWriter {
/**
* Index of all the classes.
*/
protected IndexBuilder indexbuilder;
protected IndexBuilder indexBuilder;
/**
* Construct AllClassesIndexWriter object. Also initializes the indexbuilder variable in this
* Construct AllClassesIndexWriter object. Also initializes the indexBuilder variable in this
* class.
*
* @param configuration The current configuration
* @param filename Path to the file which is getting generated.
* @param indexbuilder Unicode based Index from {@link IndexBuilder}
* @param indexBuilder Unicode based Index from {@link IndexBuilder}
*/
public AllClassesIndexWriter(HtmlConfiguration configuration,
DocPath filename, IndexBuilder indexbuilder) {
DocPath filename, IndexBuilder indexBuilder) {
super(configuration, filename);
this.indexbuilder = indexbuilder;
this.indexBuilder = indexBuilder;
}
/**
@ -134,8 +134,8 @@ public class AllClassesIndexWriter extends HtmlDocletWriter {
.addTab(resources.errorSummary, e -> utils.isError((TypeElement)e))
.addTab(resources.annotationTypeSummary, utils::isAnnotationType)
.setTabScript(i -> "show(" + i + ");");
for (Character unicode : indexbuilder.index()) {
for (Element element : indexbuilder.getMemberList(unicode)) {
for (Character unicode : indexBuilder.keys()) {
for (Element element : indexBuilder.getMemberList(unicode)) {
TypeElement typeElement = (TypeElement) element;
if (!utils.isCoreClass(typeElement)) {
continue;

View file

@ -150,7 +150,6 @@ public class HtmlDoclet extends AbstractDoclet {
if (options.classUse()) {
ClassUseWriter.generate(configuration, classtree);
}
IndexBuilder indexbuilder = new IndexBuilder(configuration, nodeprecated);
if (options.createTree()) {
TreeWriter.generate(configuration, classtree);
@ -169,11 +168,12 @@ public class HtmlDoclet extends AbstractDoclet {
}
if (options.createIndex()) {
IndexBuilder indexBuilder = new IndexBuilder(configuration, nodeprecated);
configuration.buildSearchTagIndex();
if (options.splitIndex()) {
SplitIndexWriter.generate(configuration, indexbuilder);
SplitIndexWriter.generate(configuration, indexBuilder);
} else {
SingleIndexWriter.generate(configuration, indexbuilder);
SingleIndexWriter.generate(configuration, indexBuilder);
}
AllClassesIndexWriter.generate(configuration,
new IndexBuilder(configuration, nodeprecated, true));

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 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
@ -64,26 +64,26 @@ public class SingleIndexWriter extends AbstractIndexWriter {
*
* @param configuration the configuration for this doclet
* @param filename Name of the index file to be generated.
* @param indexbuilder Unicode based Index from {@link IndexBuilder}
* @param indexBuilder Unicode based Index from {@link IndexBuilder}
*/
public SingleIndexWriter(HtmlConfiguration configuration,
DocPath filename,
IndexBuilder indexbuilder) {
super(configuration, filename, indexbuilder);
IndexBuilder indexBuilder) {
super(configuration, filename, indexBuilder);
}
/**
* Generate single index file, for all Unicode characters.
*
* @param configuration the configuration for this doclet
* @param indexbuilder IndexBuilder built by {@link IndexBuilder}
* @param indexBuilder IndexBuilder built by {@link IndexBuilder}
* @throws DocFileIOException if there is a problem generating the index
*/
public static void generate(HtmlConfiguration configuration,
IndexBuilder indexbuilder) throws DocFileIOException {
IndexBuilder indexBuilder) throws DocFileIOException {
DocPath filename = DocPaths.INDEX_ALL;
SingleIndexWriter indexgen = new SingleIndexWriter(configuration,
filename, indexbuilder);
filename, indexBuilder);
indexgen.generateIndexFile();
}
@ -101,17 +101,17 @@ public class SingleIndexWriter extends AbstractIndexWriter {
headerContent.add(navBar.getContent(true));
HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
divTree.setStyle(HtmlStyle.contentContainer);
elements = new TreeSet<>(indexbuilder.getIndexMap().keySet());
elements = new TreeSet<>(indexBuilder.asMap().keySet());
elements.addAll(configuration.tagSearchIndexKeys);
addLinksForIndexes(divTree);
for (Character unicode : elements) {
if (configuration.tagSearchIndexMap.get(unicode) == null) {
addContents(unicode, indexbuilder.getMemberList(unicode), divTree);
} else if (indexbuilder.getMemberList(unicode) == null) {
addContents(unicode, indexBuilder.getMemberList(unicode), divTree);
} else if (indexBuilder.getMemberList(unicode) == null) {
addSearchContents(unicode, configuration.tagSearchIndexMap.get(unicode), divTree);
} else {
addContents(unicode, indexbuilder.getMemberList(unicode),
configuration.tagSearchIndexMap.get(unicode), divTree);
addContents(unicode, indexBuilder.getMemberList(unicode),
configuration.tagSearchIndexMap.get(unicode), divTree);
}
}
addLinksForIndexes(divTree);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 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
@ -68,14 +68,14 @@ public class SplitIndexWriter extends AbstractIndexWriter {
*
* @param configuration the configuration for this doclet
* @param path Path to the file which is getting generated.
* @param indexbuilder Unicode based Index from {@link IndexBuilder}
* @param indexBuilder Unicode based Index from {@link IndexBuilder}
* @param elements the collection of characters for which to generate index files
*/
public SplitIndexWriter(HtmlConfiguration configuration,
DocPath path,
IndexBuilder indexbuilder,
IndexBuilder indexBuilder,
Collection<Character> elements) {
super(configuration, path, indexbuilder);
super(configuration, path, indexBuilder);
this.indexElements = new ArrayList<>(elements);
}
@ -84,13 +84,13 @@ public class SplitIndexWriter extends AbstractIndexWriter {
* the members starting with the particular unicode character.
*
* @param configuration the configuration for this doclet
* @param indexbuilder IndexBuilder built by {@link IndexBuilder}
* @param indexBuilder IndexBuilder built by {@link IndexBuilder}
* @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;
Set<Character> keys = new TreeSet<>(indexbuilder.getIndexMap().keySet());
Set<Character> keys = new TreeSet<>(indexBuilder.asMap().keySet());
keys.addAll(configuration.tagSearchIndexKeys);
ListIterator<Character> li = new ArrayList<>(keys).listIterator();
int prev;
@ -102,7 +102,7 @@ public class SplitIndexWriter extends AbstractIndexWriter {
DocPath filename = DocPaths.indexN(li.nextIndex());
SplitIndexWriter indexgen = new SplitIndexWriter(configuration,
path.resolve(filename),
indexbuilder, keys);
indexBuilder, keys);
indexgen.generateIndexFile((Character) ch);
if (!li.hasNext()) {
indexgen.createSearchIndexFiles();
@ -134,11 +134,11 @@ public class SplitIndexWriter extends AbstractIndexWriter {
divTree.setStyle(HtmlStyle.contentContainer);
addLinksForIndexes(divTree);
if (configuration.tagSearchIndexMap.get(unicode) == null) {
addContents(unicode, indexbuilder.getMemberList(unicode), divTree);
} else if (indexbuilder.getMemberList(unicode) == null) {
addContents(unicode, indexBuilder.getMemberList(unicode), divTree);
} else if (indexBuilder.getMemberList(unicode) == null) {
addSearchContents(unicode, configuration.tagSearchIndexMap.get(unicode), divTree);
} else {
addContents(unicode, indexbuilder.getMemberList(unicode),
addContents(unicode, indexBuilder.getMemberList(unicode),
configuration.tagSearchIndexMap.get(unicode), divTree);
}
addLinksForIndexes(divTree);

View file

@ -26,80 +26,74 @@
package jdk.javadoc.internal.doclets.toolkit.util;
import java.util.*;
import java.util.stream.Collectors;
import javax.lang.model.element.Element;
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.Messages;
import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Build the mapping of each Unicode character with it's member lists
* containing members names starting with it. Also build a list for all the
* Unicode characters which start a member name. Member name is
* classkind or field or method or constructor name.
* An alphabetical index of {@link Element elements}.
*
* <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>
*
* @see java.lang.Character
*/
public class IndexBuilder {
/**
* Mapping of each Unicode Character with the member list containing
* members with names starting with it.
* Sets of elements keyed by the first character of the names of the
* elements in those sets.
*/
private final Map<Character, SortedSet<Element>> indexmap;
private final Map<Character, SortedSet<Element>> indexMap;
/**
* Don't generate deprecated information if true.
*/
private boolean noDeprecated;
private final boolean noDeprecated;
/**
* Build this Index only for classes?
* Build this index only for classes?
*/
private boolean classesOnly;
/**
* Indicates javafx mode.
*/
private boolean javafx;
private final boolean classesOnly;
private final BaseConfiguration configuration;
private final Utils utils;
private final Comparator<Element> comparator;
/**
* Constructor. Build the index map.
* Creates a new {@code IndexBuilder}.
*
* @param configuration the current configuration of the doclet.
* @param configuration the current configuration of the doclet
* @param noDeprecated true if -nodeprecated option is used,
* false otherwise.
* false otherwise
*/
public IndexBuilder(BaseConfiguration configuration, boolean noDeprecated) {
public IndexBuilder(BaseConfiguration configuration,
boolean noDeprecated)
{
this(configuration, noDeprecated, false);
}
/**
* Constructor. Build the index map.
* Creates a new {@code IndexBuilder}.
*
* @param configuration the current configuration of the doclet.
* @param configuration the current configuration of the doclet
* @param noDeprecated true if -nodeprecated option is used,
* false otherwise.
* @param classesOnly Include only classes in index.
* false otherwise
* @param classesOnly include only classes in index
*/
public IndexBuilder(BaseConfiguration configuration, boolean noDeprecated,
boolean classesOnly) {
this.configuration = configuration;
public IndexBuilder(BaseConfiguration configuration,
boolean noDeprecated,
boolean classesOnly)
{
this.configuration = configuration;
this.utils = configuration.utils;
Messages messages = configuration.getMessages();
@ -111,156 +105,138 @@ public class IndexBuilder {
this.noDeprecated = noDeprecated;
this.classesOnly = classesOnly;
this.javafx = configuration.getOptions().javafx();
this.indexmap = new TreeMap<>();
this.indexMap = new TreeMap<>();
comparator = classesOnly
? utils.makeAllClassesComparator()
: utils.makeIndexUseComparator();
buildIndexMap(configuration.docEnv);
buildIndex();
}
/**
* Get all the members in all the Packages and all the Classes
* given on the command line. Form separate list of those members depending
* upon their names.
*
* @param docEnv the doclet environment
* Indexes all the members in all the packages and all the classes.
*/
protected void buildIndexMap(DocletEnvironment docEnv) {
Set<PackageElement> packages = configuration.getSpecifiedPackageElements();
private void buildIndex() {
Set<TypeElement> classes = configuration.getIncludedTypeElements();
if (!classesOnly) {
if (packages.isEmpty()) {
Set<PackageElement> set = new HashSet<>();
for (TypeElement aClass : classes) {
PackageElement pkg = utils.containingPackage(aClass);
if (pkg != null && !pkg.isUnnamed()) {
set.add(pkg);
}
}
adjustIndexMap(set);
} else {
adjustIndexMap(packages);
}
indexElements(classes);
if (classesOnly) {
return;
}
adjustIndexMap(classes);
if (!classesOnly) {
for (TypeElement aClass : classes) {
if (shouldAddToIndexMap(aClass)) {
putMembersInIndexMap(aClass);
}
}
if (configuration.showModules) {
addModulesToIndexMap();
}
Set<PackageElement> packages = configuration.getSpecifiedPackageElements();
if (packages.isEmpty()) {
packages = classes
.stream()
.map(utils::containingPackage)
.filter(_package -> _package != null && !_package.isUnnamed())
.collect(Collectors.toSet());
}
indexElements(packages);
classes.stream()
.filter(this::shouldIndex)
.forEach(this::indexMembers);
if (configuration.showModules) {
indexModules();
}
}
/**
* Put all the members(fields, methods and constructors) in the te
* to the indexmap.
* Indexes all the members (fields, methods, constructors, etc.) of the
* provided type element.
*
* @param te TypeElement whose members will be added to the indexmap.
* @param te TypeElement whose members are to be indexed
*/
protected void putMembersInIndexMap(TypeElement te) {
private void indexMembers(TypeElement te) {
VisibleMemberTable vmt = configuration.getVisibleMemberTable(te);
adjustIndexMap(vmt.getMembers(ANNOTATION_TYPE_FIELDS));
adjustIndexMap(vmt.getMembers(FIELDS));
adjustIndexMap(vmt.getMembers(METHODS));
adjustIndexMap(vmt.getMembers(CONSTRUCTORS));
adjustIndexMap(vmt.getMembers(ENUM_CONSTANTS));
indexElements(vmt.getMembers(ANNOTATION_TYPE_FIELDS));
indexElements(vmt.getMembers(FIELDS));
indexElements(vmt.getMembers(METHODS));
indexElements(vmt.getMembers(CONSTRUCTORS));
indexElements(vmt.getMembers(ENUM_CONSTANTS));
}
/**
* Adjust list of members according to their names. Check the first
* character in a member name, and then add the member to a list of members
* for that particular unicode character.
* Indexes the provided elements.
*
* @param elements Array of members.
* @param elements a collection of elements
*/
protected void adjustIndexMap(Iterable<? extends Element> elements) {
private void indexElements(Iterable<? extends Element> elements) {
for (Element element : elements) {
if (shouldAddToIndexMap(element)) {
if (shouldIndex(element)) {
String name = utils.isPackage(element)
? utils.getPackageName((PackageElement)element)
? utils.getPackageName((PackageElement) element)
: utils.getSimpleName(element);
char ch = (name.length() == 0) ?
'*' :
Character.toUpperCase(name.charAt(0));
Character unicode = ch;
SortedSet<Element> list = indexmap.computeIfAbsent(unicode,
c -> new TreeSet<>(comparator));
list.add(element);
Character ch = keyCharacter(name);
SortedSet<Element> set = indexMap.computeIfAbsent(ch, c -> new TreeSet<>(comparator));
set.add(element);
}
}
}
private static Character keyCharacter(String s) {
return s.isEmpty() ? '*' : Character.toUpperCase(s.charAt(0));
}
/**
* Add all the modules to index map.
* Indexes all the modules.
*/
protected void addModulesToIndexMap() {
for (ModuleElement mdle : configuration.modules) {
String mdleName = mdle.getQualifiedName().toString();
char ch = (mdleName.length() == 0)
? '*'
: Character.toUpperCase(mdleName.charAt(0));
Character unicode = ch;
SortedSet<Element> list = indexmap.computeIfAbsent(unicode,
c -> new TreeSet<>(comparator));
list.add(mdle);
private void indexModules() {
for (ModuleElement m : configuration.modules) {
Character ch = keyCharacter(m.getQualifiedName().toString());
SortedSet<Element> set = indexMap.computeIfAbsent(ch, c -> new TreeSet<>(comparator));
set.add(m);
}
}
/**
* Should this element be added to the index map?
* Should this element be added to the index?
*/
protected boolean shouldAddToIndexMap(Element element) {
private boolean shouldIndex(Element element) {
if (utils.hasHiddenTag(element)) {
return false;
}
if (utils.isPackage(element))
if (utils.isPackage(element)) {
// Do not add to index map if -nodeprecated option is set and the
// package is marked as deprecated.
return !(noDeprecated && configuration.utils.isDeprecated(element));
else
} else {
// Do not add to index map if -nodeprecated option is set and if the
// element is marked as deprecated or the containing package is marked as
// deprecated.
return !(noDeprecated &&
(configuration.utils.isDeprecated(element) ||
configuration.utils.isDeprecated(utils.containingPackage(element))));
}
}
/**
* Return a map of all the individual member lists with Unicode character.
* Returns a map representation of this index.
*
* @return Map index map.
* @return map
*/
public Map<Character, SortedSet<Element>> getIndexMap() {
return indexmap;
public Map<Character, SortedSet<Element>> asMap() {
return indexMap;
}
/**
* Return the sorted list of members, for passed Unicode Character.
* Returns a sorted list of elements whose names start with the
* provided character.
*
* @param index index Unicode character.
* @return List member list for specific Unicode character.
* @param key index key
* @return list of elements keyed by the provided character
*/
public List<? extends Element> getMemberList(Character index) {
SortedSet<Element> set = indexmap.get(index);
if (set == null)
public List<? extends Element> getMemberList(Character key) {
SortedSet<Element> set = indexMap.get(key);
if (set == null) {
return null;
List<Element> out = new ArrayList<>();
out.addAll(set);
return out;
}
return new ArrayList<>(set);
}
/**
* Array of IndexMap keys, Unicode characters.
* Returns a list of index keys.
*/
public List<Character> index() {
return new ArrayList<>(indexmap.keySet());
public List<Character> keys() {
return new ArrayList<>(indexMap.keySet());
}
}