From c9477d94ad3131142c98dd0fb6e7d3afdcd7319f Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Thu, 8 Nov 2018 00:04:04 +0900 Subject: [PATCH] Replace if with when: fix behavior on 'else if' #KT-4645 Fixed --- .../intentions/IfToWhenIntention.kt | 27 ++++++++++++++----- .../branched/ifWhen/ifToWhen/onElseIf.kt | 9 +++++++ .../ifWhen/ifToWhen/onElseIf.kt.after | 8 ++++++ .../branched/ifWhen/ifToWhen/onElseIf2.kt | 11 ++++++++ .../ifWhen/ifToWhen/onElseIf2.kt.after | 8 ++++++ .../branched/ifWhen/ifToWhen/onElseIf3.kt | 13 +++++++++ .../ifWhen/ifToWhen/onElseIf3.kt.after | 12 +++++++++ .../intentions/IntentionTestGenerated.java | 15 +++++++++++ 8 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf.kt create mode 100644 idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf.kt.after create mode 100644 idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf2.kt create mode 100644 idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf2.kt.after create mode 100644 idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf3.kt create mode 100644 idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf3.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfToWhenIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfToWhenIntention.kt index f42646e7692..47963522368 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfToWhenIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfToWhenIntention.kt @@ -121,19 +121,31 @@ class IfToWhenIntention : SelfTargetingRangeIntention(KtIfExpres appendFixedText("\n") } + private fun KtIfExpression.topmostIfExpression(): KtIfExpression { + var target = this + while (true) { + val container = target.parent as? KtContainerNodeForControlStructureBody ?: break + val parent = container.parent as? KtIfExpression ?: break + if (parent.`else` != target) break + target = parent + } + return target + } + override fun applyTo(element: KtIfExpression, editor: Editor?) { - val siblings = element.siblings() - val elementCommentSaver = CommentSaver(element) - val fullCommentSaver = CommentSaver(PsiChildRange(element, siblings.last()), saveLineBreaks = true) + val ifExpression = element.topmostIfExpression() + val siblings = ifExpression.siblings() + val elementCommentSaver = CommentSaver(ifExpression) + val fullCommentSaver = CommentSaver(PsiChildRange(ifExpression, siblings.last()), saveLineBreaks = true) val toDelete = ArrayList() var applyFullCommentSaver = true - val loop = element.getStrictParentOfType() + val loop = ifExpression.getStrictParentOfType() val loopJumpVisitor = LabelLoopJumpVisitor(loop) - var whenExpression = KtPsiFactory(element).buildExpression { + var whenExpression = KtPsiFactory(ifExpression).buildExpression { appendFixedText("when {\n") - var currentIfExpression = element + var currentIfExpression = ifExpression var baseIfExpressionForSyntheticBranch = currentIfExpression var canPassThrough = false while (true) { @@ -183,7 +195,8 @@ class IfToWhenIntention : SelfTargetingRangeIntention(KtIfExpres whenExpression = whenExpression.introduceSubject() } - val result = element.replaced(whenExpression) + val result = ifExpression.replaced(whenExpression) + editor?.caretModel?.moveToOffset(result.startOffset) (if (applyFullCommentSaver) fullCommentSaver else elementCommentSaver).restore(result) toDelete.forEach(PsiElement::delete) diff --git a/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf.kt b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf.kt new file mode 100644 index 00000000000..e2fb64f0e7a --- /dev/null +++ b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf.kt @@ -0,0 +1,9 @@ +fun test(n: Int): String { + return if (n == 0) + "zero" + else if (n == 1) + "one" + else if (n == 2) + "two" + else "unknown" +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf.kt.after b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf.kt.after new file mode 100644 index 00000000000..dba5a8e64d6 --- /dev/null +++ b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf.kt.after @@ -0,0 +1,8 @@ +fun test(n: Int): String { + return when (n) { + 0 -> "zero" + 1 -> "one" + 2 -> "two" + else -> "unknown" + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf2.kt b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf2.kt new file mode 100644 index 00000000000..5b504759245 --- /dev/null +++ b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf2.kt @@ -0,0 +1,11 @@ +fun test(n: Int): String { + return if (n == 0) { + "zero" + } else if (n == 1) { + "one" + } else if (n == 2) { + "two" + } else { + "unknown" + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf2.kt.after b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf2.kt.after new file mode 100644 index 00000000000..dba5a8e64d6 --- /dev/null +++ b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf2.kt.after @@ -0,0 +1,8 @@ +fun test(n: Int): String { + return when (n) { + 0 -> "zero" + 1 -> "one" + 2 -> "two" + else -> "unknown" + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf3.kt b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf3.kt new file mode 100644 index 00000000000..ac5b69a9bfd --- /dev/null +++ b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf3.kt @@ -0,0 +1,13 @@ +fun test(b: Boolean, n: Int): String { + return if (b) { + if (n == 0) + "zero" + else if (n == 1) + "one" + else if (n == 2) + "two" + else "unknown" + } else { + "" + } +} \ No newline at end of file diff --git a/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf3.kt.after b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf3.kt.after new file mode 100644 index 00000000000..b1c79fc9fac --- /dev/null +++ b/idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf3.kt.after @@ -0,0 +1,12 @@ +fun test(b: Boolean, n: Int): String { + return if (b) { + when (n) { + 0 -> "zero" + 1 -> "one" + 2 -> "two" + else -> "unknown" + } + } else { + "" + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 8ee640a5536..6d56269ed2c 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -2659,6 +2659,21 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/branched/ifWhen/ifToWhen/multipleIfWithSingleReturns.kt"); } + @TestMetadata("onElseIf.kt") + public void testOnElseIf() throws Exception { + runTest("idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf.kt"); + } + + @TestMetadata("onElseIf2.kt") + public void testOnElseIf2() throws Exception { + runTest("idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf2.kt"); + } + + @TestMetadata("onElseIf3.kt") + public void testOnElseIf3() throws Exception { + runTest("idea/testData/intentions/branched/ifWhen/ifToWhen/onElseIf3.kt"); + } + @TestMetadata("secondIfNoThen.kt") public void testSecondIfNoThen() throws Exception { runTest("idea/testData/intentions/branched/ifWhen/ifToWhen/secondIfNoThen.kt");