KT-7702 Split into 2 if's intention: produce better result for return
#KT-7702 Fixed
This commit is contained in:
@@ -360,7 +360,7 @@ public class JetPsiFactory(private val project: Project) {
|
|||||||
return JetBlockCodeFragment(project, "fragment.kt", text, null, context)
|
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)
|
return (if (elseExpr != null)
|
||||||
createExpressionByPattern("if ($0) $1 else $2", condition, thenExpr, elseExpr) as JetIfExpression
|
createExpressionByPattern("if ($0) $1 else $2", condition, thenExpr, elseExpr) as JetIfExpression
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -208,13 +208,6 @@ public class InvertIfConditionIntention : JetSelfTargetingIntention<JetIfExpress
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JetExpression.isExitStatement(): Boolean {
|
|
||||||
when (this) {
|
|
||||||
is JetContinueExpression, is JetBreakExpression, is JetThrowExpression, is JetReturnExpression -> return true
|
|
||||||
else -> return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val NEGATABLE_OPERATORS = setOf(JetTokens.EQEQ, JetTokens.EXCLEQ, JetTokens.EQEQEQ,
|
private val NEGATABLE_OPERATORS = setOf(JetTokens.EQEQ, JetTokens.EXCLEQ, JetTokens.EQEQEQ,
|
||||||
JetTokens.EXCLEQEQEQ, JetTokens.IS_KEYWORD, JetTokens.NOT_IS, JetTokens.IN_KEYWORD,
|
JetTokens.EXCLEQEQEQ, JetTokens.IS_KEYWORD, JetTokens.NOT_IS, JetTokens.IN_KEYWORD,
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import org.jetbrains.kotlin.lexer.JetTokens
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
|
|
||||||
public class SplitIfIntention : JetSelfTargetingIntention<JetExpression>(javaClass(), "Split if into 2 if's") {
|
public class SplitIfIntention : JetSelfTargetingIntention<JetExpression>(javaClass(), "Split if into 2 if's") {
|
||||||
override fun isApplicableTo(element: JetExpression, caretOffset: Int): Boolean {
|
override fun isApplicableTo(element: JetExpression, caretOffset: Int): Boolean {
|
||||||
@@ -41,24 +43,36 @@ public class SplitIfIntention : JetSelfTargetingIntention<JetExpression>(javaCla
|
|||||||
val expression = operator.getParent() as JetBinaryExpression
|
val expression = operator.getParent() as JetBinaryExpression
|
||||||
val rightExpression = JetPsiUtil.safeDeparenthesize(getRight(expression, ifExpression!!.getCondition()!!))
|
val rightExpression = JetPsiUtil.safeDeparenthesize(getRight(expression, ifExpression!!.getCondition()!!))
|
||||||
val leftExpression = JetPsiUtil.safeDeparenthesize(expression.getLeft()!!)
|
val leftExpression = JetPsiUtil.safeDeparenthesize(expression.getLeft()!!)
|
||||||
val thenExpression = ifExpression.getThen()!!
|
val thenBranch = ifExpression.getThen()!!
|
||||||
val elseExpression = ifExpression.getElse()
|
val elseBranch = ifExpression.getElse()
|
||||||
|
|
||||||
val psiFactory = JetPsiFactory(element)
|
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()
|
else -> throw IllegalArgumentException()
|
||||||
}
|
}
|
||||||
ifExpression.replace(newIf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRight(element: JetBinaryExpression, condition: JetExpression): JetExpression {
|
private fun getRight(element: JetBinaryExpression, condition: JetExpression): JetExpression {
|
||||||
//gets the textOffset of the right side of the JetBinaryExpression in context to condition
|
//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())
|
val rightString = condition.getText()!!.substring(startOffset, condition.getTextLength())
|
||||||
|
|
||||||
return JetPsiFactory(element).createExpression(rightString)
|
return JetPsiFactory(element).createExpression(rightString)
|
||||||
|
|||||||
@@ -114,3 +114,10 @@ fun JetQualifiedExpression.toResolvedCall(): ResolvedCall<out CallableDescriptor
|
|||||||
return callExpression.getResolvedCall(callExpression.analyze()) ?: return null
|
return callExpression.getResolvedCall(callExpression.analyze()) ?: return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun JetExpression.isExitStatement(): Boolean {
|
||||||
|
when (this) {
|
||||||
|
is JetContinueExpression, is JetBreakExpression, is JetThrowExpression, is JetReturnExpression -> return true
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo(p: Int): Boolean {
|
||||||
|
if (p < 0 <caret>|| p == 5) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fun foo(p: Int): Boolean {
|
||||||
|
if (p < 0) return false
|
||||||
|
if (p == 5) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -6405,6 +6405,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("ifWithElse.kt")
|
||||||
public void testIfWithElse() throws Exception {
|
public void testIfWithElse() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/splitIf/ifWithElse.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/splitIf/ifWithElse.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user