ぬるぽ撲滅のために Checker Framework を入れる (with Lombok, Gradle)

  • 7
    いいね
  • 0
    コメント

公式ガイドの通り に Gradle タスクに NullnessChecker を導入したら Lombok アノテーション周りで失敗するようになったので頑張った。

Checker Framework や NullnessCheker については draftcode さんの記事を参照すると良いかも。

実際に動くサンプルプロジェクト:

こうする:

build.gradle
// ...

configurations {
    checkerFrameworkAnnotatedJDK
    annotationProcessors
}

dependencies {
    def checkerFrameworkVersion = '2.1.4'
    checkerFrameworkAnnotatedJDK "org.checkerframework:jdk8:${checkerFrameworkVersion}"
    annotationProcessors "org.checkerframework:checker:${checkerFrameworkVersion}"
    compileOnly "org.checkerframework:checker-qual:${checkerFrameworkVersion}"
    compile 'com.google.code.findbugs:jsr305:3.0.1'

    def lombok = 'org.projectlombok:lombok:1.16.10'
    annotationProcessors lombok
    compileOnly lombok
}

compileJava {
    def processors = [
            'org.checkerframework.checker.nullness.NullnessChecker',
            'lombok.launch.AnnotationProcessorHider\$AnnotationProcessor',
    ]
    options.compilerArgs = [
            '-processor', processors.join(','),
            '-processorpath', configurations.annotationProcessors.asPath,
            "-Xbootclasspath/p:${configurations.checkerFrameworkAnnotatedJDK.asPath}"
    ]
}

// ...

補足

公式ガイドの通りに -processor で注釈プロセッサを明示的してしまうと、lombok の注釈プロセッサの自動起動が働く機能が無効になる。このため Lombok アノテーションを解釈するやつがいなくなりコンパイルできなくなる。javac ドキュメントにも書いてある:

https://docs.oracle.com/javase/jp/6/technotes/tools/windows/javac.html
-processor class1[,class2,class3...]
実行する注釈プロセッサの名前。これを指定した場合、デフォルトの検索処理は省略されます。

なので、Lombok の注釈プロセッサも明示する必要がある。

-processorpath は指定しなくてもクラスパスを漁ってくれるんだけれど、こっちのほうが処理が早そうだからこうした。Checker Framework の公式ガイドもこう書いてるし。

公式ガイドでは tasks.withType(JavaCompile).all { ... とコンパイルタスクに片っ端から適用しているけれど、必要なのは実行時にヌルポが出るのが困るのをなんとかしたかっただけで予めすべて実行されるテストコードは対象にする必要がない。このため、compileJava { ... にしている。