Refactored SimplifyBooleanWithConstantsIntention
This commit is contained in:
@@ -67,6 +67,7 @@ public class JetBinaryExpression extends JetExpressionImpl implements JetOperati
|
|||||||
return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE);
|
return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public IElementType getOperationToken() {
|
public IElementType getOperationToken() {
|
||||||
return getOperationReference().getReferencedNameElementType();
|
return getOperationReference().getReferencedNameElementType();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,8 +284,6 @@ add.name.to.argument.single=Add name to argument\: ''{0}''
|
|||||||
add.name.to.argument.multiple=Add name to argument...
|
add.name.to.argument.multiple=Add name to argument...
|
||||||
add.name.to.argument.action=Add name to argument...
|
add.name.to.argument.action=Add name to argument...
|
||||||
add.name.to.parameter.name.chooser.title=Choose parameter name
|
add.name.to.parameter.name.chooser.title=Choose parameter name
|
||||||
simplify.boolean.with.constants=Simplify boolean expression
|
|
||||||
simplify.boolean.with.constants.family=Simplify Boolean Expression
|
|
||||||
remove.explicit.type.arguments=Remove explicit type arguments
|
remove.explicit.type.arguments=Remove explicit type arguments
|
||||||
remove.explicit.type.arguments.family=Remove Explicit Type Arguments
|
remove.explicit.type.arguments.family=Remove Explicit Type Arguments
|
||||||
convert.if.with.throw.to.assert=Replace 'if' with 'assert' statement
|
convert.if.with.throw.to.assert=Replace 'if' with 'assert' statement
|
||||||
|
|||||||
+65
-72
@@ -27,20 +27,18 @@ import org.jetbrains.kotlin.psi.psiUtil.replaced
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
public class SimplifyBooleanWithConstantsIntention : JetSelfTargetingOffsetIndependentIntention<JetBinaryExpression>(
|
public class SimplifyBooleanWithConstantsIntention : JetSelfTargetingOffsetIndependentIntention<JetBinaryExpression>(javaClass(), "Simplify boolean expression") {
|
||||||
"simplify.boolean.with.constants", javaClass()) {
|
|
||||||
|
|
||||||
private var topParent : JetBinaryExpression? = null
|
|
||||||
|
|
||||||
override fun isApplicableTo(element: JetBinaryExpression): Boolean {
|
override fun isApplicableTo(element: JetBinaryExpression): Boolean {
|
||||||
topParent = PsiTreeUtil.getTopmostParentOfType(element, javaClass<JetBinaryExpression>()) ?: element
|
val topBinary = PsiTreeUtil.getTopmostParentOfType(element, javaClass<JetBinaryExpression>()) ?: element
|
||||||
return areThereExpressionsToBeSimplified(topParent)
|
return areThereExpressionsToBeSimplified(topBinary)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areThereExpressionsToBeSimplified(element: JetExpression?) : Boolean {
|
private fun areThereExpressionsToBeSimplified(element: JetExpression?) : Boolean {
|
||||||
if (element == null) return false
|
if (element == null) return false
|
||||||
when (element) {
|
when (element) {
|
||||||
is JetParenthesizedExpression -> return areThereExpressionsToBeSimplified(element.getExpression())
|
is JetParenthesizedExpression -> return areThereExpressionsToBeSimplified(element.getExpression())
|
||||||
|
|
||||||
is JetBinaryExpression -> {
|
is JetBinaryExpression -> {
|
||||||
val op = element.getOperationToken()
|
val op = element.getOperationToken()
|
||||||
if ((op == JetTokens.ANDAND || op == JetTokens.OROR) &&
|
if ((op == JetTokens.ANDAND || op == JetTokens.OROR) &&
|
||||||
@@ -52,76 +50,75 @@ public class SimplifyBooleanWithConstantsIntention : JetSelfTargetingOffsetIndep
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun applyTo(element: JetBinaryExpression, editor: Editor) {
|
override fun applyTo(element: JetBinaryExpression, editor: Editor) {
|
||||||
// we know from isApplicableTo that topParent is not null
|
val topBinary = PsiTreeUtil.getTopmostParentOfType(element, javaClass<JetBinaryExpression>()) ?: element
|
||||||
val simplified = toSimplifiedExpression(topParent!!)
|
val simplified = toSimplifiedExpression(topBinary)
|
||||||
if (simplified is JetParenthesizedExpression) {
|
topBinary.replace(JetPsiUtil.safeDeparenthesize(simplified))
|
||||||
val expr = simplified.getExpression()
|
|
||||||
if (expr != null) {
|
|
||||||
// this extra check is for the case where there are empty parentheses ()
|
|
||||||
topParent!!.replace(expr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
topParent!!.replace(simplified)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toSimplifiedExpression(element: JetExpression): JetExpression {
|
private fun toSimplifiedExpression(expression: JetExpression): JetExpression {
|
||||||
val psiFactory = JetPsiFactory(element)
|
val psiFactory = JetPsiFactory(expression)
|
||||||
if (element.canBeReducedToTrue())
|
|
||||||
return psiFactory.createExpression("true")
|
when {
|
||||||
if (element.canBeReducedToFalse())
|
expression.canBeReducedToTrue() -> {
|
||||||
return psiFactory.createExpression("false")
|
return psiFactory.createExpression("true")
|
||||||
when (element) {
|
}
|
||||||
is JetParenthesizedExpression -> {
|
|
||||||
val expr = element.getExpression()
|
expression.canBeReducedToFalse() -> {
|
||||||
if (expr == null) return element
|
return psiFactory.createExpression("false")
|
||||||
val innerSimplified = toSimplifiedExpression(expr)
|
}
|
||||||
if (innerSimplified is JetBinaryExpression) {
|
|
||||||
val simpText = innerSimplified.getText() ?: return element.copied()
|
expression is JetParenthesizedExpression -> {
|
||||||
// wrap in new parentheses to keep the user's original format
|
val expr = expression.getExpression()
|
||||||
return psiFactory.createExpression("($simpText)")
|
if (expr != null) {
|
||||||
|
val simplified = toSimplifiedExpression(expr)
|
||||||
|
return if (simplified is JetBinaryExpression) {
|
||||||
|
// wrap in new parentheses to keep the user's original format
|
||||||
|
psiFactory.createExpressionByPattern("($0)", simplified)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// if we now have a simpleName, constant, or parenthesized we don't need parentheses
|
||||||
|
simplified
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if we now have a simpleName, constant, or parenthesized we don't need parentheses
|
|
||||||
return innerSimplified
|
|
||||||
}
|
}
|
||||||
is JetBinaryExpression -> {
|
|
||||||
val left = element.getLeft()
|
|
||||||
val right = element.getRight()
|
|
||||||
val op = element.getOperationToken()
|
|
||||||
if (left == null || right == null || op == null || (op != JetTokens.ANDAND && op != JetTokens.OROR))
|
|
||||||
return element.copied()
|
|
||||||
|
|
||||||
val simpleLeft = simplifyExpression(left)
|
expression is JetBinaryExpression -> {
|
||||||
val simpleRight = simplifyExpression(right)
|
val left = expression.getLeft()
|
||||||
if (simpleLeft.canBeReducedToTrue() || simpleLeft.canBeReducedToFalse())
|
val right = expression.getRight()
|
||||||
return toSimplifiedBooleanBinaryExpressionWithConstantOperand(simpleLeft, simpleRight, op)
|
val op = expression.getOperationToken()
|
||||||
if (simpleRight.canBeReducedToTrue() || simpleRight.canBeReducedToFalse())
|
if (left != null && right != null && (op == JetTokens.ANDAND || op == JetTokens.OROR)) {
|
||||||
return toSimplifiedBooleanBinaryExpressionWithConstantOperand(simpleRight, simpleLeft, op)
|
val simpleLeft = simplifyExpression(left)
|
||||||
|
val simpleRight = simplifyExpression(right)
|
||||||
|
when {
|
||||||
|
simpleLeft.canBeReducedToTrue() -> return toSimplifiedBooleanBinaryExpressionWithConstantOperand(true, simpleRight, op)
|
||||||
|
|
||||||
val opText = element.getOperationReference().getText() ?: return element.copied()
|
simpleLeft.canBeReducedToFalse() -> return toSimplifiedBooleanBinaryExpressionWithConstantOperand(false, simpleRight, op)
|
||||||
return psiFactory.createExpressionByPattern("$0 $opText $1", simpleLeft, simpleRight)
|
|
||||||
|
simpleRight.canBeReducedToTrue() -> return toSimplifiedBooleanBinaryExpressionWithConstantOperand(true, simpleLeft, op)
|
||||||
|
|
||||||
|
simpleRight.canBeReducedToFalse() -> return toSimplifiedBooleanBinaryExpressionWithConstantOperand(false, simpleLeft, op)
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val opText = expression.getOperationReference().getText()
|
||||||
|
return psiFactory.createExpressionByPattern("$0 $opText $1", simpleLeft, simpleRight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> return element.copied()
|
}
|
||||||
|
|
||||||
|
return expression.copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toSimplifiedBooleanBinaryExpressionWithConstantOperand(constantOperand: Boolean, otherOperand: JetExpression, operation: IElementType): JetExpression {
|
||||||
|
return when {
|
||||||
|
constantOperand && operation == JetTokens.OROR -> JetPsiFactory(otherOperand).createExpression("true")
|
||||||
|
!constantOperand && operation == JetTokens.ANDAND -> JetPsiFactory(otherOperand).createExpression("false")
|
||||||
|
else -> toSimplifiedExpression(otherOperand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toSimplifiedBooleanBinaryExpressionWithConstantOperand(
|
private fun simplifyExpression(element: JetExpression) = element.replaced(toSimplifiedExpression(element))
|
||||||
booleanConstantOperand: JetExpression,
|
|
||||||
otherOperand: JetExpression,
|
|
||||||
operation: IElementType
|
|
||||||
): JetExpression {
|
|
||||||
assert(booleanConstantOperand.canBeReducedToBooleanConstant(null), "should only be called when we know it can be reduced")
|
|
||||||
val psiFactory = JetPsiFactory(otherOperand)
|
|
||||||
if (booleanConstantOperand.canBeReducedToTrue() && operation == JetTokens.OROR)
|
|
||||||
return psiFactory.createExpression("true")
|
|
||||||
if (booleanConstantOperand.canBeReducedToFalse() && operation == JetTokens.ANDAND)
|
|
||||||
return psiFactory.createExpression("false")
|
|
||||||
return toSimplifiedExpression(otherOperand)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun simplifyExpression(element: JetExpression): JetExpression {
|
|
||||||
return element.replaced(toSimplifiedExpression(element))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun JetExpression.canBeReducedToBooleanConstant(constant: Boolean?): Boolean {
|
private fun JetExpression.canBeReducedToBooleanConstant(constant: Boolean?): Boolean {
|
||||||
val bindingContext = this.analyze()
|
val bindingContext = this.analyze()
|
||||||
@@ -129,11 +126,7 @@ public class SimplifyBooleanWithConstantsIntention : JetSelfTargetingOffsetIndep
|
|||||||
return CompileTimeConstantUtils.canBeReducedToBooleanConstant(this, trace, constant)
|
return CompileTimeConstantUtils.canBeReducedToBooleanConstant(this, trace, constant)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JetExpression.canBeReducedToTrue(): Boolean {
|
private fun JetExpression.canBeReducedToTrue() = canBeReducedToBooleanConstant(true)
|
||||||
return this.canBeReducedToBooleanConstant(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun JetExpression.canBeReducedToFalse(): Boolean {
|
private fun JetExpression.canBeReducedToFalse() = canBeReducedToBooleanConstant(false)
|
||||||
return this.canBeReducedToBooleanConstant(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user