"Convert to range check" inspection: apply ReplaceRangeToWithUntilInspection after convertion

#KT-33880 Fixed
This commit is contained in:
Toshiaki Kameyama
2019-09-19 13:08:55 +09:00
committed by Dmitry Gridin
parent 54df0aad16
commit 82f75c707e
7 changed files with 41 additions and 11 deletions
@@ -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
}
}
}
@@ -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? {
@@ -1,3 +1,4 @@
// WITH_RUNTIME
fun foo(bar: Int, min: Int, max: Int) {
min < bar && bar < max<caret>
}
@@ -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
}
@@ -0,0 +1,3 @@
// WITH_RUNTIME
val N = 42
fun test(a: Int) = a >= 0 && a < N<caret>
@@ -0,0 +1,3 @@
// WITH_RUNTIME
val N = 42
fun test(a: Int) = a in 0 until N
@@ -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")