我在一个大型遗留 Java 8 (Android) 应用程序上工作。我们最近发现了一个由方法的忽略结果引起的错误。具体来说,方法的调用者send()
在发送失败时没有采取正确的行动。它已被修复,但现在我想添加一些静态分析来帮助查找我们的代码中是否存在其他相同性质的现有错误。此外,为了防止将来添加相同性质的新错误。
我们已经使用 Find Bugs、PMD、Checkstyle、Lint 和 SonarQube。所以我认为其中一个可能已经具有我正在寻找的检查,但只需要启用它。但是经过几个小时的搜索和测试,我认为情况并非如此。
作为参考,这是我正在测试的代码:
public class Application {
public status void main(String[] args) {
foo(); // I want this to be caught
Bar aBar = new Bar();
aBar.baz(); // I want this to be caught
}
static boolean foo() {
return System.currentTimeMillis() % 2 == 0;
}
}
public class Bar {
boolean baz() {
return System.currentTimeMillis() % 2 == 0;
}
}
我想在调用者方面捕捉到这一点,因为一些调用者可能会使用该值,而其他调用者则不会。(上述send()
方法就是这种情况)
我发现了以下现有的静态分析规则,但它们似乎只适用于非常特定的情况,以避免误报并且不适用于我的示例:
- 不应忽略没有副作用的函数的返回值(仅适用于 Java API 中的不可变类)
- 方法忽略异常返回值(仅适用于 File.delete() 等已知方法)
- 方法忽略返回值(我认为仅适用于使用 javax.annotation.CheckReturnValue 注释的方法......)
- 方法忽略返回值,这样可以吗?(仅当返回值与调用方法的类型相同时)
- 没有副作用的方法的返回值被忽略(仅当方法没有产生除返回值以外的任何效果时)
到目前为止,最好的选择似乎是#3,但它需要我在我的巨大项目中注释每个方法或类。Java 9+ 似乎允许在包级别进行注释,但这对我来说不是一个选择。即使是这样,该项目也有很多包。我真的想要一种方法来配置它以通过一个/几个位置应用于我的整个项目,而不是需要修改每个文件。
最后,我遇到了这个 Stack Overflow答案,它告诉我 IntelliJ 使用“报告所有忽略的非库调用”检查进行了此检查。就在 IDE 中突出显示而言,这样做似乎有效。但我希望这会导致 CI 失败。我发现有一种方法可以使用 intelliJ 工具通过命令行触发它,但这仍然会输出一个 XML/JSON 文件,我需要编写自定义代码来解析该输出。我还需要在 CI 机器上安装 IDE 工具,这似乎有点矫枉过正。
有谁知道实现我想要的更好的方法?我不能成为第一个只关心假阴性而不关心假阳性的人。我觉得应该可以管理任何当前未使用的返回值被记录或明确声明返回值通过注释故意忽略它或分配给变量约定,就像他们在容易出错时所做的那样