Java 9 の Javadoc 検索機能を使ってみる

パッケージ製品開発担当の大です。こんにちは。

Java 9では、Javadocに待望の検索機能がつくそうです。Early Access BuildのページからJavadocをダウンロードして開いてみると、こんな感じで右上に検索用のテキストボックスが追加されていますね。

検索可能になったJavadoc

検索可能になったJavadoc(クリックで拡大)

今回はこのJavadocの検索機能について調べてみました。

できること

検索といっても全文検索ではなく、検索できるのは

  • モジュール名
  • パッケージ名
  • クラス等の型名
  • メソッド等のメンバ名
  • その他、新しく追加された「@index」タグで登録された語、フレーズ

に限られています。右上の検察窓に型名やメソッド名の一部を入れると、こんな感じで部分一致するものが絞り込まれてサジェストされます。

入力文字列で絞り込み

入力文字列で絞り込み(クリックで拡大)

最後の「@index」タグで登録された語は「SearchTags」というカテゴリの下に表示されます。

@indexで指定された語

@indexで指定された語(クリックで拡大)

この例で絞り込み表示されている「jdeprscan」や「jdeps」は、jdk9/langtools/src/jdk.jdeps/share/classes/module-info.java で設定されています。

/**
 * Defines tools for analysing dependencies in Java libraries and programs,
 * including the <em>{@index jdeps jdeps tool}</em>,
 * <em>{@index javap javap tool}</em>, and 
 * <em>{@index jdeprscan jdeprscan tool}</em> tools.
 *
 * <p> 
 * This module provides the equivalent of command-line access to the 
 * <em>javap</em> and <em>jdeps</em> tools via the 
 * {@link java.util.spi.ToolProvider ToolProvider} service provider
 * interface (SPI)</p>
 *
 * <p> Instances of the tools can be obtained by calling
 * {@link java.util.spi.ToolProvider#findFirst ToolProvider.findFirst}
 * or the {@linkplain java.util.ServiceLoader service loader} with the name
 * {@code "javap"} or {@code "jdeps"} as appropriate.
 *
 * <p> 
 * <em>jdeprscan</em> only exists as a command line tool, and does not provide
 * any direct API.
 *
 * <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
 * <dt class="simpleTagLabel">Tool Guides:
 * <dd>{@extLink javap_tool_reference javap},
 *     {@extLink jdeprscan_tool_reference jdeprscan},
 *     {@extLink jdeps_tool_reference jdeps}
 * </dl>
 *
 * @provides java.util.spi.ToolProvider
 *
 * @moduleGraph
 * @since 9
 */
module jdk.jdeps {
    requires java.compiler;
    requires jdk.compiler;

    exports com.sun.tools.classfile to jdk.jlink;

    provides java.util.spi.ToolProvider with
        com.sun.tools.javap.Main.JavapToolProvider,
        com.sun.tools.jdeps.Main.JDepsToolProvider;
}

実装

Javadocがローカルのものでもサーバ上のものでも検索は動作します。いったいどうやって実装されているのでしょう?

まず、Java9の標準Docletを使用して使用してJavadocを出力すると、index.htmlと同じ階層にjqueryのフォルダが作成され、jQuery UIJSZipが配置されています。

また、インデックス用のファイルが作成されます。

  • member-search-index.js
  • member-search-index.zip
  • module-search-index.js
  • module-search-index.zip
  • package-search-index.js
  • package-search-index.zip
  • tag-search-index.js
  • tag-search-index.zip
  • type-search-index.js
  • type-search-index.zip

それぞれについてjsとzipのファイルがあります。zipのファイルは展開するとjsonのファイルになり、内容はjsのファイルと同じです。
script.jsを読んだ感じ、Ajaxで読み込んだzipをJSZipで展開してjsonとして読み込むんですが、それがうまくいかなかった場合にはjsファイルのほうを読んでるようですね。

    $.get(pathtoroot + "module-search-index.zip")
            .done(function() {
                JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) {
                    var zip = new JSZip(data);
                    zip.load(data);
                    moduleSearchIndex = JSON.parse(zip.file("module-search-index.json").asText());
                });
            });
(中略)
    if (!moduleSearchIndex) {
        createElem(doc, tag, 'module-search-index.js');
    }

上で読み込まれたインデックスファイルは、search.jsでjQuery UIのAutocompleteウィジェットに渡されます。ここで絞り込みが行われるのですね。

使ってみた

実際に使ってみました。

module-info.java

/**
 * モジュールです。
 */
module tekito {
    exports jp.co.hos.tekito;
}

package-info.java

/**
 * パッケージです
 */
package jp.co.hos.tekito;

Tekito.java

package jp.co.hos.tekito;

/**
 * クラスです
 *
 */
public class Tekito {

	/**
	 * メソッドです
	 * {@index タグ タグで検索}
	 * @param s 引数です
	 * @return 戻り値です
	 */
	public int hoge(String s) {
		return 0;
	}

}
なぜかundefinedになる

なぜかundefinedになる(クリックで拡大)

生成されたJavadocにはちゃんと検索テキストボックスがつきましたが、検索しようとするとなぜか型名の前のパッケージ名がundefinedになってしまう。。。Early Access(今回使用したのはjdk-9+181)だからまだ不具合があるんでしょうか?正式リリースされたらまた試してみようと思います。

  • 2017/09/12 修正: 不要なコメントを除去