From d583c1be5831f1103d84016d31c740127deb9016 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Fri, 8 Feb 2019 15:10:05 +0900 Subject: [PATCH] Can be replaced with binary operator: do not suggest when receiver or argument is floating point type #KT-28596 Fixed --- .../kotlin/resolve/calls/smartcasts/DataFlowUtils.kt | 7 ++++--- .../ReplaceCallWithBinaryOperatorInspection.kt | 6 ++++-- .../equalsDoubleSmartCast2.kt | 4 ++++ .../equalsDoubleSmartCast2.kt.after | 4 ++++ .../equalsDoubleSmartCast3.kt | 4 ++++ .../equalsDoubleSmartCast3.kt.after | 4 ++++ .../idea/inspections/LocalInspectionTestGenerated.java | 10 ++++++++++ 7 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast2.kt create mode 100644 idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast2.kt.after create mode 100644 idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast3.kt create mode 100644 idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast3.kt.after diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowUtils.kt index a38c2ab9245..caac6c7017c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowUtils.kt @@ -25,7 +25,8 @@ fun KtExpression?.getKotlinTypeWithPossibleSmartCastToFP( bindingContext: BindingContext, descriptor: DeclarationDescriptor?, languageVersionSettings: LanguageVersionSettings, - dataFlowValueFactory: DataFlowValueFactory + dataFlowValueFactory: DataFlowValueFactory, + defaultType: (KotlinType, Set) -> KotlinType = { givenType, _ -> givenType } ): KotlinType? { val givenType = this?.getKotlinTypeForComparison(bindingContext) ?: return null @@ -40,13 +41,13 @@ fun KtExpression?.getKotlinTypeWithPossibleSmartCastToFP( if (descriptor != null) { val dataFlow = dataFlowValueFactory.createDataFlowValue(this, givenType, bindingContext, descriptor) val stableTypes = bindingContext.getDataFlowInfoBefore(this).getStableTypes(dataFlow, languageVersionSettings) - stableTypes.firstNotNullResult { + return stableTypes.firstNotNullResult { when { KotlinBuiltIns.isDoubleOrNullableDouble(it) -> it KotlinBuiltIns.isFloatOrNullableFloat(it) -> it else -> null } - }?.let { return it } + } ?: defaultType(givenType, stableTypes) } return givenType } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/conventionNameCalls/ReplaceCallWithBinaryOperatorInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/conventionNameCalls/ReplaceCallWithBinaryOperatorInspection.kt index d20896c4db3..91a4a7e6c96 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/conventionNameCalls/ReplaceCallWithBinaryOperatorInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/conventionNameCalls/ReplaceCallWithBinaryOperatorInspection.kt @@ -187,12 +187,14 @@ class ReplaceCallWithBinaryOperatorInspection : AbstractApplicabilityBasedInspec private fun KtDotQualifiedExpression.isFloatingPointNumberEquals(): Boolean { val resolvedCall = resolveToCall() ?: return false val context = analyze(BodyResolveMode.PARTIAL) + val declarationDescriptor = containingDeclarationForPseudocode?.resolveToDescriptorIfAny() val dataFlowValueFactory = getResolutionFacade().getFrontendService(DataFlowValueFactory::class.java) + val defaultType: (KotlinType, Set) -> KotlinType = { givenType, stableTypes -> stableTypes.firstOrNull() ?: givenType } val receiverType = resolvedCall.getReceiverExpression()?.getKotlinTypeWithPossibleSmartCastToFP( - context, containingDeclarationForPseudocode?.resolveToDescriptorIfAny(), languageVersionSettings, dataFlowValueFactory + context, declarationDescriptor, languageVersionSettings, dataFlowValueFactory, defaultType ) ?: return false val argumentType = resolvedCall.getFirstArgumentExpression()?.getKotlinTypeWithPossibleSmartCastToFP( - context, containingDeclarationForPseudocode?.resolveToDescriptorIfAny(), languageVersionSettings, dataFlowValueFactory + context, declarationDescriptor, languageVersionSettings, dataFlowValueFactory, defaultType ) ?: return false return receiverType.isFpType() && argumentType.isNumericType() || argumentType.isFpType() && receiverType.isNumericType() diff --git a/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast2.kt b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast2.kt new file mode 100644 index 00000000000..b692cfe0a24 --- /dev/null +++ b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast2.kt @@ -0,0 +1,4 @@ +// FIX: Replace total order equality with IEEE 754 equality + +fun test(a: Any, b: Any) = + a is Double && b is Int && a.equals(b) \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast2.kt.after b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast2.kt.after new file mode 100644 index 00000000000..c103ff77fc9 --- /dev/null +++ b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast2.kt.after @@ -0,0 +1,4 @@ +// FIX: Replace total order equality with IEEE 754 equality + +fun test(a: Any, b: Any) = + a is Double && b is Int && a == b \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast3.kt b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast3.kt new file mode 100644 index 00000000000..fa223a4bdec --- /dev/null +++ b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast3.kt @@ -0,0 +1,4 @@ +// FIX: Replace total order equality with IEEE 754 equality + +fun test(a: Any, b: Any) = + a is Int && b is Double && a.equals(b) \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast3.kt.after b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast3.kt.after new file mode 100644 index 00000000000..abcd73fa30d --- /dev/null +++ b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast3.kt.after @@ -0,0 +1,4 @@ +// FIX: Replace total order equality with IEEE 754 equality + +fun test(a: Any, b: Any) = + a is Int && b is Double && a == b \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index b146948826e..a2143181688 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -1679,6 +1679,16 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast.kt"); } + @TestMetadata("equalsDoubleSmartCast2.kt") + public void testEqualsDoubleSmartCast2() throws Exception { + runTest("idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast2.kt"); + } + + @TestMetadata("equalsDoubleSmartCast3.kt") + public void testEqualsDoubleSmartCast3() throws Exception { + runTest("idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCast3.kt"); + } + @TestMetadata("equalsDoubleSmartCastFromGeneric.kt") public void testEqualsDoubleSmartCastFromGeneric() throws Exception { runTest("idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equalsDoubleSmartCastFromGeneric.kt");