是否有通过重构自动简化代码的工具?
Python和C有这样的工具:
但我不知道任何这样的Java程序。
在许多情况下,工具可以自动简化代码,例如:
for (String s: a) { b.add(s); }
→b.addAll(a);
if (x) return true; else return false;
→return x;
if (x) {result = a;} else {result = b;}
→result = x ? a : b;
这种自动重构的优势在于删除了大量代码行,使其更加干净和清晰。
答案 0 :(得分:2)
我是Slanec提到的AutoRefactor的作者。 您展示的所有首次重构都已实现,但以下内容尚未实现:
- 钻石操作员的自动重构/异常多捕获/ lambdas
- 更多......
请参阅open issues,包括Java 7重构。目前我只实现了Java 6兼容的重构。
答案 1 :(得分:1)
不确定。查看Program Transformation Tools (PTS)。这些工具提供了一种定义语法的方法,使用该语法将源文本解析为AST,并将AST重新打印回文本。更重要的是,相同的语法用于读取源到源转换规则,允许您直接表达转换(或根据重写集表示复合转换)。这种转换使用表达的模式来匹配AST,并修改AST;这些基于结构的转换不会被布局或空格混淆。
例如,我们的DMS软件重新设计工具包允许您以的形式编写规则,如果您看到这一点,请用替换它,采用一般形式:
rule rule_name(pattern_variables)
: pattern_syntax_category -> replacement_syntax_category
= metaquote pattern_text_in_specified_language metaquote
=> metaquote replacement_text_in_specified_language metaquote
if condition_over_bound_pattern_variables;
,其中
DMS将允许您编写并应用以下示例转换(包括OP的一些示例):
default domain Java~v8; -- specify v8 dialect of Java to manipulate
rule reduce_strength_squared(e: term):
:product -> product
= "\e ^ 2 " ==> "\e * \e "
if no_side_effects(e);
rule optimize_divide_by_self(e: term):
:product -> product
= " \e / \e " => " 1 " if is_not_zero(e);
rule accumulate_string(n: IDENTIFIER, a: expression, b: left_hand_side)
: statement -> statement
= "for (String \s: \a) { \b.add(\s); }"
=> "\b.addAll(\a);";
rule eliminate_useless_if(x: expression, s: statement)
: statement -> statement
= "if (\x) \s; else \s; " -- generalizes OP's example
=> "\s;";
rule left_factor_ternary(x: expression; t: left_hand_side; a: expression; b:expression)
: statement -> statement
= "if (\x) { \t = \a;} else {\t = \b;} "
=> "\t = \x ? \a : \b ";
rule convert_to_diamond( T1: qualified_path, T2: qualified_path,
C: qualified_path,
i: IDENTIFIER, a: arglist)
:statement -> statement
= "\T1<\T2> \i = new \C<\T2>(\a);"
=> "\T1<\T2> \i = new \C<>(\a);"
rule merge_multi_catch( b:body, i1: IDENTIFIER, e1: qualified_path,
i2: IDENTIFIER, eh: body )
:statement -> statement
= "try { \b }
catch ( \i1: \e1 ) { \eh }
catch ( \i2: \e1 ) { \eh }";
=> "try { \b }
catch ( \i1, \i2: \e1 ) { \eh }";
更复杂的转换是可能的,包括影响程序中相距很远甚至跨源文件边界的部分。这些通常需要一些额外的元编程(这里没有讨论),并且通常需要对上下文进行一些额外的检查,例如标识符的类型正确等等。[DMS有完整的符号表供Java支持]。
其他PTS可以用类似的方式表达规则。他们中的大多数都没有为更深层次的语义事实提供支持,例如符号表或类型,尽管声称您可以自己编程。经验表明,这是很多的工作,你真的希望它是正确的。 (谁希望他们的转换能够破坏代码,因为它是在不良信息上运行的?)。