|
1 /* |
|
2 * Copyright 2001-2006 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 */ |
|
25 |
|
26 package com.sun.tools.doclets.internal.toolkit.taglets; |
|
27 |
|
28 import com.sun.javadoc.*; |
|
29 import com.sun.tools.doclets.internal.toolkit.util.*; |
|
30 |
|
31 import java.io.*; |
|
32 import java.lang.reflect.*; |
|
33 import java.net.*; |
|
34 import java.util.*; |
|
35 |
|
36 /** |
|
37 * Manages the<code>Taglet</code>s used by doclets. |
|
38 * |
|
39 * This code is not part of an API. |
|
40 * It is implementation that is subject to change. |
|
41 * Do not use it as an API |
|
42 * |
|
43 * @author Jamie Ho |
|
44 * @since 1.4 |
|
45 */ |
|
46 |
|
47 public class TagletManager { |
|
48 |
|
49 /** |
|
50 * The default seperator for the simple tag option. |
|
51 */ |
|
52 public static final char SIMPLE_TAGLET_OPT_SEPERATOR = ':'; |
|
53 |
|
54 /** |
|
55 * The alternate seperator for simple tag options. Use this |
|
56 * with you want the default seperator to be in the name of the |
|
57 * custom tag. |
|
58 */ |
|
59 public static final String ALT_SIMPLE_TAGLET_OPT_SEPERATOR = "-"; |
|
60 |
|
61 /** |
|
62 * The map of custom tags. |
|
63 */ |
|
64 private LinkedHashMap customTags; |
|
65 |
|
66 /** |
|
67 * The array of custom tags that can appear in packages. |
|
68 */ |
|
69 private Taglet[] packageTags; |
|
70 |
|
71 /** |
|
72 * The array of custom tags that can appear in classes or interfaces. |
|
73 */ |
|
74 private Taglet[] typeTags; |
|
75 |
|
76 /** |
|
77 * The array of custom tags that can appear in fields. |
|
78 */ |
|
79 private Taglet[] fieldTags; |
|
80 |
|
81 /** |
|
82 * The array of custom tags that can appear in constructors. |
|
83 */ |
|
84 private Taglet[] constructorTags; |
|
85 |
|
86 /** |
|
87 * The array of custom tags that can appear in methods. |
|
88 */ |
|
89 private Taglet[] methodTags; |
|
90 |
|
91 /** |
|
92 * The array of custom tags that can appear in the overview. |
|
93 */ |
|
94 private Taglet[] overviewTags; |
|
95 |
|
96 /** |
|
97 * The array of custom tags that can appear in comments. |
|
98 */ |
|
99 private Taglet[] inlineTags; |
|
100 |
|
101 /** |
|
102 * The array of custom tags that can appear in the serialized form. |
|
103 */ |
|
104 private Taglet[] serializedFormTags; |
|
105 |
|
106 /** |
|
107 * The message retriever that will be used to print error messages. |
|
108 */ |
|
109 private MessageRetriever message; |
|
110 |
|
111 /** |
|
112 * Keep track of standard tags. |
|
113 */ |
|
114 private Set standardTags; |
|
115 |
|
116 /** |
|
117 * Keep track of standard tags in lowercase to compare for better |
|
118 * error messages when a tag like @docRoot is mistakenly spelled |
|
119 * lowercase @docroot. |
|
120 */ |
|
121 private Set standardTagsLowercase; |
|
122 |
|
123 /** |
|
124 * Keep track of overriden standard tags. |
|
125 */ |
|
126 private Set overridenStandardTags; |
|
127 |
|
128 /** |
|
129 * Keep track of the tags that may conflict |
|
130 * with standard tags in the future (any custom tag without |
|
131 * a period in its name). |
|
132 */ |
|
133 private Set potentiallyConflictingTags; |
|
134 |
|
135 /** |
|
136 * The set of unseen custom tags. |
|
137 */ |
|
138 private Set unseenCustomTags; |
|
139 |
|
140 /** |
|
141 * True if we do not want to use @since tags. |
|
142 */ |
|
143 private boolean nosince; |
|
144 |
|
145 /** |
|
146 * True if we want to use @version tags. |
|
147 */ |
|
148 private boolean showversion; |
|
149 |
|
150 /** |
|
151 * True if we want to use @author tags. |
|
152 */ |
|
153 private boolean showauthor; |
|
154 |
|
155 /** |
|
156 * Construct a new <code>TagletManager</code>. |
|
157 * @param nosince true if we do not want to use @since tags. |
|
158 * @param showversion true if we want to use @version tags. |
|
159 * @param showauthor true if we want to use @author tags. |
|
160 * @param message the message retriever to print warnings. |
|
161 */ |
|
162 public TagletManager(boolean nosince, boolean showversion, |
|
163 boolean showauthor, MessageRetriever message){ |
|
164 overridenStandardTags = new HashSet(); |
|
165 potentiallyConflictingTags = new HashSet(); |
|
166 standardTags = new HashSet(); |
|
167 standardTagsLowercase = new HashSet(); |
|
168 unseenCustomTags = new HashSet(); |
|
169 customTags = new LinkedHashMap(); |
|
170 this.nosince = nosince; |
|
171 this.showversion = showversion; |
|
172 this.showauthor = showauthor; |
|
173 this.message = message; |
|
174 initStandardTags(); |
|
175 initStandardTagsLowercase(); |
|
176 } |
|
177 |
|
178 /** |
|
179 * Add a new <code>CustomTag</code>. This is used to add a Taglet from within |
|
180 * a Doclet. No message is printed to indicate that the Taglet is properly |
|
181 * registered because these Taglets are typically added for every execution of the |
|
182 * Doclet. We don't want to see this type of error message every time. |
|
183 * @param customTag the new <code>CustomTag</code> to add. |
|
184 */ |
|
185 public void addCustomTag(Taglet customTag) { |
|
186 if (customTag != null) { |
|
187 String name = customTag.getName(); |
|
188 if (customTags.containsKey(name)) { |
|
189 customTags.remove(name); |
|
190 } |
|
191 customTags.put(name, customTag); |
|
192 checkTagName(name); |
|
193 } |
|
194 } |
|
195 |
|
196 /** |
|
197 * Add a new <code>Taglet</code>. Print a message to indicate whether or not |
|
198 * the Taglet was registered properly. |
|
199 * @param classname the name of the class representing the custom tag. |
|
200 * @param tagletPath the path to the class representing the custom tag. |
|
201 */ |
|
202 public void addCustomTag(String classname, String tagletPath) { |
|
203 try { |
|
204 Class customTagClass = null; |
|
205 // construct class loader |
|
206 String cpString = null; // make sure env.class.path defaults to dot |
|
207 |
|
208 // do prepends to get correct ordering |
|
209 cpString = appendPath(System.getProperty("env.class.path"), cpString); |
|
210 cpString = appendPath(System.getProperty("java.class.path"), cpString); |
|
211 cpString = appendPath(tagletPath, cpString); |
|
212 URLClassLoader appClassLoader = new URLClassLoader(pathToURLs(cpString)); |
|
213 customTagClass = appClassLoader.loadClass(classname); |
|
214 Method meth = customTagClass.getMethod("register", |
|
215 new Class[] {Class.forName("java.util.Map")}); |
|
216 Object[] list = customTags.values().toArray(); |
|
217 Taglet lastTag = (list != null && list.length > 0) |
|
218 ? (Taglet) list[list.length-1] : null; |
|
219 meth.invoke(null, new Object[] {customTags}); |
|
220 list = customTags.values().toArray(); |
|
221 Object newLastTag = (list != null&& list.length > 0) |
|
222 ? (Object) list[list.length-1] : null; |
|
223 if (lastTag != newLastTag) { |
|
224 //New taglets must always be added to the end of the LinkedHashMap. |
|
225 //If the current and previous last taglet are not equal, that |
|
226 //means a new Taglet has been added. |
|
227 message.notice("doclet.Notice_taglet_registered", classname); |
|
228 if (newLastTag != null) { |
|
229 checkTaglet(newLastTag); |
|
230 } |
|
231 } |
|
232 } catch (Exception exc) { |
|
233 message.error("doclet.Error_taglet_not_registered", exc.getClass().getName(), classname); |
|
234 } |
|
235 |
|
236 } |
|
237 |
|
238 private String appendPath(String path1, String path2) { |
|
239 if (path1 == null || path1.length() == 0) { |
|
240 return path2 == null ? "." : path2; |
|
241 } else if (path2 == null || path2.length() == 0) { |
|
242 return path1; |
|
243 } else { |
|
244 return path1 + File.pathSeparator + path2; |
|
245 } |
|
246 } |
|
247 |
|
248 /** |
|
249 * Utility method for converting a search path string to an array |
|
250 * of directory and JAR file URLs. |
|
251 * |
|
252 * @param path the search path string |
|
253 * @return the resulting array of directory and JAR file URLs |
|
254 */ |
|
255 private static URL[] pathToURLs(String path) { |
|
256 StringTokenizer st = new StringTokenizer(path, File.pathSeparator); |
|
257 URL[] urls = new URL[st.countTokens()]; |
|
258 int count = 0; |
|
259 while (st.hasMoreTokens()) { |
|
260 URL url = fileToURL(new File(st.nextToken())); |
|
261 if (url != null) { |
|
262 urls[count++] = url; |
|
263 } |
|
264 } |
|
265 if (urls.length != count) { |
|
266 URL[] tmp = new URL[count]; |
|
267 System.arraycopy(urls, 0, tmp, 0, count); |
|
268 urls = tmp; |
|
269 } |
|
270 return urls; |
|
271 } |
|
272 |
|
273 /** |
|
274 * Returns the directory or JAR file URL corresponding to the specified |
|
275 * local file name. |
|
276 * |
|
277 * @param file the File object |
|
278 * @return the resulting directory or JAR file URL, or null if unknown |
|
279 */ |
|
280 private static URL fileToURL(File file) { |
|
281 String name; |
|
282 try { |
|
283 name = file.getCanonicalPath(); |
|
284 } catch (IOException e) { |
|
285 name = file.getAbsolutePath(); |
|
286 } |
|
287 name = name.replace(File.separatorChar, '/'); |
|
288 if (!name.startsWith("/")) { |
|
289 name = "/" + name; |
|
290 } |
|
291 // If the file does not exist, then assume that it's a directory |
|
292 if (!file.isFile()) { |
|
293 name = name + "/"; |
|
294 } |
|
295 try { |
|
296 return new URL("file", "", name); |
|
297 } catch (MalformedURLException e) { |
|
298 throw new IllegalArgumentException("file"); |
|
299 } |
|
300 } |
|
301 |
|
302 |
|
303 /** |
|
304 * Add a new <code>SimpleTaglet</code>. If this tag already exists |
|
305 * and the header passed as an argument is null, move tag to the back of the |
|
306 * list. If this tag already exists and the header passed as an argument is |
|
307 * not null, overwrite previous tag with new one. Otherwise, add new |
|
308 * SimpleTaglet to list. |
|
309 * @param tagName the name of this tag |
|
310 * @param header the header to output. |
|
311 * @param locations the possible locations that this tag |
|
312 * can appear in. |
|
313 */ |
|
314 public void addNewSimpleCustomTag(String tagName, String header, String locations) { |
|
315 if (tagName == null || locations == null) { |
|
316 return; |
|
317 } |
|
318 Taglet tag = (Taglet) customTags.get(tagName); |
|
319 locations = locations.toLowerCase(); |
|
320 if (tag == null || header != null) { |
|
321 customTags.remove(tagName); |
|
322 customTags.put(tagName, new SimpleTaglet(tagName, header, locations)); |
|
323 if (locations != null && locations.indexOf('x') == -1) { |
|
324 checkTagName(tagName); |
|
325 } |
|
326 } else { |
|
327 //Move to back |
|
328 customTags.remove(tagName); |
|
329 customTags.put(tagName, tag); |
|
330 } |
|
331 } |
|
332 |
|
333 /** |
|
334 * Given a tag name, add it to the set of tags it belongs to. |
|
335 */ |
|
336 private void checkTagName(String name) { |
|
337 if (standardTags.contains(name)) { |
|
338 overridenStandardTags.add(name); |
|
339 } else { |
|
340 if (name.indexOf('.') == -1) { |
|
341 potentiallyConflictingTags.add(name); |
|
342 } |
|
343 unseenCustomTags.add(name); |
|
344 } |
|
345 } |
|
346 |
|
347 /** |
|
348 * Check the taglet to see if it is a legacy taglet. Also |
|
349 * check its name for errors. |
|
350 */ |
|
351 private void checkTaglet(Object taglet) { |
|
352 if (taglet instanceof Taglet) { |
|
353 checkTagName(((Taglet) taglet).getName()); |
|
354 } else if (taglet instanceof com.sun.tools.doclets.Taglet) { |
|
355 com.sun.tools.doclets.Taglet legacyTaglet = (com.sun.tools.doclets.Taglet) taglet; |
|
356 customTags.remove(legacyTaglet.getName()); |
|
357 customTags.put(legacyTaglet.getName(), new LegacyTaglet(legacyTaglet)); |
|
358 checkTagName(legacyTaglet.getName()); |
|
359 } else { |
|
360 throw new IllegalArgumentException("Given object is not a taglet."); |
|
361 } |
|
362 } |
|
363 |
|
364 /** |
|
365 * Given a name of a seen custom tag, remove it from the set of unseen |
|
366 * custom tags. |
|
367 * @param name the name of the seen custom tag. |
|
368 */ |
|
369 public void seenCustomTag(String name) { |
|
370 unseenCustomTags.remove(name); |
|
371 } |
|
372 |
|
373 /** |
|
374 * Given an array of <code>Tag</code>s, check for spelling mistakes. |
|
375 * @param doc the Doc object that holds the tags. |
|
376 * @param tags the list of <code>Tag</code>s to check. |
|
377 * @param areInlineTags true if the array of tags are inline and false otherwise. |
|
378 */ |
|
379 public void checkTags(Doc doc, Tag[] tags, boolean areInlineTags) { |
|
380 if (tags == null) { |
|
381 return; |
|
382 } |
|
383 Taglet taglet; |
|
384 for (int i = 0; i < tags.length; i++) { |
|
385 String name = tags[i].name(); |
|
386 if (name.length() > 0 && name.charAt(0) == '@') { |
|
387 name = name.substring(1, name.length()); |
|
388 } |
|
389 if (! (standardTags.contains(name) || customTags.containsKey(name))) { |
|
390 if (standardTagsLowercase.contains(name.toLowerCase())) { |
|
391 message.warning(tags[i].position(), "doclet.UnknownTagLowercase", tags[i].name()); |
|
392 continue; |
|
393 } else { |
|
394 message.warning(tags[i].position(), "doclet.UnknownTag", tags[i].name()); |
|
395 continue; |
|
396 } |
|
397 } |
|
398 //Check if this tag is being used in the wrong location. |
|
399 if((taglet = (Taglet) customTags.get(name)) != null) { |
|
400 if (areInlineTags && ! taglet.isInlineTag()) { |
|
401 printTagMisuseWarn(taglet, tags[i], "inline"); |
|
402 } |
|
403 if ((doc instanceof RootDoc) && ! taglet.inOverview()) { |
|
404 printTagMisuseWarn(taglet, tags[i], "overview"); |
|
405 } else if ((doc instanceof PackageDoc) && ! taglet.inPackage()) { |
|
406 printTagMisuseWarn(taglet, tags[i], "package"); |
|
407 } else if ((doc instanceof ClassDoc) && ! taglet.inType()) { |
|
408 printTagMisuseWarn(taglet, tags[i], "class"); |
|
409 } else if ((doc instanceof ConstructorDoc) && ! taglet.inConstructor()) { |
|
410 printTagMisuseWarn(taglet, tags[i], "constructor"); |
|
411 } else if ((doc instanceof FieldDoc) && ! taglet.inField()) { |
|
412 printTagMisuseWarn(taglet, tags[i], "field"); |
|
413 } else if ((doc instanceof MethodDoc) && ! taglet.inMethod()) { |
|
414 printTagMisuseWarn(taglet, tags[i], "method"); |
|
415 } |
|
416 } |
|
417 } |
|
418 } |
|
419 |
|
420 /** |
|
421 * Given the taglet, the tag and the type of documentation that the tag |
|
422 * was found in, print a tag misuse warning. |
|
423 * @param taglet the taglet representing the misused tag. |
|
424 * @param tag the misused tag. |
|
425 * @param holderType the type of documentation that the misused tag was found in. |
|
426 */ |
|
427 private void printTagMisuseWarn(Taglet taglet, Tag tag, String holderType) { |
|
428 Set locationsSet = new LinkedHashSet(); |
|
429 if (taglet.inOverview()) { |
|
430 locationsSet.add("overview"); |
|
431 } |
|
432 if (taglet.inPackage()) { |
|
433 locationsSet.add("package"); |
|
434 } |
|
435 if (taglet.inType()) { |
|
436 locationsSet.add("class/interface"); |
|
437 } |
|
438 if (taglet.inConstructor()) { |
|
439 locationsSet.add("constructor"); |
|
440 } |
|
441 if (taglet.inField()) { |
|
442 locationsSet.add("field"); |
|
443 } |
|
444 if (taglet.inMethod()) { |
|
445 locationsSet.add("method"); |
|
446 } |
|
447 if (taglet.isInlineTag()) { |
|
448 locationsSet.add("inline text"); |
|
449 } |
|
450 String[] locations = (String[]) locationsSet.toArray(new String[]{}); |
|
451 if (locations == null || locations.length == 0) { |
|
452 //This known tag is excluded. |
|
453 return; |
|
454 } |
|
455 StringBuffer combined_locations = new StringBuffer(); |
|
456 for (int i = 0; i < locations.length; i++) { |
|
457 if (i > 0) { |
|
458 combined_locations.append(", "); |
|
459 } |
|
460 combined_locations.append(locations[i]); |
|
461 } |
|
462 message.warning(tag.position(), "doclet.tag_misuse", |
|
463 "@" + taglet.getName(), holderType, combined_locations.toString()); |
|
464 } |
|
465 |
|
466 /** |
|
467 * Return the array of <code>Taglet</code>s that can |
|
468 * appear in packages. |
|
469 * @return the array of <code>Taglet</code>s that can |
|
470 * appear in packages. |
|
471 */ |
|
472 public Taglet[] getPackageCustomTags() { |
|
473 if (packageTags == null) { |
|
474 initCustomTagArrays(); |
|
475 } |
|
476 return packageTags; |
|
477 } |
|
478 |
|
479 /** |
|
480 * Return the array of <code>Taglet</code>s that can |
|
481 * appear in classes or interfaces. |
|
482 * @return the array of <code>Taglet</code>s that can |
|
483 * appear in classes or interfaces. |
|
484 */ |
|
485 public Taglet[] getTypeCustomTags() { |
|
486 if (typeTags == null) { |
|
487 initCustomTagArrays(); |
|
488 } |
|
489 return typeTags; |
|
490 } |
|
491 |
|
492 /** |
|
493 * Return the array of inline <code>Taglet</code>s that can |
|
494 * appear in comments. |
|
495 * @return the array of <code>Taglet</code>s that can |
|
496 * appear in comments. |
|
497 */ |
|
498 public Taglet[] getInlineCustomTags() { |
|
499 if (inlineTags == null) { |
|
500 initCustomTagArrays(); |
|
501 } |
|
502 return inlineTags; |
|
503 } |
|
504 |
|
505 /** |
|
506 * Return the array of <code>Taglet</code>s that can |
|
507 * appear in fields. |
|
508 * @return the array of <code>Taglet</code>s that can |
|
509 * appear in field. |
|
510 */ |
|
511 public Taglet[] getFieldCustomTags() { |
|
512 if (fieldTags == null) { |
|
513 initCustomTagArrays(); |
|
514 } |
|
515 return fieldTags; |
|
516 } |
|
517 |
|
518 /** |
|
519 * Return the array of <code>Taglet</code>s that can |
|
520 * appear in the serialized form. |
|
521 * @return the array of <code>Taglet</code>s that can |
|
522 * appear in the serialized form. |
|
523 */ |
|
524 public Taglet[] getSerializedFormTags() { |
|
525 if (serializedFormTags == null) { |
|
526 initCustomTagArrays(); |
|
527 } |
|
528 return serializedFormTags; |
|
529 } |
|
530 |
|
531 /** |
|
532 * @return the array of <code>Taglet</code>s that can |
|
533 * appear in the given Doc. |
|
534 */ |
|
535 public Taglet[] getCustomTags(Doc doc) { |
|
536 if (doc instanceof ConstructorDoc) { |
|
537 return getConstructorCustomTags(); |
|
538 } else if (doc instanceof MethodDoc) { |
|
539 return getMethodCustomTags(); |
|
540 } else if (doc instanceof FieldDoc) { |
|
541 return getFieldCustomTags(); |
|
542 } else if (doc instanceof ClassDoc) { |
|
543 return getTypeCustomTags(); |
|
544 } else if (doc instanceof PackageDoc) { |
|
545 return getPackageCustomTags(); |
|
546 } else if (doc instanceof RootDoc) { |
|
547 return getOverviewCustomTags(); |
|
548 } |
|
549 return null; |
|
550 } |
|
551 |
|
552 /** |
|
553 * Return the array of <code>Taglet</code>s that can |
|
554 * appear in constructors. |
|
555 * @return the array of <code>Taglet</code>s that can |
|
556 * appear in constructors. |
|
557 */ |
|
558 public Taglet[] getConstructorCustomTags() { |
|
559 if (constructorTags == null) { |
|
560 initCustomTagArrays(); |
|
561 } |
|
562 return constructorTags; |
|
563 } |
|
564 |
|
565 /** |
|
566 * Return the array of <code>Taglet</code>s that can |
|
567 * appear in methods. |
|
568 * @return the array of <code>Taglet</code>s that can |
|
569 * appear in methods. |
|
570 */ |
|
571 public Taglet[] getMethodCustomTags() { |
|
572 if (methodTags == null) { |
|
573 initCustomTagArrays(); |
|
574 } |
|
575 return methodTags; |
|
576 } |
|
577 |
|
578 /** |
|
579 * Return the array of <code>Taglet</code>s that can |
|
580 * appear in an overview. |
|
581 * @return the array of <code>Taglet</code>s that can |
|
582 * appear in overview. |
|
583 */ |
|
584 public Taglet[] getOverviewCustomTags() { |
|
585 if (overviewTags == null) { |
|
586 initCustomTagArrays(); |
|
587 } |
|
588 return overviewTags; |
|
589 } |
|
590 |
|
591 /** |
|
592 * Initialize the custom tag arrays. |
|
593 */ |
|
594 private void initCustomTagArrays() { |
|
595 Iterator it = customTags.values().iterator(); |
|
596 ArrayList pTags = new ArrayList(customTags.size()); |
|
597 ArrayList tTags = new ArrayList(customTags.size()); |
|
598 ArrayList fTags = new ArrayList(customTags.size()); |
|
599 ArrayList cTags = new ArrayList(customTags.size()); |
|
600 ArrayList mTags = new ArrayList(customTags.size()); |
|
601 ArrayList iTags = new ArrayList(customTags.size()); |
|
602 ArrayList oTags = new ArrayList(customTags.size()); |
|
603 Taglet current; |
|
604 while (it.hasNext()) { |
|
605 current = (Taglet) it.next(); |
|
606 if (current.inPackage() && !current.isInlineTag()) { |
|
607 pTags.add(current); |
|
608 } |
|
609 if (current.inType() && !current.isInlineTag()) { |
|
610 tTags.add(current); |
|
611 } |
|
612 if (current.inField() && !current.isInlineTag()) { |
|
613 fTags.add(current); |
|
614 } |
|
615 if (current.inConstructor() && !current.isInlineTag()) { |
|
616 cTags.add(current); |
|
617 } |
|
618 if (current.inMethod() && !current.isInlineTag()) { |
|
619 mTags.add(current); |
|
620 } |
|
621 if (current.isInlineTag()) { |
|
622 iTags.add(current); |
|
623 } |
|
624 if (current.inOverview() && !current.isInlineTag()) { |
|
625 oTags.add(current); |
|
626 } |
|
627 } |
|
628 packageTags = (Taglet[]) pTags.toArray(new Taglet[] {}); |
|
629 typeTags = (Taglet[]) tTags.toArray(new Taglet[] {}); |
|
630 fieldTags = (Taglet[]) fTags.toArray(new Taglet[] {}); |
|
631 constructorTags = (Taglet[]) cTags.toArray(new Taglet[] {}); |
|
632 methodTags = (Taglet[]) mTags.toArray(new Taglet[] {}); |
|
633 overviewTags = (Taglet[]) oTags.toArray(new Taglet[] {}); |
|
634 inlineTags = (Taglet[]) iTags.toArray(new Taglet[] {}); |
|
635 |
|
636 //Init the serialized form tags |
|
637 serializedFormTags = new Taglet[4]; |
|
638 serializedFormTags[0] = (Taglet) customTags.get("serialData"); |
|
639 serializedFormTags[1] = (Taglet) customTags.get("throws"); |
|
640 serializedFormTags[2] = (Taglet) customTags.get("since"); |
|
641 serializedFormTags[3] = (Taglet) customTags.get("see"); |
|
642 } |
|
643 |
|
644 /** |
|
645 * Initialize standard Javadoc tags for ordering purposes. |
|
646 */ |
|
647 private void initStandardTags() { |
|
648 Taglet temp; |
|
649 customTags.put((temp = new ParamTaglet()).getName(), temp); |
|
650 customTags.put((temp = new ReturnTaglet()).getName(), temp); |
|
651 customTags.put((temp = new ThrowsTaglet()).getName(), temp); |
|
652 customTags.put((temp = new SimpleTaglet("exception", |
|
653 null, SimpleTaglet.METHOD + SimpleTaglet.CONSTRUCTOR)).getName(), temp); |
|
654 if (!nosince) { |
|
655 customTags.put((temp = new SimpleTaglet("since", message.getText("doclet.Since"), |
|
656 SimpleTaglet.ALL)).getName(), temp); |
|
657 } |
|
658 if (showversion) { |
|
659 customTags.put((temp = new SimpleTaglet("version", message.getText("doclet.Version"), |
|
660 SimpleTaglet.PACKAGE + SimpleTaglet.TYPE + SimpleTaglet.OVERVIEW)).getName(), temp); |
|
661 } |
|
662 if (showauthor) { |
|
663 customTags.put((temp = new SimpleTaglet("author", message.getText("doclet.Author"), |
|
664 SimpleTaglet.PACKAGE + SimpleTaglet.TYPE + SimpleTaglet.OVERVIEW)).getName(), temp); |
|
665 } |
|
666 customTags.put((temp = new SimpleTaglet("serialData", message.getText("doclet.SerialData"), |
|
667 SimpleTaglet.EXCLUDED)).getName(), temp); |
|
668 customTags.put((temp = new SimpleTaglet("factory", message.getText("doclet.Factory"), |
|
669 SimpleTaglet.METHOD)).getName(), temp); |
|
670 customTags.put((temp = new SeeTaglet()).getName(), temp); |
|
671 //Standard inline tags |
|
672 customTags.put((temp = new DocRootTaglet()).getName(), temp); |
|
673 customTags.put((temp = new InheritDocTaglet()).getName(), temp); |
|
674 customTags.put((temp = new ValueTaglet()).getName(), temp); |
|
675 customTags.put((temp = new LegacyTaglet(new LiteralTaglet())).getName(), |
|
676 temp); |
|
677 customTags.put((temp = new LegacyTaglet(new CodeTaglet())).getName(), |
|
678 temp); |
|
679 |
|
680 //Keep track of the names of standard tags for error |
|
681 //checking purposes. |
|
682 standardTags.add("param"); |
|
683 standardTags.add("return"); |
|
684 standardTags.add("throws"); |
|
685 standardTags.add("exception"); |
|
686 standardTags.add("since"); |
|
687 standardTags.add("version"); |
|
688 standardTags.add("author"); |
|
689 standardTags.add("see"); |
|
690 standardTags.add("deprecated"); |
|
691 standardTags.add("link"); |
|
692 standardTags.add("linkplain"); |
|
693 standardTags.add("inheritDoc"); |
|
694 standardTags.add("docRoot"); |
|
695 standardTags.add("value"); |
|
696 standardTags.add("serial"); |
|
697 standardTags.add("serialData"); |
|
698 standardTags.add("serialField"); |
|
699 standardTags.add("Text"); |
|
700 standardTags.add("literal"); |
|
701 standardTags.add("code"); |
|
702 } |
|
703 |
|
704 /** |
|
705 * Initialize lowercase version of standard Javadoc tags. |
|
706 */ |
|
707 private void initStandardTagsLowercase() { |
|
708 Iterator it = standardTags.iterator(); |
|
709 while (it.hasNext()) { |
|
710 standardTagsLowercase.add(((String)it.next()).toLowerCase()); |
|
711 } |
|
712 } |
|
713 |
|
714 public boolean isKnownCustomTag(String tagName) { |
|
715 return customTags.containsKey(tagName); |
|
716 } |
|
717 |
|
718 /** |
|
719 * Print a list of {@link Taglet}s that might conflict with |
|
720 * standard tags in the future and a list of standard tags |
|
721 * that have been overriden. |
|
722 */ |
|
723 public void printReport() { |
|
724 printReportHelper("doclet.Notice_taglet_conflict_warn", potentiallyConflictingTags); |
|
725 printReportHelper("doclet.Notice_taglet_overriden", overridenStandardTags); |
|
726 printReportHelper("doclet.Notice_taglet_unseen", unseenCustomTags); |
|
727 } |
|
728 |
|
729 private void printReportHelper(String noticeKey, Set names) { |
|
730 if (names.size() > 0) { |
|
731 String[] namesArray = |
|
732 (String[]) names.toArray(new String[] {}); |
|
733 String result = " "; |
|
734 for (int i = 0; i < namesArray.length; i++) { |
|
735 result += "@" + namesArray[i]; |
|
736 if (i + 1 < namesArray.length) { |
|
737 result += ", "; |
|
738 } |
|
739 } |
|
740 message.notice(noticeKey, result); |
|
741 } |
|
742 } |
|
743 |
|
744 /** |
|
745 * Given the name of a tag, return the corresponding taglet. |
|
746 * Return null if the tag is unknown. |
|
747 * |
|
748 * @param name the name of the taglet to retrieve. |
|
749 * @return return the corresponding taglet. Return null if the tag is |
|
750 * unknown. |
|
751 */ |
|
752 public Taglet getTaglet(String name) { |
|
753 if (name.indexOf("@") == 0) { |
|
754 return (Taglet) customTags.get(name.substring(1)); |
|
755 } else { |
|
756 return (Taglet) customTags.get(name); |
|
757 } |
|
758 |
|
759 } |
|
760 } |