top / index / prev / next / target / source
日記形式でつづる いがぴょんコラム ウェブページです。
FindBugs の検出器(Detector)を自作できると、さまざまな応用が利きます。ここではシンプルな FindBugs ディテクターを例示します。
FindBugs の基本的なクラスである findbugs.jar をクラスパスを通します。
findbugs/lib/findbugs.jar
<?xml version="1.0" encoding="UTF-8"?>
<FindbugsPlugin
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="findbugsplugin.xsd"
pluginid="jp.igapyon.SampleFindBugsDetector"
provider="Igapyon project">
<Detector class="jp.igapyon.SampleFindBugsDetector"/>
<BugPattern abbrev="SMPL" type="SAMPLE_BUGDETECT001" category="SAMPLE" />
</FindbugsPlugin>
<?xml version="1.0" encoding="UTF-8"?>
<MessageCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="messagecollection.xsd">
<Plugin>
<ShortDescription>FindBugs Sample Plugin</ShortDescription>
<Details>Sample FindBugs plugin.</Details>
</Plugin>
<Detector class="jp.igapyon.SampleFindBugsDetector">
<Details>
<![CDATA[
<p> This detector is a simple sample detector.
]]>
</Details>
</Detector>
<BugPattern type="SAMPLE_BUGDETECT001">
<ShortDescription>Sample detector.</ShortDescription>
<LongDescription>Sample detect: '{0}' is sample detection.</LongDescription>
<Details>
<![CDATA[
<p> This is a sample detection.
]]>
</Details>
</BugPattern>
<BugCode abbrev="SMPL">Sample detector.</BugCode>
</MessageCollection>
package jp.igapyon;
import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.OpcodeStack;
import edu.umd.cs.findbugs.Priorities;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
public class SampleFindBugsDetector extends OpcodeStackDetector {
private BugReporter bugReporter;
public SampleFindBugsDetector(BugReporter bugReporter) {
this.bugReporter = bugReporter;
}
@Override
public void sawOpcode(final int seen) {
if (seen != INVOKEVIRTUAL) {
return;
}
// インスタンスをともなうメソッド呼び出しを単純にレポートします。
String report = getDottedClassConstantOperand() + "#" + getNameConstantOperand() + "(";
if (stack.getStackDepth() > 0) {
final OpcodeStack.Item name = stack.getStackItem(0);
report += name.getSignature();
}
report += ")";
bugReporter.reportBug(new BugInstance(this, "SAMPLE_BUGDETECT001", Priorities.NORMAL_PRIORITY)
.addString(report).addClassAndMethod(this).addSourceLine(this));
}
}
この例では、比較的高水準な「OpcodeStackDetector」を継承してディテクターを自作しています。用途により、別のクラスを継承することを検討することでしょう。
<project>
<property name="findbugs.home" value="<<FindBugs の実際の展開後フォルダ>>" />
<taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask">
<classpath>
<fileset dir="${findbugs.home}/lib">
<include name="**/*.jar" />
</fileset>
</classpath>
</taskdef>
<target name="runFindbugs">
<findbugs home="${findbugs.home}" output="text" outputFile="findbugs-report.txt">
<class location="<<検査対象としたい *.class ファイルが格納されているフォルダ>>" />
<auxclasspath location="./*.jar" />
</findbugs>
</target>
<target name="jar">
<delete file="SampleFindBugsDetector.jar" />
<jar destfile="SampleFindBugsDetector.jar">
<fileset dir="./bin">
<include name="**/*.class" />
</fileset>
<fileset dir="./">
<include name="findbugs.xml" />
<include name="messages.xml" />
</fileset>
</jar>
</target>
</project>
この jar タスクで作成される「SampleFindBugsDetector.jar」ファイルを findbugs/plugin フォルダにコピーすると、自作ディテクターが FindBugs の検査内容に追加反映されます。 ★Eclipse をご利用の方は、「F5」で更新することをお忘れなく。
Ant タスクの「runFindbugs」を実行すると、FindBugs のチェック一式が実行されます。通常の FindBugs 出力に混ざって、以下のような自作検出結果が出力されるはずです。
M X SMPL: Sample detect: 'java.io.File#exists(Ljava/io/File;)' is sample detection. 該当箇所 SomeClass.java:[line 166]