APP生产线构建------ErrorProne实施

宇文金鑫
2023-12-01

APP生产线构建——ErrorProne实施

简介

Error Prone是一款开源的、用于帮助开发者在编译期间查找代码缺陷的代码检查工具,适用于Java及Android开发,该工具:

  • hook正常的build过程,开发者无需考虑其它
  • 错误产生时及时告知
  • 提供修复建议,并允许基于这些修复建议制定相应模型

工作示例:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new RuntimeException();

    }
错误: [DeadException] Exception created but not thrown
        new RuntimeException();
        ^
    (see http://errorprone.info/bugpattern/DeadException)
  Did you mean 'throw new RuntimeException();'?
1 个错误

安装与配置

ErrorProne在Maven、Ant等的相关配置可参看(链接 http://errorprone.info/docs/installation),这里只关心如何在Android Studio中配置ErrorProne插件,如下:

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.10"
  }
}

apply plugin: "net.ltgt.errorprone"

需要注意的是,gradle error-prone插件各版本对可支持的gradle和javac版本有不同要求,具体的参照 https://github.com/tbroyer/gradle-errorprone-plugin

检查项

Error Prone的各项check是基于Bug Patterns,每项Check都有对应的严重级别设置,Error Prone允许用户通过修改严重级别来打开或关闭指定check,通用的设置模板如下:
-Xep:<checkName>[:severity]
其中,checkName是待修改check项的名字,severity是该check对应设置为的严重级别,取{“OFF”, “WARN”, “ERROR”}之一。例如:

-Xep:ReferenceEquality  [turns on ReferenceEquality check with the severity level from its BugPattern annotation]
-Xep:ReferenceEquality:OFF  [turns off ReferenceEquality check]
-Xep:ReferenceEquality:WARN  [turns on ReferenceEquality check as a warning]
-Xep:ReferenceEquality:ERROR  [turns on ReferenceEquality check as an error]
-Xep:ReferenceEquality:OFF -Xep:ReferenceEquality  [turns on ReferenceEquality check]

同时,Error Prone也支持统一的处理,如下:

  • -XepAllErrorsAsWarnings 所有check的ERROR改为WARN级别
  • -XepAllDisabledChecksAsWarnings 打开所有关闭的check并设为WARN级别
  • -XepDisableAllChecks 关闭所有check
  • -XepDisableWarningsInGeneratedCode 关闭所有针对生成的代码的WARN
  • -XepIgnoreUnknownCheckNames 忽略check名不可识别时的报错

具体配置实例如下:

tasks.withType(JavaCompile) {
  options.compilerArgs += [ '-Xep:DeadException:WARN', '-Xep:GuardedByValidator:OFF' ]
}

需要注意的是,在AndroidStudio中,如果检查出ERROR级别的bug,在提示的同时本次构建会失败,所以如果不是在用于持续构建情景而是日常开发中,最好关闭或更改设置那些默认ERROR级别的检查项。

目前,error prone默认执行的ERROR级别的check共97项,包括ArrayToString等。
默认执行的WARN级别的check共59项,涉及DefaultCharset等。
除此之外,还提供了一些实验性的check,这些check默认是关闭的,例如EmptyIf等。

传递额外信息

配置check时,可以通过自定义标签来将额外信息传递给BugChecks,配置模板如下:

-XepOpt:[Namespace:]FlagName[=Value]

通常为了避免自定义标签命名冲突,如果标签只用于一个检查或一组检查,可以考虑在标签名前增加命名空间。另外如果标签未赋值,默认为赋值true,即-XepOpt:MakeAwesome等同于-XepOpt:MakeAwesome=true
使用示例:

-XepOpt:FlagName=SomeValue        (flags["FlagName"] = "SomeValue")
-XepOpt:BooleanFlag               (flags["BooleanFlag"] = "true")
-XepOpt:ListFlag=1,2,3            (flags["ListFlag"] = "1,2,3")
-XepOpt:Namespace:SomeFlag=AValue (flags["Namespace:SomeFlag"] = "AValue")

在BugChecker中通过增加一个入参类型为ErrorProneFlags的构造函数来访问这些标签,如下:

public class MyChecker extends BugChecker implements SomeTreeMatcher {

  private final boolean coolness;

  public MyChecker(ErrorProneFlags flags) {
    // The ErrorProneFlags get* methods return an Optional

创建新检查

Error Prone是允许建立新检查项的,在创建前需要尽量遵守以下的基本原则:

  • 对于打开后默认警告级别为ERROR的检查
    • 检查的bug应易于理解,编译器指出的问题应显而易见
    • bug应易于修复
    • bug检查不应该存在误报概率
    • bug应该是实际问题,而不是代码风格、编程实践之类的。
  • 对于打开后默认警告级别为WARN的检查
    • 与ERROR级别的几个原则相近,据作者讲,这些原则仍存在争议
    • 可以允许一定的误报率,控制在10%以内

默认检查项

Error Prone提供了97个Error级别的默认检查项,均对应着java中的某些经典错误用法。
例如:

ArrayEquals
Reference equality used to compare arrays

问题说明:
java中Object#equals比较的是两个对象实例的堆内存首地址,地址不同返回false,即两个变量指向的不是同一对象,则两者不同;但是String类和Array类重写了Object中的equals方法,比较的是內容;非String和Array类型的变量,“==”和“equals”作用相同,比较的是堆内存首地址。

因此,如果是比较两个数组引用的一致性,应该使用==代替Object.equals,如果是比较两个数组的内容一致性,使用Array#equals().

问题警告忽略:
在闭合元素前增加@SuppressWarnings("ArrayEquals")注解

其实到这里,如何在工作中部署Error Prone已经解决了,但俗话说,前车之鉴,后事之师,研究这些经典的Error检查的同时,对于提升Java编码能力一定是有帮助的。后续我会对97个检查项进行研究,并在后续拿出来与大家交流~

参考链接

http://errorprone.info/index
https://plugins.gradle.org/plugin/net.ltgt.errorprone
https://github.com/tbroyer/gradle-errorprone-plugin
http://blog.csdn.net/littlesmallless/article/details/69939258
https://github.com/google/error-prone/blob/master/check_api/src/main/java/com/google/errorprone/ErrorProneOptions.java

示例demo

ErrorProneTest

 类似资料: