过滤文件
过滤文件
过滤文件可用于包含或排除针对特定类和方法的缺陷报告。本章介绍如何使用过滤文件。
过滤文件简介
从概念上讲,过滤器会依据一组条件对缺陷实例进行匹配。通过定义过滤器,你可以挑选出需要特殊处理的缺陷实例;例如,将其从报告中排除或纳入报告。
过滤文件是一个 XML 文档,其顶层元素为 FindBugsFilter,该元素包含若干 Match 子元素。每个 Match 元素都表示一个应用于所生成缺陷实例的谓词。通常,过滤器用于排除缺陷实例。例如:
$ spotbugs -textui -exclude myExcludeFilter.xml myApp.jar不过,过滤器也可以用来特意选出需要报告的缺陷实例:
$ spotbugs -textui -include myIncludeFilter.xml myApp.jarMatch 元素包含子元素,这些子元素是该谓词的合取项。换言之,只有当其中每个子元素都 true 时,该谓词才会 true。
Match 子句的类型
<Bug>
此元素指定要匹配的特定 bug pattern 或 patterns。pattern 属性是一个以逗号分隔的 bug 模式类型列表。要查找特定警告对应的 bug 模式类型,可以查看 -xml 输出选项生成的输出(即 BugInstance 元素的 type 属性),或者参阅 Bug 描述。
如需进行更粗粒度的匹配,请使用 code 属性。它接受一个以逗号分隔的 bug 缩写列表。如需进行最粗粒度的匹配,请使用 category 属性,它接受一个以逗号分隔的 bug 类别名称列表:CORRECTNESS、MT_CORRECTNESS、BAD_PRACTICE、PERFORMANCE、STYLE。
如果在同一个 元素上指定了上述多个属性,则所有与所指定的模式名称、缩写或类别中任意一项匹配的 bug 模式都会被匹配。
作为向后兼容措施,可以使用 和 元素来代替 元素。这两个元素都使用 name 属性来指定可接受的值列表。这些元素的支援可能会在未来版本中移除。
<Confidence>
此元素用于匹配具有特定缺陷置信度的警告。value 属性应为整数值:1 匹配高置信度警告,2 匹配普通置信度警告,3 匹配低置信度警告。<Confidence> 在 2.0.0 版本中取代了 <Priority>。
<Priority>
与 <Confidence> 相同,为向后兼容而保留。
<Rank>
此元素用于匹配至少具有指定 bug 等级的警告。value 属性应为 1 到 20 之间的整数值,其中 1 到 4 为“最可怕”,5 到 9 为“可怕”,10 到 14 为“令人不安”,15 到 20 为“值得关注”的 bug。
<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 属性用于指定局部变量名称的精确匹配或正则匹配模式。局部变量是指在方法内部定义的变量。
<Type>
此元素匹配与特定类型相关的警告。descriptor 属性用于指定类型描述符的精确匹配或正则表达式匹配模式。如果描述符以 ~ 字符开头,则属性内容的其余部分将被解释为 Java 正则表达式。role 属性是类的角色,typeParameters 是类型参数。role 和 typeParameters 均为可选属性。
<Or>
该元素将 Match 子句作为析取项进行组合。也就是说,你可以在一个 Or 子句中放入两个 Method 元素,以便匹配其中任一方法。
<And>
此元素组合了 Match 子句,且两者都必须求值为 true。也就是说,你可以在一个 And 子句中放置 Bug 和 Confidence 元素,以便仅匹配具有给定可信度的特定缺陷。
<Not>
此元素会对所包含的子元素 Match 取反。也就是说,你可以在 Bug 子句中放入一个 Not 元素,以便匹配除给定缺陷之外的所有缺陷。
Java 元素名称匹配
如果 Class、Source、Method 或 Field 的 name 属性以 ~ 字符开头,则该属性内容的其余部分会被解释为 Java 正则表达式,用于与相应 Java 元素的名称进行匹配。
注意,该模式会与元素的完整名称进行匹配,因此需要在模式的开头和/或结尾使用 .* 子句才能进行子串匹配。
有关模式语法,请参阅 java.util.regex.Pattern 文档。
注意事项
Match 子句只能匹配缺陷实例中实际包含的信息。每个缺陷实例都属于某个类,因此通常情况下,按类排除缺陷是可行的。
某些缺陷实例涉及两个(或更多)个类。例如,DE(被丢弃的异常)缺陷会同时报告包含发生异常丢弃的方法的类,以及表示被丢弃异常类型的类。只有第一个(主要)类会与 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 子句,它们会按预期生效。
示例
匹配某个类的所有缺陷报告
<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>通过指定类别匹配所有类中的特定测试
<Match>
<Bug category="PERFORMANCE" />
</Match>按缩写匹配类中指定方法的缺陷类型
<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>在特定方法中匹配特定的错误模式
<!-- A method with an open stream false positive. -->
<Match>
<Class name="com.foobar.MyClass" />
<Method name="writeDataToFile" />
<Bug pattern="OS_OPEN_STREAM" />
</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>匹配 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>匹配代码库特定部分中的缺陷
<!-- 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 anonymous inner classes warnings in ui package hierarchy -->
<Match>
<Package name="~com\.foobar\.fooproject\.ui.*" />
<Bug pattern="SIC_INNER_SHOULD_BE_STATIC_ANON" />
</Match>按特定签名匹配字段或方法上的缺陷
<!-- 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>使用 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>用于匹配从 Groovy 源文件生成的所有类的完整排除过滤器文件
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
<Match>
<Source name="~.*\.groovy" />
</Match>
</FindBugsFilter>完整示例
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter
xmlns="https://github.com/spotbugs/filter/4.8.4"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://github.com/spotbugs/filter/4.8.4 https://raw.githubusercontent.com/spotbugs/spotbugs/4.8.4/spotbugs/etc/findbugsfilter.xsd">
<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