How to make a method from an object available only from a specific Closure or Scope when creating a Groovy DSL

Viewed 23

Lets say I have a class:

Foo {
 always()
 onlyScopeB()
}

And I have different methods, which take different closures: scopeA, scopeB

foo = new Foo()

scopeA{
  foo.always()     // this should COMPILE
  foo.onlyScopeB() // this should NOT COMPILE
}

scopeB{
  foo.always()     // this should COMPILE
  foo.onlyScopeB() // this should COMPILE
}

Is there anyway to achieve this at the compilation stage? I am writing a DSL and I have scopes that correspond to stages in a process and sometimes fields are null in one scope, and then other times they are not-null and I am trying to provide the best semantic experience to find errors easily.

2 Answers

This is slight variation on your stated syntax. You can divide your Scope A and Scope B methods into interfaces and use closure delegation to provide feedback. The common method(s) like always() could be moved to a common interface if there are many. If you enable Static Type Checking on the script part of this, you will get compiler errors instead of just underlines.

interface Bar {
  void always()
  void onlyScopeA()
}
interface Baz {
  void always()
  void onlyScopeB()
}
@groovy.transform.AutoImplement
class Foo implements Bar, Baz {
}

void scopeA(@DelegatesTo.Target Bar bar, @DelegatesTo Closure block) {
  bar.with(block)
}
void scopeB(@DelegatesTo.Target Baz baz, @DelegatesTo Closure block) {
  baz.with(block)
}


def foo = new Foo()
scopeA(foo) {
  always()
  onlyScopeA()
  onlyScopeB()
}
scopeB(foo) {
  always()
  onlyScopeA()
  onlyScopeB()
}

example of IDE feedback

Related