重组模板
除了通过内置的Error Prone补丁修补代码,我们还开发了一种使用前后模板重构代码的机制(我们称之为“重组模板”)。
编写这些模板后,将它们编译成.refaster
文件,然后根据这些规则使用Error Prone编译器重构代码。
在“重构工具”研讨会上,路易斯·沃斯曼(Louis Wasserman)提出的一篇研究论文更详细地描述了重构。
构建重组模板
解释如何编写重组规则最好方法莫过于通过示例:
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.AlsoNegation;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
public class StringIsEmpty {
@BeforeTemplate
boolean equalsEmptyString(String string) {
return string.equals("");
}
@BeforeTemplate
boolean lengthEquals0(String string) {
return string.length() == 0;
}
@AfterTemplate
@AlsoNegation
boolean optimizedMethod(String string) {
return string.isEmpty();
}
}
重载模板是具有多个方法的任何类
,具有相同的返回类型
和具有相同名称的参数列表
。其中一个方法应该注释@AfterTemplate
,并且每个其他方法都应该用@BeforeTemplate
注释。
使用此模板,任何代码调用String#equals
传递空字符串文字,或者调用String#length
并将其与0进行比较都将被调用String#isEmpty
所代替。值得注意的是,无论String表达式如何生成,Refaster都将进行替换:
boolean b = someChained().methodCall().returningAString().length() == 0;
会变成
boolean b = someChained().methodCall().returningAString().isEmpty();
if (this.someStringField.equals(""))
会变成
if (this.someStringField.isEmpty())
refaster.annotations包中还有其他注释,可以让您表达更复杂的前后重构,并提供有关如何在其javadoc中使用它们的示例。
另请参阅本文档的高级功能部分。
在上面的例子中,@AlsoNegation
用于表示该规则也可以匹配@BeforeTemplate
主体的逻辑否定(string.length()!= 0
将变成!string.isEmpty()
);
运行重构
提示:这些说明在HEAD的最新快照中有效,并可能会更改
使用error prone的javac jar
和error_prone_refaster jar
来编译refaster模板:
wget http://repo1.maven.org/maven2/com/google/errorprone/javac/9-dev-r3297-4/javac-9-dev-r3297-4.jar
wget http://repo1.maven.org/maven2/com/google/errorprone/error_prone_refaster/2.0.18/error_prone_refaster-2.0.18.jar
java -cp javac-9-dev-r3297-4.jar:error_prone_refaster-2.0.18.jar \
com.google.errorprone.refaster.RefasterRuleCompiler \
StringIsEmpty.java --out `pwd`/myrule.refaster
您应该在当前目录中看到一个名为myrule.refaster
的文件。要使用它来重构代码,请将以下标记添加到Error Prone编译器中(这类似于打补丁):
-XepPatchChecks:refaster:/full/path/to/myrule.refaster
-XepPatchLocation:/full/path/to/your/source/root
这将生成一个名为error-prone.patch
的统一的diff文件,您可以类似地应用于应用其他补丁的方式:
cd /full/path/to/your/source/root
patch -p0 -u -i error-prone.patch
……
参考链接: refaster templates