はじめに
この記事では、Kotlin Multiplatform(KMP)を採用した Android アプリに
Detekt(Kotlin静的解析ツール) を導入する手順をまとめます
前提
- Kotlin Multiplatform(commonMain, androidMain, iosMain を持つ)
- サブモジュールを持つ
- composeApp(メインモジュール)
- core
- data
- Gradle Version Catalog(libs.versions.toml)使用
- detekt-formatting による自動整形も行う
実現すること
- detektによるlint設定
- detekt-formatting による自動整形の設定
- (おまけ)pre-commit hook による detekt 強制
手順
手順1と2を行えば、detektの実行(./gradlew detekt)自体はできます。3以降は任意です。
1. libs.versions.tomlに設定を追加
まず、gradle/libs.versions.toml に detekt のバージョンと plugin を定義します。
注意したいのは、detektが対応しているjvmが最新に追いついてないことが多いので、明示的に対応しているものを指定してください。
また、実行時にコードフォーマットを自動でして欲しくない場合は
autoCorrect = true を除いてください。
[versions]
detekt = "1.23.8"
[plugins]
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
[libraries]
detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
2. ルートの build.gradle.kts に detekt を適用(サブモジュール共通設定)
KMP の commonMain / androidMain / iosMain すべてを対象にする設定を
ルートの build.gradle.kts にまとめて書くのがベスト です。また、subprojects にすることでcoreやdataパッケージに対してもdetektが有効になるようにしています。
// build.gradle.kts (root)
import io.gitlab.arturbosch.detekt.Detekt
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
plugins {
alias(libs.plugins.detekt) apply false
}
// subprojects内では取得できないのでここで定義
val detektPluginId = libs.plugins.detekt.get().pluginId
val detektFormatting = libs.detekt.formatting
subprojects {
apply(plugin = detektPluginId)
extensions.configure<DetektExtension> {
// 並列処理
parallel = true
// デフォルト設定の上に自分の設定ファイルを適用する
buildUponDefaultConfig = true
// 各KMPファイルに対して有効化
source.setFrom(
"src/commonMain/kotlin",
"src/androidMain/kotlin",
"src/iosMain/kotlin",
"src/commonTest/kotlin",
)
// 設定ファイル反映(設定ファイルがない場合は不要)
config.setFrom(files("$rootDir/config/detekt/detekt.yml"))
// detekt formatterをdetekt実行時に、自動で行う。
autoCorrect = true
}
// detekt-formatting を detektPlugins に追加
dependencies {
add("detektPlugins", detektFormatting)
}
// Detektは最新のJVMに対応してないので明示的に対応したverを使う。
tasks.withType<Detekt>().configureEach {
// Kotlin コンパイルの jvmTarget に合わせて 17 か 21 辺りを選ぶ
jvmTarget = "22"
}
}
ここまでで、次のコマンドを打つことでdetekt&formatを実行できます。lintが通らなければエラーがログに表示されるので、確認して直しましょう。また、一部のエラーについてはformatによって自動でファイル修正されるので、もう一度実行するとエラーが減ることがほとんどです。
# lint兼フォーマット実行
./gradlew detekt
# フォーマットだけをしたい場合
./gradlew detekt --auto-correct
autoCorrect = true は detekt-formatting を使った
コードスタイルの自動修正に対応しています。
ただし “意味のある変更” は自動修正されないため、
安全に利用できます。
(任意)3. detekt 設定ファイルの作成(detekt.yml)
detektの細かい設定ファイルを作ります。
中身については、プロジェクトに合わせて適切に変えてください。一度detektを実行してから、不要なものをOFFにしていくことを推奨します。
プロジェクトのrootに次のように作りましょう
config/
- detekt/
- detekt.yml
# detekt.yml
build:
maxIssues: 0
config:
validation: true
# -----------------------
# Naming Rules(Compose対応)
# -----------------------
naming:
FunctionNaming:
active: true
functionPattern: '[a-z][a-zA-Z0-9]*|[A-Z][a-zA-Z0-9]*'
ignoreAnnotated:
- Composable
- Preview
# -----------------------
# Style Rules
# -----------------------
style:
NewLineAtEndOfFile:
active: true
MagicNumber:
active: true
# -----------------------
# Comments
# -----------------------
comments:
ForbiddenComment:
active: true
values: ['FIXME:', 'STOPSHIP:'] # TODO: は許可する
# -----------------------
# Complexity Rules
# -----------------------
complexity:
LongParameterList:
active: false
LongMethod:
active: false
TooManyFunctions:
active: false
LargeClass:
active: false
NestedBlockDepth:
active: false
一部のファイルについての特定のエラーだけ無視したい場合は、次のようにファイルのトップに書くことで無視できます。
// Filenameのエラーを無視したい場合、そのファイルで下記を記載する
@file:Suppress("Filename")
package com.hogehoge
....
(任意)4. detekt をコミット前に必ず実行する(pre-commit hook)
プロジェクトに git hook を仕込んで、
コミット前に detekt でチェックし、失敗したら commit を禁止 できます。
.githooks/
pre-commit
pre-commitファイルの中身は次のようにしておきます。
#!/bin/sh
echo "🔍 Running detekt..."
./gradlew detekt --quiet
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "❌ Detekt failed. Commit aborted."
exit 1
fi
echo "✅ Detekt passed."
exit 0
念の為権限付与もしておきます。
chmod +x .githooks/pre-commit
最後に開発者が一度だけ次のコマンドを行う必要があります。これはreadmeなどに書いておくことをお勧めします。
git config core.hooksPath .githooks
まとめ
この手順を踏むことで、KMP の複雑な構成でも
- detekt の共通設定を root で一括管理
- detekt-formatting によるコード自動整形
- pre-commit フックで detekt 違反を防止
- 各サブモジュール(composeApp / core / data)に自然に適用
という 実用的で強力な静的解析環境 を構築できます。