Doclet Overview |
Here are the basic steps you need to follow to create and use your own doclet:
If you run javadoc without the -doclet command-line option, it will default to the standard doclet to produce HTML-format API documentation.
Package com.sun.javadoc consists of interfaces that define the doclet API. The lib/tools.jar file in the Java 2 SDK contains these interfaces and also a private package with classes that implement the interfaces. The tools.jar file also contains the classes implementing the standard doclet.
As you might be able to guess by looking at the code, this doclet takes the classes upon which Javadoc is operating and prints their names to standard out.import com.sun.javadoc.*; public class ListClass { public static boolean start(RootDoc root) { ClassDoc[] classes = root.classes(); for (int i = 0; i < classes.length; ++i) { System.out.println(classes[i]); } return true; } }
This first thing to notice about the doclet is that it imports the com.sun.javadoc package in order to use the doclet APIs. As with all doclets, the entry point is the public static boolean start method. The start method takes a RootDoc as a parameter. This parameter carries information about any options specified on the command line when javadoc is run, and also about the classes and packages upon which javadoc is operating.
RootDoc defines a classes method that returns a ClassDoc array whose elements represent the classes that Javadoc parses. The for loop then prints out the names of each class in the array. (Passing a ClassDoc to println results in the printing of the name of the class that the ClassDoc represents.)
To run this doclet, you first have to compile it. You can compile it with the javac compiler. The doclet API classfiles are in the file lib/tools.jar in the Java 2 SDK, and you therefore need to include tools.jar on the compiler's classpath, as in this example:
To run the ListClass doclet, you point to the compiled doclet with Javadoc's -doclet tag. For example, to run the doclet on a file called MyClass.java, you could use this command:javac -classpath C:\jdk1.3\lib\tools.jar ListClass.java
The output will be the string "MyClass". Note that this command also requires tools.jar to be on the class path.% javadoc -doclet ListClass -classpath C:\jdk1.3\lib\tools.jar MyClass.java
A note about command-line options: If you run javadoc -help, you'll see that the Javadoc tool has two sets of command-line options. One set is generic and will work with any doclet. The second set of options is special to the standard doclet. Options in this second set will not be available when using custom doclets. Your custom doclets can also define their own command-line options. See the example below.
To generate API documentation, a doclet will have to be considerably more complex than this simple example. If you want to customize the format of the API documentation generated by Javadoc, you may want to start with the default standard doclet and modify it as necessary rather than write your own doclet from scratch.
For an example, see
How
can I modify the standard doclet to produce links to source code
from the API documentation? Please send any corrections to
javadoc-tool@sun.com.
Example - Creating and handling custom tags
Suppose, for example, that you want use a custom tag, say @mytag,
in your documentation comments in addition to the standard tags like
@param and @return. To make use of the information in
your custom tags, you need to have your doclet use instances of
Tag that
represent your custom tags. One of the easiest ways to do that is to use the
tags(String) method of Doc or one of Doc's subclasses.
This method returns an array of Tag objects representing any tags
whose name matches the string argument. For example, if method
is an instance of MethodDoc, then
would return an array of Tag objects representing any @mytag tags in the method's documentation comment. You can then access the information in your @mytag tags with Tag's text method. That method returns a string representing the content of the tag which you can parse or use as needed. For example, if a documentation comment contained one of your custom tags like this:method.tags("mytag")
then the text method would return the string "Some dummy text.".@mytag Some dummy text.
Here's a standalone doclet (not a subclass of the standard doclet) that uses these ideas to print out the text associated with all instances of a specified tag that it finds:
The tag for which this doclet searches is specified by the variable tagName. The value of the tagName string can be any tag name, custom or standard. This doclet writes to standard out, but its output format could be modified, for example, to write HTML output to a file.import com.sun.javadoc.*; public class ListTags { public static boolean start(RootDoc root){ String tagName = "mytag"; writeContents(root.classes(), tagName); return true; } private static void writeContents(ClassDoc[] classes, String tagName) { for (int i=0; i < classes.length; i++) { boolean classNamePrinted = false; MethodDoc[] methods = classes[i].methods(); for (int j=0; j < methods.length; j++) { Tag[] tags = methods[j].tags(tagName); if (tags.length > 0) { if (!classNamePrinted) { System.out.println("\n" + classes[i].name() + "\n"); classNamePrinted = true; } System.out.println(methods[j].name()); for (int k=0; k < tags.length; k++) { System.out.println(" " + tags[k].name() + ": " + tags[k].text()); } } } } } }
Any doclet that uses custom options must have a method called optionLength(String option) that returns an int. For each custom option that you want your doclet to recognize, optionLength must return the number of separate pieces or tokens in the option. For our example, we want to be able to use the custom option of the form -tag mytag. This option has two pieces, the -tag option itself and its value, so the optionLength method in our doclet must return 2 for the -tag option. The optionsLength method should return 0 for unrecognized options.
Here's the full, augmented doclet:
In this modified doclet, the variable tagName is set with the command-line option -tag. It has a optionLength method returns two for our custom option. Note that an explicit call to optionLength isn't required.import com.sun.javadoc.*; public class ListTags { public static boolean start(RootDoc root){ String tagName = readOptions(root.options()); writeContents(root.classes(), tagName); return true; } private static void writeContents(ClassDoc[] classes, String tagName) { for (int i=0; i < classes.length; i++) { boolean classNamePrinted = false; MethodDoc[] methods = classes[i].methods(); for (int j=0; j < methods.length; j++) { Tag[] tags = methods[j].tags(tagName); if (tags.length > 0) { if (!classNamePrinted) { System.out.println("\n" + classes[i].name() + "\n"); classNamePrinted = true; } System.out.println(methods[j].name()); for (int k=0; k < tags.length; k++) { System.out.println(" " + tags[k].name() + ": " + tags[k].text()); } } } } } private static String readOptions(String[][] options) { String tagName = null; for (int i = 0; i < options.length; i++) { String[] opt = options[i]; if (opt[0].equals("-tag")) { tagName = opt[1]; } } return tagName; } public static int optionLength(String option) { if(option.equals("-tag")) { return 2; } return 0; } public static boolean validOptions(String options[][], DocErrorReporter reporter) { boolean foundTagOption = false; for (int i = 0; i < options.length; i++) { String[] opt = options[i]; if (opt[0].equals("-tag")) { if (foundTagOption) { reporter.printError("Only one -tag option allowed."); return false; } else { foundTagOption = true; } } } if (!foundTagOption) { reporter.printError("Usage: javadoc -tag mytag -doclet ListTags ..."); } return foundTagOption; } }
This doclet also adds the readOptions methods that actually parses the command-line options looking for the -tag option. It makes use of the fact that the Rootdoc.options method returns a two-dimensional String array containing option information. For example, given the command
the RootDoc.options method will returnjavadoc -foo this that -bar other ...
The number of elements in the array's second index is determined by the optionLength method. In this example, optionLength returns 3 for option -foo and returns 2 for option -bar.options()[0][0] = "-foo" options()[0][1] = "this" options()[0][2] = "that" options()[1][0] = "-bar" options()[1][1] = "other"
The validOptions method is an optional method that you can use to test the validity of the usage of command-line tags. If the validOptions method is present, it is automatically invoked; you don't have to explicitly call it. It should return true if the option usage is valid, and false otherwise. You can also print appropriate error messages from validOptions when improper usages of command-line options are found. The validOptions method in this example doclet checks that the -tag option is used once and only once.
Copyright © 1995-98 Sun Microsystems, Inc. All Rights Reserved. Please send comments to: javadoc-tool@sun.com |