From 25ff00bd347bd4c9f81b22a0c0e6c546de625dd4 Mon Sep 17 00:00:00 2001 From: Alexey Belkov Date: Thu, 2 Oct 2025 18:32:09 +0400 Subject: [PATCH] [kotlin] KTIJ-22055 SuspiciousCascadingIfInspection: support safe call KTIJ-22055 IJ-CR-165301 GitOrigin-RevId: 7001d847604806947e6ccd32db7858f4038c1b1f --- .../SuspiciousCascadingIfInspection.kt | 7 ++++--- .../tests/K2LocalInspectionTestGenerated.java | 5 +++++ .../LocalInspectionTestGenerated.java | 5 +++++ .../ifElseBlockCascadeSafeCallExpr.kt | 13 +++++++++++++ .../ifElseBlockCascadeSafeCallExpr.kt.after | 19 +++++++++++++++++++ 5 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeSafeCallExpr.kt create mode 100644 plugins/kotlin/idea/tests/testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeSafeCallExpr.kt.after diff --git a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/SuspiciousCascadingIfInspection.kt b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/SuspiciousCascadingIfInspection.kt index 4923f26dd3fc..7d349d4e1bb9 100644 --- a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/SuspiciousCascadingIfInspection.kt +++ b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/SuspiciousCascadingIfInspection.kt @@ -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() { 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) } } diff --git a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java index 73b1b6d8327f..961f12fdf71b 100644 --- a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java +++ b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java @@ -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"); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 3caea0cf909b..061f2b610b54 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -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"); diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeSafeCallExpr.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeSafeCallExpr.kt new file mode 100644 index 000000000000..c660ccdb6866 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeSafeCallExpr.kt @@ -0,0 +1,13 @@ +// PROBLEM: Suspicious cascading 'if' expression +// FIX: Replace 'if' with 'when' (changes semantics) +// IGNORE_K1 +// WITH_STDLIB +fun test() { + if (true) { + 1 + } else if (true) { + 2 + } else { + 3 + }?.let { print(it) } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeSafeCallExpr.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeSafeCallExpr.kt.after new file mode 100644 index 000000000000..cbe2567a0192 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/suspiciousCascadingIf/ifElseBlockCascadeSafeCallExpr.kt.after @@ -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) } +}