[kotlin] KTIJ-22055 SuspiciousCascadingIfInspection: support safe call

KTIJ-22055
IJ-CR-165301

GitOrigin-RevId: 7001d847604806947e6ccd32db7858f4038c1b1f
This commit is contained in:
Alexey Belkov
2025-10-02 16:17:05 +00:00
committed by intellij-monorepo-bot
parent 6db3df7645
commit 25ff00bd34
5 changed files with 46 additions and 3 deletions
@@ -30,7 +30,7 @@ internal class SuspiciousCascadingIfInspection : KotlinApplicableInspectionBase<
if (element.parent.node.elementType == KtNodeTypes.ELSE) return false
val candidateExpression = when (val lastElseBranch = element.findLastElseBranch()) {
is KtDotQualifiedExpression -> lastElseBranch.receiverExpression
is KtQualifiedExpression -> lastElseBranch.receiverExpression
is KtBinaryExpression -> lastElseBranch.left
else -> null
}
@@ -89,12 +89,13 @@ private class ConvertIfToWhenFix : KotlinModCommandQuickFix<KtIfExpression>() {
whenExpr.replace(outerBinaryExpr)
}
is KtDotQualifiedExpression -> {
is KtQualifiedExpression -> {
val selectorText = lastElseBranch.selectorExpression?.text ?: ""
val nestedIf = lastElseBranch.receiverExpression
lastElseBranch.replace(nestedIf)
val whenExpr = convertIfToWhen(element, updater)
val outerQualifiedExpr = psiFactory.createExpressionByPattern("$0.$1", whenExpr, selectorText)
val operator = lastElseBranch.operationSign.value // . or ?.
val outerQualifiedExpr = psiFactory.createExpressionByPattern("$0$1$2", whenExpr, operator, selectorText)
whenExpr.replace(outerQualifiedExpr)
}
}
@@ -4273,6 +4273,11 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp
runTest("../../../idea/tests/testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeQualifiedExprAddBraces.kt");
}
@TestMetadata("ifElseBlockCascadeSafeCallExpr.kt")
public void testIfElseBlockCascadeSafeCallExpr() throws Exception {
runTest("../../../idea/tests/testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeSafeCallExpr.kt");
}
@TestMetadata("ifElseBlockQualifiedExpr.kt")
public void testIfElseBlockQualifiedExpr() throws Exception {
runTest("../../../idea/tests/testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockQualifiedExpr.kt");
@@ -15584,6 +15584,11 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti
runTest("testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeQualifiedExprAddBraces.kt");
}
@TestMetadata("ifElseBlockCascadeSafeCallExpr.kt")
public void testIfElseBlockCascadeSafeCallExpr() throws Exception {
runTest("testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeSafeCallExpr.kt");
}
@TestMetadata("ifElseBlockQualifiedExpr.kt")
public void testIfElseBlockQualifiedExpr() throws Exception {
runTest("testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockQualifiedExpr.kt");
@@ -0,0 +1,13 @@
// PROBLEM: Suspicious cascading 'if' expression
// FIX: Replace 'if' with 'when' (changes semantics)
// IGNORE_K1
// WITH_STDLIB
fun test() {
<caret>if (true) {
1
} else if (true) {
2
} else {
3
}?.let { print(it) }
}
@@ -0,0 +1,19 @@
// PROBLEM: Suspicious cascading 'if' expression
// FIX: Replace 'if' with 'when' (changes semantics)
// IGNORE_K1
// WITH_STDLIB
fun test() {
when {
true -> {
1
}
true -> {
2
}
else -> {
3
}
}?.let { print(it) }
}