フィルタファイル
フィルタファイルを使用して、特定のクラスやメソッドのバグレポートに含めたり除外したりできます。この章では、フィルタファイルの使用方法について説明します。
フィルタファイルの概要
概念的には、フィルタはバグインスタンスを基準のセットと照合します。フィルタを定義することで、特別扱いのバグインスタンスを選択できます。たとえば、レポートに含めたり除外したりできます。
フィルタファイルは、最上位の FindBugsFilter
要素を持つXML文書で、いくつかの Match
要素が子要素として含まれています。それぞれの Match
要素は、生成されたバグインスタンスに適用される述語を表します。通常、バグインスタンスを除外するためにフィルタが使用されます。たとえば:
$ spotbugs -textui -exclude myExcludeFilter.xml myApp.jar
また一方で、具体的に報告するバグインスタンスを選択するためにフィルタを使用することもできます。
$ spotbugs -textui -include myIncludeFilter.xml myApp.jar
Match
要素には、述語を結合した子要素が含まれます。言い換えれば、述語が 真
であるためには、それぞれの子要素も 真
でなければなりません。
マッチング条件の種類
<Bug>
この要素は、特定のバグパターンまたは一致するパターンを指定します。pattern
属性は、コンマ区切りのバグパターンタイプのリストです。特定の警告のバグパターンタイプは -xml 出力オプション (BugInstance 要素のtype属性)によって生成された出力を調べることで見つけられます。または、検知可能なバグの詳細 を参照してください。
For more coarse-grained matching, use code
attribute. It takes a comma-separated list of bug abbreviations. For most-coarse grained matching use category
attribute, that takes a comma separated list of bug category names: CORRECTNESS
, MT_CORRECTNESS
, BAD_PRACTICE
, PERFORMANCE
, STYLE
.
同じ <Bug> 要素に上記の属性が複数指定されていたときは、指定されたパターン名、略語、カテゴリのいずれかと一致するすべてのバグパターンが一致します。
下位互換性のために、<Bug> 要素の代わりに <BugPattern> と <BugCode> 要素を使用できます。それぞれの要素は、受け入れられた値のリストを指定するための name
属性を使用します。
これらの要素のサポートは、将来のリリースで削除される可能性があります。
<Confidence>
この要素は、警告を特定のバグ信頼度と照合します。value
属性は、整数値でなければなりません。1は信頼度 (High)、2は信頼度 (Medium)、3は信頼度 (Low) の警告と一致します。2.0.0リリースで、<Confidence>
は <Priority>
に換えられました。
<Priority>
<Confidence>
と同じです。下位互換性を保つために残されています。
<Rank>
This element matches warnings having at least a specified bug rank. The value
attribute should be an integer value between 1 and 20, where 1 to 4 are scariest, 5 to 9 scary, 10 to 14 troubling, and 15 to 20 of concern bugs.
<Package>
この要素は、name
属性で指定されたパッケージ内のクラスに関連した警告と照合します。ネストしたパッケージは含まれていません (Java import文に従っています)。しかし、正規表現を使用すると複数のパッケージに一致させることが簡単に実現できます。
<Class>
この要素は、特定のクラスに関連した警告と照合します。name
属性は、クラス名の正確な正規表現パターンを指定するために使用されます。role
属性はクラスの役割です。
下位互換性のために、<Class> 要素の代わりに Match
要素の class
属性を使用して厳密なクラス名を指定できます。また、 classregex
属性を使用してクラス名と一致する正規表現を指定することもできます。
Match
要素に Class
要素も class
/ classregex
属性も含まれていないときは、述語は全てのクラスに適用されます。そのような述語は適切なメソッドやフィールド述語を使用してさらに細かく分類されないかぎり、必要以上のバグインスタンスに一致する可能性があります。
<Source>
この要素は、特定のソースファイルに関連した警告と照合します。name
属性は、ソースファイル名の正確な正規表現パターンを指定するために使用されます。
<Method>
この要素は、メソッドを指定します。name
属性は、メソッド名の正確な正規表現パターンを指定するために使用されます。params
属性は、メソッドパラメータの型のコンマ区切りリストです。returns
属性は、メソッドの戻り値の型です。role
属性は、メソッドの役割です。params
と returns
はクラスの完全修飾名でなければなりません。(たとえば "String"
ではなく "java.lang.String"
を使用します)後者の属性のいずれかが指定されているときは、もう一方がメソッドシグネチャを作成するために必要です。name
属性、params
と returns
属性、あるいはすべての属性を指定できます。このように、さまざまな種類の名前とシグネチャに基づく照合条件を指定できます。
<Field>
この要素は、フィールドを指定します。name
属性は、フィールド名の正確な正規表現パターンを指定するために使用されます。シグネチャに基づいてフィールドをフィルタリングすることもできます。フィールドの完全修飾型を指定するためには type
属性を使用します。名前やシグネチャに基づいた照合を実行するために、これらの属性の一方または両方を指定できます。role
属性はフィールドの役割です。
<Local>
この要素は、ローカル変数を指定します。name
属性は、ローカル変数名の正確な正規表現パターンを指定するために使用されます。ローカル変数は、メソッド内で定義される変数です。
<Type>
この要素は、特定の型に関連した警告と照合します。descriptor
属性は、型修飾子の正確な正規表現パターンを指定するために使用されます。ディスクリプタが ~ 文字で始まるときは、残りの属性コンテンツはJavaの正規表現として解釈されます。role
属性は、クラスの役割です。typeParameters
属性は、型パラメータです。role
と typeParameters
はオプション属性です。
<Or>
この要素は、マッチング条件を論理和として組み合わせます。つまり、いずれかのメソッドと照合させるために2つの Method
要素を Or
要素に入れられます。
<And>
この要素は、マッチング条件を論理積として組み合わせます。つまり、特定のバグに与えられた信頼度だけと照合させるために Bug
要素と Confidence
要素を And
要素に入れられます。
<Not>
この要素は、含まれている子要素の Match
を反転させます。つまり、与えられたバグ以外のバグと照合させるために Bug
要素を Not
要素に入れられます。
Java 要素名との一致
Class
、Source
、Method
、Field
の name
属性が ~ 文字で始まるときは、残りの属性コンテンツはJava要素名と照合されるJavaの正規表現として解釈されます。
パターンは、要素名全体と照合されるので、部分文字列で照合をしたいときは、パターンの先頭や最後に .*
を使用する必要があることに注意してください。
See java.util.regex.Pattern documentation for pattern syntax.
注意事項
Match
節は実際にバグインスタンスに含まれている情報にしかマッチできません。すべてのバグインスタンスにはクラスがあるので、一般的にクラスによるバグの除外はうまくいきます。
いくつかのバグインスタンスは2つか、それ以上のクラスを持っています。たとえば、DE (無視された例外)バグは、無視された例外が発生するメソッドを含むクラスと無視された例外の型を表すクラスの両方を報告します。1番目 (主)のクラスだけがマッチング条件とマッチします。たとえば、クラス「com.foobar.A」と「com.foobar.B」のIC (初期化時の循環)レポートを抑制したいときは、2 つの 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」と第 3 のクラスを含む循環が誤って抑制される可能性があります。)
さまざまな種類のバグは、どのようなメソッドで発生するかを報告します。これらのバグインスタンスに対しては、Method
節を Match
要素に入れられるので、期待どおりに動作するはずです。
例
特定のクラスに対するすべてのバグレポートと一致させる
<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>