Groovy DSL convention object "Could not get unknown property"

306 views Asked by At

I have the following code in my build.gradle:

class GreetingPlugin implements Plugin<Project> {
  def void apply(Project project) {

      project.convention.plugins.greeting = new GreetingPluginConvention()

      project.task('hello') {
          doLast {
            println project.convention.plugins.greeting.message
          }
      }
  }
}

class GreetingPluginConvention {
  String message

  def greet(Closure closure) {
      closure.delegate = this
      closure()
  }
}

apply plugin: GreetingPlugin

greet {
  message = 'Hi from Gradle'
}

It executes nicely - ./gradlew hello prints "Hi from Gradle" which is expected.

However, using variable greet in the script (e.g. println greet) produces "Could not get unknown property 'greet' for project ':app' of type org.gradle.api.Project."

My question is - how the 'greet' variable is found when called against closure, but not found when used as a regular variable. What Groovy/Gradle magic is happening behind the scenes?

1

There are 1 answers

0
Calvin Taylor On

When it's called in a closure,

greet {
  message = 'Hi from Gradle'
}

you are effectively adding more code to the original greet block/closure defined in GreetingPluginConvention, it is not a variable so attempts to treat it a such fail. Think of these block closures as a handy way to set or configure your plugins.

Gradle scripts are a bit different than your average linear script.