diff --git a/README.md b/README.md index c31dfa6..7d481b2 100644 --- a/README.md +++ b/README.md @@ -68,4 +68,8 @@ val a = when { ### MutableObservablePropertyIsPrivate This rule reports exposed `MutableLive...` and `MutableStateFlow` properties. They should be -private. +private. + +### NoNotNullOperator + +This rule reports `!!` usage. `requireNotNull` should be used instead. diff --git a/src/main/kotlin/com/doist/detekt/NoNotNullOperator.kt b/src/main/kotlin/com/doist/detekt/NoNotNullOperator.kt new file mode 100644 index 0000000..86454f4 --- /dev/null +++ b/src/main/kotlin/com/doist/detekt/NoNotNullOperator.kt @@ -0,0 +1,32 @@ +package com.doist.detekt + +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.KtPostfixExpression + +class NoNotNullOperator(config: Config) : Rule(config) { + override val issue = Issue( + javaClass.simpleName, + Severity.Style, + "Detects !! operator", + Debt.FIVE_MINS, + ) + + override fun visitPostfixExpression(expression: KtPostfixExpression) { + super.visitPostfixExpression(expression) + + if (expression.text.endsWith("!!")) { + val codeSmell = CodeSmell( + issue = issue, + entity = Entity.from(expression), + message = "Use requireNotNull instead of !! operator", + ) + report(codeSmell) + } + } +} diff --git a/src/main/resources/config/config.yml b/src/main/resources/config/config.yml index c20740d..939c7f7 100644 --- a/src/main/resources/config/config.yml +++ b/src/main/resources/config/config.yml @@ -7,3 +7,5 @@ DoistRuleSet: active: true MutableObservablePropertyIsPrivate: active: true + NoNotNullOperator: + active: true diff --git a/src/test/kotlin/com/doist/detekt/NoNotNullOperatorTest.kt b/src/test/kotlin/com/doist/detekt/NoNotNullOperatorTest.kt new file mode 100644 index 0000000..072013c --- /dev/null +++ b/src/test/kotlin/com/doist/detekt/NoNotNullOperatorTest.kt @@ -0,0 +1,33 @@ +package com.doist.detekt + +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest +import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext +import io.kotest.matchers.collections.shouldHaveSize +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.junit.jupiter.api.Test + +@KotlinCoreEnvironmentTest +internal class NoNotNullOperatorTest(private val env: KotlinCoreEnvironment) { + @Test + fun `reports !! usage`() { + val code = """ + val a: String? = "" + val b = a!! + """ + val rule = NoNotNullOperator(Config.empty) + val findings = rule.compileAndLintWithContext(env, code) + findings shouldHaveSize 1 + } + + @Test + fun `doesn't reports requireNoteNull usage`() { + val code = """ + val a: String? = "" + val b = requireNotNull(a) + """ + val rule = NoNotNullOperator(Config.empty) + val findings = rule.compileAndLintWithContext(env, code) + findings shouldHaveSize 0 + } +}