diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml
index c7fb48e9b3c..047fdd67103 100644
--- a/idea/resources/META-INF/plugin-common.xml
+++ b/idea/resources/META-INF/plugin-common.xml
@@ -1479,6 +1479,11 @@
Kotlin
+
+ org.jetbrains.kotlin.idea.intentions.MergeElseIfIntention
+ Kotlin
+
+
org.jetbrains.kotlin.idea.intentions.AddMissingDestructuringIntention
Kotlin
diff --git a/idea/resources/intentionDescriptions/MergeElseIfIntention/after.kt.template b/idea/resources/intentionDescriptions/MergeElseIfIntention/after.kt.template
new file mode 100644
index 00000000000..963f2c33ed0
--- /dev/null
+++ b/idea/resources/intentionDescriptions/MergeElseIfIntention/after.kt.template
@@ -0,0 +1,5 @@
+if (a) {
+ println("a")
+} else if (b) {
+ println("not a and b")
+}
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/MergeElseIfIntention/before.kt.template b/idea/resources/intentionDescriptions/MergeElseIfIntention/before.kt.template
new file mode 100644
index 00000000000..52f7bc934ba
--- /dev/null
+++ b/idea/resources/intentionDescriptions/MergeElseIfIntention/before.kt.template
@@ -0,0 +1,7 @@
+if (a) {
+ println("a")
+} else {
+ if (b) {
+ println("not a and b")
+ }
+}
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/MergeElseIfIntention/description.html b/idea/resources/intentionDescriptions/MergeElseIfIntention/description.html
new file mode 100644
index 00000000000..4b4c713b685
--- /dev/null
+++ b/idea/resources/intentionDescriptions/MergeElseIfIntention/description.html
@@ -0,0 +1,5 @@
+
+
+This intention merges else and nested if statement without else branches into a single else if.
+
+
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/MergeElseIfIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/MergeElseIfIntention.kt
new file mode 100644
index 00000000000..9bf1dd110d8
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/MergeElseIfIntention.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.idea.intentions
+
+import com.intellij.openapi.editor.Editor
+import org.jetbrains.kotlin.psi.*
+
+
+class MergeElseIfIntention : SelfTargetingIntention(KtIfExpression::class.java, "Merge 'else if'") {
+ override fun isApplicableTo(element: KtIfExpression, caretOffset: Int): Boolean {
+ val elseBody = element.`else` ?: return false
+ val nestedIf = elseBody.nestedIf() ?: return false
+ return nestedIf.`else` == null
+ }
+
+ override fun applyTo(element: KtIfExpression, editor: Editor?) {
+ val nestedIf = element.`else`?.nestedIf() ?: return
+ val condition = nestedIf.condition ?: return
+ val nestedBody = nestedIf.then ?: return
+
+ val factory = KtPsiFactory(element)
+ element.`else`?.replace(
+ factory.createExpressionByPattern("if ($0) $1", condition, nestedBody)
+ )
+ }
+
+ companion object {
+ private fun KtExpression.nestedIf() =
+ if (this is KtBlockExpression) {
+ this.statements.singleOrNull() as? KtIfExpression
+ } else {
+ null
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeElseIf/.intention b/idea/testData/intentions/mergeElseIf/.intention
new file mode 100644
index 00000000000..02521a0360f
--- /dev/null
+++ b/idea/testData/intentions/mergeElseIf/.intention
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.intentions.MergeElseIfIntention
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeElseIf/comments.kt b/idea/testData/intentions/mergeElseIf/comments.kt
new file mode 100644
index 00000000000..faa40a9ef27
--- /dev/null
+++ b/idea/testData/intentions/mergeElseIf/comments.kt
@@ -0,0 +1,11 @@
+fun foo() {
+ // comment 1
+ if (true) {
+
+ } else /* comment 2 */ {
+ if (true) {
+ // comment 4
+ foo()
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeElseIf/comments.kt.after b/idea/testData/intentions/mergeElseIf/comments.kt.after
new file mode 100644
index 00000000000..34a5b6a7f29
--- /dev/null
+++ b/idea/testData/intentions/mergeElseIf/comments.kt.after
@@ -0,0 +1,9 @@
+fun foo() {
+ // comment 1
+ if (true) {
+
+ } else /* comment 2 */ if (true) {
+ // comment 4
+ foo()
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeElseIf/else.kt b/idea/testData/intentions/mergeElseIf/else.kt
new file mode 100644
index 00000000000..8d93114a58b
--- /dev/null
+++ b/idea/testData/intentions/mergeElseIf/else.kt
@@ -0,0 +1,13 @@
+// IS_APPLICABLE: false
+
+fun foo() {
+ if (true) {
+
+ } else {
+ if (false) {
+ foo()
+ } else {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeElseIf/expression.kt b/idea/testData/intentions/mergeElseIf/expression.kt
new file mode 100644
index 00000000000..2f2f13a2517
--- /dev/null
+++ b/idea/testData/intentions/mergeElseIf/expression.kt
@@ -0,0 +1,7 @@
+fun foo() {
+ if (true) {
+
+ } else {
+ if (false) foo()
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeElseIf/expression.kt.after b/idea/testData/intentions/mergeElseIf/expression.kt.after
new file mode 100644
index 00000000000..d20c783c0f9
--- /dev/null
+++ b/idea/testData/intentions/mergeElseIf/expression.kt.after
@@ -0,0 +1,5 @@
+fun foo() {
+ if (true) {
+
+ } else if (false) foo()
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeElseIf/ifNotSingle.kt b/idea/testData/intentions/mergeElseIf/ifNotSingle.kt
new file mode 100644
index 00000000000..1952b3fe6a0
--- /dev/null
+++ b/idea/testData/intentions/mergeElseIf/ifNotSingle.kt
@@ -0,0 +1,12 @@
+// IS_APPLICABLE: false
+
+fun foo() {
+ if (true) {
+
+ } else {
+ if (false) {
+ foo()
+ }
+ val a = 5
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeElseIf/simple.kt b/idea/testData/intentions/mergeElseIf/simple.kt
new file mode 100644
index 00000000000..8f189a25a63
--- /dev/null
+++ b/idea/testData/intentions/mergeElseIf/simple.kt
@@ -0,0 +1,9 @@
+fun foo() {
+ if (true) {
+
+ } else {
+ if (false) {
+ foo()
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeElseIf/simple.kt.after b/idea/testData/intentions/mergeElseIf/simple.kt.after
new file mode 100644
index 00000000000..8cf68c3ea38
--- /dev/null
+++ b/idea/testData/intentions/mergeElseIf/simple.kt.after
@@ -0,0 +1,7 @@
+fun foo() {
+ if (true) {
+
+ } else if (false) {
+ foo()
+ }
+}
\ 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 4e929fdef61..ad78f2d63bb 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
@@ -11722,6 +11722,44 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
}
}
+ @TestMetadata("idea/testData/intentions/mergeElseIf")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class MergeElseIf extends AbstractIntentionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
+ }
+
+ public void testAllFilesPresentInMergeElseIf() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/mergeElseIf"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("comments.kt")
+ public void testComments() throws Exception {
+ runTest("idea/testData/intentions/mergeElseIf/comments.kt");
+ }
+
+ @TestMetadata("else.kt")
+ public void testElse() throws Exception {
+ runTest("idea/testData/intentions/mergeElseIf/else.kt");
+ }
+
+ @TestMetadata("expression.kt")
+ public void testExpression() throws Exception {
+ runTest("idea/testData/intentions/mergeElseIf/expression.kt");
+ }
+
+ @TestMetadata("ifNotSingle.kt")
+ public void testIfNotSingle() throws Exception {
+ runTest("idea/testData/intentions/mergeElseIf/ifNotSingle.kt");
+ }
+
+ @TestMetadata("simple.kt")
+ public void testSimple() throws Exception {
+ runTest("idea/testData/intentions/mergeElseIf/simple.kt");
+ }
+ }
+
@TestMetadata("idea/testData/intentions/mergeIfs")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)