001    /*
002     * Copyright 1997-2005 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.doclets.formats.html;
027    
028    import com.sun.javadoc.*;
029    
030    /**
031     * Print method and constructor info.
032     *
033     * @author Robert Field
034     * @author Atul M Dambalkar
035     */
036    public abstract class AbstractExecutableMemberWriter extends AbstractMemberWriter {
037    
038        public AbstractExecutableMemberWriter(SubWriterHolderWriter writer,
039                                         ClassDoc classdoc) {
040            super(writer, classdoc);
041        }
042    
043        public AbstractExecutableMemberWriter(SubWriterHolderWriter writer) {
044            super(writer);
045        }
046    
047        /**
048         * Write the type parameters for the executable member.
049         *
050         * @param member the member to write type parameters for.
051         * @return the display length required to write this information.
052         */
053        protected int writeTypeParameters(ExecutableMemberDoc member) {
054            LinkInfoImpl linkInfo = new LinkInfoImpl(
055                LinkInfoImpl.CONTEXT_MEMBER_TYPE_PARAMS, member, false);
056            String typeParameters = writer.getTypeParameterLinks(linkInfo);
057            if (linkInfo.displayLength > 0) {
058                writer.print(typeParameters + " ");
059                writer.displayLength += linkInfo.displayLength + 1;
060            }
061            return linkInfo.displayLength;
062        }
063    
064        protected void writeSignature(ExecutableMemberDoc member) {
065            writer.displayLength = 0;
066            writer.pre();
067            writer.writeAnnotationInfo(member);
068            printModifiers(member);
069            writeTypeParameters(member);
070            if (configuration().linksource &&
071                member.position().line() != classdoc.position().line()) {
072                writer.printSrcLink(member, member.name());
073            } else {
074                strong(member.name());
075            }
076            writeParameters(member);
077            writeExceptions(member);
078            writer.preEnd();
079        }
080    
081        protected void writeDeprecatedLink(ProgramElementDoc member) {
082            ExecutableMemberDoc emd = (ExecutableMemberDoc)member;
083            writer.printDocLink(LinkInfoImpl.CONTEXT_MEMBER, (MemberDoc) emd,
084                emd.qualifiedName() + emd.flatSignature(), false);
085        }
086    
087        protected void writeSummaryLink(int context, ClassDoc cd, ProgramElementDoc member) {
088            ExecutableMemberDoc emd = (ExecutableMemberDoc)member;
089            String name = emd.name();
090            writer.strong();
091            writer.printDocLink(context, cd, (MemberDoc) emd,
092                name, false);
093            writer.strongEnd();
094            writer.displayLength = name.length();
095            writeParameters(emd, false);
096        }
097    
098        protected void writeInheritedSummaryLink(ClassDoc cd,
099                ProgramElementDoc member) {
100            writer.printDocLink(LinkInfoImpl.CONTEXT_MEMBER, cd, (MemberDoc) member,
101                member.name(), false);
102        }
103    
104        protected void writeParam(ExecutableMemberDoc member, Parameter param,
105            boolean isVarArg) {
106            if (param.type() != null) {
107                writer.printLink(new LinkInfoImpl(
108                    LinkInfoImpl.CONTEXT_EXECUTABLE_MEMBER_PARAM, param.type(),
109                    isVarArg));
110            }
111            if(param.name().length() > 0) {
112                writer.space();
113                writer.print(param.name());
114            }
115        }
116    
117        protected void writeParameters(ExecutableMemberDoc member) {
118            writeParameters(member, true);
119        }
120    
121        protected void writeParameters(ExecutableMemberDoc member,
122                boolean includeAnnotations) {
123            print('(');
124            Parameter[] params = member.parameters();
125            String indent = makeSpace(writer.displayLength);
126            if (configuration().linksource) {
127                //add spaces to offset indentation changes caused by link.
128                indent+= makeSpace(member.name().length());
129            }
130            int paramstart;
131            for (paramstart = 0; paramstart < params.length; paramstart++) {
132                Parameter param = params[paramstart];
133                if (!param.name().startsWith("this$")) {
134                    if (includeAnnotations) {
135                            boolean foundAnnotations =
136                                    writer.writeAnnotationInfo(indent.length(), member, param);
137                            if (foundAnnotations) {
138                                    writer.println();
139                                    writer.print(indent);
140                        }
141                    }
142                    writeParam(member, param,
143                        (paramstart == params.length - 1) && member.isVarArgs());
144                    break;
145                }
146            }
147    
148            for (int i = paramstart + 1; i < params.length; i++) {
149                writer.print(',');
150                writer.println();
151                writer.print(indent);
152                if (includeAnnotations) {
153                    boolean foundAnnotations =
154                        writer.writeAnnotationInfo(indent.length(), member, params[i]);
155                    if (foundAnnotations) {
156                        writer.println();
157                        writer.print(indent);
158                    }
159                }
160                writeParam(member, params[i], (i == params.length - 1) && member.isVarArgs());
161            }
162            writer.print(')');
163        }
164    
165        protected void writeExceptions(ExecutableMemberDoc member) {
166            Type[] exceptions = member.thrownExceptionTypes();
167            if(exceptions.length > 0) {
168                LinkInfoImpl memberTypeParam = new LinkInfoImpl(
169                    LinkInfoImpl.CONTEXT_MEMBER, member, false);
170                int retlen = getReturnTypeLength(member);
171                writer.getTypeParameterLinks(memberTypeParam);
172                retlen += memberTypeParam.displayLength == 0 ?
173                    0 : memberTypeParam.displayLength + 1;
174                String indent = makeSpace(modifierString(member).length() +
175                    member.name().length() + retlen - 4);
176                writer.println();
177                writer.print(indent);
178                writer.print("throws ");
179                indent += "       ";
180                writer.printLink(new LinkInfoImpl(
181                    LinkInfoImpl.CONTEXT_MEMBER, exceptions[0]));
182                for(int i = 1; i < exceptions.length; i++) {
183                    writer.println(",");
184                    writer.print(indent);
185                    writer.printLink(new LinkInfoImpl(
186                        LinkInfoImpl.CONTEXT_MEMBER, exceptions[i]));
187                }
188            }
189        }
190    
191        protected int getReturnTypeLength(ExecutableMemberDoc member) {
192            if (member instanceof MethodDoc) {
193                MethodDoc method = (MethodDoc)member;
194                Type rettype = method.returnType();
195                if (rettype.isPrimitive()) {
196                    return rettype.typeName().length() +
197                           rettype.dimension().length();
198                } else {
199                    LinkInfoImpl linkInfo = new LinkInfoImpl(
200                        LinkInfoImpl.CONTEXT_MEMBER, rettype);
201                    writer.getLink(linkInfo);
202                    return linkInfo.displayLength;
203                }
204            } else {   // it's a constructordoc
205                return -1;
206            }
207        }
208    
209        protected ClassDoc implementsMethodInIntfac(MethodDoc method,
210                                                    ClassDoc[] intfacs) {
211            for (int i = 0; i < intfacs.length; i++) {
212                MethodDoc[] methods = intfacs[i].methods();
213                if (methods.length > 0) {
214                    for (int j = 0; j < methods.length; j++) {
215                        if (methods[j].name().equals(method.name()) &&
216                              methods[j].signature().equals(method.signature())) {
217                            return intfacs[i];
218                        }
219                    }
220                }
221            }
222            return null;
223        }
224    
225        /**
226         * For backward compatibility, include an anchor using the erasures of the
227         * parameters.  NOTE:  We won't need this method anymore after we fix
228         * see tags so that they use the type instead of the erasure.
229         *
230         * @param emd the ExecutableMemberDoc to anchor to.
231         * @return the 1.4.x style anchor for the ExecutableMemberDoc.
232         */
233        protected String getErasureAnchor(ExecutableMemberDoc emd) {
234            StringBuffer buf = new StringBuffer(emd.name() + "(");
235            Parameter[] params = emd.parameters();
236            boolean foundTypeVariable = false;
237            for (int i = 0; i < params.length; i++) {
238                if (i > 0) {
239                    buf.append(",");
240                }
241                Type t = params[i].type();
242                foundTypeVariable = foundTypeVariable || t.asTypeVariable() != null;
243                buf.append(t.isPrimitive() ?
244                    t.typeName() : t.asClassDoc().qualifiedName());
245                buf.append(t.dimension());
246            }
247            buf.append(")");
248            return foundTypeVariable ? buf.toString() : null;
249        }
250    }