0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kotlin 分解宣言を Detekt で良い感じに禁止する

Last updated at Posted at 2025-08-07

要件

基本的に分解宣言(Destructuring) はクラス定義を辞めて Array<Object> と引数 index でコミュニケーション取るようなもの(言い過ぎ)なので辞めたい。

例外

一方で以下のケースは許したい

言語 for 文での受け取り

多くは key/value や idx/value なので。。

for ((key, value) in entries) {
    // OK
}

associatedBy 等の receiver

entries.associatedBy { (key, value) -> key }

実装

import io.gitlab.arturbosch.detekt.api.CodeSmell
import io.gitlab.arturbosch.detekt.api.Config
import io.gitlab.arturbosch.detekt.api.Debt
import io.gitlab.arturbosch.detekt.api.Entity
import io.gitlab.arturbosch.detekt.api.Issue
import io.gitlab.arturbosch.detekt.api.Rule
import io.gitlab.arturbosch.detekt.api.Severity
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.psiUtil.parents

class NoDestructuring(config: Config = Config.empty) : Rule(config) {

    override val issue = Issue(
        id = "NoDestructuring",
        severity = Severity.Style,
        description = "分解宣言は for-loop とラムダ(SAM)のパラメータだけ許可",
        debt = Debt.FIVE_MINS,
    )

    override fun visitDestructuringDeclaration(d: KtDestructuringDeclaration) {
        val allowed = isInForLoop(d) || isInLambdaParameter(d)
        if (!allowed) {
            report(
                CodeSmell(
                    issue,
                    Entity.from(d),
                    "変数の定義順でのアクセスとなる分解宣言は利用せず、代わりに明示的なフィールドアクセスを行ってください。必要があれば (private) data class を定義してください。",
                ),
            )
        }
        super.visitDestructuringDeclaration(d)
    }

    /** `for ((k,v) in ...) {}` の `(k,v)` 判定 */
    private fun isInForLoop(d: KtDestructuringDeclaration): Boolean {
        return d.parent is KtForExpression || d.parent?.parent is KtForExpression
    }

    /** `{ (k,v) -> ... }` ラムダの `(k,v)` 判定  */
    private fun isInLambdaParameter(d: KtDestructuringDeclaration): Boolean {
        return d.parents.any { it is KtParameter } &&
            d.parents.any { it is KtLambdaExpression }
    }
}
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?