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)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -208,13 +208,6 @@ public class InvertIfConditionIntention : JetSelfTargetingIntention<JetIfExpress
|
||||
return null
|
||||
}
|
||||
|
||||
private fun JetExpression.isExitStatement(): Boolean {
|
||||
when (this) {
|
||||
is JetContinueExpression, is JetBreakExpression, is JetThrowExpression, is JetReturnExpression -> 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,
|
||||
|
||||
@@ -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<JetExpression>(javaClass(), "Split if into 2 if's") {
|
||||
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 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)
|
||||
|
||||
@@ -114,3 +114,10 @@ fun JetQualifiedExpression.toResolvedCall(): ResolvedCall<out CallableDescriptor
|
||||
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);
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
Reference in New Issue
Block a user