[NI] Minor, simplify code a bit for sub calls preparation

This commit is contained in:
Mikhail Zarechenskiy
2019-09-17 13:22:42 +03:00
parent 7e8784dca1
commit 971b02494c
2 changed files with 41 additions and 30 deletions
@@ -294,30 +294,36 @@ internal fun createSimplePSICallArgument(
): SimplePSIKotlinCallArgument? {
val ktExpression = KtPsiUtil.getLastElementDeparenthesized(valueArgument.getArgumentExpression(), statementFilter) ?: return null
val onlyResolvedCall = ktExpression.getCall(bindingContext)?.let {
val partiallyResolvedCall = ktExpression.getCall(bindingContext)?.let {
bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)?.result
}
// todo hack for if expression: sometimes we not write properly type information for branches
val baseType = typeInfoForArgument.type?.unwrap() ?: onlyResolvedCall?.resultCallAtom?.freshReturnType ?: return null
val baseType = typeInfoForArgument.type?.unwrap() ?: partiallyResolvedCall?.resultCallAtom?.freshReturnType ?: return null
val expressionReceiver = ExpressionReceiver.create(ktExpression, baseType, bindingContext)
// For a sub-call there can't be any smartcast so we use a fast-path here to avoid calling transformToReceiverWithSmartCastInfo function
if (partiallyResolvedCall != null) {
val capturedReceiver =
ReceiverValueWithSmartCastInfo(expressionReceiver, emptySet(), isStable = true)
.prepareReceiverRegardingCaptureTypes()
return SubKotlinCallArgumentImpl(
valueArgument,
dataFlowInfoBeforeThisArgument,
typeInfoForArgument.dataFlowInfo,
capturedReceiver,
partiallyResolvedCall
)
}
// we should use DFI after this argument, because there can be some useful smartcast. Popular case: if branches.
val receiverToCast = transformToReceiverWithSmartCastInfo(
ownerDescriptor, bindingContext,
typeInfoForArgument.dataFlowInfo, // dataFlowInfoBeforeThisArgument cannot be used here, because of if() { if (x != null) return; x }
ExpressionReceiver.create(ktExpression, baseType, bindingContext),
expressionReceiver,
languageVersionSettings,
dataFlowValueFactory
).prepareReceiverRegardingCaptureTypes()
return if (onlyResolvedCall == null) {
ExpressionKotlinCallArgumentImpl(valueArgument, dataFlowInfoBeforeThisArgument, typeInfoForArgument.dataFlowInfo, receiverToCast)
} else {
SubKotlinCallArgumentImpl(
valueArgument,
dataFlowInfoBeforeThisArgument,
typeInfoForArgument.dataFlowInfo,
receiverToCast,
onlyResolvedCall
)
}
return ExpressionKotlinCallArgumentImpl(valueArgument, dataFlowInfoBeforeThisArgument, typeInfoForArgument.dataFlowInfo, receiverToCast)
}
@@ -579,37 +579,42 @@ class PSICallResolver(
oldReceiver: Receiver?,
isSafeCall: Boolean,
isForImplicitInvoke: Boolean
): ReceiverKotlinCallArgument? =
when (oldReceiver) {
): ReceiverKotlinCallArgument? {
return when (oldReceiver) {
null -> null
is QualifierReceiver -> QualifierReceiverKotlinCallArgument(oldReceiver) // todo report warning if isSafeCall
is ReceiverValue -> {
val detailedReceiver = context.transformToReceiverWithSmartCastInfo(oldReceiver)
var subCallArgument: ReceiverKotlinCallArgument? = null
is QualifierReceiver -> QualifierReceiverKotlinCallArgument(oldReceiver) // todo report warning if isSafeCall
is ReceiverValue -> {
if (oldReceiver is ExpressionReceiver) {
val ktExpression = KtPsiUtil.getLastElementDeparenthesized(oldReceiver.expression, context.statementFilter)
val bindingContext = context.trace.bindingContext
val call = bindingContext[BindingContext.DELEGATE_EXPRESSION_TO_PROVIDE_DELEGATE_CALL, ktExpression]
?: ktExpression?.getCall(bindingContext)
val call =
bindingContext[BindingContext.DELEGATE_EXPRESSION_TO_PROVIDE_DELEGATE_CALL, ktExpression]
?: ktExpression?.getCall(bindingContext)
val onlyResolvedCall = call?.let {
bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)?.result
}
if (onlyResolvedCall != null) {
subCallArgument = SubKotlinCallArgumentImpl(
val partiallyResolvedCall = call?.let { bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)?.result }
if (partiallyResolvedCall != null) {
val receiver = ReceiverValueWithSmartCastInfo(oldReceiver, emptySet(), isStable = true)
return SubKotlinCallArgumentImpl(
CallMaker.makeExternalValueArgument(oldReceiver.expression),
context.dataFlowInfo, context.dataFlowInfo, detailedReceiver, onlyResolvedCall
context.dataFlowInfo, context.dataFlowInfo, receiver, partiallyResolvedCall
)
}
}
subCallArgument ?: ReceiverExpressionKotlinCallArgument(detailedReceiver, isSafeCall, isForImplicitInvoke)
ReceiverExpressionKotlinCallArgument(
context.transformToReceiverWithSmartCastInfo(oldReceiver),
isSafeCall,
isForImplicitInvoke
)
}
else -> error("Incorrect receiver: $oldReceiver")
}
}
private fun resolveTypeArguments(context: BasicCallResolutionContext, typeArguments: List<KtTypeProjection>): List<TypeArgument> =
typeArguments.map { projection ->