< 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 >