Java

ドックレットの概要

内容

ドックレットの基本

ドックレットとは、ドックレット API を使用してプログラミング言語 JavaTM で記述した、Javadoc ツールの出力の内容と形式を指定するプログラムです。デフォルトでは、API の HTML 形式のドキュメントを生成するための、Sun が提供する「標準」ドックレットが使用されますが、独自のドックレットを作成して Javadoc の出力を好みの形式にカスタマイズすることもできます。ドックレットは、ドックレット API を使用してゼロから作成することもできますし、標準ドックレットに手を加える形で作成することもできます。

ドックレットは、次の基本手順に従って作成し、使用します。

  1. ドックレットとなる Java プログラムを記述します。ドックレット API を使用するためには、com.sun.javadoc.* をインポートする必要があります。プログラムのエントリポイントは、パラメータとして RootDoc をとる public static boolean start メソッドを含んだクラスになります。
  2. Java Development Kit に含まれるコンパイラ javac を使用してドックレットをコンパイルします。
  3. -doclet <YourDoclet> オプションを指定して javadoc ツールを実行し、ドックレットで指定した出力を生成します。
ドックレット API のクラスファイルは、JDK ソフトウェアの lib/tools.jar ファイルに含まれています。ドックレットをコンパイルしたり、カスタムドックレットを使用したりする場合は、tools.jar がクラスパスになければなりません。このために、javac および javadoc の -classpath オプションを使用できます。

コマンド行オプション -doclet を指定せずに javadoc を実行した場合は、API の HTML 形式のドキュメントを生成する標準ドックレットが使用されます。

com.sun.javadoc パッケージは、ドックレット API を定義したインタフェースで構成されています。これらのインタフェースは JDKTM ソフトウェアの lib/tools.jar ファイルに含まれています。このファイルは、このインタフェースを実装したクラスが含まれる private パッケージでもあります。この tools.jar ファイルには、標準ドックレットを実装したクラスも含まれています。

簡単な例

次に示すのは、小さなクラスが 1 つだけ含まれる簡単なドックレットの例です。この例を見れば、ドックレットの働きの感触をつかむことができるはずです。
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;
    }
}
コードを見るとわかるように、このドックレットは Javadoc の処理対象となるクラスをとり、その名前を標準出力に表示します。

ドックレットに関して最初に留意すべき点は、ドックレット API を使えるようにするために com.sun.javadoc パッケージをインポートしなければならないということです。エントリポイントは、どのドックレットでも public static boolean start メソッドになります。start メソッドはパラメータとして RootDoc をとります。このパラメータには、javadoc の実行時にコマンド行で指定したオプションと、javadoc の処理対象となるクラスとパッケージについての情報が渡されます。

RootDoc では classes というメソッドを定義しています。このメソッドは、Javadoc が解析するクラスを要素として含んだ ClassDoc 配列を返します。for ループでは、ClassDoc 配列に含まれる各クラスの名前を表示します。ClassDoc を println に引き渡すと、ClassDoc が表すクラスの名前が表示されます。

このドックレットを実行するには、まずコンパイルする必要があります。コンパイルは JDK の javac コンパイラで行います。ドックレット API のクラスファイルは JDK ソフトウェアの lib/tools.jar ファイルに含まれています。このため、次のようにしてコンパイラの classpath で tools.jar を指定する必要があります。

javac -classpath C:¥jdk1.2¥lib¥tools.jar ListClass.java 
この ListClass ドックレットを実行するには、コンパイルしたドックレットを javadoc の -doclet タグで指定します。たとえば、このドックレットを MyClass.java というファイルに対して実行するには、次のコマンドを使用します。
% javadoc -doclet ListClass -classpath C:¥jdk1.2¥lib¥tools.jar MyClass.java
出力は、MyClassという文字列になります。このコマンドを使用するには、tools.jar がクラスパスになければなりません。

コマンド行オプションについての注: javadoc -help を実行する場合、Javadoc ツールにはコマンド行オプションが 2 セットあります。一方のセットは一般用で、どのドックレットでも使用できます。もう一方のオプションセットは標準ドックレット専用で、そのオプションはカスタムドックレットを使う場合には使用できません。カスタムドックレットでは、そのドックレット中に含まれるコマンド行オプションを定義することもできます。以下に示すを参照してください。

API のドキュメントを生成させるためには、ドックレットはこの簡単な例よりもかなり複雑になります。Javadoc に生成させる API ドキュメントの形式を変更したい場合は、ドックレットを独自にゼロから作成するのではなく、デフォルトの標準ドックレットに修正を加える形で作成した方がよいといえます。

Javadoc の出力のカスタマイズ

