彻底走在Groovy的AST树

时间:2012-07-14 22:54:22

标签: groovy abstract-syntax-tree

这与我关于拦截对给定类中某个字段的所有访问的问题有关,而不仅仅是那些以与Groovy'属性'样式访问一致的方式完成的访问。您可以在此处查看:intercepting LOCAL property access in groovy

我发现的一种方法肯定会解决我的问题,即在编译时使用AST重新编写任何具有属性访问权限的非属性访问。例如,如果一个类看起来像这样:

class Foo {
  def x = 1
  def getter() {
    x
  }
  def getProperty(String name) {
    this."$name" ++
  }
}

foo = new Foo()
assert foo.getter() == 1
assert foo.x == 2

这些断言语句可以解决,因为getter方法直接访问x而foo.x通过getProperty(“x”),它在返回之前递增x。

经过一些试验和错误后,我可以使用AST转换来改变代码的行为,使得'getter'方法中的表达式'x'实际上作为Property而不是本地字段进行访问。到目前为止一切都很好!

现在,我如何进入给定类中的本地字段的所有访问?我一直在梳理互联网寻找某种类型的AST树助手,但还没找到。我真的需要在这里http://groovy.codehaus.org/api/org/codehaus/groovy/ast/expr/package-summary.html和所有18种语句类型http://groovy.codehaus.org/api/org/codehaus/groovy/ast/stmt/package-summary.html实现所有38种表达式类型的表达式walker吗?这似乎是某人必须已经写过的东西(因为它首先构建一个AST树是不可或缺的),但我似乎无法找到它。

1 个答案:

答案 0 :(得分:1)

格伦

您正在寻找某种访客。 Groovy有一些(弱文档)访问者定义,您可以使用。我的问题没有确切的答案,但我可以为您提供一些指示。

下面的代码段显示了如何横向类的AST并打印所有方法名称:

class TypeSystemUsageVisitor extends ClassCodeVisitorSupport {

@Override
public void visitExpression(MethodNode node) {
    super.visitMethod(node)
    println node.name
}

@Override
protected SourceUnit getSourceUnit() {
    // I don't know ho I should implement this, but it makes no difference
    return null;
} 
}

这就是我使用上面定义的访客的方式

def visitor = new TypeSystemUsageVisitor()
def sourceFile = new File("path/to/Class.groovy")
def ast = new AstBuilder().buildFromString(CompilePhase.CONVERSION, false, sourceFile.text).find { it.class == ClassNode.class }
ast.visitContents(visitor)

访客负责为您横渡树。他们有访问*方法,你可以覆盖它们并随心所欲地做任何事情。我相信您的问题的合适访问者是CodeVisitorSupport,它有一个visitVariableExpression方法。

我建议您阅读groovyConsole附带的code of the AST Browser,了解有关如何使用Groovy AST Visitors的更多示例。另外,请查看CodeVisitorSupport的api doc