「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()
を追加します。
buildscript {
repositories {
+ mavenCentral()
}
}
allprojects {
repositories {
+ mavenCentral()
}
}
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
は非推奨になったので、代わりに buildUponDefaultConfig
と allRules
を使ってください。
'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つでも引っかかるとビルドエラーになる ので、適切に設定すべきです。
build:
maxIssues: 3
weights:
ForbiddenComment: 0
MatchingDeclarationName: 1
ReturnCount: 0
TooGenericExceptionCaught: 0
TooGenericExceptionThrown: 1
「引っかかったルール×そのルールのウェイト」の合計が maxIssues:
で指定した数値を超えるとビルドエラーになります。
weights
で各ルールのウェイトを設定できます。
私は ForbiddenComment
がいくつ引っかかってもビルドエラーにしたくないため、 0
を指定しています。
MatchingDeclarationName
と TooGenericExceptionThrown
はそれぞれ1つずつビルドエラーにしたくない箇所があるため 1
を指定し、 maxIssues
に 3
を指定しています。そうすることで、他に1つでもウェイトが 1
以上のルールに引っかかることでビルドエラーにできます。
rulesets
各ルールの設定です。
私はルールを無効化するときに使っています。
例えば MagicNumber
ルールは style
ルールセット内のルールなので、以下のように書きます。
https://detekt.github.io/detekt/style.html#magicnumber
style:
MagicNumber:
active: false
active
active:
を false
にすることでルールを無効化できます。
severity
severity:
でルールの重大度を設定できるとのことですが、以下のエラーが発生するので注意です。
ドキュメントに残っているだけで、廃止された設定なのかもしれません。
Property 'style>ForbiddenComment>severity' is misspelled or does not exist.
console-reports
コンソールにレポートを出力するかの設定です。
console-reports:
active: true
# exclude:
# - 'ProjectStatisticsReport'
# - 'ComplexityReport'
# - 'NotificationReport'
# - 'FindingsReport'
# - 'FileBasedFindingsReport'
# - 'BuildFailureReport'
active:
を true
にすると、コンソールにレポートが出力されます。
exclude:
で出力したくないレポートを指定できますが、私は特に指定していません。
processors
すみません、こちらの設定は理解していません。
とりあえず active:
を true
にし、 exclude:
には何も指定していません。
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
全体図
最後に私の設定ファイルの全体図を載せます。
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現在、私はブラックリストとホワイトリストの両方に何も指定していません。
有用な使い方があれば教えていただきたいです。
<SmellBaseline>
<Blacklist>
</Blacklist>
<Whitelist>
</Whitelist>
</SmellBaseline>
静的解析
Android Studioのターミナルで ./gradlew detekt
を実行すると、 destination
で指定したフォルダに静的解析結果が出力されます。
TODO:
コメントが残っていることが検知されています。
特定の箇所のみルールを無効化
@Suppress("{ルール名}")
を使うことで、特定の箇所のみ特定のルールを無効化することができます。
使い過ぎるとルールを設定した意味がなくなるので、意図しない指摘のみに適用するのがいいと思います。
@Suppress("UnusedPrivateMember")
@BindingAdapter("observedList")
fun observeList(recyclerView: RecyclerView, observedList: List<Any>?) {
recyclerView.adapter?.notifyDataSetChanged()
おわりに
Kotlinのコードを静的解析できるようになりました!
これでKotlinの知識不足を多少は補ってくれるでしょう😅
参考リンク
- arturbosch/detekt: Static code analysis for Kotlin
- detekt | A static code analyzer for Kotlin
- Detekt Configuration File | A static code analyzer for Kotlin
- Configure Build Failure Thresholds | A static code analyzer for Kotlin
- Reporting | A static code analyzer for Kotlin
- Code Smell Baseline | A static code analyzer for Kotlin