Gradle 5.0 在 buid.gradle.kts 中使用 Kotlin DSL 时导致错误 Val无法重新分配

Cle*_*ent 4 gradle kotlin

这个错误在 gradle 版本 4.10.2 中没有发生

该行classDirectories = files(filesToCover)导致 gradle 抛出错误:

* What went wrong:
Script compilation error:

  Line 80:             classDirectories = files(filesToCover)
                       ^ Val cannot be reassigned
Run Code Online (Sandbox Code Playgroud)

但是,当您查看底层 Java 类时,JacocoReportBase您可以清楚地看到有一个 setter,并且类属性不是最终的。

public abstract class JacocoReportBase extends JacocoBase {
    private FileCollection executionData;
    private FileCollection sourceDirectories;
    private FileCollection classDirectories;
    private FileCollection additionalClassDirs;
    private FileCollection additionalSourceDirs;

    ...

    public void setClassDirectories(FileCollection classDirectories) {
        this.classDirectories = classDirectories;
    }
Run Code Online (Sandbox Code Playgroud)

构建.gradle.kts

tasks {
    withType<KotlinCompile<KotlinJvmOptions>> {
        kotlinOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
        kotlinOptions.jvmTarget = "1.8"
    }

    withType<JacocoReport> {
        reports {
            xml.isEnabled = false
            csv.isEnabled = false
            html.destination = file("$buildDir/jacocoHtml")
        }

        afterEvaluate {
            val filesToAvoidForCoverage = listOf(
                    "/dto",
                    "/config",
                    "AuthenticationMicroServiceKt.class"
            )
            val filesToCover = mutableListOf<String>()
            File("build/classes/kotlin/main/app/example/core/")
                    .walkTopDown()
                    .mapNotNull { file ->
                        var match = false
                        filesToAvoidForCoverage.forEach {
                            if (file.absolutePath.contains(it)) {
                                match = true
                            }
                        }
                        return@mapNotNull if (!match) {
                            file.absolutePath
                        } else {
                            null
                        }
                    }
                    .filter { it.contains(".class") }
                    .toCollection(filesToCover)

            classDirectories = files(filesToCover) // error
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我还在 Github 上发布了一个问题

mad*_*ead 5

我们看一下源代码

\n\n
/**\n * Source sets that coverage should be reported for.\n */\n@PathSensitive(PathSensitivity.RELATIVE)\n@InputFiles\npublic ConfigurableFileCollection getClassDirectories() {\n    return classDirectories;\n}\n\n/**\n * Classes that coverage should be reported for.\n * @deprecated Use {@code getClassDirectories().setFrom(...)}\n */\n@Deprecated\npublic void setClassDirectories(FileCollection classDirectories) {\n    DeprecationLogger.nagUserOfDiscontinuedMethod("JacocoReportBase.setClassDirectories(FileCollection)", "Use getClassDirectories().from(...)");\n    this.classDirectories.setFrom(classDirectories);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

如您所见,getClassDirectories返回类型为ConfigurableFileCollectionsetClassDirectories接受FileCollection。所以这不是一个有效的 Java Beans 属性,因为 getter 和 setter 操作不同的类型。所以 Kotlin 只能看到 getter,它实际上是一个val.

\n\n

您可以尝试直接调用setClassDirectoriessetClassDirectories(\xe2\x80\xa6)而不是),或者按照 Javadocs 的建议classDirectories = \xe2\x80\xa6使用。classDirectories.setFrom

\n\n

它在 4.10.2 中起作用,因为它当时是一个属性(getter 和 setter 类型相同)。这次提交发生了变化。

\n