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