duke@1: /* jjg@1606: * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: package com.sun.tools.doclets.internal.toolkit.taglets; duke@1: duke@1: import java.io.*; duke@1: import java.lang.reflect.*; duke@1: import java.net.*; duke@1: import java.util.*; duke@1: jjg@1413: import javax.tools.DocumentationTool; jjg@1413: import javax.tools.JavaFileManager; jjg@1413: jjg@1357: import com.sun.javadoc.*; jjg@1357: import com.sun.tools.doclets.internal.toolkit.util.*; jjg@1357: duke@1: /** duke@1: * Manages theTaglets used by doclets. duke@1: * jjg@1359: *

This is NOT part of any supported API. jjg@1359: * If you write code that depends on this, you do so at your own risk. jjg@1359: * This code and its internal interfaces are subject to change or jjg@1359: * deletion without notice. duke@1: * duke@1: * @author Jamie Ho duke@1: * @since 1.4 duke@1: */ duke@1: duke@1: public class TagletManager { duke@1: duke@1: /** jjg@1413: * The default separator for the simple tag option. duke@1: */ jjg@1413: public static final char SIMPLE_TAGLET_OPT_SEPARATOR = ':'; duke@1: duke@1: /** jjg@1413: * The alternate separator for simple tag options. Use this jjg@1413: * when you want the default separator to be in the name of the duke@1: * custom tag. duke@1: */ jjg@1413: public static final String ALT_SIMPLE_TAGLET_OPT_SEPARATOR = "-"; duke@1: duke@1: /** duke@1: * The map of custom tags. duke@1: */ jjg@74: private LinkedHashMap customTags; duke@1: duke@1: /** duke@1: * The array of custom tags that can appear in packages. duke@1: */ duke@1: private Taglet[] packageTags; duke@1: duke@1: /** duke@1: * The array of custom tags that can appear in classes or interfaces. duke@1: */ duke@1: private Taglet[] typeTags; duke@1: duke@1: /** duke@1: * The array of custom tags that can appear in fields. duke@1: */ duke@1: private Taglet[] fieldTags; duke@1: duke@1: /** duke@1: * The array of custom tags that can appear in constructors. duke@1: */ duke@1: private Taglet[] constructorTags; duke@1: duke@1: /** duke@1: * The array of custom tags that can appear in methods. duke@1: */ duke@1: private Taglet[] methodTags; duke@1: duke@1: /** duke@1: * The array of custom tags that can appear in the overview. duke@1: */ duke@1: private Taglet[] overviewTags; duke@1: duke@1: /** duke@1: * The array of custom tags that can appear in comments. duke@1: */ duke@1: private Taglet[] inlineTags; duke@1: duke@1: /** duke@1: * The array of custom tags that can appear in the serialized form. duke@1: */ duke@1: private Taglet[] serializedFormTags; duke@1: duke@1: /** duke@1: * The message retriever that will be used to print error messages. duke@1: */ duke@1: private MessageRetriever message; duke@1: duke@1: /** duke@1: * Keep track of standard tags. duke@1: */ jjg@74: private Set standardTags; duke@1: duke@1: /** duke@1: * Keep track of standard tags in lowercase to compare for better duke@1: * error messages when a tag like @docRoot is mistakenly spelled duke@1: * lowercase @docroot. duke@1: */ jjg@74: private Set standardTagsLowercase; duke@1: duke@1: /** duke@1: * Keep track of overriden standard tags. duke@1: */ jjg@74: private Set overridenStandardTags; duke@1: duke@1: /** duke@1: * Keep track of the tags that may conflict duke@1: * with standard tags in the future (any custom tag without duke@1: * a period in its name). duke@1: */ jjg@74: private Set potentiallyConflictingTags; duke@1: duke@1: /** duke@1: * The set of unseen custom tags. duke@1: */ jjg@74: private Set unseenCustomTags; duke@1: duke@1: /** duke@1: * True if we do not want to use @since tags. duke@1: */ duke@1: private boolean nosince; duke@1: duke@1: /** duke@1: * True if we want to use @version tags. duke@1: */ duke@1: private boolean showversion; duke@1: duke@1: /** duke@1: * True if we want to use @author tags. duke@1: */ duke@1: private boolean showauthor; duke@1: duke@1: /** jjg@1606: * True if we want to use JavaFX-related tags (@propertyGetter, jjg@1606: * @propertySetter, @propertyDescription, @defaultValue, @treatAsPrivate, jjg@1606: * @expert). jjg@1606: */ jjg@1606: private boolean javafx; jjg@1606: jjg@1606: /** duke@1: * Construct a new TagletManager. duke@1: * @param nosince true if we do not want to use @since tags. duke@1: * @param showversion true if we want to use @version tags. duke@1: * @param showauthor true if we want to use @author tags. duke@1: * @param message the message retriever to print warnings. duke@1: */ duke@1: public TagletManager(boolean nosince, boolean showversion, jjg@1606: boolean showauthor, boolean javafx, jjg@1606: MessageRetriever message) { jjg@74: overridenStandardTags = new HashSet(); jjg@74: potentiallyConflictingTags = new HashSet(); jjg@74: standardTags = new HashSet(); jjg@74: standardTagsLowercase = new HashSet(); jjg@74: unseenCustomTags = new HashSet(); jjg@74: customTags = new LinkedHashMap(); duke@1: this.nosince = nosince; duke@1: this.showversion = showversion; duke@1: this.showauthor = showauthor; jjg@1606: this.javafx = javafx; duke@1: this.message = message; duke@1: initStandardTags(); duke@1: initStandardTagsLowercase(); duke@1: } duke@1: duke@1: /** duke@1: * Add a new CustomTag. This is used to add a Taglet from within duke@1: * a Doclet. No message is printed to indicate that the Taglet is properly duke@1: * registered because these Taglets are typically added for every execution of the duke@1: * Doclet. We don't want to see this type of error message every time. duke@1: * @param customTag the new CustomTag to add. duke@1: */ duke@1: public void addCustomTag(Taglet customTag) { duke@1: if (customTag != null) { duke@1: String name = customTag.getName(); duke@1: if (customTags.containsKey(name)) { duke@1: customTags.remove(name); duke@1: } duke@1: customTags.put(name, customTag); duke@1: checkTagName(name); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Add a new Taglet. Print a message to indicate whether or not duke@1: * the Taglet was registered properly. duke@1: * @param classname the name of the class representing the custom tag. duke@1: * @param tagletPath the path to the class representing the custom tag. duke@1: */ jjg@1413: public void addCustomTag(String classname, JavaFileManager fileManager, String tagletPath) { duke@1: try { jjg@74: Class customTagClass = null; duke@1: // construct class loader duke@1: String cpString = null; // make sure env.class.path defaults to dot duke@1: jjg@1413: ClassLoader tagClassLoader; jjg@1413: if (fileManager != null && fileManager.hasLocation(DocumentationTool.Location.TAGLET_PATH)) { jjg@1413: tagClassLoader = fileManager.getClassLoader(DocumentationTool.Location.TAGLET_PATH); jjg@1413: } else { jjg@1413: // do prepends to get correct ordering jjg@1413: cpString = appendPath(System.getProperty("env.class.path"), cpString); jjg@1413: cpString = appendPath(System.getProperty("java.class.path"), cpString); jjg@1413: cpString = appendPath(tagletPath, cpString); jjg@1413: tagClassLoader = new URLClassLoader(pathToURLs(cpString)); jjg@1413: } jjg@1413: jjg@1413: customTagClass = tagClassLoader.loadClass(classname); duke@1: Method meth = customTagClass.getMethod("register", mcimadamore@184: new Class[] {java.util.Map.class}); duke@1: Object[] list = customTags.values().toArray(); duke@1: Taglet lastTag = (list != null && list.length > 0) duke@1: ? (Taglet) list[list.length-1] : null; duke@1: meth.invoke(null, new Object[] {customTags}); duke@1: list = customTags.values().toArray(); duke@1: Object newLastTag = (list != null&& list.length > 0) jjg@74: ? list[list.length-1] : null; duke@1: if (lastTag != newLastTag) { duke@1: //New taglets must always be added to the end of the LinkedHashMap. duke@1: //If the current and previous last taglet are not equal, that duke@1: //means a new Taglet has been added. duke@1: message.notice("doclet.Notice_taglet_registered", classname); duke@1: if (newLastTag != null) { duke@1: checkTaglet(newLastTag); duke@1: } duke@1: } duke@1: } catch (Exception exc) { duke@1: message.error("doclet.Error_taglet_not_registered", exc.getClass().getName(), classname); duke@1: } duke@1: duke@1: } duke@1: duke@1: private String appendPath(String path1, String path2) { duke@1: if (path1 == null || path1.length() == 0) { duke@1: return path2 == null ? "." : path2; duke@1: } else if (path2 == null || path2.length() == 0) { duke@1: return path1; duke@1: } else { duke@1: return path1 + File.pathSeparator + path2; duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Utility method for converting a search path string to an array duke@1: * of directory and JAR file URLs. duke@1: * duke@1: * @param path the search path string duke@1: * @return the resulting array of directory and JAR file URLs duke@1: */ jjg@1383: private URL[] pathToURLs(String path) { jjg@1383: Set urls = new LinkedHashSet(); jjg@1383: for (String s: path.split(File.pathSeparator)) { jjg@1383: if (s.isEmpty()) continue; jjg@1383: try { jjg@1383: urls.add(new File(s).getAbsoluteFile().toURI().toURL()); jjg@1383: } catch (MalformedURLException e) { jjg@1383: message.error("doclet.MalformedURL", s); duke@1: } duke@1: } jjg@1383: return urls.toArray(new URL[urls.size()]); duke@1: } duke@1: duke@1: duke@1: /** duke@1: * Add a new SimpleTaglet. If this tag already exists duke@1: * and the header passed as an argument is null, move tag to the back of the duke@1: * list. If this tag already exists and the header passed as an argument is duke@1: * not null, overwrite previous tag with new one. Otherwise, add new duke@1: * SimpleTaglet to list. duke@1: * @param tagName the name of this tag duke@1: * @param header the header to output. duke@1: * @param locations the possible locations that this tag duke@1: * can appear in. duke@1: */ duke@1: public void addNewSimpleCustomTag(String tagName, String header, String locations) { duke@1: if (tagName == null || locations == null) { duke@1: return; duke@1: } jjg@74: Taglet tag = customTags.get(tagName); duke@1: locations = locations.toLowerCase(); duke@1: if (tag == null || header != null) { duke@1: customTags.remove(tagName); duke@1: customTags.put(tagName, new SimpleTaglet(tagName, header, locations)); duke@1: if (locations != null && locations.indexOf('x') == -1) { duke@1: checkTagName(tagName); duke@1: } duke@1: } else { duke@1: //Move to back duke@1: customTags.remove(tagName); duke@1: customTags.put(tagName, tag); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Given a tag name, add it to the set of tags it belongs to. duke@1: */ duke@1: private void checkTagName(String name) { duke@1: if (standardTags.contains(name)) { duke@1: overridenStandardTags.add(name); duke@1: } else { duke@1: if (name.indexOf('.') == -1) { duke@1: potentiallyConflictingTags.add(name); duke@1: } duke@1: unseenCustomTags.add(name); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Check the taglet to see if it is a legacy taglet. Also duke@1: * check its name for errors. duke@1: */ duke@1: private void checkTaglet(Object taglet) { duke@1: if (taglet instanceof Taglet) { duke@1: checkTagName(((Taglet) taglet).getName()); duke@1: } else if (taglet instanceof com.sun.tools.doclets.Taglet) { duke@1: com.sun.tools.doclets.Taglet legacyTaglet = (com.sun.tools.doclets.Taglet) taglet; duke@1: customTags.remove(legacyTaglet.getName()); duke@1: customTags.put(legacyTaglet.getName(), new LegacyTaglet(legacyTaglet)); duke@1: checkTagName(legacyTaglet.getName()); duke@1: } else { duke@1: throw new IllegalArgumentException("Given object is not a taglet."); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Given a name of a seen custom tag, remove it from the set of unseen duke@1: * custom tags. duke@1: * @param name the name of the seen custom tag. duke@1: */ duke@1: public void seenCustomTag(String name) { duke@1: unseenCustomTags.remove(name); duke@1: } duke@1: duke@1: /** duke@1: * Given an array of Tags, check for spelling mistakes. duke@1: * @param doc the Doc object that holds the tags. duke@1: * @param tags the list of Tags to check. duke@1: * @param areInlineTags true if the array of tags are inline and false otherwise. duke@1: */ duke@1: public void checkTags(Doc doc, Tag[] tags, boolean areInlineTags) { duke@1: if (tags == null) { duke@1: return; duke@1: } duke@1: Taglet taglet; duke@1: for (int i = 0; i < tags.length; i++) { duke@1: String name = tags[i].name(); duke@1: if (name.length() > 0 && name.charAt(0) == '@') { duke@1: name = name.substring(1, name.length()); duke@1: } duke@1: if (! (standardTags.contains(name) || customTags.containsKey(name))) { duke@1: if (standardTagsLowercase.contains(name.toLowerCase())) { duke@1: message.warning(tags[i].position(), "doclet.UnknownTagLowercase", tags[i].name()); duke@1: continue; duke@1: } else { duke@1: message.warning(tags[i].position(), "doclet.UnknownTag", tags[i].name()); duke@1: continue; duke@1: } duke@1: } duke@1: //Check if this tag is being used in the wrong location. jjg@74: if ((taglet = customTags.get(name)) != null) { duke@1: if (areInlineTags && ! taglet.isInlineTag()) { duke@1: printTagMisuseWarn(taglet, tags[i], "inline"); duke@1: } duke@1: if ((doc instanceof RootDoc) && ! taglet.inOverview()) { duke@1: printTagMisuseWarn(taglet, tags[i], "overview"); duke@1: } else if ((doc instanceof PackageDoc) && ! taglet.inPackage()) { duke@1: printTagMisuseWarn(taglet, tags[i], "package"); duke@1: } else if ((doc instanceof ClassDoc) && ! taglet.inType()) { duke@1: printTagMisuseWarn(taglet, tags[i], "class"); duke@1: } else if ((doc instanceof ConstructorDoc) && ! taglet.inConstructor()) { duke@1: printTagMisuseWarn(taglet, tags[i], "constructor"); duke@1: } else if ((doc instanceof FieldDoc) && ! taglet.inField()) { duke@1: printTagMisuseWarn(taglet, tags[i], "field"); duke@1: } else if ((doc instanceof MethodDoc) && ! taglet.inMethod()) { duke@1: printTagMisuseWarn(taglet, tags[i], "method"); duke@1: } duke@1: } duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Given the taglet, the tag and the type of documentation that the tag duke@1: * was found in, print a tag misuse warning. duke@1: * @param taglet the taglet representing the misused tag. duke@1: * @param tag the misused tag. duke@1: * @param holderType the type of documentation that the misused tag was found in. duke@1: */ duke@1: private void printTagMisuseWarn(Taglet taglet, Tag tag, String holderType) { jjg@74: Set locationsSet = new LinkedHashSet(); duke@1: if (taglet.inOverview()) { duke@1: locationsSet.add("overview"); duke@1: } duke@1: if (taglet.inPackage()) { duke@1: locationsSet.add("package"); duke@1: } duke@1: if (taglet.inType()) { duke@1: locationsSet.add("class/interface"); duke@1: } duke@1: if (taglet.inConstructor()) { duke@1: locationsSet.add("constructor"); duke@1: } duke@1: if (taglet.inField()) { duke@1: locationsSet.add("field"); duke@1: } duke@1: if (taglet.inMethod()) { duke@1: locationsSet.add("method"); duke@1: } duke@1: if (taglet.isInlineTag()) { duke@1: locationsSet.add("inline text"); duke@1: } jjg@74: String[] locations = locationsSet.toArray(new String[]{}); duke@1: if (locations == null || locations.length == 0) { duke@1: //This known tag is excluded. duke@1: return; duke@1: } jjg@1362: StringBuilder combined_locations = new StringBuilder(); duke@1: for (int i = 0; i < locations.length; i++) { duke@1: if (i > 0) { duke@1: combined_locations.append(", "); duke@1: } duke@1: combined_locations.append(locations[i]); duke@1: } duke@1: message.warning(tag.position(), "doclet.tag_misuse", duke@1: "@" + taglet.getName(), holderType, combined_locations.toString()); duke@1: } duke@1: duke@1: /** duke@1: * Return the array of Taglets that can duke@1: * appear in packages. duke@1: * @return the array of Taglets that can duke@1: * appear in packages. duke@1: */ duke@1: public Taglet[] getPackageCustomTags() { duke@1: if (packageTags == null) { duke@1: initCustomTagArrays(); duke@1: } duke@1: return packageTags; duke@1: } duke@1: duke@1: /** duke@1: * Return the array of Taglets that can duke@1: * appear in classes or interfaces. duke@1: * @return the array of Taglets that can duke@1: * appear in classes or interfaces. duke@1: */ duke@1: public Taglet[] getTypeCustomTags() { duke@1: if (typeTags == null) { duke@1: initCustomTagArrays(); duke@1: } duke@1: return typeTags; duke@1: } duke@1: duke@1: /** duke@1: * Return the array of inline Taglets that can duke@1: * appear in comments. duke@1: * @return the array of Taglets that can duke@1: * appear in comments. duke@1: */ duke@1: public Taglet[] getInlineCustomTags() { duke@1: if (inlineTags == null) { duke@1: initCustomTagArrays(); duke@1: } duke@1: return inlineTags; duke@1: } duke@1: duke@1: /** duke@1: * Return the array of Taglets that can duke@1: * appear in fields. duke@1: * @return the array of Taglets that can duke@1: * appear in field. duke@1: */ duke@1: public Taglet[] getFieldCustomTags() { duke@1: if (fieldTags == null) { duke@1: initCustomTagArrays(); duke@1: } duke@1: return fieldTags; duke@1: } duke@1: duke@1: /** duke@1: * Return the array of Taglets that can duke@1: * appear in the serialized form. duke@1: * @return the array of Taglets that can duke@1: * appear in the serialized form. duke@1: */ duke@1: public Taglet[] getSerializedFormTags() { duke@1: if (serializedFormTags == null) { duke@1: initCustomTagArrays(); duke@1: } duke@1: return serializedFormTags; duke@1: } duke@1: duke@1: /** duke@1: * @return the array of Taglets that can duke@1: * appear in the given Doc. duke@1: */ duke@1: public Taglet[] getCustomTags(Doc doc) { duke@1: if (doc instanceof ConstructorDoc) { duke@1: return getConstructorCustomTags(); duke@1: } else if (doc instanceof MethodDoc) { duke@1: return getMethodCustomTags(); duke@1: } else if (doc instanceof FieldDoc) { duke@1: return getFieldCustomTags(); duke@1: } else if (doc instanceof ClassDoc) { duke@1: return getTypeCustomTags(); duke@1: } else if (doc instanceof PackageDoc) { duke@1: return getPackageCustomTags(); duke@1: } else if (doc instanceof RootDoc) { duke@1: return getOverviewCustomTags(); duke@1: } duke@1: return null; duke@1: } duke@1: duke@1: /** duke@1: * Return the array of Taglets that can duke@1: * appear in constructors. duke@1: * @return the array of Taglets that can duke@1: * appear in constructors. duke@1: */ duke@1: public Taglet[] getConstructorCustomTags() { duke@1: if (constructorTags == null) { duke@1: initCustomTagArrays(); duke@1: } duke@1: return constructorTags; duke@1: } duke@1: duke@1: /** duke@1: * Return the array of Taglets that can duke@1: * appear in methods. duke@1: * @return the array of Taglets that can duke@1: * appear in methods. duke@1: */ duke@1: public Taglet[] getMethodCustomTags() { duke@1: if (methodTags == null) { duke@1: initCustomTagArrays(); duke@1: } duke@1: return methodTags; duke@1: } duke@1: duke@1: /** duke@1: * Return the array of Taglets that can duke@1: * appear in an overview. duke@1: * @return the array of Taglets that can duke@1: * appear in overview. duke@1: */ duke@1: public Taglet[] getOverviewCustomTags() { duke@1: if (overviewTags == null) { duke@1: initCustomTagArrays(); duke@1: } duke@1: return overviewTags; duke@1: } duke@1: duke@1: /** duke@1: * Initialize the custom tag arrays. duke@1: */ duke@1: private void initCustomTagArrays() { jjg@74: Iterator it = customTags.values().iterator(); jjg@74: ArrayList pTags = new ArrayList(customTags.size()); jjg@74: ArrayList tTags = new ArrayList(customTags.size()); jjg@74: ArrayList fTags = new ArrayList(customTags.size()); jjg@74: ArrayList cTags = new ArrayList(customTags.size()); jjg@74: ArrayList mTags = new ArrayList(customTags.size()); jjg@74: ArrayList iTags = new ArrayList(customTags.size()); jjg@74: ArrayList oTags = new ArrayList(customTags.size()); bpatel@1324: ArrayList sTags = new ArrayList(); duke@1: Taglet current; duke@1: while (it.hasNext()) { jjg@74: current = it.next(); duke@1: if (current.inPackage() && !current.isInlineTag()) { duke@1: pTags.add(current); duke@1: } duke@1: if (current.inType() && !current.isInlineTag()) { duke@1: tTags.add(current); duke@1: } duke@1: if (current.inField() && !current.isInlineTag()) { duke@1: fTags.add(current); duke@1: } duke@1: if (current.inConstructor() && !current.isInlineTag()) { duke@1: cTags.add(current); duke@1: } duke@1: if (current.inMethod() && !current.isInlineTag()) { duke@1: mTags.add(current); duke@1: } duke@1: if (current.isInlineTag()) { duke@1: iTags.add(current); duke@1: } duke@1: if (current.inOverview() && !current.isInlineTag()) { duke@1: oTags.add(current); duke@1: } duke@1: } jjg@74: packageTags = pTags.toArray(new Taglet[] {}); jjg@74: typeTags = tTags.toArray(new Taglet[] {}); jjg@74: fieldTags = fTags.toArray(new Taglet[] {}); jjg@74: constructorTags = cTags.toArray(new Taglet[] {}); jjg@74: methodTags = mTags.toArray(new Taglet[] {}); jjg@74: overviewTags = oTags.toArray(new Taglet[] {}); jjg@74: inlineTags = iTags.toArray(new Taglet[] {}); duke@1: duke@1: //Init the serialized form tags bpatel@1324: sTags.add(customTags.get("serialData")); bpatel@1324: sTags.add(customTags.get("throws")); bpatel@1324: if (!nosince) bpatel@1324: sTags.add(customTags.get("since")); bpatel@1324: sTags.add(customTags.get("see")); bpatel@1324: serializedFormTags = sTags.toArray(new Taglet[] {}); duke@1: } duke@1: duke@1: /** duke@1: * Initialize standard Javadoc tags for ordering purposes. duke@1: */ duke@1: private void initStandardTags() { duke@1: Taglet temp; duke@1: customTags.put((temp = new ParamTaglet()).getName(), temp); duke@1: customTags.put((temp = new ReturnTaglet()).getName(), temp); duke@1: customTags.put((temp = new ThrowsTaglet()).getName(), temp); duke@1: customTags.put((temp = new SimpleTaglet("exception", duke@1: null, SimpleTaglet.METHOD + SimpleTaglet.CONSTRUCTOR)).getName(), temp); duke@1: if (!nosince) { duke@1: customTags.put((temp = new SimpleTaglet("since", message.getText("doclet.Since"), duke@1: SimpleTaglet.ALL)).getName(), temp); duke@1: } duke@1: if (showversion) { duke@1: customTags.put((temp = new SimpleTaglet("version", message.getText("doclet.Version"), duke@1: SimpleTaglet.PACKAGE + SimpleTaglet.TYPE + SimpleTaglet.OVERVIEW)).getName(), temp); duke@1: } duke@1: if (showauthor) { duke@1: customTags.put((temp = new SimpleTaglet("author", message.getText("doclet.Author"), duke@1: SimpleTaglet.PACKAGE + SimpleTaglet.TYPE + SimpleTaglet.OVERVIEW)).getName(), temp); duke@1: } duke@1: customTags.put((temp = new SimpleTaglet("serialData", message.getText("doclet.SerialData"), duke@1: SimpleTaglet.EXCLUDED)).getName(), temp); duke@1: customTags.put((temp = new SimpleTaglet("factory", message.getText("doclet.Factory"), duke@1: SimpleTaglet.METHOD)).getName(), temp); duke@1: customTags.put((temp = new SeeTaglet()).getName(), temp); duke@1: //Standard inline tags duke@1: customTags.put((temp = new DocRootTaglet()).getName(), temp); duke@1: customTags.put((temp = new InheritDocTaglet()).getName(), temp); duke@1: customTags.put((temp = new ValueTaglet()).getName(), temp); duke@1: customTags.put((temp = new LegacyTaglet(new LiteralTaglet())).getName(), duke@1: temp); duke@1: customTags.put((temp = new LegacyTaglet(new CodeTaglet())).getName(), duke@1: temp); duke@1: duke@1: //Keep track of the names of standard tags for error duke@1: //checking purposes. duke@1: standardTags.add("param"); duke@1: standardTags.add("return"); duke@1: standardTags.add("throws"); duke@1: standardTags.add("exception"); duke@1: standardTags.add("since"); duke@1: standardTags.add("version"); duke@1: standardTags.add("author"); duke@1: standardTags.add("see"); duke@1: standardTags.add("deprecated"); duke@1: standardTags.add("link"); duke@1: standardTags.add("linkplain"); duke@1: standardTags.add("inheritDoc"); duke@1: standardTags.add("docRoot"); duke@1: standardTags.add("value"); duke@1: standardTags.add("serial"); duke@1: standardTags.add("serialData"); duke@1: standardTags.add("serialField"); duke@1: standardTags.add("Text"); duke@1: standardTags.add("literal"); duke@1: standardTags.add("code"); jjg@1606: jjg@1606: if (javafx) { jjg@1606: initJavaFXTags(); jjg@1606: } jjg@1606: } jjg@1606: jjg@1606: /** jjg@1606: * Initialize JavaFX-related tags. jjg@1606: */ jjg@1606: private void initJavaFXTags() { jjg@1606: Taglet temp; jjg@1606: customTags.put((temp = new PropertyGetterTaglet()).getName(), temp); jjg@1606: customTags.put((temp = new PropertySetterTaglet()).getName(), temp); jjg@1606: customTags.put((temp = new SimpleTaglet("propertyDescription", message.getText("doclet.PropertyDescription"), jjg@1606: SimpleTaglet.FIELD + SimpleTaglet.METHOD)).getName(), temp); jjg@1606: customTags.put((temp = new SimpleTaglet("defaultValue", message.getText("doclet.DefaultValue"), jjg@1606: SimpleTaglet.FIELD + SimpleTaglet.METHOD)).getName(), temp); jjg@1606: customTags.put((temp = new SimpleTaglet("treatAsPrivate", null, jjg@1606: SimpleTaglet.FIELD + SimpleTaglet.METHOD + SimpleTaglet.TYPE)).getName(), temp); jjg@1606: customTags.put((temp = new LegacyTaglet(new ExpertTaglet())).getName(), temp); jjg@1606: jjg@1606: standardTags.add("propertyGetter"); jjg@1606: standardTags.add("propertySetter"); jjg@1606: standardTags.add("propertyDescription"); jjg@1606: standardTags.add("defaultValue"); jjg@1606: standardTags.add("treatAsPrivate"); jjg@1606: standardTags.add("expert"); duke@1: } duke@1: duke@1: /** duke@1: * Initialize lowercase version of standard Javadoc tags. duke@1: */ duke@1: private void initStandardTagsLowercase() { mcimadamore@184: Iterator it = standardTags.iterator(); duke@1: while (it.hasNext()) { mcimadamore@184: standardTagsLowercase.add(it.next().toLowerCase()); duke@1: } duke@1: } duke@1: duke@1: public boolean isKnownCustomTag(String tagName) { duke@1: return customTags.containsKey(tagName); duke@1: } duke@1: duke@1: /** duke@1: * Print a list of {@link Taglet}s that might conflict with duke@1: * standard tags in the future and a list of standard tags duke@1: * that have been overriden. duke@1: */ duke@1: public void printReport() { duke@1: printReportHelper("doclet.Notice_taglet_conflict_warn", potentiallyConflictingTags); duke@1: printReportHelper("doclet.Notice_taglet_overriden", overridenStandardTags); duke@1: printReportHelper("doclet.Notice_taglet_unseen", unseenCustomTags); duke@1: } duke@1: jjg@74: private void printReportHelper(String noticeKey, Set names) { duke@1: if (names.size() > 0) { jjg@74: String[] namesArray = names.toArray(new String[] {}); duke@1: String result = " "; duke@1: for (int i = 0; i < namesArray.length; i++) { duke@1: result += "@" + namesArray[i]; duke@1: if (i + 1 < namesArray.length) { duke@1: result += ", "; duke@1: } duke@1: } duke@1: message.notice(noticeKey, result); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Given the name of a tag, return the corresponding taglet. duke@1: * Return null if the tag is unknown. duke@1: * duke@1: * @param name the name of the taglet to retrieve. duke@1: * @return return the corresponding taglet. Return null if the tag is duke@1: * unknown. duke@1: */ duke@1: public Taglet getTaglet(String name) { duke@1: if (name.indexOf("@") == 0) { jjg@74: return customTags.get(name.substring(1)); duke@1: } else { jjg@74: return customTags.get(name); duke@1: } duke@1: duke@1: } duke@1: }