typescript-generatorプラグインでJavadocからTSDocを生成したのち、XMLを直接読み込んだらいろいろできそうだなと思いついた。
Enumの値のJavadocと、フィールドで設定された値を出力したい場合があり、試してみたらできたのでメモ。
やりたいこと
エラーコードをEnumとして管理している。
どういった場合のエラーかをJavadoc、エラーコードをフィールドとして保持しているので、Enumの値に付与されたJavadocと、フィールドとして持っている値をファイル出力したい。
実装例
Java
以下のような列挙型を用意。値の参照のため、 @Getter でgetterを生成している。
package example; @lombok.Getter @lombok.RequiredArgsConstructor public enum ExampleEnum { // Javadocなし ZERO("0"), /** 一 */ ONE("1"), /** 二 */ TWO("2"), /** 三 */ THREE("3"), ; private final String value; }
build.gradle
以下のようなタスクを記述。 xmlDoclet タスクなどは前回と同様のため省略。
task enumToCsv() {
dependsOn "compileJava", "xmlDoclet"
doLast {
def javadocXmlFile = "build/typescript-generator/xml-doclet/javadoc.xml" as File
def targetClass = "example.ExampleEnum"
def targetClassPackage = targetClass.substring(0, targetClass.lastIndexOf("."))
// nameやqualifiedは@でフィールドアクセスしないとnullになる
// enumをドットに続けて書くとエラーになるため、文字列にしている
def targetClassNode = new XmlSlurper().parseText(javadocXmlFile.getText("UTF-8"))
.package.find { it.@name == targetClassPackage }
."enum".find { it.@qualified == targetClass }
// 列挙型の値を参照するため、クラスパスからクラスローダーを生成
def urls = sourceSets.main.runtimeClasspath.files.collect { it.toURI().toURL() } as URL[]
def classloader = new URLClassLoader(urls, null as ClassLoader)
// 列挙型を読み込み、XMLと突き合わせ、MapのListを生成
def enumClass = classloader.loadClass(targetClass) as Class<Enum>
def enumContexts = enumClass.enumConstants.findResults { Enum enumValue ->
def name = enumValue.name()
def javadocNode = targetClassNode.constant.find { it.@name == name }
def javadoc = (javadocNode.comment?.text() ?: "").trim()
// Javadocが未設定であれば無視
return javadoc ? [
name : name,
value : enumValue.value,
javadoc: javadoc,
] : null
}
// MapからCSVを出力
def csvText = "name,value,javadoc\r\n" + enumContexts.collect {
"${it.name},${it.value},${it.javadoc}"
}.join("\r\n") + "\r\n"
def csvDir = "build/enum-csv"
(csvDir as File).mkdirs()
def csvFile = "${csvDir}/${enumClass.simpleName}.csv" as File
csvFile.setText(csvText, "MS932")
}
}
gradle enumToCsv すると、 build/enum-csv/ExampleEnum.csv に以下のファイルが出力される。
name,value,javadoc ONE,1,一 TWO,2,二 THREE,3,三
振り返り
実際はもっと複雑なクラスだが、Groovy側で加工することで対応できた。
この手の方法(列挙型+Javadoc+フィールド)を使うことがままあり、その都度Excelやスプレッドシートで別途管理していることもあったので、こうしたことができるのは個人的にはうれしい。
TypeScriptのインターフェース定義として出力したりと、今後の展開も考えている。
xml-docletが更新停止状態なのが惜しい...