JavaDoc を XML で吐き出すメモ
やりたい事が何かと言うと、外部プログラムにおいて、Java クラスのリスト取得と、そのドキュメントを引き抜きたいと考えた。
しかしながら、単純に javadoc のコマンドだけ実行すると、HTML ファイルが出てくる。
これは JavaDoc コマンドの仕様であり、基本動作となっていて、中間ファイルなども出てきていないようだ。
要するに javadoc コマンドの中でパースやら構築やら全部やってしまっていて、その間にあるだろう Javaクラス構成とそのドキュメント構造を引っこ抜く事がこのままだとできない。
でも当たり前だが、同じことをしたい人なんて絶対いるだろうと…むしろ居ない訳がなかろうと思ったのだ。
そして散々悩んだところ、どうも JavaDoc には Doclet なる機構が存在するらしい。
この Doclet とは、JavaDoc で読み取ったデータを出力する際のデータ整形に使われるようだ。
つまりこいつに XML 生成の Doclet 食わせてやれば、XML が吐き出されると思われた。
で、探して見たところ案の定。
そりゃそーだよなと、むしろない訳ないよなと。
って事でやってみた。
Maven3
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- 中略 --> <build> <plugins> <!-- 中略 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <version>2.10.4</version> <configuration> <doclet>com.github.markusbernhardt.xmldoclet.XmlDoclet</doclet> <additionalparam>-d ${project.build.directory} -filename ${project.artifactId}-${project.version}-javadoc.xml</additionalparam> <useStandardDocletOptions>false</useStandardDocletOptions> <docletArtifact> <groupId>com.github.markusbernhardt</groupId> <artifactId>xml-doclet</artifactId> <version>1.0.5</version> </docletArtifact> </configuration> </plugin> </plugins> </build> </project>
こんな風に書いて、 mvn javadoc:test-javadoc
とタイプしてみたところ、target 直下に下記のようなXMLが出てきた。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <root> <package name="net.white_azalea.example"> <comment>日本語パッケージネーム</comment> <class name="UnitTest2" qualified="net.white_azalea.example.UnitTest2" scope="public" abstract="false" error="false" exception="false" externalizable="false" included="true" serializable="false"> <comment>日本語メッセージテスト。. JUnit のテストケース JavaDoc に日本語を入れた場合の動作チェックを行うものである。<br> もちろん複数行で記述され、エンコードは UTF-8 だ。 Created by azalea on 2017/06/03.</comment> <class qualified="java.lang.Object"/> <constructor name="UnitTest2" signature="()" qualified="net.white_azalea.example.UnitTest2" scope="public" final="false" included="true" native="false" synchronized="false" static="false" varArgs="false"/> <method name="toHexString_returnHexString_thatArgsAsUTF8Parsed" signature="()" qualified="net.white_azalea.example.UnitTest2.toHexString_returnHexString_thatArgsAsUTF8Parsed" scope="public" abstract="false" final="false" included="true" native="false" synchronized="false" static="false" varArgs="false"> <comment>toHexString は引数を UTF-8 文字列とみなして数値化、16 進数表現に変換する。.</comment> <return qualified="void"/> <exception qualified="java.io.UnsupportedEncodingException"/> <annotation name="Test" qualified="org.junit.Test"/> </method> <annotation name="RunWith" qualified="org.junit.runner.RunWith"> <argument name="value" primitive="false" array="false"> <type qualified="java.lang.Class"> <generic qualified="?"> <wildcard> <extendsBound qualified="org.junit.runner.Runner"/> </wildcard> </generic> </type> <value>org.junit.runners.JUnit4</value> </argument> </annotation> </class> </package> <package name="net.white_azalea"> <comment>English package name. With descriptions.</comment> <class name="UnitTest1" qualified="net.white_azalea.UnitTest1" scope="public" abstract="false" error="false" exception="false" externalizable="false" included="true" serializable="false"> <comment>UnitTest1 is unit test about UnitTestTarget1 class. Description messages example. Created by azalea on 2017/06/03.</comment> <class qualified="java.lang.Object"/> <constructor name="UnitTest1" signature="()" qualified="net.white_azalea.UnitTest1" scope="public" final="false" included="true" native="false" synchronized="false" static="false" varArgs="false"/> <method name="addHelloPrefix_returnArgWithHello" signature="()" qualified="net.white_azalea.UnitTest1.addHelloPrefix_returnArgWithHello" scope="public" abstract="false" final="false" included="true" native="false" synchronized="false" static="false" varArgs="false"> <comment>addHelloPrefix are return "Hello," prefixed message. Request addHelloPrefix("Hoge") method should return "Hello, Hoge"</comment> <return qualified="void"/> <annotation name="Test" qualified="org.junit.Test"/> </method> <method name="errorTest" signature="()" qualified="net.white_azalea.UnitTest1.errorTest" scope="public" abstract="false" final="false" included="true" native="false" synchronized="false" static="false" varArgs="false"> <comment>Test for error message test.</comment> <return qualified="void"/> <annotation name="Test" qualified="org.junit.Test"/> </method> <annotation name="RunWith" qualified="org.junit.runner.RunWith"> <argument name="value" primitive="false" array="false"> <type qualified="java.lang.Class"> <generic qualified="?"> <wildcard> <extendsBound qualified="org.junit.runner.Runner"/> </wildcard> </generic> </type> <value>org.junit.runners.JUnit4</value> </argument> </annotation> </class> </package> </root>
うん、良さげな感じ。
Gradle
Gradle も 公式ドキュメント を見ると、Doclet の適用方法が乗っているので、これを元に考える。
因みに、サンプルを作るのが面倒だったので、SpringBoot のドキュメント Building a RESTful Web Service の complete ディレクトリを元にさくさくっと。
// 前略 configurations { xmlDoclet } dependencies { compile("org.springframework.boot:spring-boot-starter-web") testCompile('org.springframework.boot:spring-boot-starter-test') testCompile('com.jayway.jsonpath:json-path') xmlDoclet "com.github.markusbernhardt:xml-doclet:1.0.5" } task xmlJavadoc(type: Javadoc) { source = sourceSets.main.allJava destinationDir = reporting.file("rest-api-docs") title = null options.doclet = "com.github.markusbernhardt.xmldoclet.XmlDoclet" options.docletpath = configurations.xmlDoclet.files.asType(List) options.addStringOption("-filename", "export.xml") }
気をつけないといけないのは、 title=null
を設定しておかないと、こんなエラーが出てくる点。
この doclet で対応して居ないせいだろう。
:xmlJavadoc SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. javadoc: エラー - -doctitleは無効なフラグです 使用方法: javadoc [options] [packagenames] [sourcefiles] [@files] -overview <file> HTMLファイルから概要ドキュメントを読み込む -public publicクラスとメンバーのみを示す -protected protected/publicクラスとメンバーを示す(デフォルト) -package package/protected/publicクラスとメンバーを示す -private すべてのクラスとメンバーを示す
あとは実行するだけ。
./gradlew xmlJavadoc
Good Luck!