diff --git a/idea/resources-en/messages/KotlinBundle.properties b/idea/resources-en/messages/KotlinBundle.properties
index ed83745e44c..5862400902d 100644
--- a/idea/resources-en/messages/KotlinBundle.properties
+++ b/idea/resources-en/messages/KotlinBundle.properties
@@ -2216,4 +2216,5 @@ hints.codevision.inheritors.format={0, choice, 1#1 Inheritor|2#{0,number} Inheri
hints.codevision.inheritors.to_many.format={0,number}+ Inheritors
hints.codevision.overrides.format={0, choice, 1#1 Override|2#{0,number} Overrides}
hints.codevision.overrides.to_many.format={0,number}+ Overrides
-hints.codevision.settings=Settings...
\ No newline at end of file
+hints.codevision.settings=Settings...
+inspection.unused.result.of.data.class.copy=Unused result of data class copy
\ No newline at end of file
diff --git a/idea/resources/META-INF/inspections.xml b/idea/resources/META-INF/inspections.xml
index 56ac41ec34c..245c43ec04a 100644
--- a/idea/resources/META-INF/inspections.xml
+++ b/idea/resources/META-INF/inspections.xml
@@ -2563,6 +2563,14 @@
language="kotlin"
key="inspection.simplifiable.scope.function.display.name" bundle="messages.KotlinBundle"/>
+
+
\ No newline at end of file
diff --git a/idea/resources/inspectionDescriptions/UnusedDataClassCopyResult.html b/idea/resources/inspectionDescriptions/UnusedDataClassCopyResult.html
new file mode 100644
index 00000000000..5052b0bb0f9
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/UnusedDataClassCopyResult.html
@@ -0,0 +1,5 @@
+
+
+This inspection reports unused result of data class copy function call.
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedDataClassCopyResultInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedDataClassCopyResultInspection.kt
new file mode 100644
index 00000000000..5108f22a08d
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedDataClassCopyResultInspection.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.idea.inspections
+
+import com.intellij.codeInspection.ProblemsHolder
+import org.jetbrains.kotlin.idea.KotlinBundle
+import org.jetbrains.kotlin.idea.caches.resolve.analyze
+import org.jetbrains.kotlin.psi.callExpressionVisitor
+import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
+import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
+import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
+import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
+import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
+
+class UnusedDataClassCopyResultInspection : AbstractKotlinInspection() {
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = callExpressionVisitor(fun(call) {
+ val callee = call.calleeExpression ?: return
+ if (callee.text != "copy") return
+ val context = call.analyze(BodyResolveMode.PARTIAL_WITH_CFA)
+ val descriptor = call.getResolvedCall(context)?.resultingDescriptor ?: return
+ val receiver = descriptor.dispatchReceiverParameter ?: descriptor.extensionReceiverParameter ?: return
+ if ((receiver.value as? ImplicitClassReceiver)?.classDescriptor?.isData != true) return
+ if (call.getQualifiedExpressionForSelectorOrThis().isUsedAsExpression(context)) return
+ holder.registerProblem(callee, KotlinBundle.message("inspection.unused.result.of.data.class.copy"))
+ })
+}
diff --git a/idea/testData/inspectionsLocal/unusedDataClassCopyResult/.inspection b/idea/testData/inspectionsLocal/unusedDataClassCopyResult/.inspection
new file mode 100644
index 00000000000..62f6f9fd501
--- /dev/null
+++ b/idea/testData/inspectionsLocal/unusedDataClassCopyResult/.inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.inspections.UnusedDataClassCopyResultInspection
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/unusedDataClassCopyResult/basic.kt b/idea/testData/inspectionsLocal/unusedDataClassCopyResult/basic.kt
new file mode 100644
index 00000000000..ba37e893788
--- /dev/null
+++ b/idea/testData/inspectionsLocal/unusedDataClassCopyResult/basic.kt
@@ -0,0 +1,11 @@
+// FIX: none
+// WITH_RUNTIME
+fun main() {
+ val o = Foo("")
+ o.copy(prop = "New")
+ bar(o)
+}
+
+data class Foo(val prop: String)
+
+fun bar(foo: Foo) {}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/unusedDataClassCopyResult/basic2.kt b/idea/testData/inspectionsLocal/unusedDataClassCopyResult/basic2.kt
new file mode 100644
index 00000000000..b474ac52b36
--- /dev/null
+++ b/idea/testData/inspectionsLocal/unusedDataClassCopyResult/basic2.kt
@@ -0,0 +1,13 @@
+// FIX: none
+// WITH_RUNTIME
+fun main() {
+ val o = Foo("")
+ o.run {
+ copy(prop = "New")
+ bar(o)
+ }
+}
+
+data class Foo(val prop: String)
+
+fun bar(foo: Foo) {}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/unusedDataClassCopyResult/used.kt b/idea/testData/inspectionsLocal/unusedDataClassCopyResult/used.kt
new file mode 100644
index 00000000000..9052cdfba63
--- /dev/null
+++ b/idea/testData/inspectionsLocal/unusedDataClassCopyResult/used.kt
@@ -0,0 +1,11 @@
+// PROBLEM: none
+// WITH_RUNTIME
+fun main() {
+ val o = Foo("")
+ val o2 = o.copy(prop = "New")
+ bar(o2)
+}
+
+data class Foo(val prop: String)
+
+fun bar(foo: Foo) {}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/unusedDataClassCopyResult/used2.kt b/idea/testData/inspectionsLocal/unusedDataClassCopyResult/used2.kt
new file mode 100644
index 00000000000..3b67ee410ca
--- /dev/null
+++ b/idea/testData/inspectionsLocal/unusedDataClassCopyResult/used2.kt
@@ -0,0 +1,13 @@
+// PROBLEM: none
+// WITH_RUNTIME
+fun main() {
+ val o = Foo("")
+ o.run {
+ val o2 = copy(prop = "New")
+ bar(o2)
+ }
+}
+
+data class Foo(val prop: String)
+
+fun bar(foo: Foo) {}
\ 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 62ed03a94b8..d052704719d 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
@@ -14026,6 +14026,39 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
}
}
+ @TestMetadata("idea/testData/inspectionsLocal/unusedDataClassCopyResult")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class UnusedDataClassCopyResult extends AbstractLocalInspectionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+ }
+
+ public void testAllFilesPresentInUnusedDataClassCopyResult() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/inspectionsLocal/unusedDataClassCopyResult"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), null, true);
+ }
+
+ @TestMetadata("basic.kt")
+ public void testBasic() throws Exception {
+ runTest("idea/testData/inspectionsLocal/unusedDataClassCopyResult/basic.kt");
+ }
+
+ @TestMetadata("basic2.kt")
+ public void testBasic2() throws Exception {
+ runTest("idea/testData/inspectionsLocal/unusedDataClassCopyResult/basic2.kt");
+ }
+
+ @TestMetadata("used.kt")
+ public void testUsed() throws Exception {
+ runTest("idea/testData/inspectionsLocal/unusedDataClassCopyResult/used.kt");
+ }
+
+ @TestMetadata("used2.kt")
+ public void testUsed2() throws Exception {
+ runTest("idea/testData/inspectionsLocal/unusedDataClassCopyResult/used2.kt");
+ }
+ }
+
@TestMetadata("idea/testData/inspectionsLocal/unusedEquals")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)