フィルタファイル

フィルタファイルを使用して,特定のクラスやメソッドのバグレポートに含めたり除外したりできます。この章では,フィルタファイルの使用方法について説明します。

フィルタファイルの概要

概念的には,フィルタはバグインスタンスを基準のセットと照合します。フィルタを定義することで,特別扱いのバグインスタンスを選択できます。たとえば,レポートに含めたり除外したりできます。

フィルタファイルは,最上位の FindBugsFilter 要素を持つ XML 文書で,いくつかの Match 要素が子要素として含まれています。それぞれの Match 要素は,生成されたバグインスタンスに適用される述語を表します。通常,バグインスタンスを除外するためにフィルタが使用されます。たとえば:

$ spotbugs -textui -exclude myExcludeFilter.xml myApp.jar

また一方で,具体的に報告するバグインスタンスを選択するためにフィルタを使用することもできます。

$ spotbugs -textui -include myIncludeFilter.xml myApp.jar

Match 要素には,述語を結合した子要素が含まれます。言い換えれば,述語が であるためには,それぞれの子要素も でなければなりません。

マッチング条件の種類

<Bug>

この要素は,特定のバグパターンまたは一致するパターンを指定します。pattern 属性は,コンマ区切りのバグパターンタイプのリストです。特定の警告のバグパターンタイプは -xml 出力オプション (BugInstance 要素の type 属性) によって生成された出力を調べることで見つけられます。または,検知可能なバグの詳細 を参照してください。

もっと粒度の粗い照合をしたいときは,code 属性を使用します。コンマ区切りのバグ略語のリストを指定します。粒度の粗い照合では,category 属性を使用してコンマ区切りのバグカテゴリのリストを指定します。バグカテゴリ名は,CORRECTNESSMT_CORRECTNESSBAD_PRACTICICEPERFORMANCESTYLE です。

同じ <Bug> 要素に上記の属性が複数指定されていたときは,指定されたパターン名,略語,カテゴリのいずれかと一致するすべてのバグパターンが一致します。

下位互換性のために,<Bug> 要素の代わりに <BugPattern> と <BugCode> 要素を使用できます。それぞれの要素は,受け入れられた値のリストを指定するための name 属性を使用します。 これらの要素のサポートは,将来のリリースで削除される可能性があります。

<Confidence>

この要素は,警告を特定のバグ信頼度と照合します。value 属性は,整数値でなければなりません。1 は信頼度 (High),2 は信頼度 (Medium),3 は信頼度 (Low) の警告と一致します。2.0.0 リリースで,<Confidence><Priority> に換えられました。

<Priority>

<Confidence> と同じです。下位互換性を保つために残されています。

<Rank>

この要素は,警告を特定のバグランクと照合します。value 属性は,1 から 20 までの整数値でなければなりません。1 から 4 は恐るべきバグ, 5 から 9 は恐ろしいバグ, 10 から 14 は厄介なバグ, 15 から 20 は心配なバグを表します。

<Package>

この要素は,name 属性で指定されたパッケージ内のクラスに関連した警告と照合します。ネストしたパッケージは含まれていません (Java import 文に従っています)。しかし,正規表現を使用すると複数のパッケージに一致させることが簡単に実現できます。

<Class>

この要素は,特定のクラスに関連した警告と照合します。name 属性は,クラス名の正確な正規表現パターンを指定するために使用されます。role 属性はクラスの役割です。

下位互換性のために,<Class> 要素の代わりに Match 要素の class 属性を使用して厳密なクラス名を指定できます。また, classregex 属性を使用してクラス名と一致する正規表現を指定することもできます。

Match 要素に Class 要素も class / classregex 属性も含まれていないときは,述語は全てのクラスに適用されます。そのような述語は適切なメソッドやフィールド述語を使用してさらに細かく分類されないかぎり,必要以上のバグインスタンスに一致する可能性があります。

<Source>

この要素は,特定のソースファイルに関連した警告と照合します。name 属性は,ソースファイル名の正確な正規表現パターンを指定するために使用されます。

<Method>

この要素は,メソッドを指定します。name 属性は,メソッド名の正確な正規表現パターンを指定するために使用されます。params 属性は,メソッドパラメータの型のコンマ区切りリストです。returns 属性は,メソッドの戻り値の型です。role 属性は,メソッドの役割です。paramsreturns はクラスの完全修飾名でなければなりません。(たとえば "String" ではなく "java.lang.String" を使用します。) 後者の属性のいずれかが指定されているときは,もう一方がメソッドシグネチャを作成するために必要です。name 属性,paramsreturns 属性,あるいはすべての属性を指定できます。このように,さまざまな種類の名前とシグネチャに基づく照合条件を指定できます。

<Field>

この要素は,フィールドを指定します。name 属性は,フィールド名の正確な正規表現パターンを指定するために使用されます。シグネチャに基づいてフィールドをフィルタリングすることもできます。フィールドの完全修飾型を指定するためには type 属性を使用します。名前やシグネチャに基づいた照合を実行するために,これらの属性の一方または両方を指定できます。role 属性はフィールドの役割です。

<Local>

この要素は,ローカル変数を指定します。name 属性は,ローカル変数名の正確な正規表現パターンを指定するために使用されます。ローカル変数は,メソッド内で定義される変数です。

<Type>

この要素は,特定の型に関連した警告と照合します。descriptor 属性は,型修飾子の正確な正規表現パターンを指定するために使用されます。ディスクリプタが ~ 文字で始まるときは,残りの属性コンテンツはJavaの正規表現として解釈されます。role 属性は,クラスの役割です。typeParameters 属性は,型パラメータです。roletypeParameters はオプション属性です。

<Or>

この要素は,マッチング条件を論理和として組み合わせます。つまり,いずれかのメソッドと照合させるために 2 つの Method 要素を Or 要素に入れられます。

<And>

この要素は,マッチング条件を論理積として組み合わせます。つまり,特定のバグに与えられた信頼度だけと照合させるために Bug 要素と Confidence 要素を And 要素に入れられます。

<Not>

この要素は,含まれている子要素の Match を反転させます。つまり,与えられたバグ以外のバグと照合させるために Bug 要素を Not 要素に入れられます。

Java 要素名との一致

ClassSourceMethodFieldname 属性が ~ 文字で始まるときは,残りの属性コンテンツはJava要素名と照合されるJavaの正規表現として解釈されます。

パターンは,要素名全体と照合されるので,部分文字列で照合をしたいときは,パターンの先頭や最後に .* を使用する必要があることに注意してください。

パターン構文については java.util.regex.Pattern を参照してください。

注意事項

Match 節は実際にバグインスタンスに含まれている情報にしかマッチできません。すべてのバグインスタンスにはクラスがあるので,一般的にクラスによるバグの除外はうまくいきます。

いくつかのバグインスタンスは 2 つか,それ以上のクラスを持っています。たとえば,DE (無視された例外) バグは,無視された例外が発生するメソッドを含むクラスと無視された例外の型を表すクラスの両方を報告します。一番目 (主) のクラスだけがマッチング条件とマッチします。たとえば,クラス 「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 anonymoous 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/3.0.0"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubusercontent.com/spotbugs/spotbugs/3.1.0_RC6/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>