Skip to content

Commit

Permalink
SONARKT-540 Migrate ReasonableTypeCastsCheck to kotlin-analysis-api
Browse files Browse the repository at this point in the history
DFA in K2 reports only first CAST_NEVER_SUCCEEDS per variable.

Co-authored-by: Marharyta Nedzelska <[email protected]>
Co-authored-by: Evgeny Mandrikov <[email protected]>
  • Loading branch information
3 people authored Feb 7, 2025
1 parent b7cd4b8 commit d94efb0
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@ package checks

class ReasonableTypeCastsCheckSample {
fun noncompliant() {
val i: Int = 10
val i1: Int = 10
// Throws ClassCastException
val s1: String = i1 as String // Noncompliant {{Remove this cast that can never succeed.}}

val i2: Int = 10
// Throws ClassCastException
val s1a: String = i as String // Noncompliant {{Remove this cast that can never succeed.}}
val s1b = i as String // Noncompliant
val s2 = i2 as String // Noncompliant {{Remove this cast that can never succeed.}}

val i3: Int = 10
// Will always be null
val s2: String? = i as? String // Noncompliant
val s3: String? = i3 as? String // Noncompliant {{Remove this cast that can never succeed.}}

val list = listOf(1, 2, 3, 4)

// any operation with list elements will produce ClassCastException
val strings1 = list as List<String> // Noncompliant {{Remove this unchecked cast.}}

val list2 = listOf(1)
// any operation with list elements will produce ClassCastException
val strings2 = list as? List<String> // Noncompliant
val strings2 = list2 as? List<String> // Noncompliant {{Remove this unchecked cast.}}
}

fun compliant() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,18 @@ import org.sonar.check.Rule
import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.frontend.KotlinFileContext

@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6530")
class ReasonableTypeCastsCheck : AbstractCheck() {
override fun visitKtFile(file: KtFile, context: KotlinFileContext) {
context.diagnostics
context.kaDiagnostics
.mapNotNull { diagnostic ->
when (diagnostic.factory) {
Errors.UNCHECKED_CAST -> "Remove this unchecked cast."
Errors.CAST_NEVER_SUCCEEDS -> "Remove this cast that can never succeed."
when (diagnostic.factoryName) {
Errors.UNCHECKED_CAST.name -> "Remove this unchecked cast."
Errors.CAST_NEVER_SUCCEEDS.name -> "Remove this cast that can never succeed."
else -> null
}?.let { diagnostic to it }
}.forEach { (diagnostic, msg) ->
context.reportIssue(diagnostic.psiElement, msg)
context.reportIssue(diagnostic.psi, msg)
}
}
}

0 comments on commit d94efb0

Please sign in to comment.