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