diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt index 15da526d4d4..140ac09deda 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/FirUtils.kt @@ -28,21 +28,6 @@ import org.jetbrains.kotlin.psi.KtNameReferenceExpression import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.addToStdlib.safeAs -/** - * Checks if the function call is an implicit invoke call with a simple qualified receiver, or looks like it. - * - * For example, `foo()` and `foo.bar()` have simple qualified receivers, while `foo!!()`, `{}()` and `(foo ?: bar)()` - don't. - * - * @return `true` if the function call has a simple qualified receiver and is an implicit invoke call, - * or looks like it and resolves to the `invoke` function. - */ -fun FirFunctionCall.isImplicitFunctionCall(): Boolean { - if (extensionReceiver !is FirQualifiedAccessExpression && dispatchReceiver !is FirQualifiedAccessExpression) return false - - return this is FirImplicitInvokeCall || - calleeReference.getCandidateSymbols().any(FirBasedSymbol<*>::isInvokeFunction) -} - /** * Returns `true` if the symbol is for a function named `invoke`. */ diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt index fc3cd029df2..69ca1314f6c 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt @@ -340,19 +340,13 @@ internal object FirReferenceResolveHelper { if (expression is KtLabelReferenceExpression && fir is FirPropertyAccessExpression && fir.calleeReference is FirSuperReference) { return listOfNotNull((fir.dispatchReceiver.typeRef as? FirResolvedTypeRef)?.toTargetSymbol(session, symbolBuilder)) } - val calleeReference = - if (fir is FirFunctionCall && - fir.isImplicitFunctionCall() && - expression is KtNameReferenceExpression - ) { - // we are resolving implicit invoke call, like - // fun foo(a: () -> Unit) { - // a() - // } - val receiver = - fir.dispatchReceiver as? FirQualifiedAccessExpression ?: fir.extensionReceiver as FirQualifiedAccessExpression - receiver.calleeReference - } else fir.calleeReference + val implicitInvokeReceiver = if (fir is FirImplicitInvokeCall) { + fir.explicitReceiver as? FirQualifiedAccessExpression + } else { + null + } + val calleeReference = implicitInvokeReceiver?.calleeReference ?: fir.calleeReference + return calleeReference.toTargetSymbol(session, symbolBuilder, isInLabelReference = expression is KtLabelReferenceExpression) } diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirLibrarySourceReferenceResolveTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirLibrarySourceReferenceResolveTestGenerated.java index 2629b03f648..e14e7ff1929 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirLibrarySourceReferenceResolveTestGenerated.java +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirLibrarySourceReferenceResolveTestGenerated.java @@ -142,6 +142,18 @@ public class FirLibrarySourceReferenceResolveTestGenerated extends AbstractRefer runTest("analysis/analysis-api/testData/referenceResolve/EnumValues.kt"); } + @Test + @TestMetadata("explicitFunctionalInterfaceInvoke_globalVal.kt") + public void testExplicitFunctionalInterfaceInvoke_globalVal() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_globalVal.kt"); + } + + @Test + @TestMetadata("explicitFunctionalInterfaceInvoke_parameter.kt") + public void testExplicitFunctionalInterfaceInvoke_parameter() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_parameter.kt"); + } + @Test @TestMetadata("ExternalCompanionObject.kt") public void testExternalCompanionObject() throws Exception { @@ -508,6 +520,12 @@ public class FirLibrarySourceReferenceResolveTestGenerated extends AbstractRefer runTest("analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor3.kt"); } + @Test + @TestMetadata("TopLevelObjectVsLocalClassConstructor4.kt") + public void testTopLevelObjectVsLocalClassConstructor4() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor4.kt"); + } + @Test @TestMetadata("TopLevelObjectVsLocalClassQualifier.kt") public void testTopLevelObjectVsLocalClassQualifier() throws Exception { diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirSourceReferenceResolveTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirSourceReferenceResolveTestGenerated.java index c9f9c1bb1ae..66976ba111e 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirSourceReferenceResolveTestGenerated.java +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirSourceReferenceResolveTestGenerated.java @@ -142,6 +142,18 @@ public class FirSourceReferenceResolveTestGenerated extends AbstractReferenceRes runTest("analysis/analysis-api/testData/referenceResolve/EnumValues.kt"); } + @Test + @TestMetadata("explicitFunctionalInterfaceInvoke_globalVal.kt") + public void testExplicitFunctionalInterfaceInvoke_globalVal() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_globalVal.kt"); + } + + @Test + @TestMetadata("explicitFunctionalInterfaceInvoke_parameter.kt") + public void testExplicitFunctionalInterfaceInvoke_parameter() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_parameter.kt"); + } + @Test @TestMetadata("ExternalCompanionObject.kt") public void testExternalCompanionObject() throws Exception { @@ -508,6 +520,12 @@ public class FirSourceReferenceResolveTestGenerated extends AbstractReferenceRes runTest("analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor3.kt"); } + @Test + @TestMetadata("TopLevelObjectVsLocalClassConstructor4.kt") + public void testTopLevelObjectVsLocalClassConstructor4() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor4.kt"); + } + @Test @TestMetadata("TopLevelObjectVsLocalClassQualifier.kt") public void testTopLevelObjectVsLocalClassQualifier() throws Exception { diff --git a/analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor3.kt b/analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor3.kt index c019a32b517..2d193ba432a 100644 --- a/analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor3.kt +++ b/analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor3.kt @@ -1,5 +1,3 @@ -// IGNORE_FIR - package test object Conflict { diff --git a/analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor4.kt b/analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor4.kt new file mode 100644 index 00000000000..99897beaaa2 --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor4.kt @@ -0,0 +1,12 @@ +package test + +object Conflict + +operator fun Conflict.invoke() {} + +fun test() { + class Conflict(i: Int) + + Conflict() +} + diff --git a/analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor4.txt b/analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor4.txt new file mode 100644 index 00000000000..a8a48eb0432 --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/TopLevelObjectVsLocalClassConstructor4.txt @@ -0,0 +1,2 @@ +Resolved to: +0: (in test) operator fun test.Conflict.invoke() diff --git a/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_globalVal.kt b/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_globalVal.kt new file mode 100644 index 00000000000..9529b77801c --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_globalVal.kt @@ -0,0 +1,9 @@ +fun interface A { + operator fun invoke() +} + +val globalA: A = A {} + +fun foo() { + globalA.invoke() +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_globalVal.txt b/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_globalVal.txt new file mode 100644 index 00000000000..0f2a2440d5c --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_globalVal.txt @@ -0,0 +1,2 @@ +Resolved to: +0: (in A) operator fun invoke() diff --git a/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_parameter.kt b/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_parameter.kt new file mode 100644 index 00000000000..9b86b24818b --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_parameter.kt @@ -0,0 +1,7 @@ +fun interface A { + operator fun invoke() +} + +fun foo(param: A) { + param.invoke() +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_parameter.txt b/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_parameter.txt new file mode 100644 index 00000000000..0f2a2440d5c --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/explicitFunctionalInterfaceInvoke_parameter.txt @@ -0,0 +1,2 @@ +Resolved to: +0: (in A) operator fun invoke()