From 22830cf159b265d94938b0f9a4f9786f6e95b17d Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Mon, 21 Mar 2022 18:46:50 +0400 Subject: [PATCH] [FIR IDE] Fix resolving sugared compound operators (like +=, -=) ^KTIJ-21374 Fixed --- .../references/FirReferenceResolveHelper.kt | 30 +++++++++++++++---- ...rySourceReferenceResolveTestGenerated.java | 18 +++++++++++ ...irSourceReferenceResolveTestGenerated.java | 18 +++++++++++ .../referenceResolve/PlusAssignByHand.kt | 13 ++++++++ .../referenceResolve/PlusAssignOperator.kt | 11 +++++++ .../referenceResolve/PlusAssignOperator.txt | 2 ++ .../PlusAssignViaPlusOperator.kt | 12 ++++++++ .../PlusAssignViaPlusOperator.txt | 2 ++ 8 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 analysis/analysis-api/testData/referenceResolve/PlusAssignByHand.kt create mode 100644 analysis/analysis-api/testData/referenceResolve/PlusAssignOperator.kt create mode 100644 analysis/analysis-api/testData/referenceResolve/PlusAssignOperator.txt create mode 100644 analysis/analysis-api/testData/referenceResolve/PlusAssignViaPlusOperator.kt create mode 100644 analysis/analysis-api/testData/referenceResolve/PlusAssignViaPlusOperator.txt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt index 69ca1314f6c..5adf7c2db67 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt @@ -7,7 +7,10 @@ package org.jetbrains.kotlin.idea.references import com.intellij.psi.tree.TokenSet import org.jetbrains.kotlin.KtFakeSourceElementKind -import org.jetbrains.kotlin.analysis.api.fir.* +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.getCandidateSymbols 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 @@ -201,7 +204,7 @@ internal object FirReferenceResolveHelper { } is FirReturnExpression -> getSymbolsByReturnExpression(expression, fir, symbolBuilder) is FirErrorNamedReference -> getSymbolsByErrorNamedReference(fir, symbolBuilder) - is FirVariableAssignment -> getSymbolsByVariableAssignment(fir, session, symbolBuilder) + is FirVariableAssignment -> getSymbolsByVariableAssignment(fir, expression, session, symbolBuilder) is FirResolvedNamedReference -> getSymbolByResolvedNameReference(fir, expression, analysisSession, session, symbolBuilder) is FirDelegatedConstructorCall -> getSymbolByDelegatedConstructorCall(expression, adjustedResolutionExpression, fir, session, symbolBuilder) @@ -268,12 +271,29 @@ internal object FirReferenceResolveHelper { else -> false } - @OptIn(ExperimentalStdlibApi::class) private fun getSymbolsByVariableAssignment( fir: FirVariableAssignment, + expression: KtSimpleNameExpression, session: FirSession, - symbolBuilder: KtSymbolByFirBuilder - ): Collection = fir.calleeReference.toTargetSymbol(session, symbolBuilder) + symbolBuilder: KtSymbolByFirBuilder, + ): Collection { + if (expression is KtNameReferenceExpression) { + return fir.calleeReference.toTargetSymbol(session, symbolBuilder) + } + + val assignmentRValue = fir.rValue + if (expression is KtOperationReferenceExpression && + assignmentRValue.source?.kind is KtFakeSourceElementKind.DesugaredCompoundAssignment + ) { + require(assignmentRValue is FirResolvable) { + "Rvalue of desugared compound assignment should be resolvable, but it was ${assignmentRValue::class}" + } + + return assignmentRValue.calleeReference.toTargetSymbol(session, symbolBuilder) + } + + return emptyList() + } private fun getSymbolsByNameArgumentExpression( expression: KtSimpleNameExpression, diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirLibrarySourceReferenceResolveTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirLibrarySourceReferenceResolveTestGenerated.java index e14e7ff1929..5b5e025ebf5 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirLibrarySourceReferenceResolveTestGenerated.java +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirLibrarySourceReferenceResolveTestGenerated.java @@ -334,6 +334,24 @@ public class FirLibrarySourceReferenceResolveTestGenerated extends AbstractRefer runTest("analysis/analysis-api/testData/referenceResolve/parameterByName.kt"); } + @Test + @TestMetadata("PlusAssignByHand.kt") + public void testPlusAssignByHand() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/PlusAssignByHand.kt"); + } + + @Test + @TestMetadata("PlusAssignOperator.kt") + public void testPlusAssignOperator() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/PlusAssignOperator.kt"); + } + + @Test + @TestMetadata("PlusAssignViaPlusOperator.kt") + public void testPlusAssignViaPlusOperator() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/PlusAssignViaPlusOperator.kt"); + } + @Test @TestMetadata("ReferenceInClassWhereConstraint.kt") public void testReferenceInClassWhereConstraint() throws Exception { diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirSourceReferenceResolveTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirSourceReferenceResolveTestGenerated.java index 66976ba111e..a5462183219 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirSourceReferenceResolveTestGenerated.java +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/FirSourceReferenceResolveTestGenerated.java @@ -334,6 +334,24 @@ public class FirSourceReferenceResolveTestGenerated extends AbstractReferenceRes runTest("analysis/analysis-api/testData/referenceResolve/parameterByName.kt"); } + @Test + @TestMetadata("PlusAssignByHand.kt") + public void testPlusAssignByHand() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/PlusAssignByHand.kt"); + } + + @Test + @TestMetadata("PlusAssignOperator.kt") + public void testPlusAssignOperator() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/PlusAssignOperator.kt"); + } + + @Test + @TestMetadata("PlusAssignViaPlusOperator.kt") + public void testPlusAssignViaPlusOperator() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/PlusAssignViaPlusOperator.kt"); + } + @Test @TestMetadata("ReferenceInClassWhereConstraint.kt") public void testReferenceInClassWhereConstraint() throws Exception { diff --git a/analysis/analysis-api/testData/referenceResolve/PlusAssignByHand.kt b/analysis/analysis-api/testData/referenceResolve/PlusAssignByHand.kt new file mode 100644 index 00000000000..75f42e725b3 --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/PlusAssignByHand.kt @@ -0,0 +1,13 @@ +// UNRESOLVED_REFERENCE +package test + +interface Foo + +interface WithOperator { + operator fun plus(f: Foo): WithOperator +} + +fun test(withOperator: WithOperator, foo: Foo) { + var variable = withOperator + variable = variable + foo +} diff --git a/analysis/analysis-api/testData/referenceResolve/PlusAssignOperator.kt b/analysis/analysis-api/testData/referenceResolve/PlusAssignOperator.kt new file mode 100644 index 00000000000..fe0663360f1 --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/PlusAssignOperator.kt @@ -0,0 +1,11 @@ +package test + +interface Foo + +interface WithOperator { + operator fun plusAssign(f: Foo) +} + +fun test(withOperator: WithOperator, foo: Foo) { + withOperator += foo +} diff --git a/analysis/analysis-api/testData/referenceResolve/PlusAssignOperator.txt b/analysis/analysis-api/testData/referenceResolve/PlusAssignOperator.txt new file mode 100644 index 00000000000..c2e0b636f1a --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/PlusAssignOperator.txt @@ -0,0 +1,2 @@ +Resolved to: +0: (in test.WithOperator) operator fun plusAssign(f: test.Foo) diff --git a/analysis/analysis-api/testData/referenceResolve/PlusAssignViaPlusOperator.kt b/analysis/analysis-api/testData/referenceResolve/PlusAssignViaPlusOperator.kt new file mode 100644 index 00000000000..e68ca5662dc --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/PlusAssignViaPlusOperator.kt @@ -0,0 +1,12 @@ +package test + +interface Foo + +interface WithOperator { + operator fun plus(f: Foo): WithOperator +} + +fun test(withOperator: WithOperator, foo: Foo) { + var variable = withOperator + variable += foo +} diff --git a/analysis/analysis-api/testData/referenceResolve/PlusAssignViaPlusOperator.txt b/analysis/analysis-api/testData/referenceResolve/PlusAssignViaPlusOperator.txt new file mode 100644 index 00000000000..9d04c74e96f --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/PlusAssignViaPlusOperator.txt @@ -0,0 +1,2 @@ +Resolved to: +0: (in test.WithOperator) operator fun plus(f: test.Foo): test.WithOperator