Introduce "Unused result of data class copy" inspection
#KT-34121 Fixed
This commit is contained in:
committed by
klunnii
parent
ae6d89b100
commit
bc580d2fd9
@@ -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.inheritors.to_many.format={0,number}+ Inheritors
|
||||||
hints.codevision.overrides.format={0, choice, 1#1 Override|2#{0,number} Overrides}
|
hints.codevision.overrides.format={0, choice, 1#1 Override|2#{0,number} Overrides}
|
||||||
hints.codevision.overrides.to_many.format={0,number}+ Overrides
|
hints.codevision.overrides.to_many.format={0,number}+ Overrides
|
||||||
hints.codevision.settings=Settings...
|
hints.codevision.settings=Settings...
|
||||||
|
inspection.unused.result.of.data.class.copy=Unused result of data class copy
|
||||||
@@ -2563,6 +2563,14 @@
|
|||||||
language="kotlin"
|
language="kotlin"
|
||||||
key="inspection.simplifiable.scope.function.display.name" bundle="messages.KotlinBundle"/>
|
key="inspection.simplifiable.scope.function.display.name" bundle="messages.KotlinBundle"/>
|
||||||
|
|
||||||
|
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.UnusedDataClassCopyResultInspection"
|
||||||
|
groupPath="Kotlin"
|
||||||
|
groupName="Probable bugs"
|
||||||
|
enabledByDefault="true"
|
||||||
|
level="WARNING"
|
||||||
|
language="kotlin"
|
||||||
|
key="inspection.unused.result.of.data.class.copy" bundle="messages.KotlinBundle"/>
|
||||||
|
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
This inspection reports unused result of data class copy function call.
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -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"))
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
org.jetbrains.kotlin.idea.inspections.UnusedDataClassCopyResultInspection
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// FIX: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
fun main() {
|
||||||
|
val o = Foo("")
|
||||||
|
o.<caret>copy(prop = "New")
|
||||||
|
bar(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Foo(val prop: String)
|
||||||
|
|
||||||
|
fun bar(foo: Foo) {}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// FIX: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
fun main() {
|
||||||
|
val o = Foo("")
|
||||||
|
o.run {
|
||||||
|
<caret>copy(prop = "New")
|
||||||
|
bar(o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Foo(val prop: String)
|
||||||
|
|
||||||
|
fun bar(foo: Foo) {}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
fun main() {
|
||||||
|
val o = Foo("")
|
||||||
|
val o2 = o.<caret>copy(prop = "New")
|
||||||
|
bar(o2)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Foo(val prop: String)
|
||||||
|
|
||||||
|
fun bar(foo: Foo) {}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
fun main() {
|
||||||
|
val o = Foo("")
|
||||||
|
o.run {
|
||||||
|
val o2 = <caret>copy(prop = "New")
|
||||||
|
bar(o2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Foo(val prop: String)
|
||||||
|
|
||||||
|
fun bar(foo: Foo) {}
|
||||||
+33
@@ -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")
|
@TestMetadata("idea/testData/inspectionsLocal/unusedEquals")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user