ContractS開発者ブログ

契約マネジメントシステム「ContractS CLM」の開発者ブログです。株式会社HolmesはContractS株式会社に社名変更しました。

Lombokを利用した開発環境でGradleからJavadocを出力する

エンジニアの友野です。久しぶりのポストですが小ネタです。

日頃、開発時はIDE上でJavadocを参照していたので気にしていませんでしたが、ふと、現状整理するために俯瞰した全体のJavadocドキュメントが欲しくなりました。Lombokコンパイル時にコード生成するため、Javadoc生成時にはLombokが生成するコードがドキュメント化されません。ちなみに、onMethodのように生成したコードにアノテーション付与などするオプションではそもそもJavadoc生成時にビルドエラーになりました。

Lombokにはアノテーションからコード生成するdelombokという機能があります。つまり、delombokしてからJavadocを生成すればLombokが生成したコードのJavadoc化ができるはず。ということで試してみました。

環境

本記事のサンプルコードは以下の環境で動作確認しています。

JVM: OpenJDK Runtime Environment Corretto-11.0.12.7.2 (build 11.0.12+7-LTS)
Gradle: 6.6.1
Lombok: 1.18.12

プラグインの存在

まず初めに、gradle-lombokというプラグインが存在します。このプラグインは以下の機能を提供しており、これを使えばやりたいことは簡単にできます。

it adds the Lombok dependency to the classpath
it simplifies the Eclipse IDE installation
it offers support for delomboking
(訳)
Lombokの依存関係をクラスパスに追加
Eclipse IDEへのインストールの簡易化
delombokのサポート

しかし、以下のいくつかの理由で、このプラグインを参考に自分で書いてみることにしました。

  • すでにLombokは依存関係に追加済み
  • 開発で使用しているIDEIntellij
  • delombok以外の機能は使わなさそう
  • プラグインのコードを見るとシンプルなJavaExecタスクである
  • このプラグインは開発停止中、不具合対応のみ行う状態である

delombokタスクの実装

JavaExecタスクということは、通常のjavaコマンドによる実行をスクリプトに置き換えればうまくいきます。javaコマンドでdelombokを実行するのは以下の通りです(公式サイトから引用)。srcがdelombok対象のディレクトリ、src-delombokedがdelombok結果を格納するディレクトリです。

$ java -jar lombok.jar delombok src -d src-delomboked

これをJavaExecタスクにすると以下のように書けます。lombok.jarはすでにコンパイルのクラスパスに含まれるので、mainを直接指定しています。argsでdelombokを文字列で渡すことで、上記コマンドラインと同じ結果が得られます。
今回はプロダクションコードのJavadocだけで良いので、ソースにはsrc/main/javaを指定しました。

task delombok(type: JavaExec, dependsOn: compileJava) {
    ext.outputDir = file("$buildDir/delombok")

    classpath = sourceSets.main.compileClasspath + sourceSets.main.output.generatedSourcesDirs
    main = 'lombok.launch.Main'
    args('delombok', 'src/main/java', '-d', outputDir)

    doFirst {
        outputDir.deleteDir()
    }
}

JPAメタクラスコンパイルの依存に含んでいるので、compileJavaタスクに依存させてannotationProcesserの出力先も含めていますが、Javadoc出力のためだけであれば、これがなくともdelombokタスクでエラーが出るだけなので動作には問題ありません(気持ちの問題だけ)。

Javadocタスクの設定

次にJavadocを出力する設定です。javaプラグインをインポートしていればタスク定義はすでにあるので、設定だけ追加します。

apply plugin: 'java'

/* JavadocでJava8以降のタグを出力するためのオプション */
def tagOptions = ["apiNote:a:API Note:", "implSpec:a:Implementation Requirements:", "implNote:a:Implementation Note:"]
/* Javadoc生成時のクラスパス */
def javadocClasspath = sourceSets.main.compileClasspath + sourceSets.main.output.generatedSourcesDirs + files("$buildDir/delombok")

javadoc {
    dependsOn([compileJava, delombok])
    classpath = javadocClasspath
    source = delombok.outputDir
    options.tags = tagOptions
    failOnError = false
}

実行は以下の通りです。

$ ./gradlew javadoc

これでdelombokしたソースからJavadocを出力できました!

今回はjavadocの設定で例示しましたが、特定のクラス群だけフィルタしたい場合などは別のJavadocタスクを定義して、sourceに渡す対象を変えてあげれば可能です。

それでは良いJavadocライフを!