我目前正在尝试实现一些Groovy编译时AST转换,但是我遇到了麻烦:
我如何为一个字段的赋值语句指定AST转换?即AST转换应该转换以下代码:
class MyClass {
@MyTransformation
String myField
public void init() {
}
}
变成了
class MyClass {
String myField
public void init() {
this.myField = "initialized!"
}
}
我尝试用这个AST构建器调用:
def ast = new AstBuilder().buildFromSpec {
expression{
declaration {
variable "myField"
token "="
constant "initialized!"
}
}
}
但是在将结果语句插入声明类的"init"方法后,它插入了一个变量赋值,如
所示java.lang.Object myField = "initialized!"
我查看了Ast Builder TestCase中包含的示例,但是它们只涵盖了类主体中的字段声明,而不是对字段的赋值。我自己使用fieldNode
的尝试都导致了编译器错误。我将编译阶段设置为INSTRUCTION_SELECTION
;我想这应该没问题。
我如何做到这一点?基于AstBuilder#buildFromSpec
方法的解决方案是首选的,但任何帮助将是非常感谢的。
我通常不建议使用AST构建器。这对原型制作很有用,但你无法真正控制它生成的内容。特别是,在这里,它不能处理您创建的变量表达式应该引用字段节点这一事实。AST Builder非常适合学习AST,但不应该在生产代码中使用。
这是一个独立的例子,演示了如何实现你想要的。@ASTTest中的代码将对应于您的转换代码:
import groovy.transform.ASTTest
import org.codehaus.groovy.ast.expr.BinaryExpression
import org.codehaus.groovy.ast.expr.VariableExpression
import org.codehaus.groovy.ast.expr.ConstantExpression
import org.codehaus.groovy.ast.stmt.ExpressionStatement
import org.codehaus.groovy.syntax.Token
import org.codehaus.groovy.syntax.Types
class MyClass {
String myField
@ASTTest(phase=SEMANTIC_ANALYSIS,value={
def classNode = node.declaringClass
def field = classNode.getDeclaredField('myField')
def assignment = new BinaryExpression(
new VariableExpression(field),
Token.newSymbol(Types.EQUAL, 0, 0),
new ConstantExpression('initialized!')
)
node.code.addStatement(new ExpressionStatement(assignment))
})
public void init() {
}
}
def c = new MyClass()
c.init()
println c.myField
希望这对你有帮助!