src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java

Thu, 24 Oct 2013 11:22:50 -0700

author
bpatel
date
Thu, 24 Oct 2013 11:22:50 -0700
changeset 2169
667843bd2193
parent 1866
26437287529d
child 2413
fe033d997ddf
permissions
-rw-r--r--

8006248: Since addition of -Xdoclint, javadoc ignores unknown tags
Reviewed-by: jjg

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

mercurial