Kotlin の静的解析ツール Detekt でルールをディレクトリごとにオンオフする
日本語でざっと方法を探したけどパッとみつからなかったので簡単にまとめる。
設定する
プロジェクトごとにいろいろ都合はあるはずで、「このテストクラスが巨大なのは妥当じゃん」とか「リクエスト送受信とかデータベースで 3 とか出てくるのはどうしようもないじゃん」みたいな状況は絶対にある。 [1][2]
そういうときは detekt.yml などの設定ファイルでルールごとに excludes を設定すると制御できる。
complexity:
LargeClass:
excludes:
- "**/test/**"
吟味した上で、必要に応じて活用したい。
標準設定について
どうしても 3 などの数値が出てきやすいデータベース関係のコードなどは、MagicNumber の excludes で無効化する。
style:
MagicNumber:
excludes:
- "**/database/**"
しかしこれで検査を実行すると、テストコードが急に怒られるようになる。
$ ./gradlew detekt
/xxx/xxx/src/test/kotlin/xxx/XxxTest.kt:16:28
This expression contains a magic number.
Consider defining it to a well named constant. [MagicNumber]
実は Detekt は標準設定がいろいろされており、ルールによっては最初から excludes が設定されていることがある。
標準のルールが知りたい場合は、設定ファイルをいったん消してから次のコマンドを実行すると 1,000 行くらいの設定ファイルが吐き出される。
$ ./gradlew detektGenerateConfig
Successfully copied default config to /xxx/xxx/detekt.yml
MagicNumber に該当する部分は次のとおり。
style:
MagicNumber:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**', '**/*.kts' ]
ignoreNumbers:
- '-1'
- '0'
- '1'
- '2'
ignoreHashCodeFunction: true
ignorePropertyDeclaration: false
ignoreLocalVariableDeclaration: false
ignoreConstantDeclaration: true
ignoreCompanionObjectPropertyDeclaration: true
ignoreAnnotation: false
ignoreNamedArgument: true
ignoreEnums: false
ignoreRanges: false
ignoreExtensionFunctions: true
最初からテストっぽいものが除外されているとわかる。
ちなみに 0 や 1 の使用は実は許されている。
ignore~ のようなルール固有の設定は、説明と初期値を公式ドキュメントで確認できる。
おまけ: @Suppress との付き合い方
@Suppress アノテーションを使うとディレクトリ単位ではなく該当箇所のみ無効化できる。
@Suppress("MagicNumber")
fun getValue(): Int {
return 3
}
ただし @Suppress の運用をベースにすると「この @Suppress はいいけどその @Suppress はだめでしょ」みたいなことが起きる。
静的解析ツールを使って検査を自動化したはずなのに、@Suppress の運用が妥当かを人間がチェックするのは本末転倒だろう。
原則 @Suppress は使用しないのが望ましいと思う。
おまけ: ルールの探し方
ルールを書く際に LargeClass は complexity の設定、MagicNumber は style の設定、と決められている。
complexity:
LargeClass:
...
style:
MagicNumber:
...
しかしエラーメッセージにはカテゴリ名が書いてないので、 MagicNumber というルールに抵触したことしかわからない。
This expression contains a magic number.
Consider defining it to a well named constant. [MagicNumber]
カテゴリを調べたいときは、公式サイト ( https://detekt.dev/ ) で Search すればいい。

最初全部 style の下に書くものだと思い込んでいてハマった。
[style.MagicNumber] とか怒ってくれればいいのにな?
Discussion