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