From 93124ee98cfe4e201764339f0ebcb619056537cc Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Mon, 7 Aug 2023 23:24:57 +0200 Subject: [PATCH] KT-60957 [Analysis API] Properly handle source PSI for implicit invoke calls in `KtFirReferenceShortener` For implicit invoke operator calls, there are two instances of `FirResolvedNamedReference`. One of them references `invoke` function and cannot be used to analyze the property access, and the second one has `source == null`. Luckily, the parent of the second reference is `FirPropertyAccessExpression`, which has the correct source ^KT-60957 Fixed --- .../api/fir/components/KtFirReferenceShortener.kt | 15 ++++++++++++++- ...urceModuleReferenceShortenerTestGenerated.java | 6 ++++++ ...urceModuleReferenceShortenerTestGenerated.java | 6 ++++++ .../referenceShortener/variable_invokeOperator.kt | 15 +++++++++++++++ .../variable_invokeOperator.txt | 7 +++++++ 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variable_invokeOperator.kt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variable_invokeOperator.txt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt index b9314cc4b03..65def45640b 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt @@ -985,7 +985,7 @@ private class ElementsToShortenCollector( } private fun processPropertyAccess(firPropertyAccess: FirPropertyAccessExpression) { - val propertyReferenceExpression = (firPropertyAccess.psi as? KtDotQualifiedExpression)?.selectorExpression as? KtNameReferenceExpression ?: return + val propertyReferenceExpression = firPropertyAccess.correspondingNameReference ?: return if (!propertyReferenceExpression.textRange.intersects(selection)) return val qualifiedProperty = propertyReferenceExpression.getQualifiedElement() as? KtDotQualifiedExpression ?: return @@ -1014,6 +1014,19 @@ private class ElementsToShortenCollector( ) } + private val FirPropertyAccessExpression.correspondingNameReference: KtNameReferenceExpression? + get() { + val nameReference = when (val sourcePsi = psi) { + // usual `foo.bar.baz` case + is KtDotQualifiedExpression -> sourcePsi.selectorExpression + + // short `foo` case, or implicit invoke call like `foo.bar.baz()` + else -> sourcePsi + } + + return nameReference as? KtNameReferenceExpression + } + private val FirPropertyAccessExpression.referencedSymbol: FirVariableSymbol<*>? get() = (calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirVariableSymbol<*> diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java index c8425d113d6..514a6234080 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java @@ -460,6 +460,12 @@ public class FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated ext runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variableAssignment_plusOperator.kt"); } + @Test + @TestMetadata("variable_invokeOperator.kt") + public void testVariable_invokeOperator() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variable_invokeOperator.kt"); + } + @Nested @TestMetadata("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses") @TestDataPath("$PROJECT_ROOT") diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java index c83145d6cb6..b413405e88b 100644 --- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java @@ -460,6 +460,12 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenera runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variableAssignment_plusOperator.kt"); } + @Test + @TestMetadata("variable_invokeOperator.kt") + public void testVariable_invokeOperator() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variable_invokeOperator.kt"); + } + @Nested @TestMetadata("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses") @TestDataPath("$PROJECT_ROOT") diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variable_invokeOperator.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variable_invokeOperator.kt new file mode 100644 index 00000000000..326a4a96b47 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variable_invokeOperator.kt @@ -0,0 +1,15 @@ +// FILE: main.kt +package test + +fun usage() { + dependency.foo() +} + +// FILE: dependency.kt +package dependency + +var foo: Foo = Foo() + +class Foo { + operator fun invoke() {} +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variable_invokeOperator.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variable_invokeOperator.txt new file mode 100644 index 00000000000..335b781dc3e --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/variable_invokeOperator.txt @@ -0,0 +1,7 @@ +Before shortening: dependency.foo() +with DO_NOT_SHORTEN: +with SHORTEN_IF_ALREADY_IMPORTED: +with SHORTEN_AND_IMPORT: +[qualifier] dependency.foo() +with SHORTEN_AND_STAR_IMPORT: +[qualifier] dependency.foo()