top / index / prev / next / target / source

2014-03-16 diary: [Java][FindBugs] FindBugs ディテクターのシンプルサンプル

いがぴょんの日記 日記形式でつづる いがぴょんコラム ウェブページです。

[Java][FindBugs] FindBugs ディテクターのシンプルサンプル

FindBugs の検出器(Detector)を自作できると、さまざまな応用が利きます。ここではシンプルな FindBugs ディテクターを例示します。

ディテクター作成のために必要となるもの

findbugs.jar をクラスパスに追加

FindBugs の基本的なクラスである findbugs.jar をクラスパスを通します。

findbugs/lib/findbugs.jar

findbugs.xml

<?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>

messages.xml

<?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>

SampleFindBugsDetector.java

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」を継承してディテクターを自作しています。用途により、別のクラスを継承することを検討することでしょう。

build.xml

<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 出力に混ざって、以下のような自作検出結果が出力されるはずです。

findbugs-report.txt

M X SMPL: Sample detect: 'java.io.File#exists(Ljava/io/File;)' is sample detection.  該当箇所 SomeClass.java:[line 166]

登場キーワード


この日記について