visible true

技術的なメモを書く

Retrolambda+Robolectricでテストを動かす為にtask.name ==~ /compileTest.*Java/をフックしているのにcom.sun.tools.javac.code.Symbol$CompletionFailure: java.lang.invoke.MethodTypeが見つからずエラーになる問題

タイトル長いな。

問題

Retrolambda+Robolectricでテストを動かす為に以下の様なコードをbuild.gradleに書く必要があります。正規表現で一致するタスクの時にビルドパスをretrolambdaに向けたり、コンパイラをJava8に変更するコードです。

参考 : Android - λ... < ユニットテストのテストコード上で Retrolambda が使えない - Qiita

tasks.withType(Test) {
    project.tasks
            .findAll {
        task -> (task.name ==~ /compileTest.*Java/ )
    }
    .each { task ->
        task.doFirst {
            def buildPath = "$project.buildDir/retrolambda"
            def jarPath = "$buildPath/$project.android.compileSdkVersion"
            def javac = "${project.retrolambda.tryGetJdk()}/bin/javac"

            sourceCompatibility = JavaVersion.VERSION_1_8
            targetCompatibility = JavaVersion.VERSION_1_8

            options.fork = true
            options.compilerArgs += ["-bootclasspath", "$jarPath/android.jar"]
            options.forkOptions.executable = javac
        }
    }
}

しかし、android gradle pluginが1.1.0以上の環境ではcom.sun.tools.javac.code.Symbol$CompletionFailure: java.lang.invoke.MethodTypeが見つからずエラーになってしまいます。

原因

android gradle plugin1.1.0からJVMを利用したUnit Testをサポートしました。それに伴いTestのコンパイル時のタスク名が変わりました。

compileTestDebugJava -> compileDebugUnitTestJava

AndroidTestの場合はcompileDebugAndroidTestJavaという風に変わっています。

対応

タスクをフックする正規表現を更新すればオッケーです。

tasks.withType(Test) {
    project.tasks
            .findAll {
        task -> (task.name ==~ /compile.*?TestJava/)
    }
    .each { task ->
        task.doFirst {
            def buildPath = "$project.buildDir/retrolambda"
            def jarPath = "$buildPath/$project.android.compileSdkVersion"
            def javac = "${project.retrolambda.tryGetJdk()}/bin/javac"

            sourceCompatibility = JavaVersion.VERSION_1_8
            targetCompatibility = JavaVersion.VERSION_1_8

            options.fork = true
            options.compilerArgs += ["-bootclasspath", "$jarPath/android.jar"]
            options.forkOptions.executable = javac
        }
    }
}

まとめ

この辺の追従って大変だなー