在所有类的方法中隐式使用Groovy类别DSL

时间:2015-04-02 09:16:21

标签: groovy metaprogramming dsl

我有一个复杂的Groovy类别,它定义了我的DSL语言。例如,它包含以下内容:

class MyDSL {

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

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

    ...
}

MyDSL类别包含许多类型对象的DSL元素(不仅是StringExpr)。我可以使用use关键字在另一个班级中使用我的DSL:

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        
        }

    ...
}

我可以做些什么来避免每次在每种方法中都写use个关键字吗?我还想在我的IDE中完成代码完成和语法高亮(IntelliJ完全识别use内的DSL。)

在单元测试中有类似的问题Use Groovy Category implicitly in all instance methods of class关于避免use,但我需要在主类中做同样的事情。

1 个答案:

答案 0 :(得分:1)

除了使用AST将其自动插入每个方法之外,我认为无法实现此功能。即便如此,我怀疑IntelliJ会认出它。

IntelliJ无法识别的另一条路径是拦截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'