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

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

mercurial