【AndroidStudio】detekt で JetpackCompose 記述をチェックする

あちこちの著名なアプリ開発で使われているようなので、標準的な正しい記述を学ぶことができると思います。

【AndroidStudio】detekt で JetpackCompose 記述をチェックする (随時更新)
👉 Welcome | detekt hatena-bookmark

 

🧑‍💻 インストール方法

いくつかの方法があるのでどれを使ったらいいのか分からない。

【AndroidStudio】detekt で JetpackCompose 記述をチェックする (随時更新)

一通り「Getting Started」を読んでみたけど、まず初めは手っ取り早い「IDE プラグイン」か「Gradle プラグイン」でしょうか。

 

🧑‍💻 IDE プラグインをインストール

【AndroidStudio】detekt で JetpackCompose 記述をチェックする (随時更新)

👉 detekt - IntelliJ IDEs Plugin | Marketplace hatena-bookmark
👉 detekt/detekt-intellij-plugin: detekt plugin for IntelliJ hatena-bookmark

ファイルから右クリックで実行できるので便利そう。

【AndroidStudio】detekt で JetpackCompose 記述をチェックする (随時更新)

【AndroidStudio】detekt で JetpackCompose 記述をチェックする (随時更新)

しかし、detekt.yml を利用してのチェックポリシー変更がなぜか反映されない。

【AndroidStudio】detekt で JetpackCompose 記述をチェックする (随時更新)
👉 Issues · detekt/detekt-intellij-plugin hatena-bookmark

issues にもそのような事例多く上がっているのでとりあえず捨てる。

 

🧑‍💻 Gradle プラグインをインストール

きっと、リポジトリに mavenCentral() は設定済みだと思うので、追加するのは1行。


// build.gradle.kts

plugins {
  id("io.gitlab.arturbosch.detekt") version("1.23.1" )
}

インストールはこれだけです。

タスクに登録されているか確認します。


❯ ./gradlew tasks | grep detekt

detekt
detektBaseline - Creates a detekt baseline on the given --baseline path.
detektBaselineDebug - EXPERIMENTAL: Creates detekt baseline for debug classes with type resolution
detektBaselineDebugAndroidTest - EXPERIMENTAL: Creates detekt baseline for debugAndroidTest classes with type resolution
detektBaselineDebugUnitTest - EXPERIMENTAL: Creates detekt baseline for debugUnitTest classes with type resolution
detektBaselineMain - EXPERIMENTAL: Creates detekt baseline files for production classes across all variants with type resolution
detektBaselineRelease - EXPERIMENTAL: Creates detekt baseline for release classes with type resolution
detektBaselineReleaseUnitTest - EXPERIMENTAL: Creates detekt baseline for releaseUnitTest classes with type resolution
detektBaselineTest - EXPERIMENTAL: Creates detekt baseline files for test classes across all variants with type resolution
detektDebug - EXPERIMENTAL: Run detekt analysis for debug classes with type resolution
detektDebugAndroidTest - EXPERIMENTAL: Run detekt analysis for debugAndroidTest classes with type resolution
detektDebugUnitTest - EXPERIMENTAL: Run detekt analysis for debugUnitTest classes with type resolution
detektGenerateConfig - Generate a detekt configuration file inside your project.
detektMain - EXPERIMENTAL: Run detekt analysis for production classes across all variants with type resolution
detektRelease - EXPERIMENTAL: Run detekt analysis for release classes with type resolution
detektReleaseUnitTest - EXPERIMENTAL: Run detekt analysis for releaseUnitTest classes with type resolution
detektTest - EXPERIMENTAL: Run detekt analysis for test classes across all variants with type resolution

❯ ./gradlew tasks | grep detekt | grep -v EXPERIMENTAL

detekt
detektBaseline - Creates a detekt baseline on the given --baseline path.
detektGenerateConfig - Generate a detekt configuration file inside your project.

これらの Gradle プラグインによって登録された Gradle タスクを実行することでコード記述のチェックができるようです。

インストール方法としては、これで進めていきます。

 

🧑‍💻 設定ファイル

