FIR IDE: fix property accessor resolution

For property access with implicit receiver, the resolved fir is a
FirPropertyAccessExpression and hence we need to handle it in
KtFirCallResolver.
This commit is contained in:
Tianyu Geng
2021-10-28 16:06:14 -07:00
committed by Ilya Kirillov
parent 1a22124c02
commit a8ae704c0c
10 changed files with 84 additions and 3 deletions
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.analysis.api.withValidityAssertion
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.realPsi
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
@@ -84,6 +85,9 @@ internal class KtFirCallResolver(
}
return KtFunctionCall(ktArgumentMapping, target, KtSubstitutor.Empty(token), token)
}
is FirPropertyAccessExpression -> {
KtFunctionCall(LinkedHashMap(), fir.calleeReference.createCallTarget() ?: return null, KtSubstitutor.Empty(token), token)
}
else -> return null
}
}
@@ -255,7 +259,7 @@ internal class KtFirCallResolver(
private fun FirReference.createCallTarget(): KtCallTarget? {
return when (this) {
is FirSuperReference -> createCallTarget(source)
is FirResolvedNamedReference -> getKtFunctionOrConstructorSymbol()?.let { KtSuccessCallTarget(it, token) }
is FirResolvedNamedReference -> getKtFunctionLikeSymbol()?.let { KtSuccessCallTarget(it, token) }
is FirErrorNamedReference -> createErrorCallTarget(source)
is FirErrorReferenceWithCandidate -> createErrorCallTarget(source)
is FirSimpleNamedReference ->
@@ -334,8 +338,11 @@ internal class KtFirCallResolver(
source?.let { diagnostic.asKtDiagnostic(it, qualifiedAccessSource, diagnosticCache) }
?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token), token)
private fun FirResolvedNamedReference.getKtFunctionOrConstructorSymbol(): KtFunctionLikeSymbol? =
resolvedSymbol.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol
private fun FirResolvedNamedReference.getKtFunctionLikeSymbol(): KtFunctionLikeSymbol? {
val fir = resolvedSymbol.fir
val targetFir = if (fir is FirProperty) fir.getter else fir
return targetFir?.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol
}
private fun FirSuperReference.createCallTarget(qualifiedAccessSource: KtSourceElement?): KtCallTarget? =
when (val type = superTypeRef.coneType) {
@@ -324,6 +324,12 @@ public class FirResolveCallTestGenerated extends AbstractFirResolveCallTest {
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertyGetter.kt");
}
@Test
@TestMetadata("javaPropertyGetter_unqualified.kt")
public void testJavaPropertyGetter_unqualified() throws Exception {
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertyGetter_unqualified.kt");
}
@Test
@TestMetadata("javaPropertyNestedGetter.kt")
public void testJavaPropertyNestedGetter() throws Exception {
@@ -342,12 +348,24 @@ public class FirResolveCallTestGenerated extends AbstractFirResolveCallTest {
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertySetterIncomplete.kt");
}
@Test
@TestMetadata("javaPropertySetter_unqualified.kt")
public void testJavaPropertySetter_unqualified() throws Exception {
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertySetter_unqualified.kt");
}
@Test
@TestMetadata("kotlinPropertyGetter.kt")
public void testKotlinPropertyGetter() throws Exception {
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertyGetter.kt");
}
@Test
@TestMetadata("kotlinPropertyGetter_unqualified.kt")
public void testKotlinPropertyGetter_unqualified() throws Exception {
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertyGetter_unqualified.kt");
}
@Test
@TestMetadata("kotlinPropertyNestedGetter.kt")
public void testKotlinPropertyNestedGetter() throws Exception {
@@ -360,6 +378,12 @@ public class FirResolveCallTestGenerated extends AbstractFirResolveCallTest {
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertySetter.kt");
}
@Test
@TestMetadata("kotlinPropertySetter_unqualified.kt")
public void testKotlinPropertySetter_unqualified() throws Exception {
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertySetter_unqualified.kt");
}
@Test
@TestMetadata("memberFunctionCallWithTypeArgument.kt")
public void testMemberFunctionCallWithTypeArgument() throws Exception {
@@ -0,0 +1,9 @@
// FILE: call.kt
fun JavaClass.call() {
<expr>foo</expr>
}
// FILE: JavaClass.java
class JavaClass {
int getFoo() { return 42; }
}
@@ -0,0 +1,4 @@
KtFunctionCall:
argumentMapping = { }
targetFunction = /JavaClass.getFoo(<dispatch receiver>: JavaClass): kotlin.Int
substitutor = <empty substitutor>
@@ -0,0 +1,11 @@
// FILE: call.kt
fun JavaClass.call() {
<expr>foo</expr> = 42
}
// FILE: JavaClass.java
class JavaClass {
private int foo = -1;
int getFoo() { return foo; }
void setFoo(int v) { foo = v; }
}
@@ -0,0 +1,4 @@
KtFunctionCall:
argumentMapping = { 42 -> (v: kotlin.Int) }
targetFunction = /JavaClass.setFoo(<dispatch receiver>: JavaClass, v: kotlin.Int): kotlin.Unit
substitutor = <empty substitutor>
@@ -0,0 +1,7 @@
class A {
val i: Int = 1
}
fun A.foo() {
<expr>i</expr>
}
@@ -0,0 +1,4 @@
KtFunctionCall:
argumentMapping = { }
targetFunction = <getter>(): kotlin.Int
substitutor = <empty substitutor>
@@ -0,0 +1,7 @@
class A {
var i: Int = 1
}
fun A.foo() {
<expr>i</expr> = 1
}
@@ -0,0 +1,4 @@
KtFunctionCall:
argumentMapping = { 1 -> (value: kotlin.Int) }
targetFunction = <setter>(value: kotlin.Int): kotlin.Unit
substitutor = <empty substitutor>