在Groovy中精疲力竭地遍历AST树

在Groovy中精疲力竭地遍历AST树,groovy,abstract-syntax-tree,Groovy,Abstract Syntax Tree,这与我的问题有关,即拦截对给定类中某个字段的所有访问,而不仅仅是以与Groovy“property”样式访问一致的方式进行的访问。您可以在此处查看: 我发现有一种方法肯定能解决我的问题,那就是在编译时使用AST,用属性访问重写任何非属性访问。例如,如果一个类如下所示: class Foo { def x = 1 def getter() { x } def getProperty(String name) { this."$name" ++ } } foo

这与我的问题有关,即拦截对给定类中某个字段的所有访问,而不仅仅是以与Groovy“property”样式访问一致的方式进行的访问。您可以在此处查看:

我发现有一种方法肯定能解决我的问题,那就是在编译时使用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,因此这些assert语句将起作用

经过一些尝试和错误后,我可以使用AST转换来更改代码的行为,这样“getter”方法中的表达式“x”实际上作为属性而不是本地字段进行访问。到目前为止还不错

现在,我该如何访问给定类中的所有本地字段?我一直在互联网上寻找某种AST树行者助手,但还没有找到。我真的需要为所有38种表达式类型和所有18种语句类型实现一个表达式遍历器吗?这似乎是某些人已经写过的东西(因为它首先是构建AST树的一部分),但我似乎找不到它。

Glenn

你在找什么访客。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)
游客们会帮你穿过这棵树。它们有visit*方法,您可以重写这些方法并对它们执行任何操作。我认为解决您的问题的合适访问者是CodeVisitorSupport,它有一个visitVariableExpression方法

我建议您阅读groovyConsole附带的,以获得更多关于如何使用Groovy AST访问者的示例。另外,请看一下CodeVisitorSupport