Preserve origins when desugaring augmented array assignments

^KT-63827: Fixed
This commit is contained in:
vladislav.grechko
2023-12-20 17:15:40 +00:00
committed by Space Team
parent eb790732fd
commit 77d0d1073e
27 changed files with 259 additions and 161 deletions
@@ -129,6 +129,7 @@ internal open class FirElementsRecorder : FirVisitor<Unit, MutableMap<KtElement,
it.kind == KtFakeSourceElementKind.DesugaredPostfixNameReference ||
it.kind == KtFakeSourceElementKind.SmartCastExpression ||
it.kind == KtFakeSourceElementKind.DanglingModifierList ||
it.isSourceForArrayAugmentedAssign(element) ||
it.isSourceForCompoundAccess(element)
}.psi as? KtElement
?: return
@@ -155,6 +156,12 @@ internal open class FirElementsRecorder : FirVisitor<Unit, MutableMap<KtElement,
}
}
private fun KtSourceElement.isSourceForArrayAugmentedAssign(fir: FirElement) =
// after desugaring, we also have FirBlock with the same source element.
// We need to filter it out to map this source element to set/plusAssign call, so we check `is FirFunctionCall`
(kind is KtFakeSourceElementKind.DesugaredArrayAugmentedAssign) && fir is FirFunctionCall
private fun FirElement.isReadInCompoundCall(): Boolean {
if (this is FirPropertyAccessExpression) return true
if (this !is FirFunctionCall) return false
@@ -0,0 +1,12 @@
class Foo {
companion object {
operator fun get(n: Int): Int = 42
}
}
private operator fun Any.set(i: Int, value: Int) {}
fun usageFoo() {
<expr>Foo[1] -= 5</expr>
}
@@ -0,0 +1,37 @@
KT element: KtBinaryExpression
FIR element: FirFunctionCallImpl
FIR source kind: DesugaredArrayMinusAssign
FIR element rendered:
R|<local>/<array>|.R|/set|(R|<local>/<index_0>|, R|<local>/<array>|.R|/Foo.Companion.get|(R|<local>/<index_0>|).R|kotlin/Int.minus|(Int(5)))
FIR FILE:
FILE: [ResolvedTo(IMPORTS)] arrayMinusAssignOperatorsInVariousScopes.kt
public final [ResolvedTo(STATUS)] class Foo : R|kotlin/Any| {
public [ResolvedTo(STATUS)] [ContainingClassKey=Foo] constructor(): R|Foo| {
LAZY_super<R|kotlin/Any|>
}
public final companion [ResolvedTo(STATUS)] object Companion : R|kotlin/Any| {
private [ResolvedTo(STATUS)] [ContainingClassKey=Companion] constructor(): R|Foo.Companion| {
LAZY_super<R|kotlin/Any|>
}
public final operator [ResolvedTo(CONTRACTS)] fun get([ResolvedTo(CONTRACTS)] n: R|kotlin/Int|): R|kotlin/Int| {
^get IntegerLiteral(42)
}
}
}
private final operator [ResolvedTo(CONTRACTS)] fun R|kotlin/Any|.set([ResolvedTo(CONTRACTS)] i: R|kotlin/Int|, [ResolvedTo(CONTRACTS)] value: R|kotlin/Int|): R|kotlin/Unit| {
}
public final [ResolvedTo(BODY_RESOLVE)] fun usageFoo(): R|kotlin/Unit| {
{
[ResolvedTo(BODY_RESOLVE)] lval <array>: R|Foo.Companion| = Q|Foo|
[ResolvedTo(BODY_RESOLVE)] lval <index_0>: R|kotlin/Int| = Int(1)
R|<local>/<array>|.R|/set|(R|<local>/<index_0>|, R|<local>/<array>|.R|/Foo.Companion.get|(R|<local>/<index_0>|).R|kotlin/Int.minus|(Int(5)))
}
Unit
}
@@ -0,0 +1,10 @@
interface Bar
operator fun Bar.get(n: Int): Int = 42
private operator fun Int.timesAssign(s: String) {}
fun usageBar(bar: Bar) {
<expr>bar[1] *= "bar"</expr>
}
@@ -0,0 +1,20 @@
KT element: KtBinaryExpression
FIR element: FirFunctionCallImpl
FIR source kind: DesugaredArrayTimesAssign
FIR element rendered:
R|<local>/bar|.R|/get|(Int(1)).R|/timesAssign|(String(bar))
FIR FILE:
FILE: [ResolvedTo(IMPORTS)] arrayTimesAssignOperatorsInVariousScopes.kt
public abstract [ResolvedTo(STATUS)] interface Bar : R|kotlin/Any| {
}
public final operator [ResolvedTo(CONTRACTS)] fun R|Bar|.get([ResolvedTo(CONTRACTS)] n: R|kotlin/Int|): R|kotlin/Int| {
^get IntegerLiteral(42)
}
private final operator [ResolvedTo(CONTRACTS)] fun R|kotlin/Int|.timesAssign([ResolvedTo(CONTRACTS)] s: R|kotlin/String|): R|kotlin/Unit| {
}
public final [ResolvedTo(BODY_RESOLVE)] fun usageBar([ResolvedTo(BODY_RESOLVE)] bar: R|Bar|): R|kotlin/Unit| {
R|<local>/bar|.R|/get|(Int(1)).R|/timesAssign|(String(bar))
Unit
}
@@ -1,6 +1,6 @@
KT element: KtBinaryExpression
FIR element: FirFunctionCallImpl
FIR source kind: KtRealSourceElementKind
FIR source kind: DesugaredArrayPlusAssign
FIR element rendered:
R|<local>/<array>|.R|SubstitutionOverride</MyMap.set: R|kotlin/Unit|>|(R|<local>/<index_0>|, R|<local>/<array>|.R|SubstitutionOverride</MyMap.get: R|kotlin/Int|>|(R|<local>/<index_0>|).R|kotlin/Int.plus|(Int(1)))
@@ -1,6 +1,6 @@
KT element: KtBinaryExpression
FIR element: FirFunctionCallImpl
FIR source kind: KtRealSourceElementKind
FIR source kind: DesugaredArrayPlusAssign
FIR element rendered:
R|<local>/<array>|.R|SubstitutionOverride</MyMap.set: R|kotlin/Unit|>|(R|<local>/<index_0>|, R|<local>/<array>|.R|SubstitutionOverride</MyMap.get: R|kotlin/Int|>|(R|<local>/<index_0>|).R|kotlin/Int.plus|(Int(1)))
@@ -1,6 +1,6 @@
KT element: KtBinaryExpression
FIR element: FirFunctionCallImpl
FIR source kind: DesugaredCompoundAssignment
FIR source kind: DesugaredArrayPlusAssign
FIR element rendered:
R|<local>/m|.R|SubstitutionOverride</MyMap.get: R|A|>|(String(a)).R|/A.plusAssign|(Int(1))
@@ -1,6 +1,6 @@
KT element: KtBinaryExpression
FIR element: FirFunctionCallImpl
FIR source kind: DesugaredCompoundAssignment
FIR source kind: DesugaredArrayPlusAssign
FIR element rendered:
R|<local>/m|.R|SubstitutionOverride</MyMap.get: R|A|>|(String(a)).R|/A.plusAssign|(Int(1))
@@ -1,6 +1,6 @@
KT element: KtArrayAccessExpression
FIR element: FirFunctionCallImpl
FIR source kind: KtRealSourceElementKind
FIR source kind: DesugaredArrayPlusAssign
FIR element rendered:
R|<local>/m|.R|SubstitutionOverride</MyMap.get: R|A|>|(String(a))
@@ -293,6 +293,18 @@ public class OutOfContentRootGetOrBuildFirTestGenerated extends AbstractOutOfCon
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testData/getOrBuildFir/calls"), Pattern.compile("^(.+)\\.(kt)$"), null, true);
}
@Test
@TestMetadata("arrayMinusAssignOperatorsInVariousScopes.kt")
public void testArrayMinusAssignOperatorsInVariousScopes() throws Exception {
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/calls/arrayMinusAssignOperatorsInVariousScopes.kt");
}
@Test
@TestMetadata("arrayTimesAssignOperatorsInVariousScopes.kt")
public void testArrayTimesAssignOperatorsInVariousScopes() throws Exception {
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/calls/arrayTimesAssignOperatorsInVariousScopes.kt");
}
@Test
@TestMetadata("callArgument.kt")
public void testCallArgument() throws Exception {
@@ -293,6 +293,18 @@ public class SourceGetOrBuildFirTestGenerated extends AbstractSourceGetOrBuildFi
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testData/getOrBuildFir/calls"), Pattern.compile("^(.+)\\.(kt)$"), null, true);
}
@Test
@TestMetadata("arrayMinusAssignOperatorsInVariousScopes.kt")
public void testArrayMinusAssignOperatorsInVariousScopes() throws Exception {
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/calls/arrayMinusAssignOperatorsInVariousScopes.kt");
}
@Test
@TestMetadata("arrayTimesAssignOperatorsInVariousScopes.kt")
public void testArrayTimesAssignOperatorsInVariousScopes() throws Exception {
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/calls/arrayTimesAssignOperatorsInVariousScopes.kt");
}
@Test
@TestMetadata("callArgument.kt")
public void testCallArgument() throws Exception {