Gradle Kotlin 脚本,试图通过内置变量分配类补丁

Gradle Kotlin Script, trying to assign classpatch via builtin variable

为什么这样:

val runVersionSplicer by tasks.registering(type = JavaExec::class) {
    classpath = sourceSets.main.runtimeClasspath // error
    main = "com.concurnas.build.VersionSplicer"
}

returns:

Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public val NamedDomainObjectContainer.runtimeClasspath: NamedDomainObjectProvider defined in org.gradle.kotlin.dsl

虽然这样可以正常工作?

val runVersionSplicer by tasks.registering(type = JavaExec::class) {
    classpath = sourceSets["main"].runtimeClasspath
    main = "com.concurnas.build.VersionSplicer"
}

我知道sourceSets.main是这么定义的:

val org.gradle.api.tasks.SourceSetContainer.`main`: NamedDomainObjectProvider<org.gradle.api.tasks.SourceSet>
    get() = named<org.gradle.api.tasks.SourceSet>("main")

但是不应该替换 sourceSets["main"] 构造?

因为其中一个是提供者,另一个是对象。

    正如您所发现的,
  • sourceSets.main 在幕后使用了 NamedDomainObjectCollection.named。如果您查看 named 的 javadoc,您会看到它 returns 以下内容:

    A Provider that will return the object when queried. The object may be created and configured at this point, if not already

  • sourceSets["main"] returns源直接设置,因为它使用NamedDomainObjectCollection.getByName代替,whi:

    The object with the given name. Never returns null.

所以这两个是等价的:

sourceSets.main.get()
sourceSets["main"]

在Groovy中以下是等价的:

sourceSets.main
sourceSets["main"]
sourceSets.getAt("main")

NamedDomainObjectCollection class 实现的getAt 方法的不同语法。这就是为什么您在 Groovy 脚本中看不到很多 get() 但在 Kotlin DSL 脚本中看到很多的原因。