FIR checker: set source for assign call for augmented array set call

The source is set on the alternative block but not the XXXAssign call.
BTW, the real source is incorrect shared among the  FirAugmentedArraySetCall,
FirBlock, so this change uses a fake source for the FirBlock and the
FirFunctionCall. Using fake source does not seem to be necessary for
compilable code because in that case FirAugmentedArraySetCall is
transformed to either a FirBlock or a FirFunctionCall. But it's needed
for ambiguous code where such transformation fails. In this case, all
three FirElements are present and they should not share the same real
source.

In addition, this change also sets a fake source for the `get` call of
the array access to the left hand side of the operator. For example,
`m[a] += 1` where `m` is some custom map implementation that does not
return `null` from `get`. The (fake) source of the synthetic `get` call
in FIR is now `m[a]`. This is handy because the analysis API will
resolve `m[a]` to the `get` call.
This commit is contained in:
Tianyu Geng
2021-11-23 19:46:36 -08:00
committed by Ilya Kirillov
parent bc95733818
commit b2e1dfa6db
3 changed files with 15 additions and 5 deletions
@@ -291,6 +291,7 @@ class ExpressionsConverter(
if (firOperation in FirOperation.ASSIGNMENTS) {
return leftArgNode.generateAssignment(
binaryExpression.toFirSourceElement(),
leftArgNode?.toFirSourceElement(),
rightArg,
rightArgAsFir,
firOperation,
@@ -2176,6 +2176,7 @@ open class RawFirBuilder(
if (firOperation in FirOperation.ASSIGNMENTS) {
return expression.left.generateAssignment(
source,
expression.left?.toFirSourceElement(),
expression.right,
rightArgument,
firOperation,
@@ -537,6 +537,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
val assignment = unwrappedArgument.generateAssignment(
desugaredSource,
null,
null,
if (prefix && unwrappedArgument.elementType != REFERENCE_EXPRESSION)
generateResolvedAccessExpression(source, resultVar)
else
@@ -889,6 +890,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
fun T?.generateAssignment(
baseSource: KtSourceElement?,
arrayAccessSource: KtSourceElement?,
rhs: T?,
value: FirExpression, // value is FIR for rhs
operation: FirOperation,
@@ -909,7 +911,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
(result.annotations as MutableList<FirAnnotation>) += annotations
result
} else {
generateAugmentedArraySetCall(unwrappedLhs, baseSource, operation, rhs, annotations, convert)
generateAugmentedArraySetCall(unwrappedLhs, baseSource, arrayAccessSource, operation, rhs, annotations, convert)
}
}
@@ -973,6 +975,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
private fun generateAugmentedArraySetCall(
unwrappedReceiver: T,
baseSource: KtSourceElement?,
arrayAccessSource: KtSourceElement?,
operation: FirOperation,
rhs: T?,
annotations: List<FirAnnotation>,
@@ -981,14 +984,16 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
return buildAugmentedArraySetCall {
source = baseSource
this.operation = operation
assignCall = generateAugmentedCallForAugmentedArraySetCall(unwrappedReceiver, operation, rhs, convert)
setGetBlock = generateSetGetBlockForAugmentedArraySetCall(unwrappedReceiver, baseSource, operation, rhs, convert)
assignCall = generateAugmentedCallForAugmentedArraySetCall(unwrappedReceiver, baseSource, operation, rhs, convert)
setGetBlock =
generateSetGetBlockForAugmentedArraySetCall(unwrappedReceiver, baseSource, arrayAccessSource, operation, rhs, convert)
this.annotations += annotations
}
}
private fun generateAugmentedCallForAugmentedArraySetCall(
unwrappedReceiver: T,
baseSource: KtSourceElement?,
operation: FirOperation,
rhs: T?,
convert: T.() -> FirExpression
@@ -998,6 +1003,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
* a.get(x, y).plusAssign(z)
*/
return buildFunctionCall {
source = baseSource?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)
calleeReference = buildSimpleNamedReference {
name = FirOperationNameConventions.ASSIGNMENTS.getValue(operation)
}
@@ -1016,6 +1022,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
private fun generateSetGetBlockForAugmentedArraySetCall(
unwrappedReceiver: T,
baseSource: KtSourceElement?,
arrayAccessSource: KtSourceElement?,
operation: FirOperation,
rhs: T?,
convert: T.() -> FirExpression
@@ -1037,7 +1044,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
source = null,
specialName = "<array>",
initializer = baseCall.explicitReceiver ?: buildErrorExpression {
source = baseSource
source = baseSource?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)
diagnostic = ConeSimpleDiagnostic("No receiver for array access", DiagnosticKind.Syntax)
}
)
@@ -1047,7 +1054,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
}
statements += indexVariables
statements += buildFunctionCall {
source = baseSource
source = baseSource?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)
explicitReceiver = arrayVariable.toQualifiedAccess()
calleeReference = buildSimpleNamedReference {
name = OperatorNameConventions.SET
@@ -1059,6 +1066,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
}
val getCall = buildFunctionCall {
source = arrayAccessSource?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)
explicitReceiver = arrayVariable.toQualifiedAccess()
calleeReference = buildSimpleNamedReference {
name = OperatorNameConventions.GET