2012-07-14 67 views
1

這與我在攔截給定類中所有對字段的訪問方面的問題有關,而不僅僅是與Groovy'property'樣式訪問一致的方式。您可以在這裏查看:intercepting LOCAL property access in groovy在Groovy中徹底地行走AST樹

我發現的一種方法將肯定解決我的問題,那就是在編譯時使用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樹助手,但沒有找到。我是否真的需要爲所有38種表達式類型在這裏實現表達式步驟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?這似乎是某人必須寫的東西(因爲它首先構建AST樹不可或缺),但我似乎無法找到它。

回答

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訪問者的更多示例。另外,請查看CodeVisitorSupport的api doc