如何使用Java编译器树API(com.sun.source.util)来重构源代码



我目前正在分析Java源代码。我通过使用编译器树API解析源代码来进行AST分析。但我在向编译单元添加新的AST节点(例如插入表达式或语句)时遇到了一个问题,Java编译器稍后可以对其进行编译。我没有发现任何方法或类可以做到这一点。

我不认为Java编译器是为了让您从AST重新生成源代码而设计的。毕竟,它没有必要那样做。

如果您想修改程序,可以考虑使用源程序到源程序转换系统(PTS)。这些工具可以解析源代码(构建AST),允许您使用以解析的源代码语法编写的源到源转换规则,对AST进行更改,并且可以从AST重新生成源文本。

PTS规则本质上说,"如果你看到这个,用那个替换它"。我们的PTS(DMS软件重组工具包)的一个例子:

rule convert_square_to_multiply:(b: primitive_expression):product -> product
=  "  b ** 2 "  ->   " b * b " 
if no_side_effects(b);

该规则找到一个提升到2次方的表达式,并应用经典的编译器"强度降低"来降低计算成本。注意b上的额外语义检查约束;你的临时技术秘书处必须能够帮助你进行这种"分析"。

该规则的工作原理是:

  • 将解析的源程序的AST与规则左侧模式所暗示的AST进行匹配("如果您看到了…")
  • 匹配时,模式变量("b")绑定到相应的子树
  • 检查"if"条件以验证其为真
  • 如果是,匹配的子树将被移除,并替换为一棵树,该树的形状隐含在规则的右侧("用这个替换它")

这一切的美妙之处在于对AST的操作,而无需编写冗长的过程代码来爬上爬下树、检查节点类型、拼接节点进出等。源代码到源代码的重写更容易编写、检查和维护。

如果你不能使用PTS,你可以考虑建立自己的prettyprinter;看看我的SO关于如何做到这一点的回答。我怀疑Java编译器捕获的信息是否足以重新生成"漂亮"的源代码;它可能有足够的资源来重新生成可编译的源代码。举个例子,我确信Java编译器AST不会保留注释;因此它们将很难再生。一个标准的PTS捕捉并再现所有这些东西。

最新更新