8. 过滤文件
过滤器文件可用于包含或排除针对特定类和方法的错误报告。本章介绍如何使用过滤器文件。
1. 过滤器文件简介
从概念上讲,过滤器根据一组条件对错误实例进行匹配。通过定义过滤器,您可以选取错误实例进行特殊处理;例如,将其排除在报告之外或纳入报告之中。
过滤器文件是一个 XML 文档,其顶层元素为 FindBugsFilter,该元素包含若干 Match 子元素。每个 Match 元素表示一个应用于所生成错误实例的谓词。通常,过滤器用于排除错误实例。例如:
$ findbugs -textui -exclude myExcludeFilter.xml myApp.jar不过,过滤器也可以用来挑选需要特别报告的缺陷实例:
$ findbugs -textui -include myIncludeFilter.xml myApp.jarMatch 元素包含若干子元素,它们是谓词的合取项。换句话说,只有当所有子元素都为真时,该谓词才成立。
2. 匹配子句的类型
<Bug>
该元素用于指定要匹配的一种或多种缺陷模式。pattern 属性是一个以逗号分隔的缺陷模式类型列表。要查找特定警告对应的缺陷模式类型,可以查看 -xml 输出选项产生的输出(BugInstance 元素的 type 属性),或参阅缺陷描述文档。
若需更粗粒度的匹配,可使用 code 属性,它接受一个以逗号分隔的缺陷缩写列表。若需最粗粒度的匹配,可使用 category 属性,它接受一个以逗号分隔的缺陷类别名称列表:CORRECTNESS、MT_CORRECTNESS、BAD_PRACTICICE、PERFORMANCE、STYLE。
如果在同一个 <Bug> 元素上同时指定了上述多个属性,那么只要缺陷模式匹配其中任意一个指定的模式名称、缩写或类别,就会被匹配到。
作为向后兼容措施,可以使用 <BugPattern> 和 <BugCode> 元素来代替 <Bug> 元素。这两个元素都使用 name 属性来指定可接受的取值列表。这些元素的支持可能会在未来的版本中被移除。
<Confidence>
该元素用于匹配具有特定缺陷置信度的警告。value 属性应为整数值:1 匹配高置信度警告,2 匹配普通置信度警告,3 匹配低置信度警告。<Confidence> 在 2.0.0 版本中取代了 <Priority>。
<Priority>
与 <Confidence> 相同,仅为向后兼容而保留。
<Rank>
该元素用于匹配具有特定缺陷等级的警告。value 属性应为 1 到 20 之间的整数,其中 1 到 4 为最严重,5 到 9 为严重,10 到 14 为令人困扰,15 到 20 为值得关注。
<Package>
该元素用于匹配与 name 属性指定的包中的类相关的警告。嵌套的包不会被包含在内(与 Java 的 import 语句类似)。不过,可以借助正则名称匹配轻松实现对多个包的匹配。
<Class>
该元素用于匹配与特定类相关的警告。name 属性用于指定类名的精确匹配或正则匹配模式,role 属性表示类的角色。
作为向后兼容措施,也可以不使用这种类型的元素,而是在 Match 元素上使用 class 属性指定精确的类名,或使用 classregex 属性指定用于匹配类名的正则表达式。
如果 Match 元素既不包含 Class 元素,也不包含 class / classregex 属性,则该谓词将适用于所有类。除非进一步使用适当的方法或字段谓词加以细化,否则这样的谓词很可能会匹配到超出你预期的缺陷实例。
<Source>
该元素用于匹配与特定源文件相关的警告。name 属性用于指定源文件名的精确匹配模式或正则匹配模式。
<Method>
该元素用于指定一个方法。name 用于指定方法名的精确匹配模式或正则匹配模式。params 属性是以逗号分隔的方法参数类型列表。returns 属性是方法的返回类型。role 属性是方法的角色。在 params 和 returns 中,类名必须是完全限定的。(例如,应写成 "java.lang.String" 而不是仅写 "String"。)如果指定了其中某个属性,则必须同时提供另一个属性才能构造方法签名。请注意,你可以只提供 name 属性,或只提供 params 和 returns 属性,也可以三者全部提供。这样你便可以进行各种基于名称和基于签名的匹配。
<Field>
该元素用于指定一个字段。name 属性用于指定字段名的精确匹配模式或正则匹配模式。你也可以根据字段的签名进行过滤——使用 type 属性指定字段的完全限定类型。你可以指定其中任意一个或两个属性,以执行基于名称或基于签名的匹配。role 属性是字段的角色。
<Local>
该元素用于指定一个局部变量。name 属性用于指定局部变量名的精确匹配模式或正则匹配模式。局部变量是指在方法内部定义的变量。
<Or>
该元素将多个 Match 子句以析取方式组合。也就是说,你可以将两个 Method 元素放在一个 Or 子句中,以匹配其中任意一个方法。
<And>
该元素将多个必须同时为真的 Match 子句组合在一起。也就是说,你可以将 Bug 和 Confidence 元素放在一个 And 子句中,以便只匹配具有给定置信度的特定缺陷。
<Not>
该元素对其包含的子 Match 取反。也就是说,你可以将 Bug 元素放在一个 Not 子句中,以匹配除给定缺陷之外的任何缺陷。
3. Java 元素名称匹配
如果 Class、Source、Method 或 Field 的 name 属性以 ~ 字符开头,则属性的其余内容将被解释为 Java 正则表达式,并与相应 Java 元素的名称进行匹配。
请注意,该模式会与元素的完整名称进行匹配,因此需要在模式的开头和/或结尾使用 .* 子句才能实现子串匹配。
模式语法参见 java.util.regex.Pattern 文档。
4. 注意事项
Match 子句只能匹配 bug 实例中实际包含的信息。每个 bug 实例都有一个类,因此通常情况下,按类排除 bug 是可行的。
有些 bug 实例涉及两个(或更多)类。例如,DE(被丢弃的异常)bug 会同时报告包含发生异常丢弃之方法的类,以及表示被丢弃异常类型的类。只有第一个(主要的)类会与 Match 子句进行匹配。所以,假如你想针对类 "com.foobar.A" 和 "com.foobar.B" 屏蔽 IC(初始化循环)报告,就需要使用两个 Match 子句:
<Match>
<Class name="com.foobar.A" />
<Bug code="IC" />
</Match>
<Match>
<Class name="com.foobar.B" />
<Bug code="IC" />
</Match>通过显式匹配这两个类,可以确保 IC 缺陷实例无论循环依赖中哪个类恰好被列在缺陷实例的首位,都能被匹配到。(当然,这种方式可能会意外地抑制涉及 "com.foobar.A" 或 "com.foobar.B" 与第三个类的循环依赖。)
许多种类的缺陷会报告其发生所在的方法。对于这些缺陷实例,你可以在 Match 元素中加入 Method 子句,它们应该能按预期工作。
5. 示例
1. 匹配某个类的所有缺陷报告。
<Match>
<Class name="com.foobar.MyClass" />
</Match>
- 通过指定测试的缩写来匹配某个类中的特定测试。
<Match>
<Class name="com.foobar.MyClass"/ >
<Bug code="DE,UrF,SIC" />
</Match>
- 通过指定缩写来匹配所有类中的特定测试。
<Match>
<Bug code="DE,UrF,SIC" />
</Match>
4. 通过指定类别来匹配所有类中的特定测试。
<Match>
<Bug category="PERFORMANCE" />
</Match>
5. 通过缩写匹配某个类的指定方法中的错误类型。
<Match>
<Class name="com.foobar.MyClass" />
<Or>
<Method name="frob" params="int,java.lang.String" returns="void" />
<Method name="blat" params="" returns="boolean" />
</Or>
<Bug code="DC" />
</Match>
6. 匹配特定方法中的特定缺陷模式。
<!-- A method with an open stream false positive. -->
<Match>
<Class name="com.foobar.MyClass" />
<Method name="writeDataToFile" />
<Bug pattern="OS_OPEN_STREAM" />
</Match>
7. 在特定方法中匹配具有给定优先级的特定 bug 模式。
<!-- A method with a dead local store false positive (medium priority). -->
<Match>
<Class name="com.foobar.MyClass" />
<Method name="someMethod" />
<Bug pattern="DLS_DEAD_LOCAL_STORE" />
<Priority value="2" />
</Match>
8. 匹配 AspectJ 编译器引入的次要缺陷(除非你是 AspectJ 开发者,否则你可能对这些不感兴趣)。
<Match>
<Class name="~.*\$AjcClosure\d+" />
<Bug pattern="DLS_DEAD_LOCAL_STORE" />
<Method name="run" />
</Match>
<Match>
<Bug pattern="UUF_UNUSED_FIELD" />
<Field name="~ajc\$.*" />
</Match>
9. 匹配代码库特定部分中的缺陷
<!-- match unused fields warnings in Messages classes in all packages -->
<Match>
<Class name="~.*\.Messages" />
<Bug code="UUF" />
</Match>
<!-- match mutable statics warnings in all internal packages -->
<Match>
<Package name="~.*\.internal" />
<Bug code="MS" />
</Match>
<!-- match anonymoous inner classes warnings in ui package hierarchy -->
<Match>
<Package name="~com\.foobar\.fooproject\.ui.*" />
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON" />
</Match>
10. 匹配具有特定签名的字段或方法上的 bug
<!-- match System.exit(...) usage warnings in void main(String[]) methods in all classes -->
<Match>
<Method returns="void" name="main" params="java.lang.String[]" />
<Bug pattern="DM_EXIT" />
</Match>
<!-- match UuF warnings on fields of type com.foobar.DebugInfo on all classes -->
<Match>
<Field type="com.foobar.DebugInfo" />
<Bug code="UuF" />
</Match>
11. 使用 Not 过滤运算符匹配错误
<!-- ignore all bugs in test classes, except for those bugs specifically relating to JUnit tests -->
<!-- i.e. filter bug if ( classIsJUnitTest && ! bugIsRelatedToJUnit ) -->
<Match>
<!-- the Match filter is equivalent to a logical 'And' -->
<Class name="~.*\.*Test" />
<!-- test classes are suffixed by 'Test' -->
<Not>
<Bug code="IJU" /> <!-- 'IJU' is the code for bugs related to JUnit test code -->
</Not>
</Match>
12. 用于匹配由 Groovy 源文件生成的所有类的完整排除过滤器文件。
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
<Match>
<Source name="~.*\.groovy" />
</Match>
</FindBugsFilter>
6. 完整示例
<FindBugsFilter>
<Match>
<Class name="com.foobar.ClassNotToBeAnalyzed" />
</Match>
<Match>
<Class name="com.foobar.ClassWithSomeBugsMatched" />
<Bug code="DE,UrF,SIC" />
</Match>
<!-- Match all XYZ violations. -->
<Match>
<Bug code="XYZ" />
</Match>
<!-- Match all doublecheck violations in these methods of "AnotherClass". -->
<Match>
<Class name="com.foobar.AnotherClass" />
<Or>
<Method name="nonOverloadedMethod" />
<Method name="frob" params="int,java.lang.String" returns="void" />
<Method name="blat" params="" returns="boolean" />
</Or>
<Bug code="DC" />
</Match>
<!-- A method with a dead local store false positive (medium priority). -->
<Match>
<Class name="com.foobar.MyClass" />
<Method name="someMethod" />
<Bug pattern="DLS_DEAD_LOCAL_STORE" />
<Priority value="2" />
</Match>
<!-- All bugs in test classes, except for JUnit-specific bugs -->
<Match>
<Class name="~.*\.*Test" />
<Not>
<Bug code="IJU" />
</Not>
</Match>
</FindBugsFilter>
评论
登录后参与评论
KnowForge