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