diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt index 6942c58522c..6b57f2987d8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt @@ -360,7 +360,7 @@ public class JetPsiFactory(private val project: Project) { return JetBlockCodeFragment(project, "fragment.kt", text, null, context) } - public fun createIf(condition: JetExpression, thenExpr: JetExpression, elseExpr: JetExpression?): JetIfExpression { + public fun createIf(condition: JetExpression, thenExpr: JetExpression, elseExpr: JetExpression? = null): JetIfExpression { return (if (elseExpr != null) createExpressionByPattern("if ($0) $1 else $2", condition, thenExpr, elseExpr) as JetIfExpression else diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/InvertIfConditionIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/InvertIfConditionIntention.kt index 958ebf6caa9..f7e7efd2dc8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/InvertIfConditionIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/InvertIfConditionIntention.kt @@ -208,13 +208,6 @@ public class InvertIfConditionIntention : JetSelfTargetingIntention return true - else -> return false - } - } - companion object { private val NEGATABLE_OPERATORS = setOf(JetTokens.EQEQ, JetTokens.EXCLEQ, JetTokens.EQEQEQ, JetTokens.EXCLEQEQEQ, JetTokens.IS_KEYWORD, JetTokens.NOT_IS, JetTokens.IN_KEYWORD, diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SplitIfIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SplitIfIntention.kt index ca774aa17cd..66dca630fdc 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SplitIfIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SplitIfIntention.kt @@ -21,6 +21,8 @@ import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis +import org.jetbrains.kotlin.psi.psiUtil.startOffset public class SplitIfIntention : JetSelfTargetingIntention(javaClass(), "Split if into 2 if's") { override fun isApplicableTo(element: JetExpression, caretOffset: Int): Boolean { @@ -41,24 +43,36 @@ public class SplitIfIntention : JetSelfTargetingIntention(javaCla val expression = operator.getParent() as JetBinaryExpression val rightExpression = JetPsiUtil.safeDeparenthesize(getRight(expression, ifExpression!!.getCondition()!!)) val leftExpression = JetPsiUtil.safeDeparenthesize(expression.getLeft()!!) - val thenExpression = ifExpression.getThen()!! - val elseExpression = ifExpression.getElse() + val thenBranch = ifExpression.getThen()!! + val elseBranch = ifExpression.getElse() val psiFactory = JetPsiFactory(element) - val innerIf = psiFactory.createIf(rightExpression, thenExpression, elseExpression) - val newIf = when (operator.getReferencedNameElementType()) { - JetTokens.ANDAND -> psiFactory.createIf(leftExpression, psiFactory.wrapInABlock(innerIf), elseExpression) - JetTokens.OROR -> psiFactory.createIf(leftExpression, thenExpression, innerIf) + val innerIf = psiFactory.createIf(rightExpression, thenBranch, elseBranch) + + when (operator.getReferencedNameElementType()) { + JetTokens.ANDAND -> ifExpression.replace(psiFactory.createIf(leftExpression, psiFactory.wrapInABlock(innerIf), elseBranch)) + + JetTokens.OROR -> { + val container = ifExpression.getParent() + + if (container is JetBlockExpression && elseBranch == null && thenBranch.lastBlockStatementOrThis().isExitStatement()) { // special case + container.addAfter(innerIf, ifExpression) + container.addAfter(psiFactory.createNewLine(), ifExpression) + ifExpression.replace(psiFactory.createIf(leftExpression, thenBranch)) + return + } + + ifExpression.replace(psiFactory.createIf(leftExpression, thenBranch, innerIf)) + } else -> throw IllegalArgumentException() } - ifExpression.replace(newIf) } private fun getRight(element: JetBinaryExpression, condition: JetExpression): JetExpression { //gets the textOffset of the right side of the JetBinaryExpression in context to condition - val startOffset = element.getRight()!!.getTextOffset() - condition.getTextOffset() + val startOffset = element.getRight()!!.startOffset - condition.startOffset val rightString = condition.getText()!!.substring(startOffset, condition.getTextLength()) return JetPsiFactory(element).createExpression(rightString) diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt index 8a6fd258fd1..a93347bf804 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt @@ -114,3 +114,10 @@ fun JetQualifiedExpression.toResolvedCall(): ResolvedCall return true + else -> return false + } +} + diff --git a/idea/testData/intentions/splitIf/ifOrReturn.kt b/idea/testData/intentions/splitIf/ifOrReturn.kt new file mode 100644 index 00000000000..501fb17406f --- /dev/null +++ b/idea/testData/intentions/splitIf/ifOrReturn.kt @@ -0,0 +1,4 @@ +fun foo(p: Int): Boolean { + if (p < 0 || p == 5) return false + return true +} \ No newline at end of file diff --git a/idea/testData/intentions/splitIf/ifOrReturn.kt.after b/idea/testData/intentions/splitIf/ifOrReturn.kt.after new file mode 100644 index 00000000000..2c05ea3d96d --- /dev/null +++ b/idea/testData/intentions/splitIf/ifOrReturn.kt.after @@ -0,0 +1,5 @@ +fun foo(p: Int): Boolean { + if (p < 0) return false + if (p == 5) return false + return true +} \ 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 5b8bd30effb..7f65145f52e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -6405,6 +6405,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("ifOrReturn.kt") + public void testIfOrReturn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/splitIf/ifOrReturn.kt"); + doTest(fileName); + } + @TestMetadata("ifWithElse.kt") public void testIfWithElse() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/splitIf/ifWithElse.kt");