1/*
2 * Copyright (c) 1997, 2013, 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 com.sun.tools.javadoc.main;
27
28import java.lang.reflect.Modifier;
29import java.text.CollationKey;
30
31import com.sun.javadoc.*;
32
33import com.sun.source.util.TreePath;
34import com.sun.tools.javac.code.Flags;
35import com.sun.tools.javac.code.Symbol.*;
36import com.sun.tools.javac.code.Type;
37import com.sun.tools.javac.util.List;
38import com.sun.tools.javac.util.ListBuffer;
39
40/**
41 * Represents a method or constructor of a java class.
42 *
43 *  <p><b>This is NOT part of any supported API.
44 *  If you write code that depends on this, you do so at your own risk.
45 *  This code and its internal interfaces are subject to change or
46 *  deletion without notice.</b>
47 *
48 * @since 1.2
49 * @author Robert Field
50 * @author Neal Gafter (rewrite)
51 * @author Scott Seligman (generics, annotations)
52 */
53
54@Deprecated
55public abstract class ExecutableMemberDocImpl
56        extends MemberDocImpl implements ExecutableMemberDoc {
57
58    protected final MethodSymbol sym;
59
60    /**
61     * Constructor.
62     */
63    public ExecutableMemberDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) {
64        super(env, sym, treePath);
65        this.sym = sym;
66    }
67
68    /**
69     * Constructor.
70     */
71    public ExecutableMemberDocImpl(DocEnv env, MethodSymbol sym) {
72        this(env, sym, null);
73    }
74
75    /**
76     * Returns the flags in terms of javac's flags
77     */
78    protected long getFlags() {
79        return sym.flags();
80    }
81
82    /**
83     * Identify the containing class
84     */
85    protected ClassSymbol getContainingClass() {
86        return sym.enclClass();
87    }
88
89    /**
90     * Return true if this method is native
91     */
92    public boolean isNative() {
93        return Modifier.isNative(getModifiers());
94    }
95
96    /**
97     * Return true if this method is synchronized
98     */
99    public boolean isSynchronized() {
100        return Modifier.isSynchronized(getModifiers());
101    }
102
103    /**
104     * Return true if this method was declared to take a variable number
105     * of arguments.
106     */
107    public boolean isVarArgs() {
108        return ((sym.flags() & Flags.VARARGS) != 0
109                && !env.legacyDoclet);
110    }
111
112    /**
113     * Returns true if this field was synthesized by the compiler.
114     */
115    public boolean isSynthetic() {
116        return ((sym.flags() & Flags.SYNTHETIC) != 0);
117    }
118
119    public boolean isIncluded() {
120        return containingClass().isIncluded() && env.shouldDocument(sym);
121    }
122
123    /**
124     * Return the throws tags in this method.
125     *
126     * @return an array of ThrowTagImpl containing all {@code @exception}
127     * and {@code @throws} tags.
128     */
129    public ThrowsTag[] throwsTags() {
130        return comment().throwsTags();
131    }
132
133    /**
134     * Return the param tags in this method, excluding the type
135     * parameter tags.
136     *
137     * @return an array of ParamTagImpl containing all {@code @param} tags.
138     */
139    public ParamTag[] paramTags() {
140        return comment().paramTags();
141    }
142
143    /**
144     * Return the type parameter tags in this method.
145     */
146    public ParamTag[] typeParamTags() {
147        return env.legacyDoclet
148            ? new ParamTag[0]
149            : comment().typeParamTags();
150    }
151
152    /**
153     * Return exceptions this method or constructor throws.
154     *
155     * @return an array of ClassDoc[] representing the exceptions
156     * thrown by this method.
157     */
158    public ClassDoc[] thrownExceptions() {
159        ListBuffer<ClassDocImpl> l = new ListBuffer<>();
160        for (Type ex : sym.type.getThrownTypes()) {
161            ex = env.types.erasure(ex);
162            //### Will these casts succeed in the face of static semantic
163            //### errors in the documented code?
164            ClassDocImpl cdi = env.getClassDoc((ClassSymbol)ex.tsym);
165            if (cdi != null) l.append(cdi);
166        }
167        return l.toArray(new ClassDocImpl[l.length()]);
168    }
169
170    /**
171     * Return exceptions this method or constructor throws.
172     * Each array element is either a <code>ClassDoc</code> or a
173     * <code>TypeVariable</code>.
174     */
175    public com.sun.javadoc.Type[] thrownExceptionTypes() {
176        return TypeMaker.getTypes(env, sym.type.getThrownTypes());
177    }
178
179    /**
180     * Get argument information.
181     *
182     * @see ParameterImpl
183     *
184     * @return an array of ParameterImpl, one element per argument
185     * in the order the arguments are present.
186     */
187    public Parameter[] parameters() {
188        // generate the parameters on the fly:  they're not cached
189        List<VarSymbol> params = sym.params();
190        Parameter result[] = new Parameter[params.length()];
191
192        int i = 0;
193        for (VarSymbol param : params) {
194            result[i++] = new ParameterImpl(env, param);
195        }
196        return result;
197    }
198
199    /**
200     * Get the receiver type of this executable element.
201     *
202     * @return the receiver type of this executable element.
203     * @since 1.8
204     */
205    public com.sun.javadoc.Type receiverType() {
206        Type recvtype = sym.type.asMethodType().recvtype;
207        return (recvtype != null) ? TypeMaker.getType(env, recvtype, false, true) : null;
208    }
209
210    /**
211     * Return the formal type parameters of this method or constructor.
212     * Return an empty array if there are none.
213     */
214    public TypeVariable[] typeParameters() {
215        if (env.legacyDoclet) {
216            return new TypeVariable[0];
217        }
218        TypeVariable res[] = new TypeVariable[sym.type.getTypeArguments().length()];
219        TypeMaker.getTypes(env, sym.type.getTypeArguments(), res);
220        return res;
221    }
222
223    /**
224     * Get the signature. It is the parameter list, type is qualified.
225     * For instance, for a method <code>mymethod(String x, int y)</code>,
226     * it will return <code>(java.lang.String,int)</code>.
227     */
228    public String signature() {
229        return makeSignature(true);
230    }
231
232    /**
233     * Get flat signature.  All types are not qualified.
234     * Return a String, which is the flat signiture of this member.
235     * It is the parameter list, type is not qualified.
236     * For instance, for a method <code>mymethod(String x, int y)</code>,
237     * it will return <code>(String, int)</code>.
238     */
239    public String flatSignature() {
240        return makeSignature(false);
241    }
242
243    private String makeSignature(boolean full) {
244        StringBuilder result = new StringBuilder();
245        result.append("(");
246        for (List<Type> types = sym.type.getParameterTypes(); types.nonEmpty(); ) {
247            Type t = types.head;
248            result.append(TypeMaker.getTypeString(env, t, full));
249            types = types.tail;
250            if (types.nonEmpty()) {
251                result.append(", ");
252            }
253        }
254        if (isVarArgs()) {
255            int len = result.length();
256            result.replace(len - 2, len, "...");
257        }
258        result.append(")");
259        return result.toString();
260    }
261
262    protected String typeParametersString() {
263        return TypeMaker.typeParametersString(env, sym, true);
264    }
265
266    /**
267     * Generate a key for sorting.
268     */
269    @Override
270    CollationKey generateKey() {
271        String k = name() + flatSignature() + typeParametersString();
272        // ',' and '&' are between '$' and 'a':  normalize to spaces.
273        k = k.replace(',', ' ').replace('&', ' ');
274        // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\"");
275        return env.doclocale.collator.getCollationKey(k);
276    }
277
278    /**
279     * Return the source position of the entity, or null if
280     * no position is available.
281     */
282    @Override
283    public SourcePosition position() {
284        if (sym.enclClass().sourcefile == null) return null;
285        return SourcePositionImpl.make(sym.enclClass().sourcefile,
286                                       (tree==null) ? 0 : tree.pos,
287                                       lineMap);
288    }
289}
290