Gradle タスクを使って書き出します。


❯ ./gradlew detektGenerateConfig

> Task :app:detektGenerateConfig
Successfully copied default config to /path/to/project/config/detekt/detekt.yml

デフォルトの設定のコピー detekt.yml が表示されてる位置に書き出されました。

【AndroidStudio】detekt で JetpackCompose 記述をチェックする

【AndroidStudio】detekt で JetpackCompose 記述をチェックする

チェックポリシーを変更する場合は、この YML 形式のファイルを書き換えます。

820行もあります。

 

🧑‍💻 実行する

では、実行してチェックしてみます。


❯ ./gradlew detekt              

> Task :app:detekt FAILED
/path/to/project/app/src/main/java/com/example/ea/ui/theme/Theme.kt:41:5: Function names should match the pattern: [a-z][a-zA-Z0-9]* [FunctionNaming]
/path/to/project/app/src/main/java/com/example/ea/MainActivity.kt:92:5: Function names should match the pattern: [a-z][a-zA-Z0-9]* [FunctionNaming]
/path/to/project/app/src/main/java/com/example/ea/ui/theme/Color.kt:5:22: This expression contains a magic number. Consider defining it to a well named constant. [MagicNumber]
/path/to/project/app/src/main/java/com/example/ea/ui/theme/Color.kt:6:26: This expression contains a magic number. Consider defining it to a well named constant. [MagicNumber]
/path/to/project/app/src/main/java/com/example/ea/ui/theme/Color.kt:7:20: This expression contains a magic number. Consider defining it to a well named constant. [MagicNumber]
/path/to/project/app/src/main/java/com/example/ea/ui/theme/Color.kt:9:22: This expression contains a magic number. Consider defining it to a well named constant. [MagicNumber]
/path/to/project/app/src/main/java/com/example/ea/ui/theme/Color.kt:10:26: This expression contains a magic number. Consider defining it to a well named constant. [MagicNumber]
/path/to/project/app/src/main/java/com/example/ea/ui/theme/Color.kt:11:20: This expression contains a magic number. Consider defining it to a well named constant. [MagicNumber]


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:detekt'.
> Analysis failed with 8 weighted issues.

* 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 FAILED in 545ms
1 actionable task: 1 executed

8箇所に2種類のエラーがでました。


Function names should match the pattern: [a-z][a-zA-Z0-9]* [FunctionNaming]


This expression contains a magic number. Consider defining it to a well named constant. [MagicNumber]

チェックするコードとして、AndroidStudio 同梱の新規プロジェクトテンプレート「Empty Activity」を書き出しただけのプロジェクトなのですが。

それぞれ内容を見ていきます。

 

🧑‍💻 Function names should match the pattern: [a-z][a-zA-Z0-9]* [FunctionNaming]


