Reputation: 625
I'd like to pass a closure as configuration for a plugin. Here is a minimal version of it:
package org.samuel.gradle.plugins
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
class TestPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create("testConfig", TestConfig)
Task test = project.task("testTask") {
doFirst {
println "The message is already " + project.extensions.testConfig.message
println "Trying to run closure " + project.extensions.testConfig.closure
project.extensions.testConfig.closure()
println "did it run?"
}
}
}
}
class TestConfig {
String message = "Testing ..."
Closure closure = {
println("running closure")
}
}
This doesn't work, the closure is never evaluated (nor at configuration nor when I intend it to:
$ ./gradlew test
:buildSrc:compileJava UP-TO-DATE
:buildSrc:compileGroovy
:buildSrc:processResources UP-TO-DATE
:buildSrc:classes
:buildSrc:jar
:buildSrc:assemble
:buildSrc:compileTestJava UP-TO-DATE
:buildSrc:compileTestGroovy UP-TO-DATE
:buildSrc:processTestResources UP-TO-DATE
:buildSrc:testClasses UP-TO-DATE
:buildSrc:test UP-TO-DATE
:buildSrc:check UP-TO-DATE
:buildSrc:build
:testTask
The message is already Testing ...
Trying to run closure org.samuel.gradle.plugins.TestConfig$_closure1@5600ea3b
did it run?
BUILD SUCCESSFUL
Total time: 1.569 secs
I think I am missing something about how gradle evaluates the contents of the extensions. Is it possible to somehow pass something via an extension and evaluate it in a task in the plugin?
Upvotes: 3
Views: 1790
Reputation: 43128
The solution is surprisingly unimpressive. Change the line for calling the closure to:
project.extensions.testConfig.closure.call()
Notice the use of .call()
vs just calling ()
Also noticed that this calls the closure:
println "Trying to run closure ${project.extensions.testConfig.closure}"
Upvotes: 0