1 /* 2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 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(); 185 pe = de.getPackageElement(); 186 } 187 break; 188 case PACKAGE: 189 fo = configuration.workArounds.getJavaFileObject((PackageElement)e); 190 pe = (PackageElement)e; 191 break; 192 default: 193 return null; 194 } 195 if (fo == null) { 196 return null; 197 } 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; 239 this.dcTree = dcTree; 240 } 241 } 242 }