So I've been playing around with gradle's kotlin dsl and my buildscript has grown to a point where I wanted to introduce custom tasks for better organization.
Here's a MWE of my build.gradle.kts:
open class CustomTask : DefaultTask() {
var dir = File(".")
@TaskAction
fun action() {
println("CustomTask.dir: ${dir.absolutePath}")
}
}
tasks.create<CustomTask>("debug") {
//dir = File(".gradle") // Script compilation fails if I uncomment this line
}
tasks.create("traverseDir") {
doLast {
traverseDir(File("gradle/wrapper/gradle-wrapper.jar"))
}
}
fun traverseDir(file: File) {
var dir: File? = file.parentFile
while (dir != null) {
println(dir)
dir = dir.parentFile
}
}
Output of ./gradlew debug traverseDir without task configuration (meaning commented dir assignment):
> Task :debug
CustomTask.dir: /home/.../gradle-kotlin_dsl-smart_cast_error/.
> Task :traverseDir
gradle/wrapper
gradle
BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 executed
Output of ./gradlew debug traverseDir with task configuration (meaning uncommented dir assignment):
> Configure project :
e: /home/.../gradle-kotlin_dsl-smart_cast_error/build.gradle.kts:32:11: Smart cast to 'File' is impossible, because 'dir' is a local variable that is captured by a changing closure
FAILURE: Build failed with an exception.
* Where:
Build file '/home/.../gradle-kotlin_dsl-smart_cast_error/build.gradle.kts' line: 32
* What went wrong:
Script compilation error:
Line 32: dir = dir.parentFile
^ Smart cast to 'File' is impossible, because 'dir' is a local variable that is captured by a changing closure
1 error
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 0s
Those two tasks have no connection to each other (other than them being defined in the same buildscript file), yet when I try to configure an instance of my custom task (i.e. uncomment the dir = ... line) the build fails because of a script compilation error in the - seemingly unrelated - traverseDir function.
Further weirdness:
- The error does not occur if I rename either of the
dirvariables (i.e. todir_) - then the build succeeds. - Changing the line
dir = dir.parentFiletodir = dir?.parentFilemakes the build succeed.
Why does this happen?
Output of ./gradlew --version:
------------------------------------------------------------
Gradle 4.10
------------------------------------------------------------
Build time: 2018-08-27 18:35:06 UTC
Revision: ee3751ed9f2034effc1f0072c2b2ee74b5dce67d
Kotlin DSL: 1.0-rc-3
Kotlin: 1.2.60
Groovy: 2.4.15
Ant: Apache Ant(TM) version 1.9.11 compiled on March 23 2018
JVM: 1.8.0_181 (Oracle Corporation 25.181-b13)
OS: Linux 4.15.0-33-generic amd64
Update:
This seems to be a bug, I've created issues on:
- gradle/kotlin-dsl: https://github.com/gradle/kotlin-dsl/issues/1115
- jetbrains/kotlin: https://youtrack.jetbrains.com/issue/KT-26983