1 /* 2 * Copyright (c) 1997, 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.formats.html; 27 28 import java.util.List; 29 30 import javax.lang.model.element.AnnotationMirror; 31 import javax.lang.model.element.Element; 32 import javax.lang.model.element.ElementKind; 33 import javax.lang.model.element.ExecutableElement; 34 import javax.lang.model.element.TypeElement; 35 import javax.lang.model.element.VariableElement; 36 import javax.lang.model.type.ArrayType; 37 import javax.lang.model.type.DeclaredType; 38 import javax.lang.model.type.TypeMirror; 39 import javax.lang.model.type.TypeVariable; 40 import javax.lang.model.util.SimpleTypeVisitor9; 41 42 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; 43 import jdk.javadoc.internal.doclets.formats.html.markup.Entity; 44 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; 45 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; 46 import jdk.javadoc.internal.doclets.toolkit.Content; 47 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; 48 49 import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.EXECUTABLE_MEMBER_PARAM; 50 import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER; 51 import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER_TYPE_PARAMS; 52 import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.RECEIVER_TYPE; 53 54 /** 55 * Print method and constructor info. 56 * 57 * <p><b>This is NOT part of any supported API. 58 * If you write code that depends on this, you do so at your own risk. 59 * This code and its internal interfaces are subject to change or 60 * deletion without notice.</b> 61 * 62 * @author Robert Field 63 * @author Atul M Dambalkar 64 * @author Bhavesh Patel (Modified) 65 */ 66 public abstract class AbstractExecutableMemberWriter extends AbstractMemberWriter { 67 68 public AbstractExecutableMemberWriter(SubWriterHolderWriter writer, TypeElement typeElement) { 69 super(writer, typeElement); 70 } 71 72 public AbstractExecutableMemberWriter(SubWriterHolderWriter writer) { 73 super(writer); 74 } 75 76 /** 77 * Add the type parameters for the executable member. 78 * 79 * @param member the member to write type parameters for. 80 * @param htmltree the content tree to which the parameters will be added. 81 */ 82 protected void addTypeParameters(ExecutableElement member, Content htmltree) { 83 Content typeParameters = getTypeParameters(member); 84 if (!typeParameters.isEmpty()) { 85 htmltree.add(typeParameters); 86 htmltree.add(Entity.NO_BREAK_SPACE); 87 } 88 } 89 90 /** 91 * Get the type parameters for the executable member. 92 * 93 * @param member the member for which to get the type parameters. 94 * @return the type parameters. 95 */ 96 protected Content getTypeParameters(ExecutableElement member) { 97 LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, MEMBER_TYPE_PARAMS, member); 98 return writer.getTypeParameterLinks(linkInfo); 99 } 100 101 /** 102 * {@inheritDoc} 103 */ 104 @Override 105 protected Content getDeprecatedLink(Element member) { 106 Content deprecatedLinkContent = new ContentBuilder(); 107 deprecatedLinkContent.add(utils.getFullyQualifiedName(member)); 108 if (!utils.isConstructor(member)) { 109 deprecatedLinkContent.add("."); 110 deprecatedLinkContent.add(member.getSimpleName()); 111 } 112 String signature = utils.flatSignature((ExecutableElement) member); 113 if (signature.length() > 2) { 114 deprecatedLinkContent.add(Entity.ZERO_WIDTH_SPACE); 115 } 116 deprecatedLinkContent.add(signature); 117 118 return writer.getDocLink(MEMBER, utils.getEnclosingTypeElement(member), member, deprecatedLinkContent); 119 } 120 121 /** 122 * Add the summary link for the member. 123 * 124 * @param context the id of the context where the link will be printed 125 * @param te the type element being linked to 126 * @param member the member being linked to 127 * @param tdSummary the content tree to which the link will be added 128 */ 129 @Override 130 protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement te, Element member, 131 Content tdSummary) { 132 ExecutableElement ee = (ExecutableElement)member; 133 Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink, 134 writer.getDocLink(context, te, ee, 135 name(ee), false)); 136 Content code = HtmlTree.CODE(memberLink); 137 addParameters(ee, false, code, name(ee).length() - 1); 138 tdSummary.add(code); 139 } 140 141 /** 142 * Add the inherited summary link for the member. 143 * 144 * @param te the type element that we should link to 145 * @param member the member being linked to 146 * @param linksTree the content tree to which the link will be added 147 */ 148 @Override 149 protected void addInheritedSummaryLink(TypeElement te, Element member, Content linksTree) { 150 linksTree.add(writer.getDocLink(MEMBER, te, member, name(member), false)); 151 } 152 153 /** 154 * Add the parameter for the executable member. 155 * 156 * @param member the member to write parameter for. 157 * @param param the parameter that needs to be written. 158 * @param isVarArg true if this is a link to var arg. 159 * @param tree the content tree to which the parameter information will be added. 160 */ 161 protected void addParam(ExecutableElement member, VariableElement param, 162 boolean isVarArg, Content tree) { 163 Content link = writer.getLink(new LinkInfoImpl(configuration, EXECUTABLE_MEMBER_PARAM, 164 param.asType()).varargs(isVarArg)); 165 tree.add(link); 166 if(name(param).length() > 0) { 167 tree.add(Entity.NO_BREAK_SPACE); 168 tree.add(name(param)); 169 } 170 } 171 172 /** 173 * Add the receiver annotations information. 174 * 175 * @param member the member to write receiver annotations for. 176 * @param rcvrType the receiver type. 177 * @param descList list of annotation description. 178 * @param tree the content tree to which the information will be added. 179 */ 180 protected void addReceiverAnnotations(ExecutableElement member, TypeMirror rcvrType, 181 List<? extends AnnotationMirror> annotationMirrors, Content tree) { 182 writer.addReceiverAnnotationInfo(member, rcvrType, annotationMirrors, tree); 183 tree.add(Entity.NO_BREAK_SPACE); 184 tree.add(utils.getTypeName(rcvrType, false)); 185 LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, RECEIVER_TYPE, rcvrType); 186 tree.add(writer.getTypeParameterLinks(linkInfo)); 187 tree.add(Entity.NO_BREAK_SPACE); 188 tree.add("this"); 189 } 190 191 192 /** 193 * Add all the parameters for the executable member. 194 * 195 * @param member the member to write parameters for. 196 * @param htmltree the content tree to which the parameters information will be added. 197 */ 198 protected void addParameters(ExecutableElement member, Content htmltree, int indentSize) { 199 addParameters(member, true, htmltree, indentSize); 200 } 201 202 /** 203 * Add all the parameters for the executable member. 204 * 205 * @param member the member to write parameters for. 206 * @param includeAnnotations true if annotation information needs to be added. 207 * @param htmltree the content tree to which the parameters information will be added. 208 */ 209 protected void addParameters(ExecutableElement member, 210 boolean includeAnnotations, Content htmltree, int indentSize) { 211 Content paramTree = new ContentBuilder(); 212 String sep = ""; 213 List<? extends VariableElement> parameters = member.getParameters(); 214 CharSequence indent = makeSpace(indentSize + 1); 215 TypeMirror rcvrType = member.getReceiverType(); 216 if (includeAnnotations && rcvrType != null && utils.isAnnotated(rcvrType)) { 217 List<? extends AnnotationMirror> annotationMirrors = rcvrType.getAnnotationMirrors(); 218 addReceiverAnnotations(member, rcvrType, annotationMirrors, paramTree); 219 sep = "," + DocletConstants.NL + indent; 220 } 221 int paramstart; 222 for (paramstart = 0; paramstart < parameters.size(); paramstart++) { 223 paramTree.add(sep); 224 VariableElement param = parameters.get(paramstart); 225 226 if (param.getKind() != ElementKind.INSTANCE_INIT) { 227 if (includeAnnotations) { 228 boolean foundAnnotations = 229 writer.addAnnotationInfo(indent.length(), 230 member, param, paramTree); 231 if (foundAnnotations) { 232 paramTree.add(DocletConstants.NL); 233 paramTree.add(indent); 234 } 235 } 236 addParam(member, param, 237 (paramstart == parameters.size() - 1) && member.isVarArgs(), paramTree); 238 break; 239 } 240 } 241 242 for (int i = paramstart + 1; i < parameters.size(); i++) { 243 paramTree.add(","); 244 paramTree.add(DocletConstants.NL); 245 paramTree.add(indent); 246 if (includeAnnotations) { 247 boolean foundAnnotations = 248 writer.addAnnotationInfo(indent.length(), member, parameters.get(i), 249 paramTree); 250 if (foundAnnotations) { 251 paramTree.add(DocletConstants.NL); 252 paramTree.add(indent); 253 } 254 } 255 addParam(member, parameters.get(i), (i == parameters.size() - 1) && member.isVarArgs(), 256 paramTree); 257 } 258 if (paramTree.isEmpty()) { 259 htmltree.add("()"); 260 } else { 261 htmltree.add(Entity.ZERO_WIDTH_SPACE); 262 htmltree.add("("); 263 htmltree.add(paramTree); 264 paramTree.add(")"); 265 } 266 } 267 268 /** 269 * Add exceptions for the executable member. 270 * 271 * @param member the member to write exceptions for. 272 * @param htmltree the content tree to which the exceptions information will be added. 273 */ 274 protected void addExceptions(ExecutableElement member, Content htmltree, int indentSize) { 275 List<? extends TypeMirror> exceptions = member.getThrownTypes(); 276 if (!exceptions.isEmpty()) { 277 CharSequence indent = makeSpace(indentSize + 1 - 7); 278 htmltree.add(DocletConstants.NL); 279 htmltree.add(indent); 280 htmltree.add("throws "); 281 indent = makeSpace(indentSize + 1); 282 Content link = writer.getLink(new LinkInfoImpl(configuration, MEMBER, exceptions.get(0))); 283 htmltree.add(link); 284 for(int i = 1; i < exceptions.size(); i++) { 285 htmltree.add(","); 286 htmltree.add(DocletConstants.NL); 287 htmltree.add(indent); 288 Content exceptionLink = writer.getLink(new LinkInfoImpl(configuration, MEMBER, 289 exceptions.get(i))); 290 htmltree.add(exceptionLink); 291 } 292 } 293 } 294 295 protected TypeElement implementsMethodInIntfac(ExecutableElement method, 296 List<TypeElement> intfacs) { 297 for (TypeElement intf : intfacs) { 298 List<ExecutableElement> methods = utils.getMethods(intf); 299 if (!methods.isEmpty()) { 300 for (ExecutableElement md : methods) { 301 if (name(md).equals(name(method)) && 302 md.toString().equals(method.toString())) { 303 return intf; 304 } 305 } 306 } 307 } 308 return null; 309 } 310 311 /** 312 * For backward compatibility, include an anchor using the erasures of the 313 * parameters. NOTE: We won't need this method anymore after we fix 314 * see tags so that they use the type instead of the erasure. 315 * 316 * @param executableElement the ExecutableElement to anchor to. 317 * @return the 1.4.x style anchor for the executable element. 318 */ 319 protected String getErasureAnchor(ExecutableElement executableElement) { 320 final StringBuilder buf = new StringBuilder(writer.anchorName(executableElement)); 321 buf.append("("); 322 List<? extends VariableElement> parameters = executableElement.getParameters(); 323 boolean foundTypeVariable = false; 324 for (int i = 0; i < parameters.size(); i++) { 325 if (i > 0) { 326 buf.append(","); 327 } 328 TypeMirror t = parameters.get(i).asType(); 329 SimpleTypeVisitor9<Boolean, Void> stv = new SimpleTypeVisitor9<Boolean, Void>() { 330 boolean foundTypeVariable = false; 331 332 @Override 333 public Boolean visitArray(ArrayType t, Void p) { 334 visit(t.getComponentType()); 335 buf.append(utils.getDimension(t)); 336 return foundTypeVariable; 337 } 338 339 @Override 340 public Boolean visitTypeVariable(TypeVariable t, Void p) { 341 buf.append(utils.asTypeElement(t).getQualifiedName()); 342 foundTypeVariable = true; 343 return foundTypeVariable; 344 } 345 346 @Override 347 public Boolean visitDeclared(DeclaredType t, Void p) { 348 buf.append(utils.getQualifiedTypeName(t)); 349 return foundTypeVariable; 350 } 351 352 @Override 353 protected Boolean defaultAction(TypeMirror e, Void p) { 354 buf.append(e); 355 return foundTypeVariable; 356 } 357 }; 358 359 boolean isTypeVariable = stv.visit(t); 360 if (!foundTypeVariable) { 361 foundTypeVariable = isTypeVariable; 362 } 363 } 364 buf.append(")"); 365 return foundTypeVariable ? writer.links.getName(buf.toString()) : null; 366 } 367 }