Подтвердить что ты не робот

Retrolambda: Lint сбой при использовании лямбда-выражений с retrolambda

Я пытаюсь использовать retrolambda вместе с gradle-retrolambda плагином. В общем, он работает нормально, но когда я компилирую для выпуска, этап lint выходит из строя с исключением:

:playground.dagger:lintVitalReleaseFailed converting ECJ parse tree to Lombok for file D:\....\playground\dagger\MainActivity.java
java.lang.UnsupportedOperationException: Unknown ASTNode child: LambdaExpression
    at lombok.ast.ecj.EcjTreeVisitor.visitOther(EcjTreeVisitor.java:368)
    at lombok.ast.ecj.EcjTreeVisitor.visitEcjNode(EcjTreeVisitor.java:364)
    at lombok.ast.ecj.EcjTreeConverter.visit(EcjTreeConverter.java:295)
    at lombok.ast.ecj.EcjTreeConverter.toTree(EcjTreeConverter.java:236)
    at lombok.ast.ecj.EcjTreeConverter.fillList(EcjTreeConverter.java:282)
    at lombok.ast.ecj.EcjTreeConverter.fillList(EcjTreeConverter.java:252)
    at lombok.ast.ecj.EcjTreeConverter.access$100(EcjTreeConverter.java:141)
    at lombok.ast.ecj.EcjTreeConverter$2.visitMessageSend(EcjTreeConverter.java:1042)
    at lombok.ast.ecj.EcjTreeVisitor.visitEcjNode(EcjTreeVisitor.java:156)
    at lombok.ast.ecj.EcjTreeConverter.visit(EcjTreeConverter.java:295)
    at lombok.ast.ecj.EcjTreeConverter.toTree(EcjTreeConverter.java:236)
    at lombok.ast.ecj.EcjTreeConverter.fillList(EcjTreeConverter.java:282)
    at lombok.ast.ecj.EcjTreeConverter.fillList(EcjTreeConverter.java:252)
    at lombok.ast.ecj.EcjTreeConverter.toBlock(EcjTreeConverter.java:397)
    at lombok.ast.ecj.EcjTreeConverter.access$1500(EcjTreeConverter.java:141)
    at lombok.ast.ecj.EcjTreeConverter$2.visitMethodDeclaration(EcjTreeConverter.java:1241)
    at lombok.ast.ecj.EcjTreeVisitor.visitEcjNode(EcjTreeVisitor.java:152)
    at lombok.ast.ecj.EcjTreeConverter.visit(EcjTreeConverter.java:295)
    at lombok.ast.ecj.EcjTreeConverter.toTree(EcjTreeConverter.java:236)
    at lombok.ast.ecj.EcjTreeConverter.fillList(EcjTreeConverter.java:282)
    at lombok.ast.ecj.EcjTreeConverter.fillList(EcjTreeConverter.java:252)
    at lombok.ast.ecj.EcjTreeConverter.access$100(EcjTreeConverter.java:141)
    at lombok.ast.ecj.EcjTreeConverter$2.createNormalTypeBody(EcjTreeConverter.java:563)
    at lombok.ast.ecj.EcjTreeConverter$2.visitTypeDeclaration(EcjTreeConverter.java:486)
    at lombok.ast.ecj.EcjTreeVisitor.visitEcjNode(EcjTreeVisitor.java:48)
    at lombok.ast.ecj.EcjTreeConverter.visit(EcjTreeConverter.java:295)
    at lombok.ast.ecj.EcjTreeConverter.toTree(EcjTreeConverter.java:236)
    at lombok.ast.ecj.EcjTreeConverter.fillList(EcjTreeConverter.java:282)
    at lombok.ast.ecj.EcjTreeConverter.fillList(EcjTreeConverter.java:252)
    at lombok.ast.ecj.EcjTreeConverter.access$100(EcjTreeConverter.java:141)
    at lombok.ast.ecj.EcjTreeConverter$2.visitCompilationUnitDeclaration(EcjTreeConverter.java:441)
    at lombok.ast.ecj.EcjTreeVisitor.visitEcjNode(EcjTreeVisitor.java:264)
    at lombok.ast.ecj.EcjTreeConverter.visit(EcjTreeConverter.java:295)
    at com.android.tools.lint.EcjParser.parseJava(EcjParser.java:407)
    at com.android.tools.lint.client.api.JavaVisitor.visitFile(JavaVisitor.java:236)
    at com.android.tools.lint.client.api.LintDriver.checkJava(LintDriver.java:1491)
    at com.android.tools.lint.client.api.LintDriver.runFileDetectors(LintDriver.java:1026)
    at com.android.tools.lint.client.api.LintDriver.checkProject(LintDriver.java:882)
    at com.android.tools.lint.client.api.LintDriver.analyze(LintDriver.java:433)
    at com.android.tools.lint.client.api.LintDriver.analyze(LintDriver.java:374)
    at com.android.tools.lint.LintCliClient.run(LintCliClient.java:130)
    at com.android.build.gradle.internal.LintGradleClient.run(LintGradleClient.java:112)
    at com.android.build.gradle.internal.LintGradleClient$run.call(Unknown Source)
    at com.android.build.gradle.tasks.Lint.runLint(Lint.groovy:198)
    at com.android.build.gradle.tasks.Lint.this$4$runLint(Lint.groovy)
    at com.android.build.gradle.tasks.Lint$this$4$runLint$1.callCurrent(Unknown Source)
    at com.android.build.gradle.tasks.Lint.lintSingleVariant(Lint.groovy:173)
    at com.android.build.gradle.tasks.Lint$lintSingleVariant$0.callCurrent(Unknown Source)
    at com.android.build.gradle.tasks.Lint.lint(Lint.groovy:75)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:63)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:218)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:211)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:200)
    at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:579)
    at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:562)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:305)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:29)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:68)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:55)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:80)
    at org.gradle.tooling.internal.provider.BuildModelAction.run(BuildModelAction.java:43)
    at org.gradle.tooling.internal.provider.BuildModelAction.run(BuildModelAction.java:30)
    at org.gradle.tooling.internal.provider.ConfiguringBuildAction.run(ConfiguringBuildAction.java:119)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:36)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
    at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:47)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:34)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:35)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:24)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.StartStopIfBuildAndStop.execute(StartStopIfBuildAndStop.java:33)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:71)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:69)
    at org.gradle.util.Swapper.swap(Swapper.java:38)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:69)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:34)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:70)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:34)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.DaemonHygieneAction.execute(DaemonHygieneAction.java:39)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:46)
    at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246)
    at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Есть ли что-нибудь сделать? Конечно, тривиальная работа/работа была бы отключить проверку lint для выпуска. Но я ищу решение, позволяющее сохранить lint.

