5

【Eclipse AST】AST的修改

 3 years ago
source link: https://blog.csdn.net/lovelion/article/details/20700467
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
【Eclipse AST】AST的修改_刘伟技术博客-CSDN博客

        AST的修改主要包括三个方面的内容:修改节点移动节点创建节点

       本文将通过一个综合实例来说明如何修改AST,并通过修改AST来修改源代码。

20140307171402781

图1 代码修改实例

       可以看到实例中的代码包含以下三种修改:

       (1) 条件表达式中的符号由等号改为不等号;

       (2) 原有的then部分移动到else部分;

       (3) 创建新的then部分。

       在对AST进行修改之前,需要先了解Java语法和各AST节点的涵义。if语句在AST中对应的节点名为IfStatement;条件表达式可以通过getExpression()方法获得;then和else部分作为依附于IfStatement的两个角色分别为THEN_STATEMENT和ELSE_STATEMENT,可以通过getThenStatement()和getElseStatement()方法获得,对应的方法还有setThenStatement()和setElseStatement()。可以利用工具ASTView,了解源代码对应的AST结构。

       图2是修改前的AST,由于完整展示需要标明过多的节点而导致图变得非常复杂,因此下图仅展示跟本次代码修改相关的重要节点。(学习过前几篇AST文章的读者可以发现,这里用大写字母开头的短语表示节点名,而全大写的短语表示节点在父节点中的角色名

20140307171410281
 图2 修改之前的AST

(1) 修改节点:条件表达式的符号由等号改为不等号

       实例中的条件表达式为中缀表达式,AST中对应的节点名为InfixExpression,所做的修改是将表达式的等号改为不等号。在修改时可以通过getExpression()方法获得表达式节点并进行强制类型转换(此处转为InfixExpression),转换后即可通过setOperator()方法修改操作符(Operator)。 

       此时AST被修改为如图3所示。

20140307171427562
 图3 修改节点后的AST

(2) 移动节点:原有的then部分移动到else部分

       实例中if语句的then部分为语句块,AST中对应的节点名为Block,简单说就是带大括号的部分。现在我们要做的就是把if语句的这个Block节点从THEN_STATEMENT角色移动到ELSE_STATEMENT角色。在AST中,“移动”更准确的说是“复制”,“复制”之后把原有的部分使用delete()方法删除即可。

      那么是否可以直接通过如下代码来实现呢?

node.setElseStatement(node.getThenStatement());

       结果是不行的,抛出一个IllegalArgumentException异常,查看异常信息为“new child currently has a different parent”,类似的异常信息还有“new child is from a different AST”等。

       应当采用的方法是使用来自ASTNode类的copySubtree(AST target, ASTNode node)方法,意为将某一节点复制到某一AST,之后需经强制类型转换才可使用。

       通过copySubTree()方法产生与原父节点没有关联的独立节点,再将其连接到需要的节点上。对于本实例,正确方法如下:

       此时AST被修改为图4所示。

20140307171432046
 图4 移动节点后的AST

(3) 创建节点:创建新的then部分

       完成这一部分的工作需要借助上一篇文章的内容【【Eclipse AST】AST的创建】,需要注意的是:因为new***()方法是通过对ast的调用而来,因此需要先获得当前节点所在的ast对象;创建节点完成后,需要把新节点放回原有的AST中。 

        最终,AST被修改为图5所示:

20140307171436953

图5 创建节点后的AST

        本实例完整代码如下:

       至此,本实例全部介绍完毕,本文所介绍的流程是使用AST来实现代码重构的核心,在后续文章中还将结合一些重构实例进行深入学习。

本文作者:刘伟,刘宏韬  http://blog.csdn.net/lovelion


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK