Gradle の Findbugs の結果を標準出力に吐き出す

  • 6
    Like
  • 0
    Comment
More than 1 year has passed since last update.

Gradle で走らせた Findbugs の結果を見るのがダルいので標準出力に結果を吐き出すタスクを書く。

こんな感じ:

スクリーンショット

Findbugs の結果を見るのがダルい

レポートを見る方法としては:

  1. デフォルトだと「XML に結果出力したから見てね」って旨のメッセージが出るだけなので、そのパスを何らかのビューワーに噛ませる
  2. HTML 出力に設定変更する
    • XML を解釈してくれる CI と相性が悪い。CI のときだけ XML 出力に変える必要がある
  3. emacs 出力に設定を変更する
    • 2. と同じ問題に加えて出力される情報が少ないので、バグの識別子で詳細を調べる必要がある。

と面倒な感じ。

Intellij IDEA の findbugs のプラグイン系は、gradle と連携してくれないので話にならない。

なぜか他の gradle プラグインと違って標準出力してくれる機能がない。Findbugs プラグインにそれらしいレポーターがある が現状では機能していない:

古い Findbugs の CLI オプションだったのかな?

なんにせよ、使えてもレポーターは1つしか選べないので、上述した 2. の問題がまた出てくる。ダルい。

みんなこれどうしてるの。。。他の IDE だともっと賢いプラグインがいるのかな。

辛すぎるのでどうにかした

findbugs をライブラリとして読みこめば XML パーサもついてくるっぽいので、Findbugs 実行後に XML をパースして標準出力に吐き出す機能を書いた:

build.gradle
import edu.umd.cs.findbugs.SortedBugCollection

buildscript {
    repositories {
      mavenCentral()
    }
    dependencies {
        classpath 'com.google.code.findbugs:findbugs:3.0.1'
    }
}

apply plugin: 'findbugs'

// ... other settings

// print findbugs results to console
task printFindbugsResults << {
    [findbugsMain, findbugsTest].forEach {
        printFBXml it.reports.xml.destination
    }
}
printFindbugsResults.mustRunAfter findbugsMain, findbugsTest
check.dependsOn printFindbugsResults

def printFBXml(File xml) {
    if (!xml.exists()) return

    def bugs = new SortedBugCollection()
    bugs.readXML(xml)
    def msgs = bugs.collect { bug ->
        def srcLine = bug.primarySourceLineAnnotation
        // ※1 バグ個別の出力フォーマット
        """\
          |# ${bug.type}
          |${srcLine.className}:${srcLine.startLine}:${srcLine.endLine}
          |${bug.abridgedMessage}
          |${bug.bugPattern.detailPlainText.trim()}
        """.stripMargin().trim()
    }

    if (msgs.isEmpty()) return

    logger.error """\
        |===
        |${msgs.join("\n---\n")}
        |===
    """.stripMargin().trim()
}

コメントの ※1 のあたりが出力形式になるので、BugInstanceSourceLineAnnotation のプロパティを眺めて適当に変更しましょう。

ついでに:

System.setProperty('org.gradle.color.error', 'RED')

も書いてやると、冒頭の通りの見た目になる:

スクリーンショット

本当は出力色指定は gradle の logger とは別でやったほうが良いかも。