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