From f389c31d8e5083a60846682855ceaa1704fb9d8c Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Fri, 28 Dec 2018 13:38:52 +0900 Subject: [PATCH] Replace with binary operator: don't highlight when receiver is dynamic type #KT-28773 Fixed --- .../ReplaceCallWithBinaryOperatorInspection.kt | 11 ++++++++++- .../replaceCallWithBinaryOperator/dynamicEquals.kt | 5 +++++ .../dynamicEquals.kt.after | 5 +++++ .../inspections/LocalInspectionTestGenerated.java | 5 +++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/dynamicEquals.kt create mode 100644 idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/dynamicEquals.kt.after 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 f1e51ca554b..d20896c4db3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/conventionNameCalls/ReplaceCallWithBinaryOperatorInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/conventionNameCalls/ReplaceCallWithBinaryOperatorInspection.kt @@ -34,6 +34,8 @@ import org.jetbrains.kotlin.idea.intentions.isOperatorOrCompatible import org.jetbrains.kotlin.idea.intentions.isReceiverExpressionWithValue import org.jetbrains.kotlin.idea.intentions.toResolvedCall import org.jetbrains.kotlin.idea.project.languageVersionSettings +import org.jetbrains.kotlin.idea.project.platform +import org.jetbrains.kotlin.js.resolve.JsPlatform import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* @@ -41,6 +43,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getLastParentOfTypeInRow import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.resolve.calls.callUtil.getFirstArgumentExpression import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression +import org.jetbrains.kotlin.resolve.calls.callUtil.getType import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory @@ -48,6 +51,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.getKotlinTypeWithPossibleSm import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.expressions.OperatorConventions +import org.jetbrains.kotlin.types.isDynamic import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.util.OperatorNameConventions @@ -83,8 +87,13 @@ class ReplaceCallWithBinaryOperatorInspection : AbstractApplicabilityBasedInspec override fun inspectionHighlightType(element: KtDotQualifiedExpression): ProblemHighlightType { val calleeExpression = element.callExpression?.calleeExpression as? KtSimpleNameExpression val identifier = calleeExpression?.getReferencedNameAsName() + if (element.platform == JsPlatform && identifier == OperatorNameConventions.EQUALS) { + val context = element.analyze(BodyResolveMode.PARTIAL) + if (element.receiverExpression.getType(context)?.isDynamic() == true) { + return ProblemHighlightType.INFORMATION + } + } val isFloatingPointNumberEquals = calleeExpression?.isFloatingPointNumberEquals() ?: false - return if (isFloatingPointNumberEquals) { ProblemHighlightType.INFORMATION } else if (identifier == OperatorNameConventions.EQUALS || identifier == OperatorNameConventions.COMPARE_TO) { diff --git a/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/dynamicEquals.kt b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/dynamicEquals.kt new file mode 100644 index 00000000000..4e22cef8015 --- /dev/null +++ b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/dynamicEquals.kt @@ -0,0 +1,5 @@ +// JS +// HIGHLIGHT: INFORMATION +fun foo(a: dynamic, b: String): Boolean { + return a.equals(b) +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/dynamicEquals.kt.after b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/dynamicEquals.kt.after new file mode 100644 index 00000000000..b67ae41b4a2 --- /dev/null +++ b/idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/dynamicEquals.kt.after @@ -0,0 +1,5 @@ +// JS +// HIGHLIGHT: INFORMATION +fun foo(a: dynamic, b: String): Boolean { + return 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 0ef8c717519..f6e48ba3f81 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -1654,6 +1654,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/divSanityTest.kt"); } + @TestMetadata("dynamicEquals.kt") + public void testDynamicEquals() throws Exception { + runTest("idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/dynamicEquals.kt"); + } + @TestMetadata("equals.kt") public void testEquals() throws Exception { runTest("idea/testData/inspectionsLocal/conventionNameCalls/replaceCallWithBinaryOperator/equals.kt");