[NI] Fix determining return type of lambda in IDEA

UselessCallOnCollection tests fixed
This commit is contained in:
Dmitriy Novozhilov
2019-04-22 17:37:22 +03:00
committed by Mikhail Zarechenskiy
parent 956f27cc2d
commit 6f51415b4d
@@ -26,11 +26,16 @@ import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.resolve.calls.model.ReceiverKotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedLambdaAtom
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.tower.receiverValue
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun KotlinType.isFunctionOfAnyKind() = constructor.declarationDescriptor?.getFunctionalClassKind() != null
@@ -65,6 +70,16 @@ fun ResolvedCall<out CallableDescriptor>.isCalling(fqName: FqName): Boolean {
fun ResolvedCall<*>.hasLastFunctionalParameterWithResult(context: BindingContext, predicate: (KotlinType) -> Boolean): Boolean {
val lastParameter = resultingDescriptor.valueParameters.lastOrNull() ?: return false
val lastArgument = valueArguments[lastParameter]?.arguments?.singleOrNull() ?: return false
if (this is NewResolvedCallImpl<*>) {
// TODO: looks like hack
resolvedCallAtom.subResolvedAtoms.firstOrNull { it is ResolvedLambdaAtom }.safeAs<ResolvedLambdaAtom>()?.let { lambdaAtom ->
return lambdaAtom.resultArguments.filterIsInstance<ReceiverKotlinCallArgument>().all {
val type = it.receiverValue?.type ?: return@all false
predicate(type)
}
}
}
val functionalType = lastArgument.getArgumentExpression()?.getType(context) ?: return false
// Both Function & KFunction must pass here
if (!functionalType.isFunctionOfAnyKind()) return false