自动化重构的工作量可不小,要做很多复杂的事情,例如通过源码分析来判断作用范围和使用情况。而且修改代码的时候也不能破坏用户自己的排版格式。
现在RFactor还很年幼,只能有限的支持提取方法(Extract Method)。我们与Fabio Kung进行了沟通。
RFactor用的是ruby_parser,它可以把解析后的Ruby AST作为s-expressions(sexp)返回。但是怎么样从s-expressions重新得到Ruby代码呢?
我的原意只是想用sexp来支持重构。我用它们来帮我决定如何重构。在提取方法的时候,哪些变量应该是局部变量,哪些应该是参数?而提取变量的时候,哪段代码又要进行修改呢?
我没有直接修改sexp来产生代码;我是直接修改源码的文本。Sexp只是帮我决定在当前的作用范围中,哪些东西需要修改(也帮我找到当前的作用范围是什么)。
等我用sexp来决定哪些东西要修改以后,我就把行号和列号提取出来,然后就可以直接修改用户编写的代码了。
可是如果直接从sexp里面重新生成新的代码不是更简单么?
Ryan Davis开发的ruby2ruby确实比较酷,它可以从sexp直接输出ruby源码。我先前也考虑过用它,不过那样就没法维护注释和用户的排版格式了。
所以那样我就得把注释和排版节点(例如换行,空格和tab)全都放到解析树(Parse Tree)里面去。这确实是个解决办法,不过太复杂了。所以我决定用sexp找到行列号,然后自己直接修改源码文本。
到目前为止,这种方式对简单的重构(这也是我的目标)还挺实用。不过我可以确定,对某些复杂的重构来说(例如移动/重命名)就不适用了。这些重构需要其他办法。比如说移动和重命名,我就在考虑用Ack(grep的升级版)来寻找匹配。然后再用heuristics找到要变化的地方,然后询问用户是否接受变化。这个难度很大,不过有些不错的IDE已经提供这些实现。
不过尽管如此,我也不会太在意这些复杂的重构:他们不是我当前的目标。我不想把TextMate或者其他优秀的编辑器变成复杂的IDE。我们当前在文本编辑器里面还没有任何的重构支持。所以,先集中精力添上一点再说。
那下一步的计划是什么?
目前RFactor还很简单,因为它只能从方法内部的代码中提取方法,也就是对方法外部的代码就没辙了。而且也没做到推断方法的参数和返回值。这个功能我是想要完成的。Sexp可以告诉我哪些应该是局部变量,哪些不是。另外一个目标是用调用新创建的方法来代替雷同代码。
我也在学习其他类似的实现,例如Python的Bicycle Repair Man、Eclipse RDT、Smalltalk Refactoring Browser,不管是啥,只要有许可协议就行(Netbeans? RubyMine?)。Bicycle Repair Man的Phil Dawes也给了我很多帮助。
计划中要支持的重构包括:不幸的是,现在只有我自己搞这个项目,而且纯粹为了兴趣在业余时间搞的。跟大多数开源项目一样,我也非常欢迎任何人的贡献。
- 提取方法
- 提取变量
- 提取类
- 提取模块
- 用Ack做重命名和移动
在GitHub和Fabio的blog上可以了解到有关RFactor的更多信息,同时GitHub上还有一个TextMate bundle。
在用Ruby编写Ruby源码工具的路上,RFactor又迈出了一步。此外就是那些用ParseTree或者ruby_parser来得到Ruby AST的静态分析工具。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/14639675/viewspace-573234/ ,如需转载,请注明出处,否则将追究法律责任。