Repository: detekt/detekt (kotlin)

Issue:
ThrowingExceptionsWithoutMessageOrCause false positive
<!-- The bug you're experiencing might have already be reported! -->
<!-- Please search in the [issues](https://github.com/detekt/detekt/issues) before creating one. -->

## Expected Behavior
```kotlin
loader.errors().firstOrNull()?.exception()?.let { throw it }
```
The following code should work fine and don't violate ThrowingExceptionsWithoutMessageOrCause since we already have a message for an exception

## Observed Behavior
<!-- Tell us what happens instead of the expected behavior -->
```kotlin
loader.errors().firstOrNull()?.exception()?.let { throw it }
```
Throws ThrowingExceptionsWithoutMessageOrCause
Even the following code violates the rule
```kotlin
loader.errors().firstOrNull()?.exception()?.let { throw DataAccessException(it.message, it.cause) }
```
For some reason it reacts on method invocation `.exception()`

## Steps to Reproduce
<!-- Provide a link to a live example, or an unambiguous set of steps to -->
<!-- reproduce this bug. Include code to reproduce, if relevant -->

## Context
<!-- How has this issue affected you? What are you trying to accomplish? -->
<!-- Providing context helps us come up with a solution that is most useful in the real world -->
I'm using jooq Loader API
https://www.jooq.org/doc/latest/manual/sql-execution/importing/importing-api/

## Your Environment
<!-- Include as many relevant details about the environment you experienced the bug in -->
* Version of detekt used: 1.23.6
* Version of Gradle used (if applicable): 8.6
* Gradle scan link (add `--scan` option when running the gradle task):
* Operating System and version: MacOS
* Link to your project (if it's a public repository):

Pull request:
Fixes #7448

I searched why we had the `ignoreCase = true` and it doesn't seem intentional. We were using `SplitPattern` on this rule before. And that function had the `ignoreCase = true` but I guess that was not intentional for this rule. I can't think of a good reason for it.

Another solution would be to move this rule to `@RequiresFullAnalysis` so we can be sure if we are calling the constructor or not. But I think that it's not needed right now.

Patch:
diff --git a/detekt-rules-exceptions/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCause.kt b/detekt-rules-exceptions/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCause.kt
index e4325e8663f5..7d6ba408db37 100644
--- a/detekt-rules-exceptions/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCause.kt
+++ b/detekt-rules-exceptions/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCause.kt
@@ -57,12 +57,11 @@ class ThrowingExceptionsWithoutMessageOrCause(config: Config) : Rule(
     )
 
     override fun visitCallExpression(expression: KtCallExpression) {
-        val calleeExpressionText = expression.calleeExpression?.text
-        if (exceptions.any { calleeExpressionText?.equals(it, ignoreCase = true) == true } &&
-            expression.valueArguments.isEmpty()
-        ) {
+        super.visitCallExpression(expression)
+        val calleeExpressionText = expression.calleeExpression?.text ?: return
+
+        if (exceptions.any { calleeExpressionText == it } && expression.valueArguments.isEmpty()) {
             report(CodeSmell(Entity.from(expression), description))
         }
-        super.visitCallExpression(expression)
     }
 }


Test patch:
diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCauseSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCauseSpec.kt
index 138617c556fd..f699a8045eaa 100644
--- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCauseSpec.kt
+++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCauseSpec.kt
@@ -7,10 +7,9 @@ import org.junit.jupiter.api.Nested
 import org.junit.jupiter.api.Test
 
 class ThrowingExceptionsWithoutMessageOrCauseSpec {
-    val subject =
-        ThrowingExceptionsWithoutMessageOrCause(
-            TestConfig("exceptions" to listOf("IllegalArgumentException"))
-        )
+    val subject = ThrowingExceptionsWithoutMessageOrCause(
+        TestConfig("exceptions" to listOf("IllegalArgumentException"))
+    )
 
     @Nested
     inner class `several exception calls` {
@@ -36,17 +35,27 @@ class ThrowingExceptionsWithoutMessageOrCauseSpec {
         }
     }
 
-    @Nested
-    inner class `a test code which asserts an exception` {
+    @Test
+    fun `a test code which asserts an exception does not report a call to this exception`() {
+        val code = """
+            fun test() {
+                org.assertj.core.api.Assertions.assertThatIllegalArgumentException().isThrownBy { println() }
+            }
+        """.trimIndent()
+        assertThat(subject.compileAndLint(code)).isEmpty()
+    }
 
-        @Test
-        fun `does not report a call to this exception`() {
-            val code = """
-                fun test() {
-                    org.assertj.core.api.Assertions.assertThatIllegalArgumentException().isThrownBy { println() }
-                }
-            """.trimIndent()
-            assertThat(subject.compileAndLint(code)).isEmpty()
-        }
+    @Test
+    fun `don't raise an issue when only matches ignoring cases`() {
+        val code = """
+            fun illegalArgumentException() {
+                // no-op
+            }
+
+            fun test() {
+                illegalArgumentException()
+            }
+        """.trimIndent()
+        assertThat(subject.compileAndLint(code)).isEmpty()
     }
 }