1 /* 2 * Copyright (c) 2003, 2019, 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 package jdk.javadoc.internal.doclets.toolkit.taglets; 27 28 import java.util.EnumSet; 29 import java.util.List; 30 31 import javax.lang.model.element.Element; 32 import javax.lang.model.element.Name; 33 import javax.lang.model.element.VariableElement; 34 import javax.lang.model.type.TypeMirror; 35 36 import com.sun.source.doctree.DocTree; 37 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration; 38 import jdk.javadoc.internal.doclets.toolkit.Content; 39 import jdk.javadoc.internal.doclets.toolkit.taglets.Taglet.UnsupportedTagletOperationException; 40 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; 41 import jdk.javadoc.internal.doclets.toolkit.util.Utils; 42 43 /** 44 * The interface for the taglet writer. 45 * 46 * <p><b>This is NOT part of any supported API. 47 * If you write code that depends on this, you do so at your own risk. 48 * This code and its internal interfaces are subject to change or 49 * deletion without notice.</b> 50 * 51 * @author Jamie Ho 52 */ 53 54 public abstract class TagletWriter { 55 56 /** 57 * True if we only want to write the first sentence. 58 */ 59 protected final boolean isFirstSentence; 60 61 protected TagletWriter(boolean isFirstSentence) { 62 this.isFirstSentence = isFirstSentence; 63 } 64 65 /** 66 * @return an instance of an output object. 67 */ 68 public abstract Content getOutputInstance(); 69 70 /** 71 * Return the output for a {@code {@code ...}} tag. 72 * 73 * @param element 74 * @param tag the tag. 75 * @return the output of the taglet. 76 */ 77 protected abstract Content codeTagOutput(Element element, DocTree tag); 78 79 /** 80 * Return the output for a {@index...} tag. 81 * 82 * @param tag the tag. 83 * @return the output of the taglet. 84 */ 85 protected abstract Content indexTagOutput(Element element, DocTree tag); 86 87 /** 88 * Returns the output for the DocRoot inline tag. 89 * @return the output for the DocRoot inline tag. 90 */ 91 protected abstract Content getDocRootOutput(); 92 93 /** 94 * Return the deprecated tag output. 95 * 96 * @param element the element to write deprecated documentation for. 97 * @return the output of the deprecated tag. 98 */ 99 protected abstract Content deprecatedTagOutput(Element element); 100 101 /** 102 * Return the output for a {@code {@literal ...}} tag. 103 * 104 * @param element 105 * @param tag the tag. 106 * @return the output of the taglet. 107 */ 108 protected abstract Content literalTagOutput(Element element, DocTree tag); 109 110 /** 111 * Return the header for the param tags. 112 * 113 * @param header the header to display. 114 * @return the header for the param tags. 115 */ 116 protected abstract Content getParamHeader(String header); 117 118 /** 119 * Return the output for param tags. 120 * 121 * @param element 122 * @param paramTag the parameter to document. 123 * @param paramName the name of the parameter. 124 * @return the output of the param tag. 125 */ 126 protected abstract Content paramTagOutput(Element element, DocTree paramTag, String paramName); 127 128 /** 129 * Return the output for property tags. 130 * 131 * @param element 132 * @param propertyTag the parameter to document. 133 * @param prefix the text with which to prefix the property name. 134 * @return the output of the param tag. 135 */ 136 protected abstract Content propertyTagOutput(Element element, DocTree propertyTag, String prefix); 137 138 /** 139 * Return the return tag output. 140 * 141 * @param element 142 * @param returnTag the return tag to output. 143 * @return the output of the return tag. 144 */ 145 protected abstract Content returnTagOutput(Element element, DocTree returnTag); 146 147 /** 148 * Return the see tag output. 149 * 150 * @param holder 151 * @param seeTags the array of See tags. 152 * @return the output of the see tags. 153 */ 154 protected abstract Content seeTagOutput(Element holder, List<? extends DocTree> seeTags); 155 156 /** 157 * Return the output for a simple tag. 158 * 159 * @param element 160 * @param simpleTags the array of simple tags. 161 * @param header 162 * @return the output of the simple tags. 163 */ 164 protected abstract Content simpleTagOutput(Element element, List<? extends DocTree> simpleTags, String header); 165 166 /** 167 * Return the output for a simple tag. 168 * 169 * @param element 170 * @param simpleTag the simple tag. 171 * @param header 172 * @return the output of the simple tag. 173 */ 174 protected abstract Content simpleTagOutput(Element element, DocTree simpleTag, String header); 175 176 /** 177 * Return the system property tag output. 178 * 179 * @param element 180 * @param systemPropertyTag the system property tag 181 * @return the output of system property tag 182 */ 183 protected abstract Content systemPropertyTagOutput(Element element, DocTree systemPropertyTag); 184 185 /** 186 * Return the header for the throws tag. 187 * 188 * @return the header for the throws tag. 189 */ 190 protected abstract Content getThrowsHeader(); 191 192 /** 193 * Return the header for the throws tag. 194 * 195 * @param element 196 * @param throwsTag the throws tag. 197 * @return the output of the throws tag. 198 */ 199 protected abstract Content throwsTagOutput(Element element, DocTree throwsTag); 200 201 /** 202 * Return the output for the throws tag. 203 * 204 * @param throwsType the throws type. 205 * @return the output of the throws type. 206 */ 207 protected abstract Content throwsTagOutput(TypeMirror throwsType); 208 209 /** 210 * Return the output for the value tag. 211 * 212 * @param field the constant field that holds the value tag. 213 * @param constantVal the constant value to document. 214 * @param includeLink true if we should link the constant text to the 215 * constant field itself. 216 * @return the output of the value tag. 217 */ 218 protected abstract Content valueTagOutput(VariableElement field, 219 String constantVal, boolean includeLink); 220 221 /** 222 * Given an output object, append to it the tag documentation for 223 * the given member. 224 * 225 * @param tagletManager the manager that manages the taglets. 226 * @param element the Doc that we are print tags for. 227 * @param taglets the taglets to print. 228 * @param writer the writer that will generate the output strings. 229 * @param output the output buffer to store the output in. 230 */ 231 public static void genTagOutput(TagletManager tagletManager, Element element, 232 List<Taglet> taglets, TagletWriter writer, Content output) { 233 Utils utils = writer.configuration().utils; 234 tagletManager.checkTags(element, utils.getBlockTags(element), false); 235 tagletManager.checkTags(element, utils.getFullBody(element), true); 236 for (Taglet taglet : taglets) { 237 if (utils.isTypeElement(element) && taglet instanceof ParamTaglet) { 238 // The type parameters and state components are documented in a special 239 // section away from the tag info, so skip here. 240 continue; 241 } 242 if (taglet instanceof DeprecatedTaglet) { 243 //Deprecated information is documented "inline", not in tag info 244 //section. 245 continue; 246 } 247 if (taglet instanceof SimpleTaglet && !((SimpleTaglet) taglet).enabled) { 248 // taglet has been disabled 249 continue; 250 } 251 Content currentOutput = null; 252 try { 253 currentOutput = taglet.getTagletOutput(element, writer); 254 } catch (UnsupportedTagletOperationException utoe) { 255 //The taglet does not take a member as an argument. Let's try 256 //a single tag. 257 List<? extends DocTree> tags = utils.getBlockTags(element, taglet.getName()); 258 if (!tags.isEmpty()) { 259 currentOutput = taglet.getTagletOutput(element, tags.get(0), writer); 260 } 261 } 262 if (currentOutput != null) { 263 tagletManager.seenCustomTag(taglet.getName()); 264 output.add(currentOutput); 265 } 266 } 267 } 268 /** 269 * Given an inline tag, return its output. 270 * @param holder 271 * @param tagletManager The taglet manager for the current doclet. 272 * @param holderTag The tag this holds this inline tag. Null if there 273 * is no tag that holds it. 274 * @param inlineTag The inline tag to be documented. 275 * @param tagletWriter The taglet writer to write the output. 276 * @return The output of the inline tag. 277 */ 278 public static Content getInlineTagOutput(Element holder, TagletManager tagletManager, 279 DocTree holderTag, DocTree inlineTag, TagletWriter tagletWriter) { 280 List<Taglet> definedTags = tagletManager.getInlineTaglets(); 281 CommentHelper ch = tagletWriter.configuration().utils.getCommentHelper(holder); 282 final String inlineTagName = ch.getTagName(inlineTag); 283 //This is a custom inline tag. 284 for (Taglet definedTag : definedTags) { 285 if ((definedTag.getName()).equals(inlineTagName)) { 286 // Given a name of a seen custom tag, remove it from the 287 // set of unseen custom tags. 288 tagletManager.seenCustomTag(definedTag.getName()); 289 Content output = definedTag.getTagletOutput(holder, 290 holderTag != null && 291 definedTag.getName().equals("inheritDoc") ? 292 holderTag : inlineTag, tagletWriter); 293 return output; 294 } 295 } 296 return null; 297 } 298 299 /** 300 * Converts inline tags and text to TagOutput, expanding the 301 * inline tags along the way. Called wherever text can contain 302 * an inline tag, such as in comments or in free-form text arguments 303 * to non-inline tags. 304 * 305 * @param holderTag the tag that holds the documentation. 306 * @param tags array of text tags and inline tags (often alternating) 307 * present in the text of interest for this doc. 308 * @return the {@link Content} representing the comments. 309 */ 310 public abstract Content commentTagsToOutput(DocTree holderTag, List<? extends DocTree> tags); 311 312 /** 313 * Converts inline tags and text to TagOutput, expanding the 314 * inline tags along the way. Called wherever text can contain 315 * an inline tag, such as in comments or in free-form text arguments 316 * to non-inline tags. 317 * 318 * @param holder the element where comment resides. 319 * @param tags array of text tags and inline tags (often alternating) 320 * present in the text of interest for this doc. 321 * @return the {@link Content} representing the comments. 322 */ 323 public abstract Content commentTagsToOutput(Element holder, List<? extends DocTree> tags); 324 325 /** 326 * Converts inline tags and text to TagOutput, expanding the 327 * inline tags along the way. Called wherever text can contain 328 * an inline tag, such as in comments or in free-form text arguments 329 * to non-inline tags. 330 * 331 * @param holderTag the tag that holds the documentation. 332 * @param holder the element where comment resides. 333 * @param tags array of text tags and inline tags (often alternating) 334 * present in the text of interest for this doc. 335 * @param isFirstSentence true if this is the first sentence. 336 * @return the {@link Content} representing the comments. 337 */ 338 public abstract Content commentTagsToOutput(DocTree holderTag, 339 Element holder, List<? extends DocTree> tags, boolean isFirstSentence); 340 341 /** 342 * @return an instance of the configuration used for this doclet. 343 */ 344 public abstract BaseConfiguration configuration(); 345 }