Set correct IR origins for inc/dec operations

NB: in order to produce correct IR origins, the source element kinds for
some FIR elements has been changed. As a side effect, mapping PSI to FIR
slightly changed: namely, for `a[b]++`, `a[b]` used to be mapped on
`set` call or callable reference, but now it is mapped on `get` call.

^KT-61891: Fixed
^KT-64387: Fixed
This commit is contained in:
vladislav.grechko
2023-12-28 17:12:17 +01:00
committed by Space Team
parent 8b1d87848d
commit 9aa8fb80e7
65 changed files with 463 additions and 972 deletions
@@ -660,11 +660,17 @@ abstract class AbstractRawFirBuilder<T>(val baseSession: FirSession, val context
convert: T.() -> FirExpression,
): FirExpression {
val array = receiver.arrayExpression
val isInc = when (callName) {
OperatorNameConventions.INC -> true
OperatorNameConventions.DEC -> false
else -> error("Unexpected operator: $callName")
}
val sourceKind = sourceKindForIncOrDec(callName, prefix)
return buildBlockPossiblyUnderSafeCall(
array, convert, receiver.toFirSourceElement(),
) { arrayReceiver ->
val baseSource = wholeExpression?.toFirSourceElement()
val desugaredSource = baseSource?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
val desugaredSource = baseSource?.fakeElement(sourceKind)
source = desugaredSource
val indices = receiver.indexExpressions
@@ -686,11 +692,12 @@ abstract class AbstractRawFirBuilder<T>(val baseSession: FirSession, val context
).also { statements += it }
}
fun buildGetCall(referenceSourceKind: KtFakeSourceElementKind = KtFakeSourceElementKind.ArrayAccessNameReference) =
fun buildGetCall(sourceKind: KtFakeSourceElementKind) =
buildFunctionCall {
source = desugaredSource
val fakeSource = receiver?.toFirSourceElement(sourceKind)
source = fakeSource
calleeReference = buildSimpleNamedReference {
source = receiver?.toFirSourceElement(referenceSourceKind)
source = fakeSource
name = OperatorNameConventions.GET
}
explicitReceiver = generateResolvedAccessExpression(arrayVariable.source, arrayVariable)
@@ -702,10 +709,10 @@ abstract class AbstractRawFirBuilder<T>(val baseSession: FirSession, val context
origin = FirFunctionCallOrigin.Operator
}
fun buildSetCall(argumentExpression: FirExpression) = buildFunctionCall {
fun buildSetCall(argumentExpression: FirExpression, sourceElementKind: KtFakeSourceElementKind) = buildFunctionCall {
source = desugaredSource
calleeReference = buildSimpleNamedReference {
source = receiver.toFirSourceElement()
source = receiver.toFirSourceElement(sourceElementKind)
name = OperatorNameConventions.SET
}
explicitReceiver = generateResolvedAccessExpression(arrayVariable.source, arrayVariable)
@@ -731,29 +738,36 @@ abstract class AbstractRawFirBuilder<T>(val baseSession: FirSession, val context
if (prefix) {
statements += buildSetCall(
buildIncDecCall(
KtFakeSourceElementKind.DesugaredPrefixNameReference,
buildGetCall()
)
sourceKind,
buildGetCall(sourceKind),
),
sourceKind
)
statements += buildGetCall(
if (isInc) {
KtFakeSourceElementKind.DesugaredPrefixIncSecondGetReference
} else {
KtFakeSourceElementKind.DesugaredPrefixDecSecondGetReference
}
)
statements += buildGetCall(KtFakeSourceElementKind.DesugaredPrefixSecondGetReference)
} else {
val initialValueVar = generateTemporaryVariable(
baseModuleData,
desugaredSource,
SpecialNames.UNARY,
buildGetCall()
buildGetCall(sourceKind)
)
statements += initialValueVar
statements += buildSetCall(
buildIncDecCall(
KtFakeSourceElementKind.DesugaredPostfixNameReference,
generateResolvedAccessExpression(desugaredSource, initialValueVar)
)
sourceKind,
generateResolvedAccessExpression(null, initialValueVar)
),
sourceKind
)
statements += generateResolvedAccessExpression(desugaredSource, initialValueVar)
statements += generateResolvedAccessExpression(null, initialValueVar)
}
}
}
@@ -890,10 +904,10 @@ abstract class AbstractRawFirBuilder<T>(val baseSession: FirSession, val context
val assignmentLValue = unwrappedLhs.convert()
return buildVariableAssignment {
source = baseSource
lValue = if (baseSource?.kind == KtFakeSourceElementKind.DesugaredIncrementOrDecrement) {
lValue = if (baseSource?.kind is KtFakeSourceElementKind.DesugaredIncrementOrDecrement) {
buildDesugaredAssignmentValueReferenceExpression {
expressionRef = FirExpressionRef<FirExpression>().apply { bind(assignmentLValue) }
source = assignmentLValue.source?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
source = assignmentLValue.source?.fakeElement(baseSource.kind as KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
}
} else {
assignmentLValue