有没有一种简单的方法可以编写 FindBugs 检测器进行比较?
Is there an easy way to write a FindBugs detector for comparisons?
我目前想编写一些静态分析工具来分析 java 代码库,并帮助检测您对 java 可选和 null 进行比较的任何情况。
所以可能的代码如下:
Optional result = method();
if (result != null) {
//do something
} else {
//never reached because method should never return null
}
当我查看可能扩展 FindBugs 时,我发现的主要比较检测器在这里:https://github.com/findbugsproject/findbugs/blob/d1e60f8dbeda0a454f2d497ef8dcb878fa8e3852/findbugs/src/java/edu/umd/cs/findbugs/detect/FindRefComparison.java
要弄清楚如何编写可能能够进行这种比较检测的代码,需要收集大量代码,而且扩展起来似乎并不那么容易。
虽然这种静态分析工具对我们很有用,因为它有助于防止有人决定将函数的方法签名从可能为 null 或可能不为 null 的对象更改为始终 returns a java 可选,但没有更新它使用的所有位置,但它不是那么有价值,我可以花时间尝试在 FindBugs 中实现它。
- 我是否对 FindBugs 代码库进行了足够的解析,以至于添加这种检查需要花费一些精力来扩展?
- 有没有更简单的方法得到我想要的东西?
private static final ImmutableSet<String> OPTIONAL_CLASSES =
ImmutableSet.of(com.google.common.base.Optional.class.getName(), "java.util.Optional");
private static final Set<Kind> COMPARISON_OPERATORS =
EnumSet.of(Kind.EQUAL_TO, Kind.NOT_EQUAL_TO);
private static boolean isNull(ExpressionTree tree) {
return tree.getKind() == Kind.NULL_LITERAL;
}
private static boolean isOptional(ExpressionTree tree, VisitorState state) {
Type type = ASTHelpers.getType(tree);
for (String className : OPTIONAL_CLASSES) {
if (ASTHelpers.isSameType(type, state.getTypeFromString(className), state)) {
return true;
}
}
return false;
}
private boolean isSuppressed(Tree tree, String suppression) {
SuppressWarnings annotation = ASTHelpers.getAnnotation(ASTHelpers.getSymbol(tree), SuppressWarnings.class);
return annotation != null && Arrays.stream(annotation.value()).anyMatch(suppression::equals);
}
@Override
public Description matchBinary(BinaryTree tree, VisitorState state) {
if (!COMPARISON_OPERATORS.contains(tree.getKind())) {
return Description.NO_MATCH;
}
ExpressionTree leftOperand = tree.getLeftOperand();
ExpressionTree rightOperand = tree.getRightOperand();
if (isNull(leftOperand) && isOptional(rightOperand, state) ||
isNull(rightOperand) && isOptional(leftOperand, state)) {
return describeMatch(tree);
}
return Description.NO_MATCH;
}
我想我在 ErrorProne 中成功了。如果我得到一些适用于它的测试,我会把它回馈给社区。
我目前想编写一些静态分析工具来分析 java 代码库,并帮助检测您对 java 可选和 null 进行比较的任何情况。
所以可能的代码如下:
Optional result = method();
if (result != null) {
//do something
} else {
//never reached because method should never return null
}
当我查看可能扩展 FindBugs 时,我发现的主要比较检测器在这里:https://github.com/findbugsproject/findbugs/blob/d1e60f8dbeda0a454f2d497ef8dcb878fa8e3852/findbugs/src/java/edu/umd/cs/findbugs/detect/FindRefComparison.java
要弄清楚如何编写可能能够进行这种比较检测的代码,需要收集大量代码,而且扩展起来似乎并不那么容易。
虽然这种静态分析工具对我们很有用,因为它有助于防止有人决定将函数的方法签名从可能为 null 或可能不为 null 的对象更改为始终 returns a java 可选,但没有更新它使用的所有位置,但它不是那么有价值,我可以花时间尝试在 FindBugs 中实现它。
- 我是否对 FindBugs 代码库进行了足够的解析,以至于添加这种检查需要花费一些精力来扩展?
- 有没有更简单的方法得到我想要的东西?
private static final ImmutableSet<String> OPTIONAL_CLASSES =
ImmutableSet.of(com.google.common.base.Optional.class.getName(), "java.util.Optional");
private static final Set<Kind> COMPARISON_OPERATORS =
EnumSet.of(Kind.EQUAL_TO, Kind.NOT_EQUAL_TO);
private static boolean isNull(ExpressionTree tree) {
return tree.getKind() == Kind.NULL_LITERAL;
}
private static boolean isOptional(ExpressionTree tree, VisitorState state) {
Type type = ASTHelpers.getType(tree);
for (String className : OPTIONAL_CLASSES) {
if (ASTHelpers.isSameType(type, state.getTypeFromString(className), state)) {
return true;
}
}
return false;
}
private boolean isSuppressed(Tree tree, String suppression) {
SuppressWarnings annotation = ASTHelpers.getAnnotation(ASTHelpers.getSymbol(tree), SuppressWarnings.class);
return annotation != null && Arrays.stream(annotation.value()).anyMatch(suppression::equals);
}
@Override
public Description matchBinary(BinaryTree tree, VisitorState state) {
if (!COMPARISON_OPERATORS.contains(tree.getKind())) {
return Description.NO_MATCH;
}
ExpressionTree leftOperand = tree.getLeftOperand();
ExpressionTree rightOperand = tree.getRightOperand();
if (isNull(leftOperand) && isOptional(rightOperand, state) ||
isNull(rightOperand) && isOptional(leftOperand, state)) {
return describeMatch(tree);
}
return Description.NO_MATCH;
}
我想我在 ErrorProne 中成功了。如果我得到一些适用于它的测试,我会把它回馈给社区。