errorprone gradle plugin の備忘メモ

動作環境

利用例の参考ページ

ググってもこのサイトしか出てこなかったorz

導入手順

buildscript {
    repositories {
        jcenter()
        maven { url "https://plugins.gradle.org/m2/" }//★★
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.+'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
        classpath "io.realm:realm-gradle-plugin:3.1.4"

        classpath 'com.github.gfx.ribbonizer:plugin:1.0.0'

        classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.10' //★★
    }
    configurations.all {
        resolutionStrategy {
            force 'net.sf.proguard:proguard-gradle:5.3.3'
        }
    }
}

allprojects {
    repositories {
        jcenter()
        mavenCentral()                      //★★
        maven { url "https://jitpack.io" }   //★★
    }

    //★★
    gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
            options.encoding = 'UTF-8'
            if(it.source.asPath.indexOf("generated") != -1){
                options.compilerArgs << "-Xmaxerrs" << "500"
                //[TODO] use errorprone plugin //△△
                //options.compilerArgs << '-XepDisableWarningsInGeneratedCode'
            }
            else {
                options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
                //[TODO] use errorprone plugin //△△
                //options.compilerArgs << '-Werror'
                //options.compilerArgs += [ '-Xep:DeadException:WARN', '-Xep:GuardedByValidator:OFF' ]
            }
        }
    }

    task build_tasks << {
        def list = []

        tasks.findAll { it.group == "build" }.unique(false) { it.name }.each { task ->
            list.add(task.name);
        }

        list.unique(false).each{
            println(it)
        }
    }

    tasks.whenTaskAdded { task ->

        if (task.name.indexOf("Test")!=-1) {
            task.enabled = false
        }

        if (task.name.indexOf("assemble")!=-1) {
            task.group = "build"
        }
        if (task.name.indexOf("crashlytics")!=-1) {
            task.group = "build"
        }
        if (task.name.indexOf("clean")!=-1) {
            task.group = "build"
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

task showVersion  {
    println "[name   ]" +  buildscript.configurations.classpath.resolvedConfiguration.firstLevelModuleDependencies.moduleName
    println "[version]" +  buildscript.configurations.classpath.resolvedConfiguration.firstLevelModuleDependencies.moduleVersion
}
  • mainP
apply plugin: 'com.android.application'
apply plugin: 'com.github.gfx.ribbonizer'
apply plugin: 'net.ltgt.errorprone' //★★

うまくいった環境A

root
  build.gradle
  mainP
    |- build.gradle
  libP
     |- build.gradle

うまく動かない環境B

root
  build.gradle
  mainP
    |- build.gradle
  wearP
     |- build.gradle //ここでエラー
  • wearP側に、apply plugin: 'net.ltgt.errorprone' を指定していないが動くような挙動をして怒られる
    • 「存在しないコンパイルオプションを指定しないでください」 と怒られる

理由

  • 環境Aはソース単位だが、環境Bはソース一式でくるため、asPathが正常に判定できない
  • wearAppもgeneretedフォルダにコードが生成されるからのよう。
  • 対象ソースコード上に@generated Annotationが存在しない時
    • 通常のjavaCのコンパイラーに渡される =>そんなオプション無いよエラー
    • ソースコードが対象の時のみerrorproneが割込フックしているような挙動

対策

  • rootからerrorphone用のjavaCの記述をコメンド
  • mainPの方に tasks.withType(JavaCompile) の記述を入れる
  • もしくは指定しない*1

そもそも問題

-XepDisableWarningsInGeneratedCode

の指定はそもそも、data-bindingのテンプレート不備で、Overideアノテーションが抜けてますよエラーが大量に出るためだからな・・

errorprone自体はgoogoleのライブラリらしいのに(汗

GoogleIOのデモのために新しい技術の対応するのはイイんだけど、G様は安定化の工数を割いていない気がする

Java9では動かないという話

Installation の<My build system isn’t listed here> に

Error-prone is implemented as a compiler hook, using an internal mechanism in javac. To install our hook, we override the main() method in com.sun.tools.javac.main.Main.

確かに書いてある・・・

  • java9 では
    • com.sun.tools.XXX 廃止
    • Jigsaw によりリフレクションは禁止(packageを厳格化)

あたりだからな。。

*1:ワーニングが余計に出るけど無視をする系