Kotlinの静的解析ツールDetektを導入する (Part 2/2)

Kenji Abe
6 min readOct 21, 2022

--

Photo by Agence Olloweb on Unsplash

前回の続きでDetektを紹介していきます。。前回は基本的な設定について紹介しましたが、まだDetektにはいろんな機能があるので紹介していきます。

ktlint対応

Detektにはktlintのラッパーである Formatting というルールを使うことでktlintと同じ対応をすることができます。

Formatting はデフォルトでは入っていないのですが、以下のように dependencies に追加してあげるだけで対応できます。

dependencies {
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.22.0-RC1")
}

注意ですが、 通常のktlintと異なり .editorconfig を認識してくれません。Detekt側のYAMLで設定する必要があります。
例えば、インデントサイズを変更するのには以下のようにYAMLに記載します。

formatting:
Indentation:
indentSize: 2

Suppressについて

設定でルールを無効にするのではなく、一部例外的に無効にする場合は、 @Suppress("...") を使います。

引数にはルールIDを指定するのですが、何を指定すれば良いのかわからない場合は、レポートファイルやGradleの実行ログから確認できます。

XMLのレポートファイルの場合は、以下のようになっていて、source の部分がルールIDになるので、 @Suppress("PackageName") のように指定します。

<file name="path_to/Sample.kt">
<error message="..." source="detekt.PackageName" />
</file>

Gradleタスクの場合は、以下のようになっているので、そこの [] の中がルールIDになります。

path_to/Sample.kt:2:1: Package name must not contain underscore [PackageName]

IntelliJプラグイン

DetektのIntelliJプラグインも提供されていて、こちらを使うとエディタ上でルールに違反してるものが表示されるようになります。

例えば、ArrayPrimitive のルールに違反してるものは以下のような表示なります。

ただ、いくつかルールは表示されないものもあります。おそらく、Type Resolutionが必要なルールは表示されていないと思われます。

Jetpack Compose対応

Jetpack Composeを使う際はデフォルトのルールと異なる規則があるため、YAML側にいくつか設定が必要になります。

以下のページにまとまってますので、そちらを参考に設定すれば対応できます。

レポートのマージ

Detektにはレポートファイルをマージするタスクがあり、そちらを使用することで、複数のレポートファイルをマージして1つのファイルにすることができます。

設定方法が以下にありますので、そちらを参考に設定するだけです。

GitHubにSarifファイルをアップロードするときなどは、こちらのタスクでマージしてアップロードすると良いでしょう。

おすすめのルール

最後に、デフォルト無効だけど有効にしておくと良いおすすめのルールを紹介していきます。

ClassOrdering

クラス内で定義に関する順番のルールになります。
例えば、 companion objectがメソッドより先に定義されてたり、プロパティがメソッドの後に定義されてるとルール違反となります。

MandatoryBracesIfStatements

複数行のif文において、中括弧がない場合にルール違反になります。
以下はルール違反となります。

if (i > 0)
println(i)

MandatoryBracesLoops

先程のLoop版で、for や while 等で中括弧がない場合に違反となります。

MultilineLambdaItParameter

Lamda式において処理が複数行ある場合は it の変数名を禁止します。ちゃんと変数名をつける必要があります。

// NG
val digits = 1234.let {
println(it)
listOf(it)
}
// OK
val digits = 1234.let { num ->
println(num)
listOf(num)
}

UseEmptyCounterpart

空のコレクションを表すときに、 listOf() ではなく emptyList() である必要があります。

まとめ

Detektは最初はとっつきにくい感じがしますが、デフォルトで便利なルールがあるため、一度設定しておくとレビュー等が楽になると思います。

また、今回は紹介していませんが、自分でカスタムルールも作ることができるのでそちらを作ることでもっと便利に出来るかと思います。

--

--

Kenji Abe
Kenji Abe

Written by Kenji Abe

Programmer / Gamer / Google Developers Expert for Android, Kotlin / @STAR_ZERO

No responses yet