Funny how the Gradle Kotlin DSL makes some things more consistent, but at the same time others less so.
Another alternative that I use and that is equivalent (as far as I know) is this:
tasks.run<JavaExec> {
standardInput = System.`in`
}
This works because run comes pre-defined as an extension property on TaskContainer in the kotlin-dsl. If you jump to to the implementation you will find this:
val TaskContainer.`run`: TaskProvider<org.gradle.api.tasks.JavaExec>
get() = named<org.gradle.api.tasks.JavaExec>("run")
We need the explicit <JavaExec> to get the invoke extension from Gradle to take precedence over the kotlin run scope-function. However since invoke operators are just syntactic sugar for just typing out invoke as a method call, we can also do this:
tasks.run.invoke {
standardInput = System.`in`
}
And now it becomes interesting again, because how is invoke implemented? Let’s have a look:
operator fun <T> NamedDomainObjectProvider<T>.invoke(action: T.() -> Unit) =
configure(action)
So the invoke method simply forwards to configure, which means we can also do this:
tasks.run.configure {
standardInput = System.`in`
}
I am sticking with the first option I mentioned, but having many ways to do the same thing sure is confusing.