< 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


  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /**
  27  *  A utility class.
  28  *
  29  *  <p><b>This is NOT part of any supported API.
  30  *  If you write code that depends on this, you do so at your own risk.
  31  *  This code and its internal interfaces are subject to change or
  32  *  deletion without notice.</b>
  33  */
  34 
  35 package jdk.javadoc.internal.doclets.toolkit;
  36 
  37 import java.net.URI;
  38 import java.util.ArrayList;
  39 import java.util.HashMap;
  40 import java.util.List;


  41 
  42 import javax.lang.model.element.Element;
  43 import javax.lang.model.element.ExecutableElement;
  44 import javax.lang.model.element.Name;
  45 import javax.lang.model.element.PackageElement;


  46 import javax.lang.model.element.VariableElement;
  47 import javax.lang.model.util.Elements;
  48 import javax.tools.FileObject;
  49 import javax.tools.JavaFileObject;
  50 import javax.tools.SimpleJavaFileObject;
  51 

  52 import com.sun.source.doctree.DocCommentTree;
  53 import com.sun.source.doctree.DocTree;
  54 import com.sun.source.doctree.IdentifierTree;

  55 import com.sun.source.doctree.ReferenceTree;
  56 import com.sun.source.doctree.TextTree;
  57 import com.sun.source.util.DocTreeFactory;
  58 import com.sun.source.util.DocTreePath;
  59 import com.sun.source.util.DocTrees;
  60 import com.sun.source.util.TreePath;
  61 import com.sun.tools.javac.util.DefinedBy;
  62 import com.sun.tools.javac.util.DefinedBy.Api;
  63 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
  64 
  65 public class CommentUtils {
  66 
  67     final BaseConfiguration configuration;

  68     final Resources resources;
  69     final DocTreeFactory treeFactory;
  70     final HashMap<Element, DocCommentDuo> dcTreesMap = new HashMap<>();
  71     final DocTrees trees;
  72     final Elements elementUtils;
  73 
  74     protected CommentUtils(BaseConfiguration configuration) {
  75         this.configuration = configuration;

  76         resources = configuration.getResources();
  77         trees = configuration.docEnv.getDocTrees();
  78         treeFactory = trees.getDocTreeFactory();
  79         elementUtils = configuration.docEnv.getElementUtils();
  80     }
  81 
  82     public List<? extends DocTree> makePropertyDescriptionTree(List<? extends DocTree> content) {
  83         List<DocTree> out = new ArrayList<>();
  84         Name name = elementUtils.getName("propertyDescription");
  85         out.add(treeFactory.newUnknownBlockTagTree(name, content));
  86         return out;
  87     }
  88 
  89     public List<? extends DocTree> makePropertyDescriptionTree(String content) {
  90         List<DocTree> inlist = new ArrayList<>();
  91         inlist.add(treeFactory.newCommentTree(content));
  92         List<DocTree> out = new ArrayList<>();
  93         Name name = elementUtils.getName("propertyDescription");
  94         out.add(treeFactory.newUnknownBlockTagTree(name, inlist));
  95         return out;
  96     }
  97 
  98     public List<? extends DocTree> makeFirstSentenceTree(String content) {
  99         List<DocTree> out = new ArrayList<>();
 100         out.add(treeFactory.newTextTree(content));
 101         return out;
 102     }
 103 
 104     public DocTree makeSeeTree(String sig, Element e) {
 105         List<DocTree> list = new ArrayList<>();
 106         list.add(treeFactory.newReferenceTree(sig));
 107         return treeFactory.newSeeTree(list);
 108     }
 109 
 110     public DocTree makeTextTree(String content) {
 111         TextTree text = treeFactory.newTextTree(content);
 112         return (DocTree) text;
 113     }
 114 
 115     public void setEnumValuesTree(Element e) {
 116         Utils utils = configuration.utils;
 117         String klassName = utils.getSimpleName(utils.getEnclosingTypeElement(e));
 118 

 119         List<DocTree> fullBody = new ArrayList<>();
 120         fullBody.add(treeFactory.newTextTree(resources.getText("doclet.enum_values_doc.fullbody", klassName)));
 121 
 122         List<DocTree> descriptions = new ArrayList<>();
 123         descriptions.add(treeFactory.newTextTree(resources.getText("doclet.enum_values_doc.return")));
 124 
 125         List<DocTree> tags = new ArrayList<>();
 126         tags.add(treeFactory.newReturnTree(descriptions));
 127         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
 128         dcTreesMap.put(e, new DocCommentDuo(null, docTree));
 129     }
 130 
 131     public void setEnumValueOfTree(Element e) {
 132 
 133         List<DocTree> fullBody = new ArrayList<>();
 134         fullBody.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.fullbody")));
 135 
 136         List<DocTree> tags = new ArrayList<>();
 137 
 138         List<DocTree> paramDescs = new ArrayList<>();
 139         paramDescs.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.param_name")));
 140         ExecutableElement ee = (ExecutableElement) e;
 141         java.util.List<? extends VariableElement> parameters = ee.getParameters();
 142         VariableElement param = parameters.get(0);
 143         IdentifierTree id = treeFactory.newIdentifierTree(elementUtils.getName(param.getSimpleName().toString()));
 144         tags.add(treeFactory.newParamTree(false, id, paramDescs));
 145 
 146         List<DocTree> returnDescs = new ArrayList<>();
 147         returnDescs.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.return")));
 148         tags.add(treeFactory.newReturnTree(returnDescs));
 149 
 150         List<DocTree> throwsDescs = new ArrayList<>();
 151         throwsDescs.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.throws_ila")));
 152 
 153         ReferenceTree ref = treeFactory.newReferenceTree("java.lang.IllegalArgumentException");
 154         tags.add(treeFactory.newThrowsTree(ref, throwsDescs));
 155 
 156         throwsDescs = new ArrayList<>();
 157         throwsDescs.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.throws_npe")));
 158 
 159         ref = treeFactory.newReferenceTree("java.lang.NullPointerException");
 160         tags.add(treeFactory.newThrowsTree(ref, throwsDescs));
 161 
 162         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
 163 
 164         dcTreesMap.put(e, new DocCommentDuo(null, docTree));
































































































































































































































 165     }
 166 
 167     /*
 168      * Returns the TreePath/DocCommentTree duo for synthesized element.
 169      */
 170     public DocCommentDuo getSyntheticCommentDuo(Element e) {
 171         return dcTreesMap.get(e);
 172     }
 173 
 174     /*
 175      * Returns the TreePath/DocCommentTree duo for html sources.
 176      */
 177     public DocCommentDuo getHtmlCommentDuo(Element e) {
 178         FileObject fo = null;
 179         PackageElement pe = null;
 180         switch (e.getKind()) {
 181             case OTHER:
 182                 if (e instanceof DocletElement) {
 183                     DocletElement de = (DocletElement)e;
 184                     fo = de.getFileObject();


 198 
 199         DocCommentTree dcTree = trees.getDocCommentTree(fo);
 200         if (dcTree == null) {
 201             return null;
 202         }
 203         DocTreePath treePath = trees.getDocTreePath(fo, pe);
 204         return new DocCommentDuo(treePath.getTreePath(), dcTree);
 205     }
 206 
 207     public DocCommentTree parse(URI uri, String text) {
 208         return trees.getDocCommentTree(new SimpleJavaFileObject(
 209                 uri, JavaFileObject.Kind.SOURCE) {
 210             @Override @DefinedBy(Api.COMPILER)
 211             public CharSequence getCharContent(boolean ignoreEncoding) {
 212                 return text;
 213             }
 214         });
 215     }
 216 
 217     public void setDocCommentTree(Element element, List<? extends DocTree> fullBody,
 218                                   List<? extends DocTree> blockTags, Utils utils) {
 219         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, blockTags);
 220         dcTreesMap.put(element, new DocCommentDuo(null, docTree));
 221         // A method having null comment (no comment) that might need to be replaced
 222         // with a synthetic comment, remove such a comment from the cache.
 223         utils.removeCommentHelper(element);
 224     }
 225 
 226     /**
 227      * A simplistic container to transport a TreePath, DocCommentTree pair.
 228      * Here is why we need this:
 229      * a. not desirable to add javac's pair.
 230      * b. DocTreePath is not a viable  option either, as a null TreePath is required
 231      * to represent synthetic comments for Enum.values, valuesOf, javafx properties.
 232      */
 233     public static class DocCommentDuo {
 234         public final TreePath treePath;
 235         public final DocCommentTree dcTree;
 236 
 237         public DocCommentDuo(TreePath treePath, DocCommentTree dcTree) {
 238             this.treePath = treePath;


  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /**
  27  *  A utility class.
  28  *
  29  *  <p><b>This is NOT part of any supported API.
  30  *  If you write code that depends on this, you do so at your own risk.
  31  *  This code and its internal interfaces are subject to change or
  32  *  deletion without notice.</b>
  33  */
  34 
  35 package jdk.javadoc.internal.doclets.toolkit;
  36 
  37 import java.net.URI;
  38 import java.util.ArrayList;
  39 import java.util.HashMap;
  40 import java.util.List;
  41 import java.util.regex.Matcher;
  42 import java.util.regex.Pattern;
  43 
  44 import javax.lang.model.element.Element;
  45 import javax.lang.model.element.ExecutableElement;
  46 import javax.lang.model.element.Name;
  47 import javax.lang.model.element.PackageElement;
  48 import javax.lang.model.element.RecordComponentElement;
  49 import javax.lang.model.element.TypeElement;
  50 import javax.lang.model.element.VariableElement;
  51 import javax.lang.model.util.Elements;
  52 import javax.tools.FileObject;
  53 import javax.tools.JavaFileObject;
  54 import javax.tools.SimpleJavaFileObject;
  55 
  56 import com.sun.source.doctree.AttributeTree;
  57 import com.sun.source.doctree.DocCommentTree;
  58 import com.sun.source.doctree.DocTree;
  59 import com.sun.source.doctree.IdentifierTree;
  60 import com.sun.source.doctree.ParamTree;
  61 import com.sun.source.doctree.ReferenceTree;
  62 import com.sun.source.doctree.TextTree;
  63 import com.sun.source.util.DocTreeFactory;
  64 import com.sun.source.util.DocTreePath;
  65 import com.sun.source.util.DocTrees;
  66 import com.sun.source.util.TreePath;
  67 import com.sun.tools.javac.util.DefinedBy;
  68 import com.sun.tools.javac.util.DefinedBy.Api;
  69 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
  70 
  71 public class CommentUtils {
  72 
  73     final BaseConfiguration configuration;
  74     final Utils utils;
  75     final Resources resources;
  76     final DocTreeFactory treeFactory;
  77     final HashMap<Element, DocCommentDuo> dcTreesMap = new HashMap<>();
  78     final DocTrees trees;
  79     final Elements elementUtils;
  80 
  81     protected CommentUtils(BaseConfiguration configuration) {
  82         this.configuration = configuration;
  83         utils = configuration.utils;
  84         resources = configuration.getResources();
  85         trees = configuration.docEnv.getDocTrees();
  86         treeFactory = trees.getDocTreeFactory();
  87         elementUtils = configuration.docEnv.getElementUtils();
  88     }
  89 
  90     public List<? extends DocTree> makePropertyDescriptionTree(List<? extends DocTree> content) {
  91         List<DocTree> out = new ArrayList<>();
  92         Name name = elementUtils.getName("propertyDescription");
  93         out.add(treeFactory.newUnknownBlockTagTree(name, content));
  94         return out;
  95     }
  96 
  97     public List<? extends DocTree> makePropertyDescriptionTree(String content) {
  98         List<DocTree> inlist = new ArrayList<>();
  99         inlist.add(treeFactory.newCommentTree(content));
 100         List<DocTree> out = new ArrayList<>();
 101         Name name = elementUtils.getName("propertyDescription");
 102         out.add(treeFactory.newUnknownBlockTagTree(name, inlist));
 103         return out;
 104     }
 105 
 106     public List<? extends DocTree> makeFirstSentenceTree(String content) {
 107         List<DocTree> out = new ArrayList<>();
 108         out.add(treeFactory.newTextTree(content));
 109         return out;
 110     }
 111 
 112     public DocTree makeSeeTree(String sig, Element e) {
 113         List<DocTree> list = new ArrayList<>();
 114         list.add(treeFactory.newReferenceTree(sig));
 115         return treeFactory.newSeeTree(list);
 116     }
 117 
 118     public TextTree makeTextTree(String content) {
 119         return treeFactory.newTextTree(content);

 120     }
 121 
 122     public TextTree makeTextTreeForResource(String key) {
 123         return treeFactory.newTextTree(resources.getText(key));
 124     }
 125 
 126     public void setEnumValuesTree(ExecutableElement ee) {
 127         List<DocTree> fullBody = new ArrayList<>();
 128         fullBody.add(treeFactory.newTextTree(resources.getText("doclet.enum_values_doc.fullbody")));
 129 
 130         List<DocTree> descriptions = new ArrayList<>();
 131         descriptions.add(treeFactory.newTextTree(resources.getText("doclet.enum_values_doc.return")));
 132 
 133         List<DocTree> tags = new ArrayList<>();
 134         tags.add(treeFactory.newReturnTree(descriptions));
 135         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
 136         dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
 137     }
 138 
 139     public void setEnumValueOfTree(ExecutableElement ee) {

 140         List<DocTree> fullBody = new ArrayList<>();
 141         fullBody.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.fullbody")));
 142 
 143         List<DocTree> tags = new ArrayList<>();
 144 
 145         List<DocTree> paramDescs = new ArrayList<>();
 146         paramDescs.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.param_name")));

 147         java.util.List<? extends VariableElement> parameters = ee.getParameters();
 148         VariableElement param = parameters.get(0);
 149         IdentifierTree id = treeFactory.newIdentifierTree(elementUtils.getName(param.getSimpleName().toString()));
 150         tags.add(treeFactory.newParamTree(false, id, paramDescs));
 151 
 152         List<DocTree> returnDescs = new ArrayList<>();
 153         returnDescs.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.return")));
 154         tags.add(treeFactory.newReturnTree(returnDescs));
 155 
 156         List<DocTree> throwsDescs = new ArrayList<>();
 157         throwsDescs.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.throws_ila")));
 158 
 159         ReferenceTree ref = treeFactory.newReferenceTree("java.lang.IllegalArgumentException");
 160         tags.add(treeFactory.newThrowsTree(ref, throwsDescs));
 161 
 162         throwsDescs = new ArrayList<>();
 163         throwsDescs.add(treeFactory.newTextTree(resources.getText("doclet.enum_valueof_doc.throws_npe")));
 164 
 165         ref = treeFactory.newReferenceTree("java.lang.NullPointerException");
 166         tags.add(treeFactory.newThrowsTree(ref, throwsDescs));
 167 
 168         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
 169 
 170         dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
 171     }
 172 
 173     /**
 174      * Generates the description for the canonical constructor for a record.
 175      * @param ee the constructor
 176      */
 177     public void setRecordConstructorTree(ExecutableElement ee) {
 178         TypeElement te = utils.getEnclosingTypeElement(ee);
 179 
 180         List<DocTree> fullBody =
 181                 makeDescriptionWithName("doclet.record_constructor_doc.fullbody", te.getSimpleName());
 182 
 183         List<DocTree> tags = new ArrayList<>();
 184         java.util.List<? extends VariableElement> parameters = ee.getParameters();
 185         for (VariableElement param : ee.getParameters()) {
 186             Name name = param.getSimpleName();
 187             IdentifierTree id = treeFactory.newIdentifierTree(name);
 188             tags.add(treeFactory.newParamTree(false, id,
 189                     makeDescriptionWithComponent("doclet.record_constructor_doc.param_name", te, name)));
 190         }
 191 
 192         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags);
 193         dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
 194     }
 195 
 196     /**
 197      * Generates the description for the standard {@code equals} method for a record.
 198      * @param ee the {@code equals} method
 199      */
 200     @SuppressWarnings("preview")
 201     public void setRecordEqualsTree(ExecutableElement ee) {
 202         List<DocTree> fullBody = new ArrayList<>();
 203         add(fullBody, "doclet.record_equals_doc.fullbody.head");
 204         fullBody.add(treeFactory.newTextTree(" "));
 205 
 206         List<? extends RecordComponentElement> comps = ((TypeElement) ee.getEnclosingElement()).getRecordComponents();
 207         boolean hasPrimitiveComponents =
 208                 comps.stream().anyMatch(e -> e.asType().getKind().isPrimitive());
 209         boolean hasReferenceComponents =
 210                 comps.stream().anyMatch(e -> !e.asType().getKind().isPrimitive());
 211         if (hasPrimitiveComponents && hasReferenceComponents) {
 212             add(fullBody, "doclet.record_equals_doc.fullbody.tail.both");
 213         } else if (hasPrimitiveComponents) {
 214             add(fullBody, "doclet.record_equals_doc.fullbody.tail.primitive");
 215         } else if (hasReferenceComponents) {
 216             add(fullBody, "doclet.record_equals_doc.fullbody.tail.reference");
 217         }
 218         Name paramName = ee.getParameters().get(0).getSimpleName();
 219         IdentifierTree id = treeFactory.newIdentifierTree(paramName);
 220         List<DocTree> paramDesc =
 221                 makeDescriptionWithName("doclet.record_equals_doc.param_name", paramName);
 222         DocTree paramTree = treeFactory.newParamTree(false, id, paramDesc);
 223 
 224         DocTree returnTree = treeFactory.newReturnTree(
 225                 makeDescriptionWithName("doclet.record_equals_doc.return", paramName));
 226 
 227         TreePath treePath = utils.getTreePath(ee.getEnclosingElement());
 228         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, List.of(paramTree, returnTree));
 229         dcTreesMap.put(ee, new DocCommentDuo(treePath, docTree));
 230     }
 231 
 232     private void add(List<DocTree> contents, String resourceKey) {
 233         // Special case to allow '{@link ...}' to appear in the string.
 234         // A less general case would be to detect literal use of Object.equals
 235         // A more general case would be to allow access to DocCommentParser somehow
 236         String body = resources.getText(resourceKey);
 237         Pattern p = Pattern.compile("\\{@link (\\S*)(.*)}");
 238         Matcher m = p.matcher(body);
 239         int start = 0;
 240         while (m.find(start)) {
 241             if (m.start() > start) {
 242                 contents.add(treeFactory.newTextTree(body.substring(start, m.start())));
 243             }
 244             ReferenceTree refTree = treeFactory.newReferenceTree(m.group(1));
 245             List<DocTree> descr = List.of(treeFactory.newTextTree(m.group(2).trim())) ;
 246             contents.add(treeFactory.newLinkTree(refTree, descr));
 247             start = m.end();
 248         }
 249         if (start < body.length()) {
 250             contents.add(treeFactory.newTextTree(body.substring(start)));
 251         }
 252     }
 253 
 254     /**
 255      * Generates the description for the standard {@code hashCode} method for a record.
 256      * @param ee the {@code hashCode} method
 257      */
 258     public void setRecordHashCodeTree(ExecutableElement ee) {
 259         List<DocTree> fullBody = List.of(makeTextTreeForResource("doclet.record_hashCode_doc.fullbody"));
 260 
 261         DocTree returnTree = treeFactory.newReturnTree(
 262                 List.of(makeTextTreeForResource("doclet.record_hashCode_doc.return")));
 263 
 264         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, List.of(returnTree));
 265         dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
 266     }
 267 
 268     /**
 269      * Generates the description for the standard {@code toString} method for a record.
 270      * @param ee the {@code toString} method
 271      */
 272     public void setRecordToStringTree(ExecutableElement ee) {
 273         List<DocTree> fullBody = List.of(
 274                 treeFactory.newTextTree(resources.getText("doclet.record_toString_doc.fullbody")));
 275 
 276         DocTree returnTree = treeFactory.newReturnTree(List.of(
 277                 treeFactory.newTextTree(resources.getText("doclet.record_toString_doc.return"))));
 278 
 279         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, List.of(returnTree));
 280         dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
 281     }
 282 
 283     /**
 284      * Generates the description for the accessor method for a state component of a record.
 285      * @param ee the accessor method
 286      */
 287     public void setRecordAccessorTree(ExecutableElement ee) {
 288         TypeElement te = utils.getEnclosingTypeElement(ee);
 289 
 290         List<DocTree> fullBody =
 291                 makeDescriptionWithComponent("doclet.record_accessor_doc.fullbody", te, ee.getSimpleName());
 292 
 293         DocTree returnTree = treeFactory.newReturnTree(
 294                     makeDescriptionWithComponent("doclet.record_accessor_doc.return", te, ee.getSimpleName()));
 295 
 296         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, List.of(returnTree));
 297         dcTreesMap.put(ee, new DocCommentDuo(null, docTree));
 298     }
 299 
 300     /**
 301      * Generates the description for the field for a state component of a record.
 302      * @param ve the field
 303      */
 304     public void setRecordFieldTree(VariableElement ve) {
 305         TypeElement te = utils.getEnclosingTypeElement(ve);
 306 
 307         List<DocTree> fullBody =
 308             makeDescriptionWithComponent("doclet.record_field_doc.fullbody", te, ve.getSimpleName());
 309 
 310         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, List.of());
 311         dcTreesMap.put(ve, new DocCommentDuo(null, docTree));
 312     }
 313 
 314     /**
 315      * Creates a description that contains a reference to a state component of a record.
 316      * The description is looked up as a resource, and should contain {@code {0}} where the
 317      * reference to the component is to be inserted. The reference will be a link if the
 318      * doc comment for the record has a {@code @param} tag for the component.
 319      * @param key the resource key for the description
 320      * @param elem the record element
 321      * @param component the name of the component
 322      * @return the description
 323      */
 324     private List<DocTree> makeDescriptionWithComponent(String key, TypeElement elem, Name component) {
 325         List<DocTree> result = new ArrayList<>();
 326         String text = resources.getText(key);
 327         int index = text.indexOf("{0}");
 328         result.add(treeFactory.newTextTree(text.substring(0, index)));
 329         Name A = elementUtils.getName("a");
 330         Name CODE = elementUtils.getName("code");
 331         Name HREF = elementUtils.getName("href");
 332         List<DocTree> code = List.of(
 333                 treeFactory.newStartElementTree(CODE, List.of(), false),
 334                 treeFactory.newTextTree(component.toString()),
 335                 treeFactory.newEndElementTree(CODE));
 336         if (hasParamForComponent(elem, component)) {
 337             DocTree href = treeFactory.newAttributeTree(HREF,
 338                     AttributeTree.ValueKind.DOUBLE,
 339                     List.of(treeFactory.newTextTree("#param-" + component)));
 340             result.add(treeFactory.newStartElementTree(A, List.of(href), false));
 341             result.addAll(code);
 342             result.add(treeFactory.newEndElementTree(A));
 343         } else {
 344             result.addAll(code);
 345         }
 346         result.add(treeFactory.newTextTree(text.substring(index + 3)));
 347         return result;
 348     }
 349 
 350     /**
 351      * Returns whether or not the doc comment for a record contains an {@code @param}}
 352      * for a state component of the record.
 353      * @param elem the record element
 354      * @param component the name of the component
 355      * @return whether or not there is a {@code @param}} for the component
 356      */
 357     private boolean hasParamForComponent(TypeElement elem, Name component) {
 358         DocCommentTree elemComment = utils.getDocCommentTree(elem);
 359         if (elemComment == null) {
 360             return false;
 361         }
 362 
 363         for (DocTree t : elemComment.getBlockTags()) {
 364             if (t instanceof ParamTree && ((ParamTree) t).getName().getName() == component) {
 365                 return true;
 366             }
 367         }
 368 
 369         return false;
 370     }
 371 
 372     /**
 373      * Creates a description that contains the simple name of a program element
 374      * The description is looked up as a resource, and should contain {@code {0}} where the
 375      * name is to be inserted. T
 376      * @param key the resource key for the description
 377      * @param name the name
 378      * @return the description
 379      */
 380     private List<DocTree> makeDescriptionWithName(String key, Name name) {
 381         String text = resources.getText(key);
 382         int index = text.indexOf("{0}");
 383         if (index == -1) {
 384             return List.of(treeFactory.newTextTree(text));
 385         } else {
 386             Name CODE = elementUtils.getName("code");
 387             return List.of(
 388                     treeFactory.newTextTree(text.substring(0, index)),
 389                     treeFactory.newStartElementTree(CODE, List.of(), false),
 390                     treeFactory.newTextTree(name.toString()),
 391                     treeFactory.newEndElementTree(CODE),
 392                     treeFactory.newTextTree(text.substring(index + 3))
 393             );
 394         }
 395     }
 396 
 397     /*
 398      * Returns the TreePath/DocCommentTree duo for synthesized element.
 399      */
 400     public DocCommentDuo getSyntheticCommentDuo(Element e) {
 401         return dcTreesMap.get(e);
 402     }
 403 
 404     /*
 405      * Returns the TreePath/DocCommentTree duo for html sources.
 406      */
 407     public DocCommentDuo getHtmlCommentDuo(Element e) {
 408         FileObject fo = null;
 409         PackageElement pe = null;
 410         switch (e.getKind()) {
 411             case OTHER:
 412                 if (e instanceof DocletElement) {
 413                     DocletElement de = (DocletElement)e;
 414                     fo = de.getFileObject();


 428 
 429         DocCommentTree dcTree = trees.getDocCommentTree(fo);
 430         if (dcTree == null) {
 431             return null;
 432         }
 433         DocTreePath treePath = trees.getDocTreePath(fo, pe);
 434         return new DocCommentDuo(treePath.getTreePath(), dcTree);
 435     }
 436 
 437     public DocCommentTree parse(URI uri, String text) {
 438         return trees.getDocCommentTree(new SimpleJavaFileObject(
 439                 uri, JavaFileObject.Kind.SOURCE) {
 440             @Override @DefinedBy(Api.COMPILER)
 441             public CharSequence getCharContent(boolean ignoreEncoding) {
 442                 return text;
 443             }
 444         });
 445     }
 446 
 447     public void setDocCommentTree(Element element, List<? extends DocTree> fullBody,
 448                                   List<? extends DocTree> blockTags) {
 449         DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, blockTags);
 450         dcTreesMap.put(element, new DocCommentDuo(null, docTree));
 451         // A method having null comment (no comment) that might need to be replaced
 452         // with a synthetic comment, remove such a comment from the cache.
 453         utils.removeCommentHelper(element);
 454     }
 455 
 456     /**
 457      * A simplistic container to transport a TreePath, DocCommentTree pair.
 458      * Here is why we need this:
 459      * a. not desirable to add javac's pair.
 460      * b. DocTreePath is not a viable  option either, as a null TreePath is required
 461      * to represent synthetic comments for Enum.values, valuesOf, javafx properties.
 462      */
 463     public static class DocCommentDuo {
 464         public final TreePath treePath;
 465         public final DocCommentTree dcTree;
 466 
 467         public DocCommentDuo(TreePath treePath, DocCommentTree dcTree) {
 468             this.treePath = treePath;
< prev index next >