[FIR] Correctly insert FirImplicitInvokeCall expression when needed

Before that, implicit invoke call were inserted only for
double-brackets expressions (like `foo()()`)

In fact, it is intended to be present in every place where `invoke`
function is used as an operator:

`foo()` - `invoke` operator usage, should be `ImplicitInvokeCall`
`foo.invoke()` - `invoke` function used, should be simple `FunctionCall`

Also, handle implicit invokes in `FirDelegatedPropertyChecker`
This commit is contained in:
Roman Golyshev
2021-09-08 19:40:39 +03:00
committed by teamcityserver
parent f4a59de1c2
commit c7a6a77a04
3 changed files with 30 additions and 7 deletions
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirImplicitInvokeCall
import org.jetbrains.kotlin.fir.expressions.arguments import org.jetbrains.kotlin.fir.expressions.arguments
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
@@ -55,6 +56,10 @@ object FirDelegatedPropertyChecker : FirPropertyChecker() {
checkFunctionCall(functionCall) checkFunctionCall(functionCall)
} }
override fun visitImplicitInvokeCall(implicitInvokeCall: FirImplicitInvokeCall) {
checkFunctionCall(implicitInvokeCall)
}
private fun checkFunctionCall(functionCall: FirFunctionCall) { private fun checkFunctionCall(functionCall: FirFunctionCall) {
val hasReferenceError = checkFunctionReferenceErrors(functionCall) val hasReferenceError = checkFunctionReferenceErrors(functionCall)
if (isGet && !hasReferenceError) checkReturnType(functionCall) if (isGet && !hasReferenceError) checkReturnType(functionCall)
@@ -58,6 +58,25 @@ fun FirFunctionCall.copy(
return (builder as FirCallBuilder).build() as FirFunctionCall return (builder as FirCallBuilder).build() as FirFunctionCall
} }
internal fun FirFunctionCall.copyAsImplicitInvokeCall(
setupCopy: FirImplicitInvokeCallBuilder.() -> Unit
): FirImplicitInvokeCall {
val original = this
return buildImplicitInvokeCall {
source = original.source
annotations.addAll(original.annotations)
typeArguments.addAll(original.typeArguments)
explicitReceiver = original.explicitReceiver
dispatchReceiver = original.dispatchReceiver
extensionReceiver = original.extensionReceiver
argumentList = original.argumentList
calleeReference = original.calleeReference
setupCopy()
}
}
fun FirAnonymousFunction.copy( fun FirAnonymousFunction.copy(
receiverTypeRef: FirTypeRef? = this.receiverTypeRef, receiverTypeRef: FirTypeRef? = this.receiverTypeRef,
source: FirSourceElement? = this.source, source: FirSourceElement? = this.source,
@@ -44,7 +44,6 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import java.lang.annotation.ElementType
class FirCallResolver( class FirCallResolver(
private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents, private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents,
@@ -115,12 +114,12 @@ class FirCallResolver(
// We need desugaring // We need desugaring
val resultFunctionCall = if (candidate != null && candidate.callInfo != result.info) { val resultFunctionCall = if (candidate != null && candidate.callInfo != result.info) {
functionCall.copy( functionCall.copyAsImplicitInvokeCall {
explicitReceiver = candidate.callInfo.explicitReceiver, explicitReceiver = candidate.callInfo.explicitReceiver
dispatchReceiver = candidate.dispatchReceiverExpression(), dispatchReceiver = candidate.dispatchReceiverExpression()
extensionReceiver = candidate.extensionReceiverExpression(), extensionReceiver = candidate.extensionReceiverExpression()
argumentList = candidate.callInfo.argumentList, argumentList = candidate.callInfo.argumentList
) }
} else { } else {
resultExpression resultExpression
} }