From a8ae704c0ce5dee622eea2259681d5751222ff87 Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Thu, 28 Oct 2021 16:06:14 -0700 Subject: [PATCH] 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. --- .../api/fir/components/KtFirCallResolver.kt | 13 +++++++--- .../FirResolveCallTestGenerated.java | 24 +++++++++++++++++++ .../javaPropertyGetter_unqualified.kt | 9 +++++++ .../javaPropertyGetter_unqualified.txt | 4 ++++ .../javaPropertySetter_unqualified.kt | 11 +++++++++ .../javaPropertySetter_unqualified.txt | 4 ++++ .../kotlinPropertyGetter_unqualified.kt | 7 ++++++ .../kotlinPropertyGetter_unqualified.txt | 4 ++++ .../kotlinPropertySetter_unqualified.kt | 7 ++++++ .../kotlinPropertySetter_unqualified.txt | 4 ++++ 10 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertyGetter_unqualified.kt create mode 100644 analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertyGetter_unqualified.txt create mode 100644 analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertySetter_unqualified.kt create mode 100644 analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertySetter_unqualified.txt create mode 100644 analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertyGetter_unqualified.kt create mode 100644 analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertyGetter_unqualified.txt create mode 100644 analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertySetter_unqualified.kt create mode 100644 analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertySetter_unqualified.txt 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 1e020d48a9f..e9b81d6cb3f 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 @@ -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) { diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/FirResolveCallTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/FirResolveCallTestGenerated.java index a000e856a45..40490d1c9b3 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/FirResolveCallTestGenerated.java +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/FirResolveCallTestGenerated.java @@ -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 { diff --git a/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertyGetter_unqualified.kt b/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertyGetter_unqualified.kt new file mode 100644 index 00000000000..52b52c5e8e3 --- /dev/null +++ b/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertyGetter_unqualified.kt @@ -0,0 +1,9 @@ +// FILE: call.kt +fun JavaClass.call() { + foo +} + +// FILE: JavaClass.java +class JavaClass { + int getFoo() { return 42; } +} diff --git a/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertyGetter_unqualified.txt b/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertyGetter_unqualified.txt new file mode 100644 index 00000000000..45451cb00e4 --- /dev/null +++ b/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertyGetter_unqualified.txt @@ -0,0 +1,4 @@ +KtFunctionCall: +argumentMapping = { } +targetFunction = /JavaClass.getFoo(: JavaClass): kotlin.Int +substitutor = \ No newline at end of file diff --git a/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertySetter_unqualified.kt b/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertySetter_unqualified.kt new file mode 100644 index 00000000000..e3e0da2189a --- /dev/null +++ b/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertySetter_unqualified.kt @@ -0,0 +1,11 @@ +// FILE: call.kt +fun JavaClass.call() { + foo = 42 +} + +// FILE: JavaClass.java +class JavaClass { + private int foo = -1; + int getFoo() { return foo; } + void setFoo(int v) { foo = v; } +} diff --git a/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertySetter_unqualified.txt b/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertySetter_unqualified.txt new file mode 100644 index 00000000000..9e2a274fba3 --- /dev/null +++ b/analysis/analysis-api/testData/analysisSession/resolveCall/javaPropertySetter_unqualified.txt @@ -0,0 +1,4 @@ +KtFunctionCall: +argumentMapping = { 42 -> (v: kotlin.Int) } +targetFunction = /JavaClass.setFoo(: JavaClass, v: kotlin.Int): kotlin.Unit +substitutor = diff --git a/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertyGetter_unqualified.kt b/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertyGetter_unqualified.kt new file mode 100644 index 00000000000..981c8d1d433 --- /dev/null +++ b/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertyGetter_unqualified.kt @@ -0,0 +1,7 @@ +class A { + val i: Int = 1 +} + +fun A.foo() { + i +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertyGetter_unqualified.txt b/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertyGetter_unqualified.txt new file mode 100644 index 00000000000..6115b7389b2 --- /dev/null +++ b/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertyGetter_unqualified.txt @@ -0,0 +1,4 @@ +KtFunctionCall: +argumentMapping = { } +targetFunction = (): kotlin.Int +substitutor = \ No newline at end of file diff --git a/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertySetter_unqualified.kt b/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertySetter_unqualified.kt new file mode 100644 index 00000000000..281e1366c12 --- /dev/null +++ b/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertySetter_unqualified.kt @@ -0,0 +1,7 @@ +class A { + var i: Int = 1 +} + +fun A.foo() { + i = 1 +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertySetter_unqualified.txt b/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertySetter_unqualified.txt new file mode 100644 index 00000000000..fb443f6ff52 --- /dev/null +++ b/analysis/analysis-api/testData/analysisSession/resolveCall/kotlinPropertySetter_unqualified.txt @@ -0,0 +1,4 @@ +KtFunctionCall: +argumentMapping = { 1 -> (value: kotlin.Int) } +targetFunction = (value: kotlin.Int): kotlin.Unit +substitutor = \ No newline at end of file