< prev index next >
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java
Print this page
rev 58565 : records: mark record related model API as preview
*** 36,59 ****
--- 36,65 ----
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+ import java.util.regex.Matcher;
+ import java.util.regex.Pattern;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.PackageElement;
+ import javax.lang.model.element.RecordComponentElement;
+ import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.Elements;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
+ import com.sun.source.doctree.AttributeTree;
import com.sun.source.doctree.DocCommentTree;
import com.sun.source.doctree.DocTree;
import com.sun.source.doctree.IdentifierTree;
+ import com.sun.source.doctree.ParamTree;
import com.sun.source.doctree.ReferenceTree;
import com.sun.source.doctree.TextTree;
import com.sun.source.util.DocTreeFactory;
import com.sun.source.util.DocTreePath;
import com.sun.source.util.DocTrees;
*** 63,80 ****
--- 69,88 ----
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
public class CommentUtils {
final BaseConfiguration configuration;
+ final Utils utils;
final Resources resources;
final DocTreeFactory treeFactory;
final HashMap<Element, DocCommentDuo> dcTreesMap = new HashMap<>();
final DocTrees trees;
final Elements elementUtils;
protected CommentUtils(BaseConfiguration configuration) {
this.configuration = configuration;
+ utils = configuration.utils;
resources = configuration.getResources();
trees = configuration.docEnv.getDocTrees();
treeFactory = trees.getDocTreeFactory();
elementUtils = configuration.docEnv.getElementUtils();
}
*** 105,145 ****
List<DocTree> list = new ArrayList<>();
list.add(treeFactory.newReferenceTree(sig));
return treeFactory.newSeeTree(list);
}
! public DocTree makeTextTree(String content) {
! TextTree text = treeFactory.newTextTree(content);
! return (DocTree) text;
}
! public void setEnumValuesTree(Element e) {
! Utils utils = configuration.utils;
! String klassName = utils.getSimpleName(utils.getEnclosingTypeElement(e));
List<DocTree> fullBody = new ArrayList<>();
! fullBody.add(treeFactory.newTextTree(resources.getText("doclet.enum_values_doc.fullbody", klassName)));
List<DocTree> descriptions = new ArrayList<>();
descriptions.add(treeFactory.newTextTree(resources.getText("doclet.enum_values_doc.return")));
List<DocTree> tags = new ArrayList<>();
tags.add(treeFactory.newReturnTree(descriptions));
DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
! dcTreesMap.put(e, new DocCommentDuo(null, docTree));
}
! public void setEnumValueOfTree(Element e) {
!
List<DocTree> fullBody = new ArrayList<>();
fullBody.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.fullbody")));
List<DocTree> tags = new ArrayList<>();
List<DocTree> paramDescs = new ArrayList<>();
paramDescs.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.param_name")));
- ExecutableElement ee = (ExecutableElement) e;
java.util.List<? extends VariableElement> parameters = ee.getParameters();
VariableElement param = parameters.get(0);
IdentifierTree id = treeFactory.newIdentifierTree(elementUtils.getName(param.getSimpleName().toString()));
tags.add(treeFactory.newParamTree(false, id, paramDescs));
--- 113,151 ----
List<DocTree> list = new ArrayList<>();
list.add(treeFactory.newReferenceTree(sig));
return treeFactory.newSeeTree(list);
}
! public TextTree makeTextTree(String content) {
! return treeFactory.newTextTree(content);
}
! public TextTree makeTextTreeForResource(String key) {
! return treeFactory.newTextTree(resources.getText(key));
! }
+ public void setEnumValuesTree(ExecutableElement ee) {
List<DocTree> fullBody = new ArrayList<>();
! fullBody.add(treeFactory.newTextTree(resources.getText("doclet.enum_values_doc.fullbody")));
List<DocTree> descriptions = new ArrayList<>();
descriptions.add(treeFactory.newTextTree(resources.getText("doclet.enum_values_doc.return")));
List<DocTree> tags = new ArrayList<>();
tags.add(treeFactory.newReturnTree(descriptions));
DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
! dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
}
! public void setEnumValueOfTree(ExecutableElement ee) {
List<DocTree> fullBody = new ArrayList<>();
fullBody.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.fullbody")));
List<DocTree> tags = new ArrayList<>();
List<DocTree> paramDescs = new ArrayList<>();
paramDescs.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.param_name")));
java.util.List<? extends VariableElement> parameters = ee.getParameters();
VariableElement param = parameters.get(0);
IdentifierTree id = treeFactory.newIdentifierTree(elementUtils.getName(param.getSimpleName().toString()));
tags.add(treeFactory.newParamTree(false, id, paramDescs));
*** 159,169 ****
ref = treeFactory.newReferenceTree("java.lang.NullPointerException");
tags.add(treeFactory.newThrowsTree(ref, throwsDescs));
DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
! dcTreesMap.put(e, new DocCommentDuo(null, docTree));
}
/*
* Returns the TreePath/DocCommentTree duo for synthesized element.
*/
--- 165,399 ----
ref = treeFactory.newReferenceTree("java.lang.NullPointerException");
tags.add(treeFactory.newThrowsTree(ref, throwsDescs));
DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
! dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
! }
!
! /**
! * Generates the description for the canonical constructor for a record.
! * @param ee the constructor
! */
! public void setRecordConstructorTree(ExecutableElement ee) {
! TypeElement te = utils.getEnclosingTypeElement(ee);
!
! List<DocTree> fullBody =
! makeDescriptionWithName("doclet.record_constructor_doc.fullbody", te.getSimpleName());
!
! List<DocTree> tags = new ArrayList<>();
! java.util.List<? extends VariableElement> parameters = ee.getParameters();
! for (VariableElement param : ee.getParameters()) {
! Name name = param.getSimpleName();
! IdentifierTree id = treeFactory.newIdentifierTree(name);
! tags.add(treeFactory.newParamTree(false, id,
! makeDescriptionWithComponent("doclet.record_constructor_doc.param_name", te, name)));
! }
!
! DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
! dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
! }
!
! /**
! * Generates the description for the standard {@code equals} method for a record.
! * @param ee the {@code equals} method
! */
! @SuppressWarnings("preview")
! public void setRecordEqualsTree(ExecutableElement ee) {
! List<DocTree> fullBody = new ArrayList<>();
! add(fullBody, "doclet.record_equals_doc.fullbody.head");
! fullBody.add(treeFactory.newTextTree(" "));
!
! List<? extends RecordComponentElement> comps = ((TypeElement) ee.getEnclosingElement()).getRecordComponents();
! boolean hasPrimitiveComponents =
! comps.stream().anyMatch(e -> e.asType().getKind().isPrimitive());
! boolean hasReferenceComponents =
! comps.stream().anyMatch(e -> !e.asType().getKind().isPrimitive());
! if (hasPrimitiveComponents && hasReferenceComponents) {
! add(fullBody, "doclet.record_equals_doc.fullbody.tail.both");
! } else if (hasPrimitiveComponents) {
! add(fullBody, "doclet.record_equals_doc.fullbody.tail.primitive");
! } else if (hasReferenceComponents) {
! add(fullBody, "doclet.record_equals_doc.fullbody.tail.reference");
! }
! Name paramName = ee.getParameters().get(0).getSimpleName();
! IdentifierTree id = treeFactory.newIdentifierTree(paramName);
! List<DocTree> paramDesc =
! makeDescriptionWithName("doclet.record_equals_doc.param_name", paramName);
! DocTree paramTree = treeFactory.newParamTree(false, id, paramDesc);
!
! DocTree returnTree = treeFactory.newReturnTree(
! makeDescriptionWithName("doclet.record_equals_doc.return", paramName));
!
! TreePath treePath = utils.getTreePath(ee.getEnclosingElement());
! DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, List.of(paramTree, returnTree));
! dcTreesMap.put(ee, new DocCommentDuo(treePath, docTree));
! }
!
! private void add(List<DocTree> contents, String resourceKey) {
! // Special case to allow '{@link ...}' to appear in the string.
! // A less general case would be to detect literal use of Object.equals
! // A more general case would be to allow access to DocCommentParser somehow
! String body = resources.getText(resourceKey);
! Pattern p = Pattern.compile("\\{@link (\\S*)(.*)}");
! Matcher m = p.matcher(body);
! int start = 0;
! while (m.find(start)) {
! if (m.start() > start) {
! contents.add(treeFactory.newTextTree(body.substring(start, m.start())));
! }
! ReferenceTree refTree = treeFactory.newReferenceTree(m.group(1));
! List<DocTree> descr = List.of(treeFactory.newTextTree(m.group(2).trim())) ;
! contents.add(treeFactory.newLinkTree(refTree, descr));
! start = m.end();
! }
! if (start < body.length()) {
! contents.add(treeFactory.newTextTree(body.substring(start)));
! }
! }
!
! /**
! * Generates the description for the standard {@code hashCode} method for a record.
! * @param ee the {@code hashCode} method
! */
! public void setRecordHashCodeTree(ExecutableElement ee) {
! List<DocTree> fullBody = List.of(makeTextTreeForResource("doclet.record_hashCode_doc.fullbody"));
!
! DocTree returnTree = treeFactory.newReturnTree(
! List.of(makeTextTreeForResource("doclet.record_hashCode_doc.return")));
!
! DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, List.of(returnTree));
! dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
! }
!
! /**
! * Generates the description for the standard {@code toString} method for a record.
! * @param ee the {@code toString} method
! */
! public void setRecordToStringTree(ExecutableElement ee) {
! List<DocTree> fullBody = List.of(
! treeFactory.newTextTree(resources.getText("doclet.record_toString_doc.fullbody")));
!
! DocTree returnTree = treeFactory.newReturnTree(List.of(
! treeFactory.newTextTree(resources.getText("doclet.record_toString_doc.return"))));
!
! DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, List.of(returnTree));
! dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
! }
!
! /**
! * Generates the description for the accessor method for a state component of a record.
! * @param ee the accessor method
! */
! public void setRecordAccessorTree(ExecutableElement ee) {
! TypeElement te = utils.getEnclosingTypeElement(ee);
!
! List<DocTree> fullBody =
! makeDescriptionWithComponent("doclet.record_accessor_doc.fullbody", te, ee.getSimpleName());
!
! DocTree returnTree = treeFactory.newReturnTree(
! makeDescriptionWithComponent("doclet.record_accessor_doc.return", te, ee.getSimpleName()));
!
! DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, List.of(returnTree));
! dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
! }
!
! /**
! * Generates the description for the field for a state component of a record.
! * @param ve the field
! */
! public void setRecordFieldTree(VariableElement ve) {
! TypeElement te = utils.getEnclosingTypeElement(ve);
!
! List<DocTree> fullBody =
! makeDescriptionWithComponent("doclet.record_field_doc.fullbody", te, ve.getSimpleName());
!
! DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, List.of());
! dcTreesMap.put(ve, new DocCommentDuo(null, docTree));
! }
!
! /**
! * Creates a description that contains a reference to a state component of a record.
! * The description is looked up as a resource, and should contain {@code {0}} where the
! * reference to the component is to be inserted. The reference will be a link if the
! * doc comment for the record has a {@code @param} tag for the component.
! * @param key the resource key for the description
! * @param elem the record element
! * @param component the name of the component
! * @return the description
! */
! private List<DocTree> makeDescriptionWithComponent(String key, TypeElement elem, Name component) {
! List<DocTree> result = new ArrayList<>();
! String text = resources.getText(key);
! int index = text.indexOf("{0}");
! result.add(treeFactory.newTextTree(text.substring(0, index)));
! Name A = elementUtils.getName("a");
! Name CODE = elementUtils.getName("code");
! Name HREF = elementUtils.getName("href");
! List<DocTree> code = List.of(
! treeFactory.newStartElementTree(CODE, List.of(), false),
! treeFactory.newTextTree(component.toString()),
! treeFactory.newEndElementTree(CODE));
! if (hasParamForComponent(elem, component)) {
! DocTree href = treeFactory.newAttributeTree(HREF,
! AttributeTree.ValueKind.DOUBLE,
! List.of(treeFactory.newTextTree("#param-" + component)));
! result.add(treeFactory.newStartElementTree(A, List.of(href), false));
! result.addAll(code);
! result.add(treeFactory.newEndElementTree(A));
! } else {
! result.addAll(code);
! }
! result.add(treeFactory.newTextTree(text.substring(index + 3)));
! return result;
! }
!
! /**
! * Returns whether or not the doc comment for a record contains an {@code @param}}
! * for a state component of the record.
! * @param elem the record element
! * @param component the name of the component
! * @return whether or not there is a {@code @param}} for the component
! */
! private boolean hasParamForComponent(TypeElement elem, Name component) {
! DocCommentTree elemComment = utils.getDocCommentTree(elem);
! if (elemComment == null) {
! return false;
! }
!
! for (DocTree t : elemComment.getBlockTags()) {
! if (t instanceof ParamTree && ((ParamTree) t).getName().getName() == component) {
! return true;
! }
! }
!
! return false;
! }
!
! /**
! * Creates a description that contains the simple name of a program element
! * The description is looked up as a resource, and should contain {@code {0}} where the
! * name is to be inserted. T
! * @param key the resource key for the description
! * @param name the name
! * @return the description
! */
! private List<DocTree> makeDescriptionWithName(String key, Name name) {
! String text = resources.getText(key);
! int index = text.indexOf("{0}");
! if (index == -1) {
! return List.of(treeFactory.newTextTree(text));
! } else {
! Name CODE = elementUtils.getName("code");
! return List.of(
! treeFactory.newTextTree(text.substring(0, index)),
! treeFactory.newStartElementTree(CODE, List.of(), false),
! treeFactory.newTextTree(name.toString()),
! treeFactory.newEndElementTree(CODE),
! treeFactory.newTextTree(text.substring(index + 3))
! );
! }
}
/*
* Returns the TreePath/DocCommentTree duo for synthesized element.
*/
*** 213,223 ****
}
});
}
public void setDocCommentTree(Element element, List<? extends DocTree> fullBody,
! List<? extends DocTree> blockTags, Utils utils) {
DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, blockTags);
dcTreesMap.put(element, new DocCommentDuo(null, docTree));
// A method having null comment (no comment) that might need to be replaced
// with a synthetic comment, remove such a comment from the cache.
utils.removeCommentHelper(element);
--- 443,453 ----
}
});
}
public void setDocCommentTree(Element element, List<? extends DocTree> fullBody,
! List<? extends DocTree> blockTags) {
DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, blockTags);
dcTreesMap.put(element, new DocCommentDuo(null, docTree));
// A method having null comment (no comment) that might need to be replaced
// with a synthetic comment, remove such a comment from the cache.
utils.removeCommentHelper(element);
< prev index next >