Repository: detekt/detekt (kotlin)

Issue:
False positive on `ForbiddenMethodCall`
```kotlin
@Test
fun `should report property setters call 2`() {
    val code = """
        import java.util.Calendar
        
        fun main() {
            val calendar = Calendar.getInstance()
            val day = calendar.firstDayOfWeek
            calendar.firstDayOfWeek = 1
        }
    """.trimIndent()
    val findings = ForbiddenMethodCall(
        TestConfig(METHODS to listOf("java.util.Calendar.getFirstDayOfWeek", "java.util.Calendar.setFirstDayOfWeek"))
    ).lintWithContext(env, code)
    assertThat(findings).hasSize(2)
}
```

This test should pass but it fails because this code reports 4 findings instead of just 2. I know how to fix this but I'll wait to merge #8281 to avoid conflicts.

Pull request:
Fix #8282

If you report the getter and then you use the setter `ForbiddenMethodCall` was reporting it as an issue. In my test case without the fix I was getting 4 issues but there were only 2.

Patch:
diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCall.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCall.kt
index 2370ce1274c8..62806c4a04db 100644
--- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCall.kt
+++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCall.kt
@@ -25,10 +25,10 @@ import org.jetbrains.kotlin.psi.KtExpression
 import org.jetbrains.kotlin.psi.KtOperationReferenceExpression
 import org.jetbrains.kotlin.psi.KtPostfixExpression
 import org.jetbrains.kotlin.psi.KtPrefixExpression
+import org.jetbrains.kotlin.psi.KtProperty
 import org.jetbrains.kotlin.psi.psiUtil.isDotSelector
 import org.jetbrains.kotlin.resolve.calls.util.asCallableReferenceExpression
 import org.jetbrains.kotlin.resolve.calls.util.getCalleeExpressionIfAny
-import org.jetbrains.kotlin.utils.yieldIfNotNull
 
 /**
  * Reports all method or constructor invocations that are forbidden.
@@ -119,36 +119,26 @@ class ForbiddenMethodCall(config: Config) :
             val call = expression.resolveToCall()
                 ?: expression.asCallableReferenceExpression()?.resolveToCall()
                 ?: return
-            val symbols = when (val symbol = call.successfulCallOrNull<KaCall>()) {
-                is KaCallableMemberCall<*, *> -> {
-                    val appliedSymbol = symbol.partiallyAppliedSymbol.symbol
-                    if (appliedSymbol is KaPropertySymbol) {
-                        if (expression !is KtOperationReferenceExpression) {
-                            sequence {
-                                yieldIfNotNull(appliedSymbol.getter)
-                                yieldIfNotNull(appliedSymbol.setter)
-                            }
+
+            sequence {
+                val symbol = when (val symbol = call.successfulCallOrNull<KaCall>()) {
+                    is KaCallableMemberCall<*, *> -> {
+                        val appliedSymbol = symbol.partiallyAppliedSymbol.symbol
+                        if (appliedSymbol is KaPropertySymbol && expression !is KtOperationReferenceExpression) {
+                            getPropertyAccessorSymbol(appliedSymbol, expression)
                         } else {
-                            emptySequence()
+                            appliedSymbol
                         }
-                    } else {
-                        sequenceOf(appliedSymbol)
                     }
-                }
-                is KaCompoundAccessCall -> {
-                    sequenceOf(symbol.compoundOperation.operationPartiallyAppliedSymbol.symbol)
-                }
-                else -> {
-                    emptySequence()
-                }
-            }.flatMap { symbol ->
-                sequence {
-                    yield(symbol)
-                    yieldAll(symbol.allOverriddenSymbols)
-                }
-            }
 
-            for (symbol in symbols) {
+                    is KaCompoundAccessCall -> symbol.compoundOperation.operationPartiallyAppliedSymbol.symbol
+
+                    else -> null
+                } ?: return@sequence
+
+                yield(symbol)
+                yieldAll(symbol.allOverriddenSymbols)
+            }.forEach { symbol ->
                 methods.find { it.value.match(symbol) }?.let { forbidden ->
                     val message = if (forbidden.reason != null) {
                         "The method `${forbidden.value}` has been forbidden: ${forbidden.reason}"
@@ -163,3 +153,10 @@ class ForbiddenMethodCall(config: Config) :
 
     internal data class ForbiddenMethod(val value: FunctionMatcher, val reason: String?)
 }
+
+private fun getPropertyAccessorSymbol(appliedSymbol: KaPropertySymbol, expression: KtExpression) =
+    when (expression.parent) {
+        is KtBinaryExpression -> appliedSymbol.setter
+        is KtProperty -> appliedSymbol.getter
+        else -> null
+    }


Test patch:
diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCallSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCallSpec.kt
index 729af42ba847..7d8c2718bdf4 100644
--- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCallSpec.kt
+++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCallSpec.kt
@@ -651,6 +651,25 @@ class ForbiddenMethodCallSpec(val env: KotlinEnvironmentContainer) {
             ).lintWithContext(env, code)
             assertThat(findings).hasSize(1)
         }
+
+        @Test
+        fun `should report property getter and setter call`() {
+            val code = """
+                import java.util.Calendar
+                
+                fun main() {
+                    val calendar = Calendar.getInstance()
+                    val day = calendar.firstDayOfWeek
+                    calendar.firstDayOfWeek = 1
+                }
+            """.trimIndent()
+            val findings = ForbiddenMethodCall(
+                TestConfig(
+                    METHODS to listOf("java.util.Calendar.getFirstDayOfWeek", "java.util.Calendar.setFirstDayOfWeek"),
+                )
+            ).lintWithContext(env, code)
+            assertThat(findings).hasSize(2)
+        }
     }
 
     @Test