diff --git a/idea/resources/intentionDescriptions/MergeIfsIntention/after.kt.template b/idea/resources/intentionDescriptions/MergeIfsIntention/after.kt.template
new file mode 100644
index 00000000000..39a4a8cd01d
--- /dev/null
+++ b/idea/resources/intentionDescriptions/MergeIfsIntention/after.kt.template
@@ -0,0 +1,3 @@
+if (a && b) {
+ println("a and b")
+}
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/MergeIfsIntention/before.kt.template b/idea/resources/intentionDescriptions/MergeIfsIntention/before.kt.template
new file mode 100644
index 00000000000..5f676d9cb4a
--- /dev/null
+++ b/idea/resources/intentionDescriptions/MergeIfsIntention/before.kt.template
@@ -0,0 +1,5 @@
+if (a) {
+ if (b) {
+ println("a and b")
+ }
+}
\ No newline at end of file
diff --git a/idea/resources/intentionDescriptions/MergeIfsIntention/description.html b/idea/resources/intentionDescriptions/MergeIfsIntention/description.html
new file mode 100644
index 00000000000..2ad1232c69c
--- /dev/null
+++ b/idea/resources/intentionDescriptions/MergeIfsIntention/description.html
@@ -0,0 +1,5 @@
+
+
+This intention merges two nested 'if's without 'else' branches into a single one.
+
+
\ No newline at end of file
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index f9579e44fd5..ea107f62ece 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -1502,6 +1502,11 @@
Kotlin
+
+ org.jetbrains.kotlin.idea.intentions.MergeIfsIntention
+ Kotlin
+
+
(KtIfExpression::class.java, "Merge 'if's") {
+
+ override fun isApplicableTo(element: KtIfExpression, caretOffset: Int): Boolean {
+ if (element.`else` != null) return false
+ val then = element.then ?: return false
+
+ val nestedIf = then.nestedIf() ?: return false
+ if (nestedIf.`else` != null) return false
+
+ return true
+ }
+
+ override fun applyTo(element: KtIfExpression, editor: Editor?) {
+ applyTo(element)
+ }
+
+ companion object {
+ fun applyTo(element: KtIfExpression): Int {
+ val nestedIf = element.then?.nestedIf() ?: return -1
+ val condition = element.condition ?: return -1
+ val secondCondition = nestedIf.condition ?: return -1
+ val nestedBody = nestedIf.then ?: return -1
+
+ val factory = KtPsiFactory(element)
+
+ condition.replace(factory.createExpressionByPattern("$0 && $1", condition, secondCondition))
+ val newBody = element.then!!.replace(nestedBody)
+
+ return newBody.textRange!!.startOffset
+ }
+
+ private fun KtExpression.nestedIf() = when (this) {
+ is KtBlockExpression -> this.statements.singleOrNull() as? KtIfExpression
+ is KtIfExpression -> this
+ else -> null
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/kotlin/idea/joinLines/JoinBlockIntoSingleStatementHandler.kt b/idea/src/org/jetbrains/kotlin/idea/joinLines/JoinBlockIntoSingleStatementHandler.kt
index f53fecad418..b0eda87fbd2 100644
--- a/idea/src/org/jetbrains/kotlin/idea/joinLines/JoinBlockIntoSingleStatementHandler.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/joinLines/JoinBlockIntoSingleStatementHandler.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2015 JetBrains s.r.o.
+ * Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.joinLines
import com.intellij.codeInsight.editorActions.JoinRawLinesHandlerDelegate
import com.intellij.openapi.editor.Document
import com.intellij.psi.PsiFile
+import org.jetbrains.kotlin.idea.intentions.MergeIfsIntention
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
@@ -45,15 +46,7 @@ class JoinBlockIntoSingleStatementHandler : JoinRawLinesHandlerDelegate {
// if outer if has else-branch and inner does not have it, do not remove braces otherwise else-branch will belong to different if!
if (pparent.`else` != null) return -1
- val condition1 = pparent.condition
- val condition2 = statement.condition
- val body = statement.then
- if (condition1 != null && condition2 != null && body != null) {
- val newCondition = KtPsiFactory(pparent).createExpressionByPattern("$0 && $1", condition1, condition2)
- condition1.replace(newCondition)
- val newBody = block.replace(body)
- return newBody.textRange!!.startOffset
- }
+ return MergeIfsIntention.applyTo(pparent)
}
val newStatement = block.replace(statement)
diff --git a/idea/testData/intentions/mergeIfs/.intention b/idea/testData/intentions/mergeIfs/.intention
new file mode 100644
index 00000000000..afd0e52ad24
--- /dev/null
+++ b/idea/testData/intentions/mergeIfs/.intention
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.intentions.MergeIfsIntention
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeIfs/comments.kt b/idea/testData/intentions/mergeIfs/comments.kt
new file mode 100644
index 00000000000..17c50d4adc1
--- /dev/null
+++ b/idea/testData/intentions/mergeIfs/comments.kt
@@ -0,0 +1,9 @@
+fun foo() {
+ // comment 1
+ if (/* comment 2 */ true /* comment 3 */) {
+ if (false) {
+ // comment 4
+ foo()
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeIfs/comments.kt.after b/idea/testData/intentions/mergeIfs/comments.kt.after
new file mode 100644
index 00000000000..ad30a82ba14
--- /dev/null
+++ b/idea/testData/intentions/mergeIfs/comments.kt.after
@@ -0,0 +1,7 @@
+fun foo() {
+ // comment 1
+ if (/* comment 2 */ true && false /* comment 3 */) {
+ // comment 4
+ foo()
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeIfs/else1.kt b/idea/testData/intentions/mergeIfs/else1.kt
new file mode 100644
index 00000000000..9a17430a835
--- /dev/null
+++ b/idea/testData/intentions/mergeIfs/else1.kt
@@ -0,0 +1,10 @@
+// IS_APPLICABLE: false
+
+fun foo() {
+ if (true) {
+ if (false) {
+ foo()
+ }
+ } else {
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeIfs/else2.kt b/idea/testData/intentions/mergeIfs/else2.kt
new file mode 100644
index 00000000000..3401aa33bda
--- /dev/null
+++ b/idea/testData/intentions/mergeIfs/else2.kt
@@ -0,0 +1,11 @@
+// IS_APPLICABLE: false
+
+fun foo() {
+ if (true) {
+ if (false) {
+ foo()
+ } else {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeIfs/expression.kt b/idea/testData/intentions/mergeIfs/expression.kt
new file mode 100644
index 00000000000..2dc0335d523
--- /dev/null
+++ b/idea/testData/intentions/mergeIfs/expression.kt
@@ -0,0 +1,5 @@
+fun foo() {
+ if (true) if (false) {
+ foo()
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeIfs/expression.kt.after b/idea/testData/intentions/mergeIfs/expression.kt.after
new file mode 100644
index 00000000000..96ba55fd1d4
--- /dev/null
+++ b/idea/testData/intentions/mergeIfs/expression.kt.after
@@ -0,0 +1,5 @@
+fun foo() {
+ if (true && false) {
+ foo()
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeIfs/simple.kt b/idea/testData/intentions/mergeIfs/simple.kt
new file mode 100644
index 00000000000..e77cd753b93
--- /dev/null
+++ b/idea/testData/intentions/mergeIfs/simple.kt
@@ -0,0 +1,7 @@
+fun foo() {
+ if (true) {
+ if (false) {
+ foo()
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/intentions/mergeIfs/simple.kt.after b/idea/testData/intentions/mergeIfs/simple.kt.after
new file mode 100644
index 00000000000..96ba55fd1d4
--- /dev/null
+++ b/idea/testData/intentions/mergeIfs/simple.kt.after
@@ -0,0 +1,5 @@
+fun foo() {
+ if (true && 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 045af0251fc..cc75996ecae 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
@@ -10507,6 +10507,45 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
}
}
+ @TestMetadata("idea/testData/intentions/mergeIfs")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class MergeIfs extends AbstractIntentionTest {
+ public void testAllFilesPresentInMergeIfs() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/mergeIfs"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("comments.kt")
+ public void testComments() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/mergeIfs/comments.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("else1.kt")
+ public void testElse1() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/mergeIfs/else1.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("else2.kt")
+ public void testElse2() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/mergeIfs/else2.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("expression.kt")
+ public void testExpression() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/mergeIfs/expression.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("simple.kt")
+ public void testSimple() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/mergeIfs/simple.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("idea/testData/intentions/moveLambdaInsideParentheses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)