13
10

More than 3 years have passed since last update.

Kotlinの静的解析ツール「detekt」のセットアップ&操作方法

Last updated at Posted at 2020-04-14

「detekt」とは?

Kotlin用の静的解析ツールです。

環境

  • OS:macOS Big Sur 11.1
  • Kotlin:1.5.0
  • Gradle:6.8
  • Gradle plugin:4.2.1
  • detekt:1.17.0

セットアップ

インストール

ルート直下の「build.gradle」に mavenCentral() を追加します。

/build.gradle
buildscript {
    repositories {
+         mavenCentral()
    }
}

allprojects {
    repositories {
+         mavenCentral()
    }
}

appフォルダ配下の「build.gradle」にプラグインと設定を追加します。

/app/build.gradle
plugins {
+     id 'io.gitlab.arturbosch.detekt' version '1.17.0'
}

+ detekt {
+     buildUponDefaultConfig = true
+     allRules = false
+     config = files("$projectDir/config/detekt/detekt.yml")
+     baseline = file("$projectDir/config/detekt/baseline.xml")
+ 
+     reports {
+         xml {
+             enabled = true
+             destination = file("$buildDir/reports/detekt/detekt.xml")
+         }
+         html {
+             enabled = true
+             destination = file("$buildDir/reports/detekt/detekt.html")
+         }
+         txt {
+             enabled = true
+             destination = file("$buildDir/reports/detekt/detekt.txt")
+         }
+         sarif {
+             enabled = true
+             destination = file("$buildDir/reports/detekt/detekt.sarif")
+         }
+     }
+ }

failFast は非推奨になったので、代わりに buildUponDefaultConfigallRules を使ってください。

'failFast' is deprecated. Please use 'buildUponDefaultConfig' together with 'allRules'.

設定ファイル

ルールや出力フォーマットを設定するファイルです。

デフォルトの設定ファイルを参考に編集するといいです。
https://github.com/arturbosch/detekt/blob/master/detekt-cli/src/main/resources/default-detekt-config.yml

2020/05/11現在、私は最小限の設定のみ行っています。
最初からルールをすべて読み込んで設定すると学習コストがかかるので、育てていく方針にします。

私が設定している内容をひとつずつ紹介します。

build

ビルドエラーの設定です。
デフォルトでは1つでも引っかかるとビルドエラーになる ので、適切に設定すべきです。

detekt.yml
build:
  maxIssues: 3
  weights:
    ForbiddenComment: 0
    MatchingDeclarationName: 1
    ReturnCount: 0
    TooGenericExceptionCaught: 0
    TooGenericExceptionThrown: 1

「引っかかったルール×そのルールのウェイト」の合計が maxIssues: で指定した数値を超えるとビルドエラーになります。

weights で各ルールのウェイトを設定できます。
私は ForbiddenComment がいくつ引っかかってもビルドエラーにしたくないため、 0 を指定しています。
MatchingDeclarationNameTooGenericExceptionThrown はそれぞれ1つずつビルドエラーにしたくない箇所があるため 1 を指定し、 maxIssues3 を指定しています。そうすることで、他に1つでもウェイトが 1 以上のルールに引っかかることでビルドエラーにできます。

rulesets

各ルールの設定です。
私はルールを無効化するときに使っています。

例えば MagicNumber ルールは style ルールセット内のルールなので、以下のように書きます。
https://detekt.github.io/detekt/style.html#magicnumber

detekt.yml
style:
  MagicNumber:
    active: false
active

active:false にすることでルールを無効化できます。

severity

severity: でルールの重大度を設定できるとのことですが、以下のエラーが発生するので注意です。
ドキュメントに残っているだけで、廃止された設定なのかもしれません。

Property 'style>ForbiddenComment>severity' is misspelled or does not exist.

console-reports

コンソールにレポートを出力するかの設定です。

detekt.yml
console-reports:
  active: true
  # exclude:
  # - 'ProjectStatisticsReport'
  # - 'ComplexityReport'
  # - 'NotificationReport'
  # - 'FindingsReport'
  # - 'FileBasedFindingsReport'
  # - 'BuildFailureReport'

active:true にすると、コンソールにレポートが出力されます。
exclude: で出力したくないレポートを指定できますが、私は特に指定していません。

processors

すみません、こちらの設定は理解していません。
とりあえず active:true にし、 exclude: には何も指定していません。

detekt.yml
processors:
  active: true
  # exclude:
  # - 'FunctionCountProcessor'
  # - 'PropertyCountProcessor'
  # - 'ClassCountProcessor'
  # - 'PackageCountProcessor'
  # - 'KtFileCountProcessor'

output-reports

output-reports: を指定すると、以下のエラーが発生するので注意です。
ドキュメントに残っているだけで、廃止された設定なのかもしれません。

$ ./gradlew detekt

> Task :app:detekt FAILED
Property 'output-reports' is misspelled or does not exist.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:detekt'.
> Run failed with 1 invalid config property.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

全体図

最後に私の設定ファイルの全体図を載せます。

detekt.yml
build:
  maxIssues: 3
  weights:
    ForbiddenComment: 0
    MatchingDeclarationName: 1
    ReturnCount: 0
    TooGenericExceptionCaught: 0
    TooGenericExceptionThrown: 1

style:
  MagicNumber:
    active: false

console-reports:
  active: true
  # exclude:
  # - 'ProjectStatisticsReport'
  # - 'ComplexityReport'
  # - 'NotificationReport'
  # - 'FindingsReport'
  # - 'FileBasedFindingsReport'
  # - 'BuildFailureReport'

processors:
  active: true
  # exclude:
  # - 'FunctionCountProcessor'
  # - 'PropertyCountProcessor'
  # - 'ClassCountProcessor'
  # - 'PackageCountProcessor'
  # - 'KtFileCountProcessor'

ベースラインファイル

ホワイトリストとブラックリストを設定するファイルです。

ブラックリストは、誤検知されるファイルの指定に使います。
ホワイトリストは、私にはまだわかりません。

2020/05/11現在、私はブラックリストとホワイトリストの両方に何も指定していません。
有用な使い方があれば教えていただきたいです。

baseline.xml
<SmellBaseline>
  <Blacklist>
  </Blacklist>
  <Whitelist>
  </Whitelist>
</SmellBaseline>

静的解析

Android Studioのターミナルで ./gradlew detekt を実行すると、 destination で指定したフォルダに静的解析結果が出力されます。

HTMLの出力例を載せます。
スクリーンショット_2020-04-14_11_32_21.jpg

TODO: コメントが残っていることが検知されています。

特定の箇所のみルールを無効化

@Suppress("{ルール名}") を使うことで、特定の箇所のみ特定のルールを無効化することができます。
使い過ぎるとルールを設定した意味がなくなるので、意図しない指摘のみに適用するのがいいと思います。

@Suppress("UnusedPrivateMember")
@BindingAdapter("observedList")
fun observeList(recyclerView: RecyclerView, observedList: List<Any>?) {
    recyclerView.adapter?.notifyDataSetChanged()

おわりに

Kotlinのコードを静的解析できるようになりました!
これでKotlinの知識不足を多少は補ってくれるでしょう😅

参考リンク

13
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10