I was looking at the closure scopes and found the output counter intuitive, this code was in build.gradle file
plugins {
id 'java'
}
sourceSets {
println 'source sets closure scopes this,owner, delegate'
println this.toString() // output: root project 'multigradle'
println owner.toString() // output: DynamicObject for SourceSet container
println delegate.toString() // output: SourceSet container
}
Why the owner is not equal to this, does gradle clone the closure?
PS : For anyone who will read it in future 'multigradle' is my gradle project name.
TL;DR;
Essentially within the gradle source there is a method something like this:
so when you call:
(which incidentally is the same as calling
sourceSets({ some code }), just with the parens removed which is ok in groovy)"some code" is not executed immediately when the
sourceSetsmethod is called. Gradle can choose to execute it whenever they decide it's time. Specifically, they can (and do) configure things like owner and delegate before actually executing the closure.Longer version
Turns out the
sourceSetsmethod in yourbuild.gradlefile is actually added by plugins such as the java/kotlin/groovy plugins.As an example we can look at the java plugin and the DefaultJavaPluginConvention class which has the following code:
this is the method that gets called when you type
sourceSets { ... }in yourbuild.gradlefile. It gets handed the closure and proceeds to hand it off to theconfiguremethod of the source set container. Note that we have not executed the closure yet, we are just passing it around as a non-executed block of code.If we dig a little, we find the
configuremethod in the AbstractNamedDomainObjectContainer class:(
SourceSetContaineris an interface and the implementing class inherits fromAbstractNamedDomainObjectContainer...this is the rightconfiguremethod)Where the ConfigureUtil has the following code:
where the relevant part is the call to the groovy Closure rehydrate method which according to docs does the following:
Only on the last line of the
configureTargetmethod does gradle callexecuteon the action created to represent the closure. So the execution of the closure is done after the owner, the delegate and the this pointer have been configured according to gradle needs.