All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gitlab.arturbosch.detekt.rules.style.ExplicitItLambdaParameter.kt Maven / Gradle / Ivy

The newest version!
package io.gitlab.arturbosch.detekt.rules.style

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 io.gitlab.arturbosch.detekt.api.internal.ActiveByDefault
import io.gitlab.arturbosch.detekt.rules.IT_LITERAL
import org.jetbrains.kotlin.psi.KtLambdaExpression

/**
 * Lambda expressions are one of the core features of the language. They often include very small chunks of
 * code using only one parameter. In this cases Kotlin can supply the implicit `it` parameter
 * to make code more concise. It fits most use cases, but when faced larger or nested chunks of code,
 * you might want to add an explicit name for the parameter. Naming it just `it` is meaningless and only
 * makes your code misleading, especially when dealing with nested functions.
 *
 * 
 * a?.let { it -> it.plus(1) }
 * foo.flatMapObservable { it -> Observable.fromIterable(it) }
 * listOfPairs.map(::second).forEach { it ->
 *     it.execute()
 * }
 * collection.zipWithNext { it, next -> Pair(it, next) }
 * 
 *
 * 
 * a?.let { it.plus(1) } // Much better to use implicit it
 * a?.let { value: Int -> value.plus(1) } // Better as states the type more clearly
 * foo.flatMapObservable(Observable::fromIterable) // Here we can have a method reference
 *
 * // For multiline blocks it is usually better come up with a clear and more meaningful name
 * listOfPairs.map(::second).forEach { apiRequest ->
 *     apiRequest.execute()
 * }
 *
 * // Lambdas with multiple parameter should be named clearly, using it for one of them can be confusing
 * collection.zipWithNext { prev, next ->
 *     Pair(prev, next)
 * }
 * 
 */
@ActiveByDefault(since = "1.21.0")
class ExplicitItLambdaParameter(val config: Config) : Rule(config) {
    override val issue = Issue(
        javaClass.simpleName,
        Severity.Style,
        "Declaring lambda parameters as `it` is redundant.",
        Debt.FIVE_MINS
    )

    override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {
        super.visitLambdaExpression(lambdaExpression)
        val parameterNames = lambdaExpression.valueParameters.map { it.name }
        if (IT_LITERAL in parameterNames) {
            val message =
                if (
                    parameterNames.size == 1 &&
                    lambdaExpression.valueParameters[0].typeReference == null
                ) {
                    "This explicit usage of `it` as the lambda parameter name can be omitted."
                } else {
                    "`it` should not be used as name for a lambda parameter."
                }
            report(
                CodeSmell(
                    issue,
                    Entity.from(lambdaExpression),
                    message
                )
            )
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy