/* * 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.toolkit.util; import java.util.Objects; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.ModuleElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.util.SimpleElementVisitor14; import com.sun.source.doctree.DocTree; /** * An item to be included in the index pages and in interactive search. * *
* Items are primarily defined by their position in the documentation, * which is one of: * *
* All items have a "label", which is the presentation string used * to display the item in the list of matching choices. The * label is specified when the item is created. Items also * have a "url" and a "description", which are provided by * the specific doclet. * *
* Each item provides details to be included in the search index files * read and processed by JavaScript. * Items have a "category", which is normally derived from the element * kind or doc tree kind; it corresponds to the JavaScript file * in which this item will be written. * *
* Items for an element may have one or more of the following: * "containing module", "containing package", "containing type". * *
* Items for a node in a doc tree have a "holder", which is a * text form of the enclosing element or page. * They will typically also have a "description" derived from * content in the doc tree node. * * *
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.
*/
public class IndexItem {
/**
* The "category" used to group items for the interactive search index.
* Categories correspond directly to the JavaScript files that will be generated.
*/
public enum Category {
MODULES,
PACKAGES,
TYPES,
MEMBERS,
TAGS
}
/**
* The presentation string for the item. It must be non-empty.
*/
private final String label;
/**
* The element for the item. It is only null for items for summary pages that are not
* associated with any specific element.
*
*/
private final Element element;
/**
* The URL pointing to the element, doc tree or page being indexed.
* It may be empty if the information can be determined from other fields.
*/
private String url = "";
/**
* The containing module, if any, for the item.
* It will be empty if the element is not in a package, and may be omitted if the
* name of the package is unique.
*/
private String containingModule = "";
/**
* The containing package, if any, for the item.
*/
private String containingPackage = "";
/**
* The containing class, if any, for the item.
*/
private String containingClass = "";
/**
* Creates an index item for a module element.
*
* @param moduleElement the element
* @param utils the common utilities class
*
* @return the item
*/
public static IndexItem of(ModuleElement moduleElement, Utils utils) {
return new IndexItem(moduleElement, utils.getFullyQualifiedName(moduleElement));
}
/**
* Creates an index item for a package element.
*
* @param packageElement the element
* @param utils the common utilities class
*
* @return the item
*/
public static IndexItem of(PackageElement packageElement, Utils utils) {
return new IndexItem(packageElement, utils.getPackageName(packageElement));
}
/**
* Creates an index item for a type element.
* Note: use {@code getElement()} to access this value, not {@code getTypeElement}.
*
* @param typeElement the element
* @param utils the common utilities class
*
* @return the item
*/
public static IndexItem of(TypeElement typeElement, Utils utils) {
return new IndexItem(typeElement, utils.getSimpleName(typeElement));
}
/**
* Creates an index item for a member element.
* Note: the given type element may not be the same as the enclosing element of the member
* in cases where the enclosing element is not visible in the documentation.
*
* @param typeElement the element that contains the member
* @param member the member
* @param utils the common utilities class
*
* @return the item
*
* @see #getContainingTypeElement()
*/
public static IndexItem of(TypeElement typeElement, Element member, Utils utils) {
String name = utils.getSimpleName(member);
if (utils.isExecutableElement(member)) {
ExecutableElement ee = (ExecutableElement)member;
name += utils.flatSignature(ee, typeElement);
}
return new IndexItem(member, name) {
@Override
public TypeElement getContainingTypeElement() {
return typeElement;
}
};
}
/**
* Creates an index item for a node in the doc comment for an element.
* The node should only be one that gives rise to an entry in the index.
*
* @param element the element
* @param docTree the node in the doc comment
* @param label the label
* @param holder the holder for the comment
* @param description the description of the item
* @param link the root-relative link to the item in the generated docs
*
* @return the item
*/
public static IndexItem of(Element element, DocTree docTree, String label,
String holder, String description, DocLink link) {
Objects.requireNonNull(element);
Objects.requireNonNull(holder);
Objects.requireNonNull(description);
Objects.requireNonNull(link);
switch (docTree.getKind()) {
case INDEX, SYSTEM_PROPERTY -> { }
default -> throw new IllegalArgumentException(docTree.getKind().toString());
}
return new IndexItem(element, label, link.toString()) {
@Override
public DocTree getDocTree() {
return docTree;
}
@Override
public Category getCategory() {
return getCategory(docTree);
}
@Override
public String getHolder() {
return holder;
}
@Override
public String getDescription() {
return description;
}
};
}
/**
* Creates an index item for a summary page, that is not associated with any element or
* node in a doc comment.
*
* @param category the category for the item
* @param label the label for the item
* @param path the path for the page
*
* @return the item
*/
public static IndexItem of(Category category, String label, DocPath path) {
Objects.requireNonNull(category);
return new IndexItem(null, label, path.getPath()) {
@Override
public DocTree getDocTree() {
return null;
}
@Override
public Category getCategory() {
return category;
}
@Override
public String getHolder() {
return "";
}
@Override
public String getDescription() {
return "";
}
};
}
private IndexItem(Element element, String label) {
if (label.isEmpty()) {
throw new IllegalArgumentException();
}
this.element = element;
this.label = label;
}
private IndexItem(Element element, String label, String url) {
this(element, label);
setUrl(url);
}
/**
* Returns the label of the item.
*
* @return the label
*/
public String getLabel() {
return label;
}
/**
* Returns the part of the label after the last dot, or the whole label if there are no dots.
*
* @return the simple name
*/
public String getSimpleName() {
return label.substring(label.lastIndexOf('.') + 1);
}
/**
* Returns the label with a fully-qualified type name.
* (Used to determine if labels are unique or need to be qualified.)
*
* @param utils the common utilities class
*
* @return the fully qualified name
*/
public String getFullyQualifiedLabel(Utils utils) {
TypeElement typeElement = getContainingTypeElement();
if (typeElement != null) {
return utils.getFullyQualifiedName(typeElement) + "." + label;
} else if (isElementItem()) {
return utils.getFullyQualifiedName(element);
} else {
return label;
}
}
/**
* Returns the element associate with this item, or {@code null}.
*
* @return the element
*/
public Element getElement() {
return element;
}
/**
* Returns the category for this item, that indicates the JavaScript file
* in which this item should be written.
*
* @return the category
*/
public Category getCategory() {
return getCategory(element);
}
protected Category getCategory(DocTree docTree) {
return switch (docTree.getKind()) {
case INDEX, SYSTEM_PROPERTY -> Category.TAGS;
default -> throw new IllegalArgumentException(docTree.getKind().toString());
};
}
@SuppressWarnings("preview")
protected Category getCategory(Element element) {
return new SimpleElementVisitor14