KT-4794: Added functionality to KT-4574: Split If. Intention is now offered inside IF keyword
This commit is contained in:
@@ -22,13 +22,76 @@ import org.jetbrains.jet.lang.psi.JetBinaryExpression
|
|||||||
import org.jetbrains.jet.lang.psi.JetPsiFactory
|
import org.jetbrains.jet.lang.psi.JetPsiFactory
|
||||||
import org.jetbrains.jet.lexer.JetTokens
|
import org.jetbrains.jet.lexer.JetTokens
|
||||||
import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
|
import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
|
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression
|
||||||
|
import org.jetbrains.jet.lang.psi.JetPsiUtil
|
||||||
|
|
||||||
public class SplitIfIntention : JetSelfTargetingIntention<JetSimpleNameExpression>("split.if", javaClass()) {
|
public class SplitIfIntention : JetSelfTargetingIntention<JetExpression>("split.if", javaClass()) {
|
||||||
|
override fun isApplicableTo(element: JetExpression): Boolean {
|
||||||
|
throw IllegalStateException("isApplicableTo(JetExpression, Editor) should be called instead")
|
||||||
|
}
|
||||||
|
|
||||||
override fun isApplicableTo(element: JetSimpleNameExpression): Boolean {
|
override fun isApplicableTo(element: JetExpression, editor: Editor): Boolean {
|
||||||
|
if (element !is JetSimpleNameExpression && element !is JetIfExpression) return false
|
||||||
|
|
||||||
|
if (element is JetSimpleNameExpression) {
|
||||||
|
return isOperatorValid(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element is JetIfExpression) {
|
||||||
|
if (!isCursorOnIfKeyword(element, editor)) return false
|
||||||
|
if (getFirstValidOperator(element) == null) return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyTo(element: JetExpression, editor: Editor) {
|
||||||
|
val currentElement = when (element) {
|
||||||
|
is JetIfExpression -> getFirstValidOperator(element)
|
||||||
|
else -> element as JetSimpleNameExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
val ifExpression = currentElement!!.getParentByType(javaClass<JetIfExpression>())
|
||||||
|
val expression = currentElement.getParent() as JetBinaryExpression
|
||||||
|
val rightExpression = getRight(expression, ifExpression!!.getCondition() as JetExpression)
|
||||||
|
val leftExpression = expression.getLeft()
|
||||||
|
val elseExpression = ifExpression.getElse()
|
||||||
|
val thenExpression = ifExpression.getThen()
|
||||||
|
|
||||||
|
if (currentElement.getReferencedNameElementType() == JetTokens.ANDAND) {
|
||||||
|
ifExpression.replace(JetPsiFactory.createIf(element.getProject(), leftExpression,
|
||||||
|
JetPsiFactory.wrapInABlock(JetPsiFactory.createIf(element.getProject(), rightExpression, thenExpression,
|
||||||
|
elseExpression)), elseExpression))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ifExpression.replace(JetPsiFactory.createIf(element.getProject(), leftExpression, thenExpression,
|
||||||
|
JetPsiFactory.createIf(element.getProject(), rightExpression, thenExpression, elseExpression)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 rightString = condition.getText()!![startOffset, condition.getTextLength()].toString()
|
||||||
|
|
||||||
|
return JetPsiFactory.createExpression(element.getProject(), rightString)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isCursorOnIfKeyword(element: JetIfExpression, editor: Editor): Boolean {
|
||||||
|
val ifKeyword = JetPsiUtil.findChildByType(element, JetTokens.IF_KEYWORD) ?: return false
|
||||||
|
val cursor = editor.getCaretModel().getOffset()
|
||||||
|
return (cursor >= ifKeyword.getTextOffset() && cursor <= ifKeyword.getTextOffset() + ifKeyword.getTextLength())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFirstValidOperator(element: JetIfExpression): JetSimpleNameExpression? {
|
||||||
|
if (element.getCondition() == null) return null
|
||||||
|
val condition = element.getCondition()
|
||||||
|
val childElements = PsiTreeUtil.findChildrenOfType(condition, javaClass<JetSimpleNameExpression>())
|
||||||
|
return childElements.firstOrNull { isOperatorValid(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isOperatorValid(element: JetSimpleNameExpression): Boolean {
|
||||||
val operator = element.getReferencedNameElementType()
|
val operator = element.getReferencedNameElementType()
|
||||||
if (operator != JetTokens.ANDAND && operator != JetTokens.OROR) return false
|
if (operator != JetTokens.ANDAND && operator != JetTokens.OROR) return false
|
||||||
|
|
||||||
@@ -53,32 +116,5 @@ public class SplitIfIntention : JetSelfTargetingIntention<JetSimpleNameExpressio
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyTo(element: JetSimpleNameExpression, editor: Editor) {
|
|
||||||
val ifExpression = element.getParentByType(javaClass<JetIfExpression>())
|
|
||||||
val expression = element.getParent() as JetBinaryExpression
|
|
||||||
val rightExpression = getRight(expression, ifExpression!!.getCondition() as JetExpression)
|
|
||||||
val leftExpression = expression.getLeft()
|
|
||||||
val elseExpression = ifExpression.getElse()
|
|
||||||
val thenExpression = ifExpression.getThen()
|
|
||||||
|
|
||||||
if (element.getReferencedNameElementType() == JetTokens.ANDAND) {
|
|
||||||
ifExpression.replace(JetPsiFactory.createIf(element.getProject(), leftExpression,
|
|
||||||
JetPsiFactory.wrapInABlock(JetPsiFactory.createIf(element.getProject(), rightExpression, thenExpression,
|
|
||||||
elseExpression)), elseExpression))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ifExpression.replace(JetPsiFactory.createIf(element.getProject(), leftExpression, thenExpression,
|
|
||||||
JetPsiFactory.createIf(element.getProject(), rightExpression, thenExpression, elseExpression)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 rightString = condition.getText()!![startOffset, condition.getTextLength()].toString()
|
|
||||||
|
|
||||||
return JetPsiFactory.createExpression(element.getProject(), rightString)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
val d = false
|
||||||
|
<caret>if ((a && b) && c || d) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
val d = false
|
||||||
|
if ((a && b) && c) {
|
||||||
|
doSomething("test")
|
||||||
|
} else if (d) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
val d = false
|
||||||
|
<caret>if ((a || b) && (c || d)) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
val d = false
|
||||||
|
if (a || b) {
|
||||||
|
if (c || d) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
<caret>if (a && b) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
if (a) {
|
||||||
|
if (b) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
if (a) {
|
||||||
|
<caret>if (b && c) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
if (a) {
|
||||||
|
if (b) {
|
||||||
|
if (c) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
<caret>if (a) {
|
||||||
|
if (b && c) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
val d = false
|
||||||
|
if (a || b) {
|
||||||
|
<caret>if (c || d) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
val d = false
|
||||||
|
if (a || b) {
|
||||||
|
if (c) {
|
||||||
|
doSomething("test")
|
||||||
|
} else if (d) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
val d = false
|
||||||
|
<caret>if (a && b) {
|
||||||
|
if (c && d) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
val d = false
|
||||||
|
if (a) {
|
||||||
|
if (b) {
|
||||||
|
if (c && d) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
<caret>if (a && b || c) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
if (a && b) {
|
||||||
|
doSomething("test")
|
||||||
|
} else if (c) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
val d = false
|
||||||
|
<caret>if ((a && b || c) || d) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
fun doSomething<T>(a: T) {}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val a = true
|
||||||
|
val b = false
|
||||||
|
val c = true
|
||||||
|
val d = false
|
||||||
|
if (a && b || c) {
|
||||||
|
doSomething("test")
|
||||||
|
} else if (d) {
|
||||||
|
doSomething("test")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3026,11 +3026,51 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
|
|||||||
doTestSplitIf("idea/testData/intentions/splitIf/splitIfAndOr.kt");
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfAndOr.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("splitIfAndOrWithBraces.kt")
|
||||||
|
public void testSplitIfAndOrWithBraces() throws Exception {
|
||||||
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfAndOrWithBraces.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("splitIfAndWithBraces.kt")
|
||||||
|
public void testSplitIfAndWithBraces() throws Exception {
|
||||||
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfAndWithBraces.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("splitIfCaretOnIf.kt")
|
||||||
|
public void testSplitIfCaretOnIf() throws Exception {
|
||||||
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfCaretOnIf.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("splitIfNestedIf.kt")
|
||||||
|
public void testSplitIfNestedIf() throws Exception {
|
||||||
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfNestedIf.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("splitIfNestedIfNotApplicable.kt")
|
||||||
|
public void testSplitIfNestedIfNotApplicable() throws Exception {
|
||||||
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfNestedIfNotApplicable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("splitIfNestedInside.kt")
|
||||||
|
public void testSplitIfNestedInside() throws Exception {
|
||||||
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfNestedInside.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("splitIfNestedOutside.kt")
|
||||||
|
public void testSplitIfNestedOutside() throws Exception {
|
||||||
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfNestedOutside.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("splitIfNotIf.kt")
|
@TestMetadata("splitIfNotIf.kt")
|
||||||
public void testSplitIfNotIf() throws Exception {
|
public void testSplitIfNotIf() throws Exception {
|
||||||
doTestSplitIf("idea/testData/intentions/splitIf/splitIfNotIf.kt");
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfNotIf.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("splitIfOnIfWithOr.kt")
|
||||||
|
public void testSplitIfOnIfWithOr() throws Exception {
|
||||||
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfOnIfWithOr.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("splitIfOneAND.kt")
|
@TestMetadata("splitIfOneAND.kt")
|
||||||
public void testSplitIfOneAND() throws Exception {
|
public void testSplitIfOneAND() throws Exception {
|
||||||
doTestSplitIf("idea/testData/intentions/splitIf/splitIfOneAND.kt");
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfOneAND.kt");
|
||||||
@@ -3051,6 +3091,11 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
|
|||||||
doTestSplitIf("idea/testData/intentions/splitIf/splitIfOrAnd.kt");
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfOrAnd.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("splitIfOrWithBraces.kt")
|
||||||
|
public void testSplitIfOrWithBraces() throws Exception {
|
||||||
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfOrWithBraces.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("splitIfTwoOperatorsFirst.kt")
|
@TestMetadata("splitIfTwoOperatorsFirst.kt")
|
||||||
public void testSplitIfTwoOperatorsFirst() throws Exception {
|
public void testSplitIfTwoOperatorsFirst() throws Exception {
|
||||||
doTestSplitIf("idea/testData/intentions/splitIf/splitIfTwoOperatorsFirst.kt");
|
doTestSplitIf("idea/testData/intentions/splitIf/splitIfTwoOperatorsFirst.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user