diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ReplacePutWithAssignmentInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ReplacePutWithAssignmentInspection.kt index 8ef97775b5c..12f04718ef9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/ReplacePutWithAssignmentInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ReplacePutWithAssignmentInspection.kt @@ -23,9 +23,11 @@ import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.intentions.callExpression +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getExplicitReceiverValue @@ -44,6 +46,15 @@ class ReplacePutWithAssignmentInspection : AbstractApplicabilityBasedInspection< val context = element.analyze() if (element.isUsedAsExpression(context)) return false + + // This fragment had to be added because of incorrect behaviour of isUsesAsExpression + // TODO: remove it after fix of KT-25682 + val binaryExpression = element.getStrictParentOfType() + val right = binaryExpression?.right + if (binaryExpression?.operationToken == KtTokens.ELVIS && + right != null && (right == element || KtPsiUtil.deparenthesize(right) == element) + ) return false + val resolvedCall = element.getResolvedCall(context) val receiverType = resolvedCall?.getExplicitReceiverValue()?.type ?: return false val receiverClass = receiverType.constructor.declarationDescriptor as? ClassDescriptor ?: return false diff --git a/idea/testData/inspectionsLocal/replacePutWithAssignment/afterElvis.kt b/idea/testData/inspectionsLocal/replacePutWithAssignment/afterElvis.kt new file mode 100644 index 00000000000..e49e9ccfb85 --- /dev/null +++ b/idea/testData/inspectionsLocal/replacePutWithAssignment/afterElvis.kt @@ -0,0 +1,6 @@ +// PROBLEM: none +// WITH_RUNTIME + +fun test(i: Int?, m: MutableMap) { + i ?: m.put("", 1) +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replacePutWithAssignment/afterElvis2.kt b/idea/testData/inspectionsLocal/replacePutWithAssignment/afterElvis2.kt new file mode 100644 index 00000000000..926442aa550 --- /dev/null +++ b/idea/testData/inspectionsLocal/replacePutWithAssignment/afterElvis2.kt @@ -0,0 +1,6 @@ +// PROBLEM: none +// WITH_RUNTIME + +fun test(i: Int?, m: MutableMap) { + i ?: ((m.put("", 1))) +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replacePutWithAssignment/beforeElvis.kt b/idea/testData/inspectionsLocal/replacePutWithAssignment/beforeElvis.kt new file mode 100644 index 00000000000..a5fce8faa9a --- /dev/null +++ b/idea/testData/inspectionsLocal/replacePutWithAssignment/beforeElvis.kt @@ -0,0 +1,6 @@ +// PROBLEM: none +// WITH_RUNTIME + +fun test(i: Int?, m: MutableMap) { + m.put("", 1) ?: i +} \ 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 eae8a59e52d..e428835171f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -4188,10 +4188,25 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); } + @TestMetadata("afterElvis.kt") + public void testAfterElvis() throws Exception { + runTest("idea/testData/inspectionsLocal/replacePutWithAssignment/afterElvis.kt"); + } + + @TestMetadata("afterElvis2.kt") + public void testAfterElvis2() throws Exception { + runTest("idea/testData/inspectionsLocal/replacePutWithAssignment/afterElvis2.kt"); + } + public void testAllFilesPresentInReplacePutWithAssignment() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/replacePutWithAssignment"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); } + @TestMetadata("beforeElvis.kt") + public void testBeforeElvis() throws Exception { + runTest("idea/testData/inspectionsLocal/replacePutWithAssignment/beforeElvis.kt"); + } + @TestMetadata("nonMap.kt") public void testNonMap() throws Exception { runTest("idea/testData/inspectionsLocal/replacePutWithAssignment/nonMap.kt");