在Groovy中使用AST转换修改方法

时间:2018-10-28 19:24:53

标签: groovy transformation abstract-syntax-tree

最初的问题已删除,然后我才能对其作进一步回答,因此我将问题与答案一起重新发布:

由于无法确定修改后如何执行以前的方法语句,因此无法使用AST Transformation修改方法。我从方法中提取语句,将其保存在一些临时变量中,但是稍后,在修改后,当我尝试执行它时,我得到MissingPropertyException:无此类属性:类代码:计算器,就像我尝试使用属性一样从我的类,而不是我的方法的前一个代码块。有什么想法我做错了吗?

 child: new ListView(
        children: <Widget>[

          new HorizontalList(list1),
          new HorizontalList(list2),
          new HorizontalList(list3),
          new HorizontalList(list4),
       ]
)

该问题的代码超出了实际需要的代码。重要的部分是方法的修改。预先感谢。

从我的角度来看,我不知道AST中的代码是否真的有用,或者仅仅是为了使示例工作,学习AST转换...

1 个答案:

答案 0 :(得分:0)

所以我的原始答案是:

在AST转换方面很难获得帮助。尽管这是一个猜测,但我认为这可能与可变范围有关。有一个VariableScopeVisitor在AST流程的早期运行,设置变量的作用域,但是从AST的描述中,您正在添加要稍后访问的代码。因此,您可能必须再次运行VariableScopeVisitor进行修复,以使现有代码可以访问您注入的代码。

我今年在GR8Conf.US上做了一个AST简介,它有很多资源:

https://docs.google.com/presentation/d/1D4B0YQd0_0HYxK2FOt3xILM9XIymh-G-jh1TbQldbVA/edit?usp=sharing

我将看一下有关变量范围的这篇文章:

但是真正的答案是

AST转换可能很困难,使用便捷的AstBuilder可能会引入问题,因此我经常直接使用API​​。学习宏和宏方法(Groovy 2.5的新功能)后,我可能不必过多使用该API,但是直到那时,我才使用以下API重写部分代码:

        //modification of method "add"
        def addMethods = myClass.getMethods("add")
        for(m in addMethods){
            def code = m.getCode().statements

            //statement
            //AstBuilder abc = new AstBuilder()
            Statement s1 = new ExpressionStatement(
                    new BinaryExpression(
                            new VariableExpression('timeOfInstantiation'),
                            Token.newSymbol(org.codehaus.groovy.syntax.Types.EQUAL,0,0),
                            new MethodCallExpression(
                                    new ClassExpression(new ClassNode(java.lang.System)),
                                    'currentTimeMillis',
                                    ArgumentListExpression.EMPTY_ARGUMENTS
                            )
                    )

            )
//            List<ASTNode> statement1 = abc.buildFromString('timeOfInstantiation = System.currentTimeMillis()')
//            List<ASTNode> statement1 = abc.buildFromCode {
//                timeOfInstantiation = System.currentTimeMillis()
//                for(c in code){
//                    c.expression
//                }
//            }

            code.add(0,s1)
            //m.setCode(statement1[0])
        }

可以稍微清理一下此代码,但是它应该可以工作。我还必须将timeOfInstantiation更改为private,而不是final,以便分配代码可以像这样工作:

FieldNode field = new FieldNode("timeOfInstantiation", FieldNode.ACC_PRIVATE, longClass, myClass, new ConstantExpression(System.currentTimeMillis()))

我还将在演示文稿中查看测试应用程序参考,因为它将允许调试AST转换并使用Groovy控制台查看转换的作用。