1 /* 2 * Copyright (c) 1997, 2015, 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 com.sun.tools.doclets.formats.html; 27 28 import java.io.*; 29 30 import com.sun.javadoc.*; 31 import com.sun.tools.doclets.formats.html.markup.*; 32 import com.sun.tools.doclets.internal.toolkit.*; 33 import com.sun.tools.doclets.internal.toolkit.util.*; 34 import com.sun.tools.javac.util.StringUtils; 35 36 /** 37 * Writes method documentation in HTML format. 38 * 39 * <p><b>This is NOT part of any supported API. 40 * If you write code that depends on this, you do so at your own risk. 41 * This code and its internal interfaces are subject to change or 42 * deletion without notice.</b> 43 * 44 * @author Robert Field 45 * @author Atul M Dambalkar 46 * @author Jamie Ho (rewrite) 47 * @author Bhavesh Patel (Modified) 48 */ 49 public class MethodWriterImpl extends AbstractExecutableMemberWriter 50 implements MethodWriter, MemberSummaryWriter { 51 52 /** 53 * Construct a new MethodWriterImpl. 54 * 55 * @param writer the writer for the class that the methods belong to. 56 * @param classDoc the class being documented. 57 */ 58 public MethodWriterImpl(SubWriterHolderWriter writer, ClassDoc classDoc) { 59 super(writer, classDoc); 60 } 61 62 /** 63 * Construct a new MethodWriterImpl. 64 * 65 * @param writer The writer for the class that the methods belong to. 66 */ 67 public MethodWriterImpl(SubWriterHolderWriter writer) { 68 super(writer); 69 } 70 71 /** 72 * {@inheritDoc} 73 */ 74 public Content getMemberSummaryHeader(ClassDoc classDoc, 75 Content memberSummaryTree) { 76 memberSummaryTree.addContent(HtmlConstants.START_OF_METHOD_SUMMARY); 77 Content memberTree = writer.getMemberTreeHeader(); 78 writer.addSummaryHeader(this, classDoc, memberTree); 79 return memberTree; 80 } 81 82 /** 83 * {@inheritDoc} 84 */ 85 public void addMemberTree(Content memberSummaryTree, Content memberTree) { 86 writer.addMemberTree(memberSummaryTree, memberTree); 87 } 88 89 /** 90 * {@inheritDoc} 91 */ 92 public Content getMethodDetailsTreeHeader(ClassDoc classDoc, 93 Content memberDetailsTree) { 94 memberDetailsTree.addContent(HtmlConstants.START_OF_METHOD_DETAILS); 95 Content methodDetailsTree = writer.getMemberTreeHeader(); 96 methodDetailsTree.addContent(writer.getMarkerAnchor( 97 SectionName.METHOD_DETAIL)); 98 Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, 99 writer.methodDetailsLabel); 100 methodDetailsTree.addContent(heading); 101 return methodDetailsTree; 102 } 103 104 /** 105 * {@inheritDoc} 106 */ 107 public Content getMethodDocTreeHeader(MethodDoc method, 108 Content methodDetailsTree) { 109 String erasureAnchor; 110 if ((erasureAnchor = getErasureAnchor(method)) != null) { 111 methodDetailsTree.addContent(writer.getMarkerAnchor((erasureAnchor))); 112 } 113 methodDetailsTree.addContent( 114 writer.getMarkerAnchor(writer.getAnchor(method))); 115 Content methodDocTree = writer.getMemberTreeHeader(); 116 Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); 117 heading.addContent(method.name()); 118 methodDocTree.addContent(heading); 119 return methodDocTree; 120 } 121 122 /** 123 * Get the signature for the given method. 124 * 125 * @param method the method being documented. 126 * @return a content object for the signature 127 */ 128 public Content getSignature(MethodDoc method) { 129 Content pre = new HtmlTree(HtmlTag.PRE); 130 writer.addAnnotationInfo(method, pre); 131 int annotationLength = pre.charCount(); 132 addModifiers(method, pre); 133 addTypeParameters(method, pre); 134 addReturnType(method, pre); 135 if (configuration.linksource) { 136 Content methodName = new StringContent(method.name()); 137 writer.addSrcLink(method, methodName, pre); 138 } else { 139 addName(method.name(), pre); 140 } 141 int indent = pre.charCount() - annotationLength; 142 addParameters(method, pre, indent); 143 addExceptions(method, pre, indent); 144 return pre; 145 } 146 147 /** 148 * {@inheritDoc} 149 */ 150 public void addDeprecated(MethodDoc method, Content methodDocTree) { 151 addDeprecatedInfo(method, methodDocTree); 152 } 153 154 /** 155 * {@inheritDoc} 156 */ 157 public void addComments(Type holder, MethodDoc method, Content methodDocTree) { 158 ClassDoc holderClassDoc = holder.asClassDoc(); 159 if (method.inlineTags().length > 0) { 160 if (holder.asClassDoc().equals(classdoc) || 161 (! (holderClassDoc.isPublic() || 162 utils.isLinkable(holderClassDoc, configuration)))) { 163 writer.addInlineComment(method, methodDocTree); 164 } else { 165 Content link = 166 writer.getDocLink(LinkInfoImpl.Kind.METHOD_DOC_COPY, 167 holder.asClassDoc(), method, 168 holder.asClassDoc().isIncluded() ? 169 holder.typeName() : holder.qualifiedTypeName(), 170 false); 171 Content codelLink = HtmlTree.CODE(link); 172 Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel, holder.asClassDoc().isClass()? 173 writer.descfrmClassLabel : writer.descfrmInterfaceLabel); 174 descfrmLabel.addContent(writer.getSpace()); 175 descfrmLabel.addContent(codelLink); 176 methodDocTree.addContent(HtmlTree.DIV(HtmlStyle.block, descfrmLabel)); 177 writer.addInlineComment(method, methodDocTree); 178 } 179 } 180 } 181 182 /** 183 * {@inheritDoc} 184 */ 185 public void addTags(MethodDoc method, Content methodDocTree) { 186 writer.addTagsInfo(method, methodDocTree); 187 } 188 189 /** 190 * {@inheritDoc} 191 */ 192 public Content getMethodDetails(Content methodDetailsTree) { 193 if (configuration.allowTag(HtmlTag.SECTION)) { 194 HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(methodDetailsTree)); 195 return htmlTree; 196 } 197 return getMemberTree(methodDetailsTree); 198 } 199 200 /** 201 * {@inheritDoc} 202 */ 203 public Content getMethodDoc(Content methodDocTree, 204 boolean isLastContent) { 205 return getMemberTree(methodDocTree, isLastContent); 206 } 207 208 /** 209 * Close the writer. 210 */ 211 public void close() throws IOException { 212 writer.close(); 213 } 214 215 public int getMemberKind() { 216 return VisibleMemberMap.METHODS; 217 } 218 219 /** 220 * {@inheritDoc} 221 */ 222 public void addSummaryLabel(Content memberTree) { 223 Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, 224 writer.getResource("doclet.Method_Summary")); 225 memberTree.addContent(label); 226 } 227 228 /** 229 * {@inheritDoc} 230 */ 231 public String getTableSummary() { 232 return configuration.getText("doclet.Member_Table_Summary", 233 configuration.getText("doclet.Method_Summary"), 234 configuration.getText("doclet.methods")); 235 } 236 237 /** 238 * {@inheritDoc} 239 */ 240 public Content getCaption() { 241 return configuration.getResource("doclet.Methods"); 242 } 243 244 /** 245 * {@inheritDoc} 246 */ 247 public String[] getSummaryTableHeader(ProgramElementDoc member) { 248 String[] header = new String[] { 249 writer.getModifierTypeHeader(), 250 configuration.getText("doclet.0_and_1", 251 configuration.getText("doclet.Method"), 252 configuration.getText("doclet.Description")) 253 }; 254 return header; 255 } 256 257 /** 258 * {@inheritDoc} 259 */ 260 public void addSummaryAnchor(ClassDoc cd, Content memberTree) { 261 memberTree.addContent(writer.getMarkerAnchor( 262 SectionName.METHOD_SUMMARY)); 263 } 264 265 /** 266 * {@inheritDoc} 267 */ 268 public void addInheritedSummaryAnchor(ClassDoc cd, Content inheritedTree) { 269 inheritedTree.addContent(writer.getMarkerAnchor( 270 SectionName.METHODS_INHERITANCE, configuration.getClassName(cd))); 271 } 272 273 /** 274 * {@inheritDoc} 275 */ 276 public void addInheritedSummaryLabel(ClassDoc cd, Content inheritedTree) { 277 Content classLink = writer.getPreQualifiedClassLink( 278 LinkInfoImpl.Kind.MEMBER, cd, false); 279 Content label = new StringContent(cd.isClass() ? 280 configuration.getText("doclet.Methods_Inherited_From_Class") : 281 configuration.getText("doclet.Methods_Inherited_From_Interface")); 282 Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING, 283 label); 284 labelHeading.addContent(writer.getSpace()); 285 labelHeading.addContent(classLink); 286 inheritedTree.addContent(labelHeading); 287 } 288 289 /** 290 * {@inheritDoc} 291 */ 292 protected void addSummaryType(ProgramElementDoc member, Content tdSummaryType) { 293 MethodDoc meth = (MethodDoc)member; 294 addModifierAndType(meth, meth.returnType(), tdSummaryType); 295 } 296 297 /** 298 * {@inheritDoc} 299 */ 300 protected static void addOverridden(HtmlDocletWriter writer, 301 Type overriddenType, MethodDoc method, Content dl) { 302 if (writer.configuration.nocomment) { 303 return; 304 } 305 ClassDoc holderClassDoc = overriddenType.asClassDoc(); 306 if (! (holderClassDoc.isPublic() || 307 writer.configuration.utils.isLinkable(holderClassDoc, writer.configuration))) { 308 //This is an implementation detail that should not be documented. 309 return; 310 } 311 if (overriddenType.asClassDoc().isIncluded() && ! method.isIncluded()) { 312 //The class is included but the method is not. That means that it 313 //is not visible so don't document this. 314 return; 315 } 316 Content label = writer.overridesLabel; 317 LinkInfoImpl.Kind context = LinkInfoImpl.Kind.METHOD_OVERRIDES; 318 319 if (method != null) { 320 if (overriddenType.asClassDoc().isAbstract() && method.isAbstract()){ 321 //Abstract method is implemented from abstract class, 322 //not overridden 323 label = writer.specifiedByLabel; 324 context = LinkInfoImpl.Kind.METHOD_SPECIFIED_BY; 325 } 326 Content dt = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.overrideSpecifyLabel, label)); 327 dl.addContent(dt); 328 Content overriddenTypeLink = 329 writer.getLink(new LinkInfoImpl(writer.configuration, context, overriddenType)); 330 Content codeOverridenTypeLink = HtmlTree.CODE(overriddenTypeLink); 331 String name = method.name(); 332 Content methlink = writer.getLink( 333 new LinkInfoImpl(writer.configuration, LinkInfoImpl.Kind.MEMBER, 334 overriddenType.asClassDoc()) 335 .where(writer.getName(writer.getAnchor(method))).label(name)); 336 Content codeMethLink = HtmlTree.CODE(methlink); 337 Content dd = HtmlTree.DD(codeMethLink); 338 dd.addContent(writer.getSpace()); 339 dd.addContent(writer.getResource("doclet.in_class")); 340 dd.addContent(writer.getSpace()); 341 dd.addContent(codeOverridenTypeLink); 342 dl.addContent(dd); 343 } 344 } 345 346 /** 347 * {@inheritDoc} 348 */ 349 protected static void addImplementsInfo(HtmlDocletWriter writer, 350 MethodDoc method, Content dl) { 351 if(writer.configuration.nocomment){ 352 return; 353 } 354 ImplementedMethods implementedMethodsFinder = 355 new ImplementedMethods(method, writer.configuration); 356 MethodDoc[] implementedMethods = implementedMethodsFinder.build(); 357 for (MethodDoc implementedMeth : implementedMethods) { 358 Type intfac = implementedMethodsFinder.getMethodHolder(implementedMeth); 359 Content intfaclink = writer.getLink(new LinkInfoImpl( 360 writer.configuration, LinkInfoImpl.Kind.METHOD_SPECIFIED_BY, intfac)); 361 Content codeIntfacLink = HtmlTree.CODE(intfaclink); 362 Content dt = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.overrideSpecifyLabel, writer.specifiedByLabel)); 363 dl.addContent(dt); 364 Content methlink = writer.getDocLink( 365 LinkInfoImpl.Kind.MEMBER, implementedMeth, 366 implementedMeth.name(), false); 367 Content codeMethLink = HtmlTree.CODE(methlink); 368 Content dd = HtmlTree.DD(codeMethLink); 369 dd.addContent(writer.getSpace()); 370 dd.addContent(writer.getResource("doclet.in_interface")); 371 dd.addContent(writer.getSpace()); 372 dd.addContent(codeIntfacLink); 373 dl.addContent(dd); 374 } 375 } 376 377 /** 378 * Add the return type. 379 * 380 * @param method the method being documented. 381 * @param htmltree the content tree to which the return type will be added 382 */ 383 protected void addReturnType(MethodDoc method, Content htmltree) { 384 Type type = method.returnType(); 385 if (type != null) { 386 Content linkContent = writer.getLink( 387 new LinkInfoImpl(configuration, LinkInfoImpl.Kind.RETURN_TYPE, type)); 388 htmltree.addContent(linkContent); 389 htmltree.addContent(writer.getSpace()); 390 } 391 } 392 393 /** 394 * {@inheritDoc} 395 */ 396 protected Content getNavSummaryLink(ClassDoc cd, boolean link) { 397 if (link) { 398 if (cd == null) { 399 return writer.getHyperLink( 400 SectionName.METHOD_SUMMARY, 401 writer.getResource("doclet.navMethod")); 402 } else { 403 return writer.getHyperLink( 404 SectionName.METHODS_INHERITANCE, 405 configuration.getClassName(cd), writer.getResource("doclet.navMethod")); 406 } 407 } else { 408 return writer.getResource("doclet.navMethod"); 409 } 410 } 411 412 /** 413 * {@inheritDoc} 414 */ 415 protected void addNavDetailLink(boolean link, Content liNav) { 416 if (link) { 417 liNav.addContent(writer.getHyperLink( 418 SectionName.METHOD_DETAIL, writer.getResource("doclet.navMethod"))); 419 } else { 420 liNav.addContent(writer.getResource("doclet.navMethod")); 421 } 422 } 423 }