From 0d966ec65aa5774ee17d5efa0474d0abecdebae7 Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Fri, 15 Oct 2021 10:01:25 -0700 Subject: [PATCH] FIR IDE: resolve implicit invoke to callable property --- .../references/FirReferenceResolveHelper.kt | 28 ++++++++++++++----- .../fir/FirReferenceResolveTestGenerated.java | 18 ++++++++++++ .../implicitExtensionInvoke.kt | 5 ++++ .../implicitExtensionInvoke.txt | 2 ++ .../implicitFunctionInvoke.kt | 3 ++ .../implicitFunctionInvoke.txt | 2 ++ .../implicitFunctionalInterfaceInvoke.kt | 6 ++++ .../implicitFunctionalInterfaceInvoke.txt | 2 ++ 8 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 analysis/analysis-api/testData/referenceResolve/implicitExtensionInvoke.kt create mode 100644 analysis/analysis-api/testData/referenceResolve/implicitExtensionInvoke.txt create mode 100644 analysis/analysis-api/testData/referenceResolve/implicitFunctionInvoke.kt create mode 100644 analysis/analysis-api/testData/referenceResolve/implicitFunctionInvoke.txt create mode 100644 analysis/analysis-api/testData/referenceResolve/implicitFunctionalInterfaceInvoke.kt create mode 100644 analysis/analysis-api/testData/referenceResolve/implicitFunctionalInterfaceInvoke.txt 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 97bdc759fa8..63952ee9593 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 @@ -6,6 +6,11 @@ package org.jetbrains.kotlin.idea.references import com.intellij.psi.tree.TokenSet +import org.jetbrains.kotlin.analysis.api.fir.* +import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirPackageSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.buildImport @@ -26,13 +31,9 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols -import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir -import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.analysis.api.fir.buildSymbol -import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirPackageSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.ClassId @@ -186,7 +187,7 @@ internal object FirReferenceResolveHelper { is FirErrorNamedReference -> getSymbolsByErrorNamedReference(fir, symbolBuilder) is FirVariableAssignment -> getSymbolsByVariableAssignment(fir, session, symbolBuilder) is FirResolvedNamedReference -> getSymbolByResolvedNameReference(fir, expression, analysisSession, session, symbolBuilder) - is FirResolvable -> getSymbolsByResolvable(fir, session, symbolBuilder) + is FirResolvable -> getSymbolsByResolvable(fir, expression, session, symbolBuilder) is FirNamedArgumentExpression -> getSymbolsByNameArgumentExpression(expression, analysisSession, symbolBuilder) else -> handleUnknownFirElement(expression, analysisSession, session, symbolBuilder) } @@ -211,7 +212,7 @@ internal object FirReferenceResolveHelper { if (parentAsCall != null) { val firResolvable = parentAsCall.getOrBuildFirSafe(analysisSession.firResolveState) if (firResolvable != null) { - return getSymbolsByResolvable(firResolvable, session, symbolBuilder) + return getSymbolsByResolvable(firResolvable, expression, session, symbolBuilder) } } return fir.toTargetSymbol(session, symbolBuilder) @@ -284,10 +285,23 @@ internal object FirReferenceResolveHelper { private fun getSymbolsByResolvable( fir: FirResolvable, + expression: KtSimpleNameExpression, session: FirSession, symbolBuilder: KtSymbolByFirBuilder ): Collection { - val calleeReference = fir.calleeReference + 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 return calleeReference.toTargetSymbol(session, symbolBuilder) } diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirReferenceResolveTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirReferenceResolveTestGenerated.java index 0b20771dd78..f84d000965d 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirReferenceResolveTestGenerated.java +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirReferenceResolveTestGenerated.java @@ -216,6 +216,24 @@ public class FirReferenceResolveTestGenerated extends AbstractFirReferenceResolv runTest("analysis/analysis-api/testData/referenceResolve/GenericTypeInFunctionParameter.kt"); } + @Test + @TestMetadata("implicitExtensionInvoke.kt") + public void testImplicitExtensionInvoke() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/implicitExtensionInvoke.kt"); + } + + @Test + @TestMetadata("implicitFunctionInvoke.kt") + public void testImplicitFunctionInvoke() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/implicitFunctionInvoke.kt"); + } + + @Test + @TestMetadata("implicitFunctionalInterfaceInvoke.kt") + public void testImplicitFunctionalInterfaceInvoke() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/implicitFunctionalInterfaceInvoke.kt"); + } + @Test @TestMetadata("ImportFromRootScope.kt") public void testImportFromRootScope() throws Exception { diff --git a/analysis/analysis-api/testData/referenceResolve/implicitExtensionInvoke.kt b/analysis/analysis-api/testData/referenceResolve/implicitExtensionInvoke.kt new file mode 100644 index 00000000000..b455a075c4f --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/implicitExtensionInvoke.kt @@ -0,0 +1,5 @@ +fun foo(a: Int) { + a() +} + +operator fun Int.invoke() {} \ No newline at end of file diff --git a/analysis/analysis-api/testData/referenceResolve/implicitExtensionInvoke.txt b/analysis/analysis-api/testData/referenceResolve/implicitExtensionInvoke.txt new file mode 100644 index 00000000000..d0f5675993c --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/implicitExtensionInvoke.txt @@ -0,0 +1,2 @@ +Resolved to: +0: value-parameter a: kotlin.Int diff --git a/analysis/analysis-api/testData/referenceResolve/implicitFunctionInvoke.kt b/analysis/analysis-api/testData/referenceResolve/implicitFunctionInvoke.kt new file mode 100644 index 00000000000..f985fa78de0 --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/implicitFunctionInvoke.kt @@ -0,0 +1,3 @@ +fun foo(a: () -> Unit) { + a() +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/referenceResolve/implicitFunctionInvoke.txt b/analysis/analysis-api/testData/referenceResolve/implicitFunctionInvoke.txt new file mode 100644 index 00000000000..85a29b4d96c --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/implicitFunctionInvoke.txt @@ -0,0 +1,2 @@ +Resolved to: +0: value-parameter a: () -> kotlin.Unit diff --git a/analysis/analysis-api/testData/referenceResolve/implicitFunctionalInterfaceInvoke.kt b/analysis/analysis-api/testData/referenceResolve/implicitFunctionalInterfaceInvoke.kt new file mode 100644 index 00000000000..56f54bf5960 --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/implicitFunctionalInterfaceInvoke.kt @@ -0,0 +1,6 @@ +fun interface A { + operator fun invoke() +} +fun foo(a: A) { + a() +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/referenceResolve/implicitFunctionalInterfaceInvoke.txt b/analysis/analysis-api/testData/referenceResolve/implicitFunctionalInterfaceInvoke.txt new file mode 100644 index 00000000000..0577081ccfb --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/implicitFunctionalInterfaceInvoke.txt @@ -0,0 +1,2 @@ +Resolved to: +0: value-parameter a: A