How can I get the current containing block a method is called from?

I am writing a gradle plugin, and I have a method like the following:

foo {
  bar {
    plugin.doMagic
  }
}

The foo and bar blocks happen to be added by another plugin (e.g. “productFlavors” by the android plugin). What I’d like to do is get the context of the method call as a parameter, so that my method would look like:

public void doMagic(Object containingBlock) {
  // containingBlock is the object representing bar in the above example
}

This way, I can determine what context the call was made in. Using this as a parameter to the method gives me the project in which the call was made, rather than the specific containing block. Is there a way to get this using gradle?

Hi Scott,

The delegate property is what you’re after.

foo {
  bar {
    plugin.doMagic(delegate)
  }
}
1 Like

Thanks, @luke_daley. One followup question: Is it possible to access the delegate from which a method is called (perhaps at evaluation-time), so I could do something like:

 foo {
  bar {
    plugin.doMagic
  }
}

rather than

foo {
  bar {
    plugin.doMagic delegate
  }
}

I’m basically just wondering if there’s a way to pass that closure during evaluation, so I don’t have to rely on the user of my plugin knowing about the delegate object.

These implicit variables (like delegate) are only available to closures. Since you are calling a plain Java method, it would have to be passed as an argument explicitly. You could define this method as a closure, using extra properties. Here’s an example of how that might work using the ‘java’ plugin. In this case owner.delegate is the ‘main’ source set.

apply plugin: 'java'

sourceSets.all { s ->
    s.ext.foo = {
        println owner.delegate
    }
}

sourceSets {
    main {
        foo()
    }
}