Thu, 02 Oct 2008 19:58:40 -0700
6754988: Update copyright year
Summary: Update for files that have been modified starting July 2008
Reviewed-by: ohair, tbell
1 /*
2 * Copyright 2001-2008 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.doclets.internal.toolkit.taglets;
28 import com.sun.javadoc.*;
29 import com.sun.tools.doclets.internal.toolkit.util.*;
30 import java.util.*;
32 /**
33 * A taglet that represents the @param tag.
34 *
35 * This code is not part of an API.
36 * It is implementation that is subject to change.
37 * Do not use it as an API
38 *
39 * @author Jamie Ho
40 * @since 1.4
41 */
42 public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
44 /**
45 * Construct a ParamTaglet.
46 */
47 public ParamTaglet() {
48 name = "param";
49 }
51 /**
52 * Given an array of <code>Parameter</code>s, return
53 * a name/rank number map. If the array is null, then
54 * null is returned.
55 * @param params The array of parmeters (from type or executable member) to
56 * check.
57 * @return a name-rank number map.
58 */
59 private static Map<String,String> getRankMap(Object[] params){
60 if (params == null) {
61 return null;
62 }
63 HashMap<String,String> result = new HashMap<String,String>();
64 for (int i = 0; i < params.length; i++) {
65 String name = params[i] instanceof Parameter ?
66 ((Parameter) params[i]).name() :
67 ((TypeVariable) params[i]).typeName();
68 result.put(name, String.valueOf(i));
69 }
70 return result;
71 }
73 /**
74 * {@inheritDoc}
75 */
76 public void inherit(DocFinder.Input input, DocFinder.Output output) {
77 if (input.tagId == null) {
78 input.isTypeVariableParamTag = ((ParamTag) input.tag).isTypeParameter();
79 Object[] parameters = input.isTypeVariableParamTag ?
80 (Object[]) ((MethodDoc) input.tag.holder()).typeParameters() :
81 (Object[]) ((MethodDoc) input.tag.holder()).parameters();
82 String target = ((ParamTag) input.tag).parameterName();
83 int i;
84 for (i = 0; i < parameters.length; i++) {
85 String name = parameters[i] instanceof Parameter ?
86 ((Parameter) parameters[i]).name() :
87 ((TypeVariable) parameters[i]).typeName();
88 if (name.equals(target)) {
89 input.tagId = String.valueOf(i);
90 break;
91 }
92 }
93 if (i == parameters.length) {
94 //Someone used {@inheritDoc} on an invalid @param tag.
95 //We don't know where to inherit from.
96 //XXX: in the future when Configuration is available here,
97 //print a warning for this mistake.
98 return;
99 }
100 }
101 ParamTag[] tags = input.isTypeVariableParamTag ?
102 input.method.typeParamTags() : input.method.paramTags();
103 Map rankMap = getRankMap(input.isTypeVariableParamTag ?
104 (Object[]) input.method.typeParameters() :
105 (Object[]) input.method.parameters());
106 for (int i = 0; i < tags.length; i++) {
107 if (rankMap.containsKey(tags[i].parameterName()) &&
108 rankMap.get(tags[i].parameterName()).equals((input.tagId))) {
109 output.holder = input.method;
110 output.holderTag = tags[i];
111 output.inlineTags = input.isFirstSentence ?
112 tags[i].firstSentenceTags() : tags[i].inlineTags();
113 return;
114 }
115 }
116 }
118 /**
119 * {@inheritDoc}
120 */
121 public boolean inField() {
122 return false;
123 }
125 /**
126 * {@inheritDoc}
127 */
128 public boolean inMethod() {
129 return true;
130 }
132 /**
133 * {@inheritDoc}
134 */
135 public boolean inOverview() {
136 return false;
137 }
139 /**
140 * {@inheritDoc}
141 */
142 public boolean inPackage() {
143 return false;
144 }
146 /**
147 * {@inheritDoc}
148 */
149 public boolean inType() {
150 return true;
151 }
153 /**
154 * {@inheritDoc}
155 */
156 public boolean isInlineTag() {
157 return false;
158 }
160 /**
161 * Given an array of <code>ParamTag</code>s,return its string representation.
162 * @param holder the member that holds the param tags.
163 * @param writer the TagletWriter that will write this tag.
164 * @return the TagletOutput representation of these <code>ParamTag</code>s.
165 */
166 public TagletOutput getTagletOutput(Doc holder, TagletWriter writer) {
167 if (holder instanceof ExecutableMemberDoc) {
168 ExecutableMemberDoc member = (ExecutableMemberDoc) holder;
169 TagletOutput output = getTagletOutput(false, member, writer,
170 member.typeParameters(), member.typeParamTags());
171 output.appendOutput(getTagletOutput(true, member, writer,
172 member.parameters(), member.paramTags()));
173 return output;
174 } else {
175 ClassDoc classDoc = (ClassDoc) holder;
176 return getTagletOutput(false, classDoc, writer,
177 classDoc.typeParameters(), classDoc.typeParamTags());
178 }
179 }
181 /**
182 * Given an array of <code>ParamTag</code>s,return its string representation.
183 * Try to inherit the param tags that are missing.
184 *
185 * @param doc the doc that holds the param tags.
186 * @param writer the TagletWriter that will write this tag.
187 * @param formalParameters The array of parmeters (from type or executable
188 * member) to check.
189 *
190 * @return the TagletOutput representation of these <code>ParamTag</code>s.
191 */
192 private TagletOutput getTagletOutput(boolean isNonTypeParams, Doc holder,
193 TagletWriter writer, Object[] formalParameters, ParamTag[] paramTags) {
194 TagletOutput result = writer.getOutputInstance();
195 Set<String> alreadyDocumented = new HashSet<String>();
196 if (paramTags.length > 0) {
197 result.appendOutput(
198 processParamTags(isNonTypeParams, paramTags,
199 getRankMap(formalParameters), writer, alreadyDocumented)
200 );
201 }
202 if (alreadyDocumented.size() != formalParameters.length) {
203 //Some parameters are missing corresponding @param tags.
204 //Try to inherit them.
205 result.appendOutput(getInheritedTagletOutput (isNonTypeParams, holder,
206 writer, formalParameters, alreadyDocumented));
207 }
208 return result;
209 }
211 /**
212 * Loop through each indivitual parameter. It it does not have a
213 * corresponding param tag, try to inherit it.
214 */
215 private TagletOutput getInheritedTagletOutput(boolean isNonTypeParams, Doc holder,
216 TagletWriter writer, Object[] formalParameters,
217 Set<String> alreadyDocumented) {
218 TagletOutput result = writer.getOutputInstance();
219 if ((! alreadyDocumented.contains(null)) &&
220 holder instanceof MethodDoc) {
221 for (int i = 0; i < formalParameters.length; i++) {
222 if (alreadyDocumented.contains(String.valueOf(i))) {
223 continue;
224 }
225 //This parameter does not have any @param documentation.
226 //Try to inherit it.
227 DocFinder.Output inheritedDoc =
228 DocFinder.search(new DocFinder.Input((MethodDoc) holder, this,
229 String.valueOf(i), ! isNonTypeParams));
230 if (inheritedDoc.inlineTags != null &&
231 inheritedDoc.inlineTags.length > 0) {
232 result.appendOutput(
233 processParamTag(isNonTypeParams, writer,
234 (ParamTag) inheritedDoc.holderTag,
235 isNonTypeParams ?
236 ((Parameter) formalParameters[i]).name():
237 ((TypeVariable) formalParameters[i]).typeName(),
238 alreadyDocumented.size() == 0));
239 }
240 alreadyDocumented.add(String.valueOf(i));
241 }
242 }
243 return result;
244 }
246 /**
247 * Given an array of <code>Tag</code>s representing this custom
248 * tag, return its string representation. Print a warning for param
249 * tags that do not map to parameters. Print a warning for param
250 * tags that are duplicated.
251 *
252 * @param paramTags the array of <code>ParamTag</code>s to convert.
253 * @param writer the TagletWriter that will write this tag.
254 * @param alreadyDocumented the set of exceptions that have already
255 * been documented.
256 * @param rankMap a {@link java.util.Map} which holds ordering
257 * information about the parameters.
258 * @param nameMap a {@link java.util.Map} which holds a mapping
259 * of a rank of a parameter to its name. This is
260 * used to ensure that the right name is used
261 * when parameter documentation is inherited.
262 * @return the TagletOutput representation of this <code>Tag</code>.
263 */
264 private TagletOutput processParamTags(boolean isNonTypeParams,
265 ParamTag[] paramTags, Map rankMap, TagletWriter writer,
266 Set<String> alreadyDocumented) {
267 TagletOutput result = writer.getOutputInstance();
268 if (paramTags.length > 0) {
269 for (int i = 0; i < paramTags.length; ++i) {
270 ParamTag pt = paramTags[i];
271 String paramName = isNonTypeParams ?
272 pt.parameterName() : "<" + pt.parameterName() + ">";
273 if (! rankMap.containsKey(pt.parameterName())) {
274 writer.getMsgRetriever().warning(pt.position(),
275 isNonTypeParams ?
276 "doclet.Parameters_warn" :
277 "doclet.Type_Parameters_warn",
278 paramName);
279 }
280 String rank = (String) rankMap.get(pt.parameterName());
281 if (rank != null && alreadyDocumented.contains(rank)) {
282 writer.getMsgRetriever().warning(pt.position(),
283 isNonTypeParams ?
284 "doclet.Parameters_dup_warn" :
285 "doclet.Type_Parameters_dup_warn",
286 paramName);
287 }
288 result.appendOutput(processParamTag(isNonTypeParams, writer, pt,
289 pt.parameterName(), alreadyDocumented.size() == 0));
290 alreadyDocumented.add(rank);
291 }
292 }
293 return result;
294 }
295 /**
296 * Convert the individual ParamTag into TagletOutput.
297 *
298 * @param isNonTypeParams true if this is just a regular param tag. False
299 * if this is a type param tag.
300 * @param writer the taglet writer for output writing.
301 * @param paramTag the tag whose inline tags will be printed.
302 * @param name the name of the parameter. We can't rely on
303 * the name in the param tag because we might be
304 * inheriting documentation.
305 * @param isFirstParam true if this is the first param tag being printed.
306 *
307 */
308 private TagletOutput processParamTag(boolean isNonTypeParams,
309 TagletWriter writer, ParamTag paramTag, String name,
310 boolean isFirstParam) {
311 TagletOutput result = writer.getOutputInstance();
312 String header = writer.configuration().getText(
313 isNonTypeParams ? "doclet.Parameters" : "doclet.TypeParameters");
314 if (isFirstParam) {
315 result.appendOutput(writer.getParamHeader(header));
316 }
317 result.appendOutput(writer.paramTagOutput(paramTag,
318 name));
319 return result;
320 }
321 }