Revert "Convert to range check: don't report it if recursive call will be created"
This reverts commit 73184884
This commit is contained in:
+10
-26
@@ -10,22 +10,17 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||||
import org.jetbrains.kotlin.idea.analysis.analyzeAsReplacement
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.evaluatesTo
|
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.evaluatesTo
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
|
||||||
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.constants.evaluate.ConstantExpressionEvaluator
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
|
||||||
|
|
||||||
class ConvertTwoComparisonsToRangeCheckInspection :
|
class ConvertTwoComparisonsToRangeCheckInspection :
|
||||||
AbstractApplicabilityBasedInspection<KtBinaryExpression>(KtBinaryExpression::class.java) {
|
AbstractApplicabilityBasedInspection<KtBinaryExpression>(KtBinaryExpression::class.java) {
|
||||||
@@ -33,35 +28,24 @@ class ConvertTwoComparisonsToRangeCheckInspection :
|
|||||||
|
|
||||||
override val defaultFixText get() = KotlinBundle.message("convert.to.a.range.check")
|
override val defaultFixText get() = KotlinBundle.message("convert.to.a.range.check")
|
||||||
|
|
||||||
override fun isApplicable(element: KtBinaryExpression): Boolean {
|
override fun isApplicable(element: KtBinaryExpression) = generateRangeExpressionData(element) != null
|
||||||
val rangeData = generateRangeExpressionData(element) ?: return false
|
|
||||||
val function = element.getStrictParentOfType<KtNamedFunction>()
|
|
||||||
if (function != null && function.hasModifier(KtTokens.OPERATOR_KEYWORD) && function.nameAsName == OperatorNameConventions.CONTAINS) {
|
|
||||||
val context = element.analyze(BodyResolveMode.PARTIAL)
|
|
||||||
val functionDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, function]
|
|
||||||
val newExpression = rangeData.createExpression()
|
|
||||||
val newContext = newExpression.analyzeAsReplacement(element, context)
|
|
||||||
if (newExpression.operationReference.getResolvedCall(newContext)?.resultingDescriptor == functionDescriptor) return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun applyTo(element: KtBinaryExpression, project: Project, editor: Editor?) {
|
override fun applyTo(element: KtBinaryExpression, project: Project, editor: Editor?) {
|
||||||
val rangeData = generateRangeExpressionData(element) ?: return
|
val rangeData = generateRangeExpressionData(element) ?: return
|
||||||
val replaced = element.replace(rangeData.createExpression())
|
val factory = KtPsiFactory(element)
|
||||||
|
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 {
|
(replaced as? KtBinaryExpression)?.right?.let {
|
||||||
ReplaceRangeToWithUntilInspection.applyFixIfApplicable(it)
|
ReplaceRangeToWithUntilInspection.applyFixIfApplicable(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class RangeExpressionData(val value: KtExpression, val min: String, val max: String) {
|
private data class RangeExpressionData(val value: KtExpression, val min: String, val max: String)
|
||||||
fun createExpression(): KtBinaryExpression {
|
|
||||||
val factory = KtPsiFactory(value)
|
|
||||||
return factory.createExpressionByPattern(
|
|
||||||
"$0 in $1..$2", value, factory.createExpression(min), factory.createExpression(max)
|
|
||||||
) as KtBinaryExpression
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateRangeExpressionData(condition: KtBinaryExpression): RangeExpressionData? {
|
private fun generateRangeExpressionData(condition: KtBinaryExpression): RangeExpressionData? {
|
||||||
if (condition.operationToken != KtTokens.ANDAND) return null
|
if (condition.operationToken != KtTokens.ANDAND) return null
|
||||||
|
|||||||
-21
@@ -1,21 +0,0 @@
|
|||||||
// PROBLEM: none
|
|
||||||
// WITH_RUNTIME
|
|
||||||
class TimeIndex(val intValue: Int) : Comparable<TimeIndex> {
|
|
||||||
override fun compareTo(other: TimeIndex): Int {
|
|
||||||
TODO()
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun rangeTo(other: TimeIndex): TimeIndexRange {
|
|
||||||
return TimeIndexRange(this, other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class TimeIndexRange(val start: TimeIndex, val end: TimeIndex) : Iterable<TimeIndex> {
|
|
||||||
override fun iterator(): Iterator<TimeIndex> {
|
|
||||||
TODO()
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun contains(index: TimeIndex): Boolean {
|
|
||||||
return <caret>start <= index && index <= end
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-5
@@ -3871,11 +3871,6 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
runTest("idea/testData/inspectionsLocal/convertTwoComparisonsToRangeCheck/nonConstants.kt");
|
runTest("idea/testData/inspectionsLocal/convertTwoComparisonsToRangeCheck/nonConstants.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("recursiveCall.kt")
|
|
||||||
public void testRecursiveCall() throws Exception {
|
|
||||||
runTest("idea/testData/inspectionsLocal/convertTwoComparisonsToRangeCheck/recursiveCall.kt");
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestMetadata("until.kt")
|
@TestMetadata("until.kt")
|
||||||
public void testUntil() throws Exception {
|
public void testUntil() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/convertTwoComparisonsToRangeCheck/until.kt");
|
runTest("idea/testData/inspectionsLocal/convertTwoComparisonsToRangeCheck/until.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user