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 /** 78 * Get the type parameters for the executable member. 79 * 80 * @param member the member for which to get the type parameters. 81 * @return the type parameters. 82 */ 83 protected Content getTypeParameters(ExecutableElement member) { 84 LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, MEMBER_TYPE_PARAMS, member); 85 return writer.getTypeParameterLinks(linkInfo); 86 } 87 88 /** 89 * {@inheritDoc} 90 */ 91 @Override 92 protected Content getDeprecatedLink(Element member) { 93 Content deprecatedLinkContent = new ContentBuilder(); 94 deprecatedLinkContent.add(utils.getFullyQualifiedName(member)); 95 if (!utils.isConstructor(member)) { 96 deprecatedLinkContent.add("."); 97 deprecatedLinkContent.add(member.getSimpleName()); 98 } 99 String signature = utils.flatSignature((ExecutableElement) member); 100 if (signature.length() > 2) { 101 deprecatedLinkContent.add(Entity.ZERO_WIDTH_SPACE); 102 } 103 deprecatedLinkContent.add(signature); 104 105 return writer.getDocLink(MEMBER, utils.getEnclosingTypeElement(member), member, deprecatedLinkContent); 106 } 107 108 /** 109 * Add the summary link for the member. 110 * 111 * @param context the id of the context where the link will be printed 112 * @param te the type element being linked to 113 * @param member the member being linked to 114 * @param tdSummary the content tree to which the link will be added 115 */ 116 @Override 117 protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement te, Element member, 118 Content tdSummary) { 119 ExecutableElement ee = (ExecutableElement)member; 120 Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink, 121 writer.getDocLink(context, te, ee, 122 name(ee), false)); 123 Content code = HtmlTree.CODE(memberLink); 124 addParameters(ee, code); 125 tdSummary.add(code); 126 } 127 128 /** 129 * Add the inherited summary link for the member. 130 * 131 * @param te the type element that we should link to 132 * @param member the member being linked to 133 * @param linksTree the content tree to which the link will be added 134 */ 135 @Override 136 protected void addInheritedSummaryLink(TypeElement te, Element member, Content linksTree) { 137 linksTree.add(writer.getDocLink(MEMBER, te, member, name(member), false)); 138 } 139 140 /** 141 * Add the parameter for the executable member. 142 * 143 * @param member the member to write parameter for. 144 * @param param the parameter that needs to be written. 145 * @param isVarArg true if this is a link to var arg. 146 * @param tree the content tree to which the parameter information will be added. 147 */ 148 protected void addParam(ExecutableElement member, VariableElement param, 149 boolean isVarArg, Content tree) { 150 Content link = writer.getLink(new LinkInfoImpl(configuration, EXECUTABLE_MEMBER_PARAM, 151 param.asType()).varargs(isVarArg)); 152 tree.add(link); 153 if(name(param).length() > 0) { 154 tree.add(Entity.NO_BREAK_SPACE); 155 tree.add(name(param)); 156 } 157 } 158 159 /** 160 * Add the receiver annotations information. 161 * 162 * @param member the member to write receiver annotations for. 163 * @param rcvrType the receiver type. 164 * @param annotationMirrors list of annotation descriptions. 165 * @param tree the content tree to which the information will be added. 166 */ 167 protected void addReceiverAnnotations(ExecutableElement member, TypeMirror rcvrType, 168 List<? extends AnnotationMirror> annotationMirrors, Content tree) { 169 writer.addReceiverAnnotationInfo(member, rcvrType, annotationMirrors, tree); 170 tree.add(Entity.NO_BREAK_SPACE); 171 tree.add(utils.getTypeName(rcvrType, false)); 172 LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, RECEIVER_TYPE, rcvrType); 173 tree.add(writer.getTypeParameterLinks(linkInfo)); 174 tree.add(Entity.NO_BREAK_SPACE); 175 tree.add("this"); 176 } 177 178 179 /** 180 * Add all the parameters for the executable member. 181 * 182 * @param member the member to write parameters for. 183 * @param htmltree the content tree to which the parameters information will be added. 184 */ 185 protected void addParameters(ExecutableElement member, Content htmltree) { 186 Content paramTree = getParameters(member, false); 187 if (paramTree.isEmpty()) { 188 htmltree.add("()"); 189 } else { 190 htmltree.add(Entity.ZERO_WIDTH_SPACE); 191 htmltree.add("("); 192 htmltree.add(paramTree); 193 paramTree.add(")"); 194 } 195 } 196 197 /** 198 * Add all the parameters for the executable member. 199 * 200 * @param member the member to write parameters for. 201 * @param includeAnnotations true if annotation information needs to be added. 202 * @return the content tree containing the parameter information 203 */ 204 protected Content getParameters(ExecutableElement member, boolean includeAnnotations) { 205 Content paramTree = new ContentBuilder(); 206 String sep = ""; 207 List<? extends VariableElement> parameters = member.getParameters(); 208 TypeMirror rcvrType = member.getReceiverType(); 209 if (includeAnnotations && rcvrType != null && utils.isAnnotated(rcvrType)) { 210 List<? extends AnnotationMirror> annotationMirrors = rcvrType.getAnnotationMirrors(); 211 addReceiverAnnotations(member, rcvrType, annotationMirrors, paramTree); 212 sep = "," + DocletConstants.NL; 213 } 214 int paramstart; 215 for (paramstart = 0; paramstart < parameters.size(); paramstart++) { 216 paramTree.add(sep); 217 VariableElement param = parameters.get(paramstart); 218 219 if (param.getKind() != ElementKind.INSTANCE_INIT) { 220 if (includeAnnotations) { 221 boolean foundAnnotations = 222 writer.addAnnotationInfo(param, paramTree); 223 if (foundAnnotations) { 224 paramTree.add(DocletConstants.NL); 225 } 226 } 227 addParam(member, param, 228 (paramstart == parameters.size() - 1) && member.isVarArgs(), paramTree); 229 break; 230 } 231 } 232 233 for (int i = paramstart + 1; i < parameters.size(); i++) { 234 paramTree.add(","); 235 paramTree.add(DocletConstants.NL); 236 if (includeAnnotations) { 237 boolean foundAnnotations = 238 writer.addAnnotationInfo(parameters.get(i), 239 paramTree); 240 if (foundAnnotations) { 241 paramTree.add(DocletConstants.NL); 242 } 243 } 244 addParam(member, parameters.get(i), (i == parameters.size() - 1) && member.isVarArgs(), 245 paramTree); 246 } 247 248 return paramTree; 249 } 250 251 /** 252 * Get a content tree containing the exception information for the executable member. 253 * 254 * @param member the member to write exceptions for. 255 * @return the content tree containing the exceptions information. 256 */ 257 protected Content getExceptions(ExecutableElement member) { 258 List<? extends TypeMirror> exceptions = member.getThrownTypes(); 259 Content htmltree = new ContentBuilder(); 260 if (!exceptions.isEmpty()) { 261 Content link = writer.getLink(new LinkInfoImpl(configuration, MEMBER, exceptions.get(0))); 262 htmltree.add(link); 263 for(int i = 1; i < exceptions.size(); i++) { 264 htmltree.add(","); 265 htmltree.add(DocletConstants.NL); 266 Content exceptionLink = writer.getLink(new LinkInfoImpl(configuration, MEMBER, 267 exceptions.get(i))); 268 htmltree.add(exceptionLink); 269 } 270 } 271 return htmltree; 272 } 273 274 protected TypeElement implementsMethodInIntfac(ExecutableElement method, 275 List<TypeElement> intfacs) { 276 for (TypeElement intf : intfacs) { 277 List<ExecutableElement> methods = utils.getMethods(intf); 278 if (!methods.isEmpty()) { 279 for (ExecutableElement md : methods) { 280 if (name(md).equals(name(method)) && 281 md.toString().equals(method.toString())) { 282 return intf; 283 } 284 } 285 } 286 } 287 return null; 288 } 289 290 /** 291 * For backward compatibility, include an anchor using the erasures of the 292 * parameters. NOTE: We won't need this method anymore after we fix 293 * see tags so that they use the type instead of the erasure. 294 * 295 * @param executableElement the ExecutableElement to anchor to. 296 * @return the 1.4.x style anchor for the executable element. 297 */ 298 protected String getErasureAnchor(ExecutableElement executableElement) { 299 final StringBuilder buf = new StringBuilder(writer.anchorName(executableElement)); 300 buf.append("("); 301 List<? extends VariableElement> parameters = executableElement.getParameters(); 302 boolean foundTypeVariable = false; 303 for (int i = 0; i < parameters.size(); i++) { 304 if (i > 0) { 305 buf.append(","); 306 } 307 TypeMirror t = parameters.get(i).asType(); 308 SimpleTypeVisitor9<Boolean, Void> stv = new SimpleTypeVisitor9<Boolean, Void>() { 309 boolean foundTypeVariable = false; 310 311 @Override 312 public Boolean visitArray(ArrayType t, Void p) { 313 visit(t.getComponentType()); 314 buf.append(utils.getDimension(t)); 315 return foundTypeVariable; 316 } 317 318 @Override 319 public Boolean visitTypeVariable(TypeVariable t, Void p) { 320 buf.append(utils.asTypeElement(t).getQualifiedName()); 321 foundTypeVariable = true; 322 return foundTypeVariable; 323 } 324 325 @Override 326 public Boolean visitDeclared(DeclaredType t, Void p) { 327 buf.append(utils.getQualifiedTypeName(t)); 328 return foundTypeVariable; 329 } 330 331 @Override 332 protected Boolean defaultAction(TypeMirror e, Void p) { 333 buf.append(e); 334 return foundTypeVariable; 335 } 336 }; 337 338 boolean isTypeVariable = stv.visit(t); 339 if (!foundTypeVariable) { 340 foundTypeVariable = isTypeVariable; 341 } 342 } 343 buf.append(")"); 344 return foundTypeVariable ? writer.links.getName(buf.toString()) : null; 345 } 346 }