Ниже приведен модуль приложения build.gradle:

apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
apply plugin: 'com.neenbedankt.android-apt'

configurations {
    apt
}

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    compileSdkVersion 22
    buildToolsVersion "21.1.2"

    defaultConfig {
        minSdkVersion 10
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

repositories {
    maven{
        url 'https://oss.sonatype.org/content/repositories/snapshots/'
    }
}


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.0.0'
    compile 'com.jakewharton:butterknife:6.1.0'
    compile 'com.google.dagger:dagger:2.0-SNAPSHOT'
    compile 'de.greenrobot:eventbus:2.4.0'
    retrolambdaConfig 'net.orfjackal.retrolambda:retrolambda:1.8.1'
    apt 'com.google.dagger:dagger-compiler:2.0-SNAPSHOT'
    provided 'org.glassfish:javax.annotation:10.0-b28'
}

Корень build.gradle:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.1.0'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
        classpath 'me.tatarka:gradle-retrolambda:2.5.0'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}
4b9b3361

Ответ 1

Вы можете использовать специальную версию lombok с lint, которая не скулит о функциях Java 8.

buildscript {
    repositories {
        jcenter()
        ...
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:<version>'
        classpath 'me.tatarka:gradle-retrolambda:<version>'
        classpath 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2'
    }

    // Exclude the version that the android plugin depends on.
    configurations.classpath.exclude group: 'com.android.tools.external.lombok'
}

Таким образом, вы можете продолжать использовать lint для всего проекта, даже с последними версиями плагина Android Gradle.

Примечание. Если вы получаете те же ошибки, попробуйте перевести конфигурацию выше в самый верхний build.gradle файл. Он должен работать тогда.

Ответ 2

Существует проблема GitHub, которая обсуждает эту проблему: https://github.com/evant/gradle-retrolambda/issues/96

В одном из комментариев в этом вопросе упоминается, что lint никогда не работал с retrolambda, а скорее с новейшей версией lint теперь "не работает громко", а не просто пропускает остальную часть файла, когда лямбда была встречаются.

Имея это в виду, кажется, что есть два варианта. Во-первых, вы можете просто отключить lint, как вы упомянули в своем вопросе. Конечно, проблема заключается в том, что вы потеряете преимущество lint сканирования остальной части вашего кода. Второй вариант - откат вашей версии lint таким образом, чтобы она больше не "терпела неудачу", а просто пропускала проверку источника, связанного с лямбдой; Таким образом, lint может все еще сканировать остальную часть вашего исходного кода приложения.

Согласно проблеме GitHub, откат вашей версии lint от 24.0.1 (у вас может быть другая версия) до 24.0.0, похоже, устраняет проблему. Вы можете найти эту информацию в выпуске (ссылка выложена в начале ответа).