Javadoc ツールの出力をカスタマイズするには、目的の出力内容と出力形式を指定した独自のドックレットを作成する必要があります。デフォルトの出力とほぼ同じ形式の HTML 出力を得たい場合は、ドックレット作成の出発点として標準ドックレットを使用すると便利です。標準ドックレットに含まれる適当なクラスをサブクラス化し、目的の出力が生成されるようにメソッドを追加またはオーバーライドします。また、標準ドックレット全体をコピーして、それに修正を加えていくという方法もあります。標準ドックレットのコピーを出発点として使用する場合は、必要に応じて、各ソースファイルの先頭にある package 文を削除し、新しい独自のパッケージの名前に置き換えてください。

例 - カスタムタグの作成と処理

コメントの中で、@param@return などの標準のタグに加えてカスタムタグ (たとえば、@mytag) を使用したいとします。カスタムタグの中の情報を使用するには、そのカスタムタグを表す Tag のインスタンスをドックレットで使用する必要があります。このためのもっとも簡単な方法の 1 つは、Doc または Doc のサブクラスの tags(String) メソッドを使用することです。このメソッドは、名前が文字列引数に一致するすべてのタグを含んだ Tag の配列を返します。たとえば、methodMethodDoc のインスタンスである場合、次のコードは、このメソッドのコメントに含まれるすべての @mytag を表す Tag オブジェクトの配列を返します。
method.tags("mytag")
@mytag タグ内の情報には、Tagtext メソッドを使用すればアクセスできます。このメソッドは、タグの内容を表す文字列を返すので、用途に応じてこの文字列を解析したり使用したりできます。たとえば、カスタムタグに次のようなコメントが含まれているとします。
@mytag Some dummy text.
この場合、text メソッドは 「Some dummy text.」 という文字列を返します。

以上の考え方を使用して、指定されたタグに一致するインスタンスが持つテキストをすべて表示するドックレットを次に示します。

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());
                    }
                } 
            }
        }
    }
}
このドックレットが探すタグは、変数 tagName により指定されたタグです。tagName には、カスタムタグ、標準タグを問わず、任意のタグの名前を指定できます。このドックレットは結果を標準出力に出力しますが、出力の形式は変更可能です (HTML 形式の出力をファイルに書き出すなど)。

例 - カスタムコマンド行オプションの使用

ドックレットは、カスタムコマンド行オプションをとるようにすることも可能です。ここでは、検索するタグの名前をコマンド行オプションで指定できるように上のドックレットを拡張します。

カスタムオプションをとるドックレットでは、int 型の値を返す optionLength(String option) というメソッドを使用します。ドックレットに認識させるカスタムオプションごとに、オプションを構成する要素 (トークン) の数を optionLength で返すようにします。ここでは、-tag mytag という形式のカスタムオプションが使えるようにしてみます。このカスタムオプションは、-tag オプションそのものと、その値の 2 つの要素で構成されるので、ドックレット内の optionLength メソッドは、-tag オプションに対しては 2 を返さなければなりません。また、認識できないオプションに対しては、0 を返すようにします。

拡張を施したドックレットの完全なコードを次に示します。

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;
    }
}
修正が加えられたこのドックレットでは、変数 tagName をコマンド行オプション -tag で設定するようになっています。また、カスタムオプションに対して 2 を返す optionLength メソッドが使用されています。なお、optionLength は明示的に呼び出す必要はありません。

このドックレットでは、コマンド行オプションを解析して -tag オプションを探す readOptions メソッドも追加されています。このメソッドでは、オプションの情報が含んだ String 型の 2 次元配列を返す Rootdoc.options メソッドを利用しています。たとえば、次のコマンドを実行すると、

javadoc -foo this that -bar other ...
RootDoc.options メソッドは次の戻り値を返します。
options()[0][0] = "-foo"
options()[0][1] = "this"
options()[0][2] = "that"
options()[1][0] = "-bar"
options()[1][1] = "other"
配列の 2 番目のインデックスに入っている要素数は、optionLength メソッドにより求められています。この例では、optionLength は、-foo オプションに対しては 3 を返し、-bar オプションに対しては 2 を返します。

valdOptions メソッドは、コマンド行オプションの指定が正しいかどうかをチェックするための、省略可能なメソッドです。validOptions メソッドは、存在すれば自動的に呼び出されるため、明示的に呼び出す必要はありません。このメソッドでは、オプションの指定が正しい場合は true を返し、正しくない場合は false を返すようにします。また、指定の正しくないコマンド行オプションが見つかった場合に、validOptions から得た適切なエラーメッセージを表示することもできます。このドックレットでは、-tag オプションが 1 つ指定されているかどうか、2 回以上指定されていないかどうかを validOptions でチェックしています。


Copyright © 1995-98 Sun Microsystems, Inc. All Rights Reserved.

コメントの送付先: javadoc-tool@sun.com
Sun