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が更新停止状態なのが惜しい...