👀

【Android】detektのセットアップ方法

2023/11/28に公開

Androidのモジュール分割していないプロジェクトでの情報が少なかったのでメモ。

detektを導入する

まずは、detektをプロジェク直下のbuild.gradle.ktsに追加します。

build.gradle.kts
plugins {  
    id("io.gitlab.arturbosch.detekt") version "1.23.3" apply false  
}

次に各モジュールのbuild.gradle.ktsで有効にします。
モジュール分割していなければ、以下のようになります。

app/build.gradle.kts
plugins {  
    id("io.gitlab.arturbosch.detekt") version "1.23.3"  
}

以下のコマンドを実行すると、detektのルールに違反している箇所が出力されます。

$ ./gradlew detekt

適用するルールのカスタマイズ

このままではdetektのデフォルトのルールが適用されるので、ルールをカスタマイズできるようにします。

以下のコマンドを実行することで/config/detekt/detekt.ymlが生成されます。
このファイルを編集することで、必要なルールのみ有効にできます。

$ ./gradlew detektConfig

上記で生成したymlを使用するように指定します。

app/build.gradle.kts
detekt{  
    config.setFrom("${rootProject.projectDir}/config/detekt/detekt.yml")  
    buildUponDefaultConfig = true  
}

例:

detekt.yml
naming:  
  active: true  
  BooleanPropertyNaming:  
    active: false  
  ClassNaming:  
    active: true

Jetpack Compose用のルールを追加

detektのルールのいくつかはJetpack Composeには適していません(特に関数の命名規則など)。
そこで、Jetpack Compose用のルールを追加していきます。

以下をapp/build.gradle.ktsに追加します。

app/build.gradle.kts
dependencies {
	detektPlugins ("io.nlopez.compose.rules:detekt:0.3.3")
}

これで新たなルールが適用されるようになります。
また、detekt.ymlで適用するルールを選択できます。
ルールの詳細は公式ドキュメントで確認できます。

例:

detekt.yml
Compose:  
  ComposableAnnotationNaming:  
    active: true  
  PreviewPublic:  
    active: false

レポートの種類と出力場所の設定

出力するレポートの形式と出力場所を指定できます。
html形式のレポートのみを出力するように変更しました。

app/build.gradle.kts
tasks {  
    withType<Detekt> {  
        reports {  
            html.required.set(true)  
            html.outputLocation.set(file("${buildDir}/reports/detekt.html"))  
            xml.required.set(false)  
            txt.required.set(false)  
            sarif.required.set(false)  
        }  
    }
}

Formattingの導入

Formattingを使用することで、detektの実行時に自動でフォーマットを行えます。

app/build.gradle.kts
dependencies {
    detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.1")  
}

detekt{  
    config.setFrom("${rootProject.projectDir}/config/detekt/detekt.yml")  
    buildUponDefaultConfig = true  
    autoCorrect = true  //自動でフォーマット
}

また、フォーマットに関するルールもdetekt.ymlで指定できます。
例:

detekt.yml
formatting:  
  active: true 
  android: true
  autoCorrect: true  
  TrailingCommaOnDeclarationSite:  
    active: true  

pre-commitの導入

pre-commitを使用することで、commit時にdetektを実行できます。
pre-commit公式の手順通りに設定します。

pre-commit-config.ymldetekt.shは以下のようにしました。

.pre-commit-config.yml
repos:  
  - repo: local  
    hooks:  
      - id: detekt  
        name: detekt check  
        description: Runs `detekt` on modified .kt files.  
        language: script  
        entry: ./scripts/detekt.sh  
        files: \.kt
script/detekt.sh
#!/usr/bin/env bash
echo "Running detekt check..."
OUTPUT="/tmp/detekt-$(date +%s)"
./gradlew detekt > $OUTPUT
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
  cat $OUTPUT
  rm $OUTPUT
  echo "***********************************************"
  echo "                 detekt failed                 "
  echo " Please fix the above issues before committing "
  echo "***********************************************"
  exit $EXIT_CODE
fi
rm $OUTPUT

detekt.shに対して権限の付与が必要です(chmod +x detekt.sh)。
最後に、$ pre-commit installを実行します。

また、自分の場合は、.pre-commit-config.yml, detekt.shを一度commitしないと、有効になりませんでした(要確認)。

pre-commitでstageされたファイルにのみdetektを実行

detekt cliを利用することで、stageされたファイルのみを対象にpre-commitを実行できます。
ただし、Formattingとcompose-ruleを使用する場合、公式で紹介されている方法ではうまくいきませんでした[1]

そこで、detekt.shを以下のように書き換えます。

detekt.sh
#!/usr/bin/env bash
echo "Running detekt check..."
OUTPUT="/tmp/detekt-$(date +%s)"
./gradlew detekt -PstagedOnly=true > $OUTPUT
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
  cat $OUTPUT
  echo "***********************************************"
  echo "                 detekt failed                 "
  echo " Please fix the above issues before committing "
  echo "***********************************************"
fi
rm $OUTPUT
exit $EXIT_CODE

detekt cliは使用せず、-PstagedOnly=trueを指定することで、stageされたファイルのみチェックできます。

参考

脚注
  1. detekt cliの実行時に--pluginsでプラグインのjarファイルへのパスを渡せばできるようなのですが、やり方がよくわかりませんでした。 ↩︎

Discussion