KT-4568: Cleaned up some of the code in ConvertNegatedBooleanSequence to match the other DeMorgan intention
This commit is contained in:
committed by
Mikhael Bogdanov
parent
4de6960443
commit
a5f7ac63a8
+34
-29
@@ -24,6 +24,8 @@ import com.intellij.psi.impl.source.tree.PsiErrorElementImpl
|
|||||||
import org.jetbrains.jet.lang.psi.JetPsiFactory
|
import org.jetbrains.jet.lang.psi.JetPsiFactory
|
||||||
import org.jetbrains.jet.lang.psi.JetParenthesizedExpression
|
import org.jetbrains.jet.lang.psi.JetParenthesizedExpression
|
||||||
import org.jetbrains.jet.lang.psi.JetPsiUtil
|
import org.jetbrains.jet.lang.psi.JetPsiUtil
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
|
||||||
public class ConvertNegatedBooleanSequenceIntention : JetSelfTargetingIntention<JetBinaryExpression>(
|
public class ConvertNegatedBooleanSequenceIntention : JetSelfTargetingIntention<JetBinaryExpression>(
|
||||||
@@ -31,50 +33,30 @@ public class ConvertNegatedBooleanSequenceIntention : JetSelfTargetingIntention<
|
|||||||
|
|
||||||
override fun isApplicableTo(element: JetBinaryExpression): Boolean {
|
override fun isApplicableTo(element: JetBinaryExpression): Boolean {
|
||||||
if (element.getParent() is JetBinaryExpression) return false // operate only on the longest sequence
|
if (element.getParent() is JetBinaryExpression) return false // operate only on the longest sequence
|
||||||
var binaryExpression : JetBinaryExpression? = element
|
|
||||||
val originalOperator = element.getOperationToken()
|
val originalOperator = element.getOperationToken()
|
||||||
|
|
||||||
if (!(originalOperator == JetTokens.ANDAND || originalOperator == JetTokens.OROR)) {
|
if (!(originalOperator == JetTokens.ANDAND || originalOperator == JetTokens.OROR)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
return splitBooleanSequence(element) != null
|
||||||
val leftChild = binaryExpression?.getLeft()
|
|
||||||
val rightChild = binaryExpression?.getRight()
|
|
||||||
val operator = binaryExpression?.getOperationToken()
|
|
||||||
when {
|
|
||||||
rightChild !is JetPrefixExpression,
|
|
||||||
operator != originalOperator,
|
|
||||||
!(leftChild is JetPrefixExpression || leftChild is JetBinaryExpression) -> return false
|
|
||||||
else -> binaryExpression = leftChild as? JetBinaryExpression
|
|
||||||
}
|
|
||||||
} while (binaryExpression != null)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyTo(element: JetBinaryExpression, editor: Editor) {
|
override fun applyTo(element: JetBinaryExpression, editor: Editor) {
|
||||||
var binaryExpression = element : JetBinaryExpression?
|
val operator = element.getOperationToken()
|
||||||
var expressionText = ""
|
val operatorText = when(operator) {
|
||||||
val operator = binaryExpression!!.getOperationToken()
|
|
||||||
val operatorText = when(binaryExpression!!.getOperationToken()) {
|
|
||||||
JetTokens.ANDAND -> JetTokens.OROR.getValue()
|
JetTokens.ANDAND -> JetTokens.OROR.getValue()
|
||||||
JetTokens.OROR -> JetTokens.ANDAND.getValue()
|
JetTokens.OROR -> JetTokens.ANDAND.getValue()
|
||||||
else -> throw IllegalArgumentException("Invalid operator: '$operator'. Only expressions using '&&' or '||' can be converted.")
|
else -> throw IllegalArgumentException("Invalid operator: '$operator'. Only expressions using '&&' or '||' can be converted.")
|
||||||
}
|
}
|
||||||
|
|
||||||
while (binaryExpression != null) {
|
val elements = splitBooleanSequence(element)!!
|
||||||
val leftChild = binaryExpression!!.getLeft()
|
val bareExpressions = elements.map { prefixExpression -> prefixExpression.getBaseExpression()!!.getText() }
|
||||||
val rightChild = binaryExpression!!.getRight() as JetPrefixExpression
|
val negatedExpression = bareExpressions.subList(0, bareExpressions.size()-1).foldRight(
|
||||||
expressionText = " $operatorText ${rightChild.getBaseExpression()!!.getText()}$expressionText"
|
"!(${bareExpressions.last()}", { negated, expression -> "$expression $operatorText $negated"}
|
||||||
if (leftChild is JetPrefixExpression) {
|
)
|
||||||
val leftChildText = (leftChild as JetPrefixExpression).getBaseExpression()!!.getText()
|
|
||||||
expressionText = "$leftChildText$expressionText"
|
|
||||||
}
|
|
||||||
binaryExpression = leftChild as? JetBinaryExpression
|
|
||||||
}
|
|
||||||
|
|
||||||
val newExpression = JetPsiFactory.createExpression(element.getProject(),"!($expressionText)")
|
val newExpression = JetPsiFactory.createExpression(element.getProject(), "$negatedExpression)")
|
||||||
|
|
||||||
val insertedElement = element.replace(newExpression)
|
val insertedElement = element.replace(newExpression)
|
||||||
val insertedElementParent = insertedElement.getParent() as? JetParenthesizedExpression ?: return
|
val insertedElementParent = insertedElement.getParent() as? JetParenthesizedExpression ?: return
|
||||||
@@ -84,4 +66,27 @@ public class ConvertNegatedBooleanSequenceIntention : JetSelfTargetingIntention<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun splitBooleanSequence(expression: JetBinaryExpression) : List<JetPrefixExpression>? {
|
||||||
|
val itemList = ArrayList<JetPrefixExpression>()
|
||||||
|
val firstOperator = expression.getOperationToken()
|
||||||
|
var currentItem : JetBinaryExpression? = expression
|
||||||
|
|
||||||
|
while(currentItem != null) {
|
||||||
|
if (currentItem!!.getOperationToken() != firstOperator) return null //Boolean sequence must be homogenous
|
||||||
|
|
||||||
|
val rightChild = currentItem!!.getRight() as? JetPrefixExpression ?: return null
|
||||||
|
itemList.add(rightChild)
|
||||||
|
val leftChild = currentItem!!.getLeft()
|
||||||
|
if (leftChild is JetPrefixExpression) {
|
||||||
|
itemList.add(leftChild as JetPrefixExpression)
|
||||||
|
} else if (leftChild !is JetBinaryExpression) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
currentItem = leftChild as? JetBinaryExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemList
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fun foo(a: Int, b: Int, c: Int, d: Int) : Boolean {
|
||||||
|
return !(a == b) && !(b <caret>== c) && !(a < d)
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fun foo(a: Int, b: Int, c: Int, d: Int) : Boolean {
|
||||||
|
return !((a == b) || (b == c) || (a < d))
|
||||||
|
}
|
||||||
@@ -2970,6 +2970,11 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/intentions/convertNegatedBooleanSequence"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/intentions/convertNegatedBooleanSequence"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("complexNegatedSequence.kt")
|
||||||
|
public void testComplexNegatedSequence() throws Exception {
|
||||||
|
doTestConvertNegatedBooleanSequence("idea/testData/intentions/convertNegatedBooleanSequence/complexNegatedSequence.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("conjunctionOfThreeNegations.kt")
|
@TestMetadata("conjunctionOfThreeNegations.kt")
|
||||||
public void testConjunctionOfThreeNegations() throws Exception {
|
public void testConjunctionOfThreeNegations() throws Exception {
|
||||||
doTestConvertNegatedBooleanSequence("idea/testData/intentions/convertNegatedBooleanSequence/conjunctionOfThreeNegations.kt");
|
doTestConvertNegatedBooleanSequence("idea/testData/intentions/convertNegatedBooleanSequence/conjunctionOfThreeNegations.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user