From 82f75c707e08195f235d9e5cc32bf82feeda0832 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Thu, 19 Sep 2019 13:08:55 +0900 Subject: [PATCH] "Convert to range check" inspection: apply ReplaceRangeToWithUntilInspection after convertion #KT-33880 Fixed --- .../ReplaceRangeToWithUntilInspection.kt | 31 +++++++++++++------ ...vertTwoComparisonsToRangeCheckIntention.kt | 6 +++- .../nonConstants.kt | 1 + .../nonConstants.kt.after | 3 +- .../until.kt | 3 ++ .../until.kt.after | 3 ++ .../intentions/IntentionTestGenerated.java | 5 +++ 7 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 idea/testData/intentions/convertTwoComparisonsToRangeCheck/until.kt create mode 100644 idea/testData/intentions/convertTwoComparisonsToRangeCheck/until.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ReplaceRangeToWithUntilInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ReplaceRangeToWithUntilInspection.kt index df697eaf0e5..60e3a1ca008 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/ReplaceRangeToWithUntilInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ReplaceRangeToWithUntilInspection.kt @@ -27,8 +27,7 @@ import org.jetbrains.kotlin.psi.* class ReplaceRangeToWithUntilInspection : AbstractPrimitiveRangeToInspection() { override fun visitRangeToExpression(expression: KtExpression, holder: ProblemsHolder) { - if (expression.getArguments()?.second?.deparenthesize()?.isMinusOne() != true) return - + if (!isApplicable(expression)) return holder.registerProblem( expression, "'rangeTo' or the '..' call should be replaced with 'until'", @@ -44,6 +43,20 @@ class ReplaceRangeToWithUntilInspection : AbstractPrimitiveRangeToInspection() { override fun applyFix(project: Project, descriptor: ProblemDescriptor) { val element = descriptor.psiElement as KtExpression + applyFix(element) + } + } + + companion object { + fun applyFixIfApplicable(expression: KtExpression) { + if (isApplicable(expression)) applyFix(expression) + } + + private fun isApplicable(expression: KtExpression): Boolean { + return expression.getArguments()?.second?.deparenthesize()?.isMinusOne() == true + } + + private fun applyFix(element: KtExpression) { val args = element.getArguments() ?: return element.replace( KtPsiFactory(element).createExpressionByPattern( @@ -53,15 +66,15 @@ class ReplaceRangeToWithUntilInspection : AbstractPrimitiveRangeToInspection() { ) ) } - } - private fun KtExpression.isMinusOne(): Boolean { - if (this !is KtBinaryExpression) return false - if (operationToken != KtTokens.MINUS) return false + private fun KtExpression.isMinusOne(): Boolean { + if (this !is KtBinaryExpression) return false + if (operationToken != KtTokens.MINUS) return false - val constantValue = right?.constantValueOrNull() - val rightValue = (constantValue?.value as? Number)?.toInt() ?: return false - return rightValue == 1 + val constantValue = right?.constantValueOrNull() + val rightValue = (constantValue?.value as? Number)?.toInt() ?: return false + return rightValue == 1 + } } } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTwoComparisonsToRangeCheckIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTwoComparisonsToRangeCheckIntention.kt index 2e1a46e149f..f82356bb3ea 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTwoComparisonsToRangeCheckIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTwoComparisonsToRangeCheckIntention.kt @@ -21,6 +21,7 @@ import com.intellij.psi.tree.IElementType import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection +import org.jetbrains.kotlin.idea.inspections.ReplaceRangeToWithUntilInspection import org.jetbrains.kotlin.idea.intentions.branchedTransformations.evaluatesTo import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* @@ -49,13 +50,16 @@ class ConvertTwoComparisonsToRangeCheckIntention : SelfTargetingOffsetIndependen override fun applyTo(element: KtBinaryExpression, editor: Editor?) { val rangeData = generateRangeExpressionData(element) ?: return val factory = KtPsiFactory(element) - element.replace( + val replaced = element.replace( factory.createExpressionByPattern( "$0 in $1..$2", rangeData.value, factory.createExpression(rangeData.min), factory.createExpression(rangeData.max) ) ) + (replaced as? KtBinaryExpression)?.right?.let { + ReplaceRangeToWithUntilInspection.applyFixIfApplicable(it) + } } private fun generateRangeExpressionData(condition: KtBinaryExpression): RangeExpressionData? { diff --git a/idea/testData/intentions/convertTwoComparisonsToRangeCheck/nonConstants.kt b/idea/testData/intentions/convertTwoComparisonsToRangeCheck/nonConstants.kt index 76942efde28..add4aefe48e 100644 --- a/idea/testData/intentions/convertTwoComparisonsToRangeCheck/nonConstants.kt +++ b/idea/testData/intentions/convertTwoComparisonsToRangeCheck/nonConstants.kt @@ -1,3 +1,4 @@ +// WITH_RUNTIME fun foo(bar: Int, min: Int, max: Int) { min < bar && bar < max } \ No newline at end of file diff --git a/idea/testData/intentions/convertTwoComparisonsToRangeCheck/nonConstants.kt.after b/idea/testData/intentions/convertTwoComparisonsToRangeCheck/nonConstants.kt.after index a71fa6a0f50..4c4ef479f70 100644 --- a/idea/testData/intentions/convertTwoComparisonsToRangeCheck/nonConstants.kt.after +++ b/idea/testData/intentions/convertTwoComparisonsToRangeCheck/nonConstants.kt.after @@ -1,3 +1,4 @@ +// WITH_RUNTIME fun foo(bar: Int, min: Int, max: Int) { - bar in (min + 1)..(max - 1) + bar in (min + 1) until max } \ No newline at end of file diff --git a/idea/testData/intentions/convertTwoComparisonsToRangeCheck/until.kt b/idea/testData/intentions/convertTwoComparisonsToRangeCheck/until.kt new file mode 100644 index 00000000000..5ac16bf45b0 --- /dev/null +++ b/idea/testData/intentions/convertTwoComparisonsToRangeCheck/until.kt @@ -0,0 +1,3 @@ +// WITH_RUNTIME +val N = 42 +fun test(a: Int) = a >= 0 && a < N \ No newline at end of file diff --git a/idea/testData/intentions/convertTwoComparisonsToRangeCheck/until.kt.after b/idea/testData/intentions/convertTwoComparisonsToRangeCheck/until.kt.after new file mode 100644 index 00000000000..4fade4fac05 --- /dev/null +++ b/idea/testData/intentions/convertTwoComparisonsToRangeCheck/until.kt.after @@ -0,0 +1,3 @@ +// WITH_RUNTIME +val N = 42 +fun test(a: Int) = a in 0 until N \ 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 c442369d150..f253684465e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -7809,6 +7809,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest { public void testNonConstants() throws Exception { runTest("idea/testData/intentions/convertTwoComparisonsToRangeCheck/nonConstants.kt"); } + + @TestMetadata("until.kt") + public void testUntil() throws Exception { + runTest("idea/testData/intentions/convertTwoComparisonsToRangeCheck/until.kt"); + } } @TestMetadata("idea/testData/intentions/convertUnsafeCastCallToUnsafeCast")