diff --git a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated.java b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated.java index 534d688b779..31caf3d3f65 100644 --- a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated.java +++ b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/callResolver/Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated.java @@ -1019,6 +1019,12 @@ public class Fe10IdeNormalAnalysisSourceModuleResolveCallTestGenerated extends A runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incorrectCodeJavaDeclaration.kt"); } + @Test + @TestMetadata("invalidImplicitInvoke.kt") + public void testInvalidImplicitInvoke() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/invalidImplicitInvoke.kt"); + } + @Test @TestMetadata("typeParameterAsValue.kt") public void testTypeParameterAsValue() throws Exception { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt index 45d73b5a51e..ca92dfe7a6d 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt @@ -404,16 +404,25 @@ internal class KtFirCallResolver( // the `invoke` member function. In this case, we use the `calleeExpression` in the `KtCallExpression` as the PSI // representation of this receiver. Caller can then use this PSI for further call resolution, which is implemented by the // parameter `resolveCalleeExpressionOfFunctionCall` in `toKtCallInfo`. - val explicitReceiverPsi = when (psi) { - is KtQualifiedExpression -> (psi.selectorExpression as KtCallExpression).calleeExpression - is KtCallExpression -> psi.calleeExpression + var explicitReceiverPsi = when (psi) { + is KtQualifiedExpression -> { + psi.selectorExpression + ?: errorWithAttachment("missing selectorExpression in PSI ${psi::class} for FirImplicitInvokeCall") { + withPsiEntry("psi", psi, analysisSession::getModule) + } + } + is KtExpression -> psi else -> errorWithAttachment("unexpected PSI ${psi::class} for FirImplicitInvokeCall") { withPsiEntry("psi", psi, analysisSession::getModule) } } - ?: errorWithAttachment("missing calleeExpression in PSI ${psi::class} for FirImplicitInvokeCall") { - withPsiEntry("psi", psi, analysisSession::getModule) - } + + if (explicitReceiverPsi is KtCallExpression) { + explicitReceiverPsi = explicitReceiverPsi.calleeExpression + ?: errorWithAttachment("missing calleeExpression in PSI ${psi::class} for FirImplicitInvokeCall") { + withPsiEntry("psi", psi, analysisSession::getModule) + } + } // Specially handle @ExtensionFunctionType if (dispatchReceiver?.resolvedType?.isExtensionFunctionType == true) { @@ -434,10 +443,14 @@ internal class KtFirCallResolver( } dispatchReceiverValue = KtExplicitReceiverValue(explicitReceiverPsi, dispatchReceiver.resolvedType.asKtType(), false, token) - if (firstArgIsExtensionReceiver) { - extensionReceiverValue = (fir as FirFunctionCall).arguments.firstOrNull()?.toKtReceiverValue() + extensionReceiverValue = if (firstArgIsExtensionReceiver) { + when (fir) { + is FirFunctionCall -> fir.arguments.firstOrNull()?.toKtReceiverValue() + is FirPropertyAccessExpression -> fir.explicitReceiver?.toKtReceiverValue() + else -> null + } } else { - extensionReceiverValue = extensionReceiver?.toKtReceiverValue() + extensionReceiver?.toKtReceiverValue() } } @@ -557,7 +570,7 @@ internal class KtFirCallResolver( partiallyAppliedSymbol as KtPartiallyAppliedFunctionSymbol, LinkedHashMap(), fir.toTypeArgumentsMapping(partiallyAppliedSymbol), - _isImplicitInvoke = false, + isImplicitInvoke, ) } } diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated.java index 1199816449e..cb323ee6d93 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/callResolver/FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated.java @@ -1019,6 +1019,12 @@ public class FirIdeNormalAnalysisSourceModuleResolveCallTestGenerated extends Ab runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incorrectCodeJavaDeclaration.kt"); } + @Test + @TestMetadata("invalidImplicitInvoke.kt") + public void testInvalidImplicitInvoke() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/invalidImplicitInvoke.kt"); + } + @Test @TestMetadata("typeParameterAsValue.kt") public void testTypeParameterAsValue() throws Exception { diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated.java index 393a242ffca..2bf7ebca6a0 100644 --- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated.java +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/callResolver/FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated.java @@ -1019,6 +1019,12 @@ public class FirStandaloneNormalAnalysisSourceModuleResolveCallTestGenerated ext runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/incorrectCodeJavaDeclaration.kt"); } + @Test + @TestMetadata("invalidImplicitInvoke.kt") + public void testInvalidImplicitInvoke() throws Exception { + runTest("analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/invalidImplicitInvoke.kt"); + } + @Test @TestMetadata("typeParameterAsValue.kt") public void testTypeParameterAsValue() throws Exception { diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/invalidImplicitInvoke.kt b/analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/invalidImplicitInvoke.kt new file mode 100644 index 00000000000..535fc30dc9f --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/invalidImplicitInvoke.kt @@ -0,0 +1,4 @@ +// IGNORE_FE10 +fun f(s: String, action: (String.() -> Unit)?) { + s.action?.let { it() } +} diff --git a/analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/invalidImplicitInvoke.txt b/analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/invalidImplicitInvoke.txt new file mode 100644 index 00000000000..776312b50f9 --- /dev/null +++ b/analysis/analysis-api/testData/components/callResolver/resolveCall/invalidCode/invalidImplicitInvoke.txt @@ -0,0 +1,30 @@ +KtErrorCallInfo: + candidateCalls = [ + KtSimpleFunctionCall: + isImplicitInvoke = true + partiallyAppliedSymbol = KtPartiallyAppliedSymbol: + dispatchReceiver = KtExplicitReceiverValue: + expression = action + isSafeNavigation = false + type = @ExtensionFunctionType kotlin.Function1? + extensionReceiver = KtExplicitReceiverValue: + expression = s + isSafeNavigation = false + type = kotlin.String + signature = KtFunctionLikeSignature: + receiverType = null + returnType = kotlin.Unit + symbol = kotlin/Function1.invoke(: kotlin.Function1, p1: P1): R + valueParameters = [ + KtVariableLikeSignature: + name = p1 + receiverType = null + returnType = kotlin.String + symbol = p1: P1 + callableIdIfNonLocal = null + ] + callableIdIfNonLocal = kotlin/Function1.invoke + typeArgumentsMapping = {} + argumentMapping = {} + ] + diagnostic = ERROR \ No newline at end of file