From f91819ace7f9988bd9faecb2876a3be380444f2d Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Sat, 24 Mar 2018 10:50:27 +0300 Subject: [PATCH] "Simplify boolean expression": handle Boolean? comparison correctly So #KT-23377 Fixed --- .../SimplifyBooleanWithConstantsIntention.kt | 19 ++++++++++++------- .../nullableComplex2.kt | 5 +++++ .../nullableComplex2.kt.after | 5 +++++ .../intentions/IntentionTestGenerated.java | 6 ++++++ 4 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/nullableComplex2.kt create mode 100644 idea/testData/intentions/simplifyBooleanWithConstants/nullableComplex2.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyBooleanWithConstantsIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyBooleanWithConstantsIntention.kt index 27c020d4cc2..b2a074d075c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyBooleanWithConstantsIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyBooleanWithConstantsIntention.kt @@ -35,14 +35,15 @@ import org.jetbrains.kotlin.types.isFlexible class SimplifyBooleanWithConstantsInspection : IntentionBasedInspection(SimplifyBooleanWithConstantsIntention::class) -class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndependentIntention(KtBinaryExpression::class.java, "Simplify boolean expression") { +class SimplifyBooleanWithConstantsIntention : + SelfTargetingOffsetIndependentIntention(KtBinaryExpression::class.java, "Simplify boolean expression") { override fun isApplicableTo(element: KtBinaryExpression): Boolean { val topBinary = PsiTreeUtil.getTopmostParentOfType(element, KtBinaryExpression::class.java) ?: element return areThereExpressionsToBeSimplified(topBinary) } - private fun areThereExpressionsToBeSimplified(element: KtExpression?) : Boolean { + private fun areThereExpressionsToBeSimplified(element: KtExpression?): Boolean { if (element == null) return false when (element) { is KtParenthesizedExpression -> return areThereExpressionsToBeSimplified(element.expression) @@ -70,14 +71,14 @@ class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndependentInte val fqName = callExpression.getCallableDescriptor()?.fqNameOrNull() val valueArguments = callExpression.valueArguments val isRedundant = fqName?.asString() == "kotlin.assert" && - valueArguments.singleOrNull()?.getArgumentExpression().isTrueConstant() + valueArguments.singleOrNull()?.getArgumentExpression().isTrueConstant() if (isRedundant) callExpression.delete() } private fun toSimplifiedExpression(expression: KtExpression): KtExpression { val psiFactory = KtPsiFactory(expression) - when { + when { expression.canBeReducedToTrue() -> { return psiFactory.createExpression("true") } @@ -93,8 +94,7 @@ class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndependentInte return if (simplified is KtBinaryExpression) { // wrap in new parentheses to keep the user's original format psiFactory.createExpressionByPattern("($0)", simplified) - } - else { + } else { // if we now have a simpleName, constant, or parenthesized we don't need parentheses simplified } @@ -102,6 +102,7 @@ class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndependentInte } expression is KtBinaryExpression -> { + if (!areThereExpressionsToBeSimplified(expression)) return expression.copied() val left = expression.left val right = expression.right val op = expression.operationToken @@ -129,7 +130,11 @@ class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndependentInte return expression.copied() } - private fun toSimplifiedBooleanBinaryExpressionWithConstantOperand(constantOperand: Boolean, otherOperand: KtExpression, operation: IElementType): KtExpression { + private fun toSimplifiedBooleanBinaryExpressionWithConstantOperand( + constantOperand: Boolean, + otherOperand: KtExpression, + operation: IElementType + ): KtExpression { val factory = KtPsiFactory(otherOperand) when (operation) { OROR -> { diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/nullableComplex2.kt b/idea/testData/intentions/simplifyBooleanWithConstants/nullableComplex2.kt new file mode 100644 index 00000000000..1a08f42f4cd --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/nullableComplex2.kt @@ -0,0 +1,5 @@ +data class Test(val notnull: Boolean, val nullable: Boolean?) + +fun test(a: Test, b: Test?) { + a.notnull == true || a.nullable == true || b?.notnull == true || b?.nullable == true +} \ No newline at end of file diff --git a/idea/testData/intentions/simplifyBooleanWithConstants/nullableComplex2.kt.after b/idea/testData/intentions/simplifyBooleanWithConstants/nullableComplex2.kt.after new file mode 100644 index 00000000000..96bc5a56ced --- /dev/null +++ b/idea/testData/intentions/simplifyBooleanWithConstants/nullableComplex2.kt.after @@ -0,0 +1,5 @@ +data class Test(val notnull: Boolean, val nullable: Boolean?) + +fun test(a: Test, b: Test?) { + a.notnull || a.nullable == true || b?.notnull == true || b?.nullable == true +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 81f2b7b6b2f..fb1a82c3229 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -15399,6 +15399,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("nullableComplex2.kt") + public void testNullableComplex2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyBooleanWithConstants/nullableComplex2.kt"); + doTest(fileName); + } + @TestMetadata("reduceableBinary.kt") public void testReduceableBinary() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/simplifyBooleanWithConstants/reduceableBinary.kt");