Stanislav Poslavsky
Stanislav Poslavsky

Reputation: 2428

Use Groovy Category DSL implicitly in all methods of class

I have a complicated Groovy category which defines my DSL language. For example it contains something like:

class MyDSL {

    static Expr getParse(String expr) {
        Parser.parse(expr)
    }

    static Expr plus(Expr a, Expr b){
        a.add(b)
    }

    ...
}

The MyDSL category contains DSL elements for many types of objects (not only String and Expr). I can use my DSL in another class by using the use keyword:

class MyAlgorithm {

    Expr method1(Expr expr) {
        use(MyDSL) {
            def sum = 'x + y'.parse
            return sum + expr        
        }

    Expr method2(String t) {
        use(MyDSL) {
            def x = t.parse
            return method1(x) + x        
        }

    ...
}

Can I do something to avoid writing of use keyword each time in each method? I also would like still to have code completion and syntax highlighting in my IDE (IntelliJ perfectly recognises DSL inside use).

There is similar question Use Groovy Category implicitly in all instance methods of class about avoiding use in unit tests, but I need to do the same in main classes.

Upvotes: 2

Views: 286

Answers (1)

Will
Will

Reputation: 14549

I see no way to implement this other than using an AST to insert it automatically into each method. Even then, i doubt IntelliJ would recognize it.

Another path, which IntelliJ won't ever recognize, is intercepting invokeMethod:

class Captain {
  def sayWot() {
    "my string".foo()
  }

  def sayNigh() {
    9.bar()
  }
}

Captain.metaClass.invokeMethod = { String name, args ->
  def self = delegate
  def method = self.metaClass.getMetaMethod name, args
  use(MyCategory) { 
    method.invoke self, args 
  }
}

class MyCategory {
  static foo(String s) {
    s + " foo"
  }
  static bar(Integer i) {
    i + " bar"
  }
}

c = new Captain()

assert c.sayWot() == 'my string foo'
assert c.sayNigh() == '9 bar'

Upvotes: 1

Related Questions