UselessCallOnCollectionInspection: fix false positive when lambda last statement is function call that returns generic type
#KT-38267 Fixed
This commit is contained in:
committed by
igoriakovlev
parent
3c8ef5749f
commit
148f49d54a
@@ -27,12 +27,14 @@ import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ReceiverKotlinCallArgument
|
import org.jetbrains.kotlin.resolve.calls.model.ReceiverKotlinCallArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaAtom
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaAtom
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.unwrap
|
import org.jetbrains.kotlin.resolve.calls.model.unwrap
|
||||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getImplicitReceiverValue
|
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getImplicitReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
|
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tower.SubKotlinCallArgumentImpl
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.receiverValue
|
import org.jetbrains.kotlin.resolve.calls.tower.receiverValue
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf
|
||||||
@@ -78,7 +80,13 @@ fun ResolvedCall<*>.hasLastFunctionalParameterWithResult(context: BindingContext
|
|||||||
// TODO: looks like hack
|
// TODO: looks like hack
|
||||||
resolvedCallAtom.subResolvedAtoms?.firstOrNull { it is ResolvedLambdaAtom }.safeAs<ResolvedLambdaAtom>()?.let { lambdaAtom ->
|
resolvedCallAtom.subResolvedAtoms?.firstOrNull { it is ResolvedLambdaAtom }.safeAs<ResolvedLambdaAtom>()?.let { lambdaAtom ->
|
||||||
return lambdaAtom.unwrap().resultArgumentsInfo!!.nonErrorArguments.filterIsInstance<ReceiverKotlinCallArgument>().all {
|
return lambdaAtom.unwrap().resultArgumentsInfo!!.nonErrorArguments.filterIsInstance<ReceiverKotlinCallArgument>().all {
|
||||||
val type = it.receiverValue?.type ?: return@all false
|
val type = it.receiverValue?.type?.let { type ->
|
||||||
|
if (type.constructor is TypeVariableTypeConstructor) {
|
||||||
|
it.safeAs<SubKotlinCallArgumentImpl>()?.valueArgument?.getArgumentExpression()?.getType(context) ?: type
|
||||||
|
} else {
|
||||||
|
type
|
||||||
|
}
|
||||||
|
} ?: return@all false
|
||||||
predicate(type)
|
predicate(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// FIX: Change call to 'map'
|
||||||
|
|
||||||
|
fun test(): List<String> {
|
||||||
|
return listOf(1, 2, 3).<caret>mapNotNull { i ->
|
||||||
|
foo {
|
||||||
|
bar(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> foo(f: () -> T): T = f()
|
||||||
|
|
||||||
|
fun bar(i: Int): String = ""
|
||||||
Vendored
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// FIX: Change call to 'map'
|
||||||
|
|
||||||
|
fun test(): List<String> {
|
||||||
|
return listOf(1, 2, 3).map { i ->
|
||||||
|
foo {
|
||||||
|
bar(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> foo(f: () -> T): T = f()
|
||||||
|
|
||||||
|
fun bar(i: Int): String = ""
|
||||||
Vendored
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
fun test(): List<String> {
|
||||||
|
return listOf(1, 2, 3).<caret>mapNotNull { i ->
|
||||||
|
foo {
|
||||||
|
bar(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> foo(f: () -> T): T = f()
|
||||||
|
|
||||||
|
fun bar(i: Int): String? = null
|
||||||
+10
@@ -2058,11 +2058,21 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithLambda4.kt");
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithLambda4.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MapNotNullWithLambda5.kt")
|
||||||
|
public void testMapNotNullWithLambda5() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithLambda5.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("MapNotNullWithLambdaFake.kt")
|
@TestMetadata("MapNotNullWithLambdaFake.kt")
|
||||||
public void testMapNotNullWithLambdaFake() throws Exception {
|
public void testMapNotNullWithLambdaFake() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithLambdaFake.kt");
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithLambdaFake.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MapNotNullWithLambdaFake2.kt")
|
||||||
|
public void testMapNotNullWithLambdaFake2() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithLambdaFake2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("MapNotNullWithReference.kt")
|
@TestMetadata("MapNotNullWithReference.kt")
|
||||||
public void testMapNotNullWithReference() throws Exception {
|
public void testMapNotNullWithReference() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithReference.kt");
|
runTest("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithReference.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user