torutkのブログ

ソフトウェア・エンジニアのブログ

Docletを作ってJDK 6で追加されたメソッド一覧を取得する

JDK 6で追加されたクラス、メソッドの一覧があると便利です。JDKのソースファイルには、コメントに@sinceタグでそのメソッドがどのバージョンで追加されたかが記述されているので、これを抜き出す方法が考えられます。

ソースを解析してみると、以下の@sinceバージョン表記がJDK 6で追加されたものです。

  • @since 1.6
  • @since 6.0

ただし、JDK 6で搭載されるようになったJAXB、JAX-WSなどは、それぞれAPIのバージョン番号が@sinceに記述されています。

  • @since JAXB 2.0
  • @since JAX-WS 2.0

JDKには、Doclet APIが提供されており、Javadocコマンドの処理に組み込むプログラムを作ることが出来ます。
Doclet APIを使ってJDKソースコードから@sinceで、1.6および6.0のコメントが記述されたメソッドをプリントする簡単なプログラムを作ってみます。

import com.sun.javadoc.Doclet;
import com.sun.javadoc.RootDoc;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.ExecutableMemberDoc;
import com.sun.javadoc.Tag;

public class ListSince extends Doclet {
    
   public static boolean start(RootDoc root) {
      ClassDoc[] classDocs = root.classes();
      for (ClassDoc classDoc : classDocs) {
         printSinceMembers(classDoc.constructors());
         printSinceMembers(classDoc.methods());
      }
      return true;
   }

   static void printSinceMembers(ExecutableMemberDoc[] memberDocs) {
      for (ExecutableMemberDoc memberDoc : memberDocs) {
         Tag[] tags = memberDoc.tags("since");
         for (Tag tag : tags) {
            if (tag.text().equals("1.6") || tag.text().equals("6.0")) {
               System.out.println(memberDoc);
            }
         }
      }
   }
}

doclet APIは、com.sun.javadocパッケージに含まれます。javadocコマンドでDocletを実行すると、startメソッドが呼び出されます。startメソッドには、解析対象ソースコードの解析情報の根っこ(RootDoc)が引数で渡されます。
今回は、この根っこからクラス情報の一覧をとり、各クラス情報についてコンストラクタ、メソッドの一覧を取り出し、これらに@sinceタグが付与されていたらそれを印字する処理を記述しています。

このDocletのコンパイルには、クラスパスJDKのtools.jarが必要です。

D:\work> java -cp .;C:\java\jdk1.6.0\lib\tools.jar ListSince.java

JDKのソースを展開した場所を指定してjavadocを実行します。

D:\work> javadoc -J-Xmx256m -doclet ListSince -classpath .;C:\java\jdk1.6.0\lib\tools.jar -sourcepath C:\java\jdk1.6.0\src
 -private java.util 2>error
パッケージ java.util のソースファイルを読み込んでいます...
Javadoc 情報を構築しています...
java.util.Arrays.binarySearch(long[], int, int, long)
java.util.Arrays.binarySearch(int[], int, int, int)
java.util.Arrays.binarySearch(short[], int, int, short)
java.util.Arrays.binarySearch(char[], int, int, char)
java.util.Arrays.binarySearch(byte[], int, int, byte)
java.util.Arrays.binarySearch(double[], int, int, double)
java.util.Arrays.binarySearch(float[], int, int, float)
java.util.Arrays.binarySearch(java.lang.Object[], int, int, java.lang.Object)
java.util.Arrays.binarySearch(T[], int, int, T, java.util.Comparator)
java.util.Arrays.copyOf(T[], int)
java.util.Arrays.copyOf(U[], int, java.lang.Class)
java.util.Arrays.copyOf(byte[], int)
java.util.Arrays.copyOf(short[], int)
java.util.Arrays.copyOf(int[], int)
  :(略)

javadocの処理はメモリを喰うので、-J-Xmx オプションでJavaVMのヒープサイズを大きく指定しています。
警告メッセージが出るので、System.errの出力はファイルにリダイレクトしています。
解析対象ソースコードの指定は、ファイル名かパッケージ名、ファイル名一覧を記述したファイルのいずれかで指定します。ファイル名の場合、どうもフルパスで指定しなくてはならないようで、ちょっと大変です。ファイル名一覧を別途作成するのがよさそうです。