Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add list of functions to skip in IgnoredReturnValue rule #4434

Merged
merged 9 commits into from Jan 28, 2022
1 change: 1 addition & 0 deletions detekt-core/src/main/resources/default-detekt-config.yml
Expand Up @@ -552,6 +552,7 @@ potential-bugs:
- '*.CheckReturnValue'
ignoreReturnValueAnnotations:
- '*.CanIgnoreReturnValue'
ignoreFunctionCall: []
ImplicitDefaultLocale:
active: true
ImplicitUnitReturnType:
Expand Down
1 change: 1 addition & 0 deletions detekt-rules-errorprone/build.gradle.kts
Expand Up @@ -4,6 +4,7 @@ plugins {

dependencies {
compileOnly(projects.detektApi)
implementation(projects.detektTooling)
testImplementation(projects.detektTest)
testImplementation(libs.bundles.testImplementation)
testRuntimeOnly(libs.spek.runner)
Expand Down
@@ -1,5 +1,6 @@
package io.gitlab.arturbosch.detekt.rules.bugs

import io.github.detekt.tooling.api.FunctionMatcher
import io.gitlab.arturbosch.detekt.api.CodeSmell
import io.gitlab.arturbosch.detekt.api.Config
import io.gitlab.arturbosch.detekt.api.Debt
Expand Down Expand Up @@ -58,6 +59,17 @@ class IgnoredReturnValue(config: Config = Config.empty) : Rule(config) {
it.map(String::simplePatternToRegex)
}

@Configuration(
"List of fully-qualified function call signatures which should be ignored by this rule. " +
"Functions can be defined without full signature (i.e. `java.time.LocalDate.now`) which will ignore " +
"calls of all functions with this name or with full signature " +
"(i.e. `java.time.LocalDate.now(java.time.Clock)`) which would ignore only call " +
"with this concrete signature."
BraisGabin marked this conversation as resolved.
Show resolved Hide resolved
)
private val ignoreFunctionCall: List<FunctionMatcher> by config(emptyList<String>()) {
it.map(FunctionMatcher::fromFunctionSignature)
}

@Suppress("ReturnCount")
override fun visitCallExpression(expression: KtCallExpression) {
super.visitCallExpression(expression)
Expand All @@ -68,6 +80,8 @@ class IgnoredReturnValue(config: Config = Config.empty) : Rule(config) {
val resultingDescriptor = expression.getResolvedCall(bindingContext)?.resultingDescriptor ?: return
if (resultingDescriptor.returnType?.isUnit() == true) return

if (ignoreFunctionCall.any { it.match(resultingDescriptor) }) return

val annotations = resultingDescriptor.annotations
if (annotations.any { it in ignoreReturnValueAnnotations }) return
if (restrictToAnnotatedMethods &&
Expand Down
Expand Up @@ -813,5 +813,28 @@ object IgnoredReturnValueSpec : Spek({
val findings = rule.compileAndLintWithContext(env, code)
assertThat(findings).isEmpty()
}

it("does not report when a function is in ignoreFunctionCall") {
val code = """
package foo

fun listOfChecked(value: String) = listOf(value)

fun foo() : Int {
listOfChecked("hello")
return 42
}
"""
val rule = IgnoredReturnValue(
TestConfig(
mapOf(
"ignoreFunctionCall" to listOf("foo.listOfChecked"),
"restrictToAnnotatedMethods" to false
)
)
)
val findings = rule.compileAndLintWithContext(env, code)
assertThat(findings).isEmpty()
}
}
})