@Composable
fun FooButton(text: String, onClick: () -> Unit) {

Unit を返す @Composable 関数名は PascalCase なので、JetpackCompose に向けて設定ファイル detekt.yml を以下のいずれかに変更します。


  FunctionNaming:
    active: true
    excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**']
#   functionPattern: '[a-z][a-zA-Z0-9]*'
    functionPattern: '[a-zA-Z][a-zA-Z0-9]*'
    excludeClassPattern: '$^'


  FunctionNaming:
    active: true
    excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**']
    functionPattern: '[a-z][a-zA-Z0-9]*'
    excludeClassPattern: '$^'
    ignoreAnnotated: ['Composable'] # 追加


  FunctionNaming:
    active: true
    excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**']
    functionPattern: '[a-z][a-zA-Z0-9]*'
    excludeClassPattern: '$^'
    ignoreAnnotated: # 追加
      - 'Composable' # 追加

どうやら、detekt デフォルトの設定は JetpackCompose に十分には対応してないようです。

 

🧑‍💻 This expression contains a magic number. Consider defining it to a well named constant. [MagicNumber]


val color1 = Color(0xFFEA6D7E)

クラス、コンパニオンオブジェクト、トップレベルのプロパティのオブジェクト記述は、名前付きパラメータを指定しないと違反となるようです。

以下のいずれかで。


val color1 = Color(color = 0xFFEA6D7E)


  MagicNumber:
    active: true
    excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**', '**/*.kts']
    ignoreNumbers:
      - '-1'
      - '0'
      - '1'
      - '2'
    ignoreHashCodeFunction: true
#   ignorePropertyDeclaration: false
    ignorePropertyDeclaration: true

あまり、ignore* 系は使わない方がいいような気もする。

 

🧑‍💻 まとめ

などと書いてきましたが、これらは以下の detekt 公式ページにまとめられています。

Configuration for Compose | detekt hatena-bookmark
👉 Configuration for Compose | detekt hatena-bookmark

逆にいえば、これらは、

「Kotlin と JetpackCompose の記述ルールの違い」

ということになるのでしょう。

detekt を使わない方も一読しておくといいと思われます。

👉 【Gradle Plugin】detekt「baseline」とは hatena-bookmark

👉 ファイルの末尾に改行を追加するように Android Studio を設定するにはどうすればよいですか? hatena-bookmark


【AndroidStudio】実行時に自動でそれまでのログを消して logcat ウインドウを開く設定

こういう設定があるのは知っているけど設定をどこでするのか毎回分からない、ので。


[Run]

  ↓

[Edit Configulations...]

  ↓

✅ [Show logcat automatically]
✅ [Clear log before launch]


✔[Show logcat automatically]
✔[Clear log before launch]

基本的にこの2つはONにしてていいと思います。


【Android】TextField フォーカスを利用した IME 開閉が Material3 で壊れたので修正していく

Material3 に改修してみると、

こんなかんじに入力欄とIMEの挙動がおかしくなったので、

2023年8月31日以降 アプリは Android 13(API レベル 33)以降を対象にする必要があります。
2023年9月26日
Jetpack Compose Dependency versions API-33 vs API-34
2023年9月23日
メモリーリークを防ぐには欠かせない Lifecycle Observer は remove/unregister 不要
2023年9月10日
Gson が R8 で落ちる
2023年8月28日
【Kotlin DSL】Deprecated な packagingOptions が fun Packaging.() に変換される件
2023年8月27日
【Android】通知が表示されないときのアプリ別の端末設定 ON/OFF ⚙️
2023年8月25日
Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in /app/build/outputs/mapping/debug/missing_rules.txt
2023年8月24日
Unresolved reference: BuildConfig
2023年8月16日
ログインに使っている Twitter (X) アカウントの連携を削除する手順
2023年8月11日
【iPhone】Yahoo天気アプリ 「現在地ボタンが変わりました」は「現在地ボタンは無くなりました」では?
2023年8月10日
【Mac】絵文字 や GitHubショートコード は「GitHub Emoji Picker」で入力する 😀
2023年8月9日
ChatGPT クローラー の UA(ユーザーエージェント) と IPアドレス範囲 まとめ
2023年8月4日
Android OS version market share
2023年7月30日
【iPhone】「パケ詰まり」「パケ止まり」を修復するショートカット 📱
2023年7月26日
Android Studio Giraffe | 2022.3.1 の dependencies の揃え方
2023年7月24日
将来、URL の twitter.com は x.com となるんだろうか。
2023年7月20日
Service Locator と DI どちらを使うか、という話。
2023年7月13日
【iPhone/Android】富士山 にいくなら「富士山」アプリ 🏔
2023年7月12日
Chromecast の 素晴らしい背景画面 をダウンロードできる件
2023年7月11日
スマホスタンド(充電不可)を作ってみたが、まあまあ使っている 📱
2023年7月10日
【Android Studio】[File] - [Project Structure] - [Suggestions] で「Update」する dependencies の妥当性 💉
2023年7月7日
【WordPress】自分のブログで「無効なトラフィック」を発生させないための Adsense タグ記述
【Jetpack Compose】TextField の フォーカス と IME 開閉 と カーソル位置

以下を元に少し見直していきます。

👉 【Jetpack Compose】TextField の フォーカス と IME 開閉 と カーソル位置 hatena-bookmark

(更新中...)