FIR IDE: resolve implicit invoke to callable property

This commit is contained in:
Tianyu Geng
2021-10-15 10:01:25 -07:00
committed by Space
parent b27b202c28
commit 0d966ec65a
8 changed files with 59 additions and 7 deletions
@@ -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<FirResolvable>(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<KtSymbol> {
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) {
// <expression>a</expression>()
// }
val receiver =
fir.dispatchReceiver as? FirQualifiedAccessExpression ?: fir.extensionReceiver as FirQualifiedAccessExpression
receiver.calleeReference
} else fir.calleeReference
return calleeReference.toTargetSymbol(session, symbolBuilder)
}
@@ -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 {
@@ -0,0 +1,5 @@
fun foo(a: Int) {
<caret>a()
}
operator fun Int.invoke() {}
@@ -0,0 +1,2 @@
Resolved to:
0: value-parameter a: kotlin.Int
@@ -0,0 +1,3 @@
fun foo(a: () -> Unit) {
<caret>a()
}
@@ -0,0 +1,2 @@
Resolved to:
0: value-parameter a: () -> kotlin.Unit
@@ -0,0 +1,6 @@
fun interface A {
operator fun invoke()
}
fun foo(a: A) {
<caret>a()
}
@@ -0,0 +1,2 @@
Resolved to:
0: value-parameter a: A