Fix false positive in +0.0 == -0.0 comparison simplification (KT-17735)
This commit is contained in:
+31
@@ -18,10 +18,13 @@ import org.jetbrains.kotlin.lexer.KtTokens.*
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
|
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
||||||
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils
|
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode.PARTIAL
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode.PARTIAL
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.isFlexible
|
import org.jetbrains.kotlin.types.isFlexible
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@@ -47,12 +50,40 @@ class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndependentInte
|
|||||||
if (areThereExpressionsToBeSimplified(element.left) && element.right.hasBooleanType()) return true
|
if (areThereExpressionsToBeSimplified(element.left) && element.right.hasBooleanType()) return true
|
||||||
if (areThereExpressionsToBeSimplified(element.right) && element.left.hasBooleanType()) return true
|
if (areThereExpressionsToBeSimplified(element.right) && element.left.hasBooleanType()) return true
|
||||||
}
|
}
|
||||||
|
if (isPositiveNegativeZeroComparison(element)) return false
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return element.canBeReducedToBooleanConstant()
|
return element.canBeReducedToBooleanConstant()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isPositiveNegativeZeroComparison(element: KtBinaryExpression): Boolean {
|
||||||
|
val op = element.operationToken
|
||||||
|
if (op != EQEQ && op != EQEQEQ) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val left = element.left?.deparenthesize() as? KtExpression ?: return false
|
||||||
|
val right = element.right?.deparenthesize() as? KtExpression ?: return false
|
||||||
|
|
||||||
|
val context = element.analyze(PARTIAL)
|
||||||
|
|
||||||
|
fun KtExpression.getConstantValue() =
|
||||||
|
ConstantExpressionEvaluator.getConstant(this, context)?.toConstantValue(TypeUtils.NO_EXPECTED_TYPE)?.value
|
||||||
|
|
||||||
|
val leftValue = left.getConstantValue()
|
||||||
|
val rightValue = right.getConstantValue()
|
||||||
|
|
||||||
|
fun isPositiveZero(value: Any?) = value == +0.0 || value == +0.0f
|
||||||
|
fun isNegativeZero(value: Any?) = value == -0.0 || value == -0.0f
|
||||||
|
|
||||||
|
val hasPositiveZero = isPositiveZero(leftValue) || isPositiveZero(rightValue)
|
||||||
|
val hasNegativeZero = isNegativeZero(leftValue) || isNegativeZero(rightValue)
|
||||||
|
|
||||||
|
return hasPositiveZero && hasNegativeZero
|
||||||
|
}
|
||||||
|
|
||||||
override fun applyTo(element: KtBinaryExpression, editor: Editor?) {
|
override fun applyTo(element: KtBinaryExpression, editor: Editor?) {
|
||||||
val topBinary = element.topBinary()
|
val topBinary = element.topBinary()
|
||||||
val simplified = toSimplifiedExpression(topBinary)
|
val simplified = toSimplifiedExpression(topBinary)
|
||||||
|
|||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
-0.0 <caret>== +0.0
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
+0.0f <caret>== -0.0f
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun foo() {
|
||||||
|
+0.0f <caret>== +0.0f
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun foo() {
|
||||||
|
true
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
|
||||||
|
fun foo(y: Boolean) {
|
||||||
|
0.0f <caret>=== -0.0f
|
||||||
|
}
|
||||||
@@ -15703,6 +15703,26 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
runTest("idea/testData/intentions/simplifyBooleanWithConstants/nullableComplex2.kt");
|
runTest("idea/testData/intentions/simplifyBooleanWithConstants/nullableComplex2.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("positiveZeroNegativeZero1.kt")
|
||||||
|
public void testPositiveZeroNegativeZero1() throws Exception {
|
||||||
|
runTest("idea/testData/intentions/simplifyBooleanWithConstants/positiveZeroNegativeZero1.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("positiveZeroNegativeZero2.kt")
|
||||||
|
public void testPositiveZeroNegativeZero2() throws Exception {
|
||||||
|
runTest("idea/testData/intentions/simplifyBooleanWithConstants/positiveZeroNegativeZero2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("positiveZeroNegativeZero3.kt")
|
||||||
|
public void testPositiveZeroNegativeZero3() throws Exception {
|
||||||
|
runTest("idea/testData/intentions/simplifyBooleanWithConstants/positiveZeroNegativeZero3.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("positiveZeroNegativeZero4.kt")
|
||||||
|
public void testPositiveZeroNegativeZero4() throws Exception {
|
||||||
|
runTest("idea/testData/intentions/simplifyBooleanWithConstants/positiveZeroNegativeZero4.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("reduceableBinary.kt")
|
@TestMetadata("reduceableBinary.kt")
|
||||||
public void testReduceableBinary() throws Exception {
|
public void testReduceableBinary() throws Exception {
|
||||||
runTest("idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt");
|
runTest("idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user