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) { if (firOperation in FirOperation.ASSIGNMENTS) {
return leftArgNode.generateAssignment( return leftArgNode.generateAssignment(
binaryExpression.toFirSourceElement(), binaryExpression.toFirSourceElement(),
leftArgNode?.toFirSourceElement(),
rightArg, rightArg,
rightArgAsFir, rightArgAsFir,
firOperation, firOperation,
@@ -2176,6 +2176,7 @@ open class RawFirBuilder(
if (firOperation in FirOperation.ASSIGNMENTS) { if (firOperation in FirOperation.ASSIGNMENTS) {
return expression.left.generateAssignment( return expression.left.generateAssignment(
source, source,
expression.left?.toFirSourceElement(),
expression.right, expression.right,
rightArgument, rightArgument,
firOperation, firOperation,
@@ -537,6 +537,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
val assignment = unwrappedArgument.generateAssignment( val assignment = unwrappedArgument.generateAssignment(
desugaredSource, desugaredSource,
null, null,
null,
if (prefix && unwrappedArgument.elementType != REFERENCE_EXPRESSION) if (prefix && unwrappedArgument.elementType != REFERENCE_EXPRESSION)
generateResolvedAccessExpression(source, resultVar) generateResolvedAccessExpression(source, resultVar)
else else
@@ -889,6 +890,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
fun T?.generateAssignment( fun T?.generateAssignment(
baseSource: KtSourceElement?, baseSource: KtSourceElement?,
arrayAccessSource: KtSourceElement?,
rhs: T?, rhs: T?,
value: FirExpression, // value is FIR for rhs value: FirExpression, // value is FIR for rhs
operation: FirOperation, operation: FirOperation,
@@ -909,7 +911,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
(result.annotations as MutableList<FirAnnotation>) += annotations (result.annotations as MutableList<FirAnnotation>) += annotations
result result
} else { } 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( private fun generateAugmentedArraySetCall(
unwrappedReceiver: T, unwrappedReceiver: T,
baseSource: KtSourceElement?, baseSource: KtSourceElement?,
arrayAccessSource: KtSourceElement?,
operation: FirOperation, operation: FirOperation,
rhs: T?, rhs: T?,
annotations: List<FirAnnotation>, annotations: List<FirAnnotation>,
@@ -981,14 +984,16 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
return buildAugmentedArraySetCall { return buildAugmentedArraySetCall {
source = baseSource source = baseSource
this.operation = operation this.operation = operation
assignCall = generateAugmentedCallForAugmentedArraySetCall(unwrappedReceiver, operation, rhs, convert) assignCall = generateAugmentedCallForAugmentedArraySetCall(unwrappedReceiver, baseSource, operation, rhs, convert)
setGetBlock = generateSetGetBlockForAugmentedArraySetCall(unwrappedReceiver, baseSource, operation, rhs, convert) setGetBlock =
generateSetGetBlockForAugmentedArraySetCall(unwrappedReceiver, baseSource, arrayAccessSource, operation, rhs, convert)
this.annotations += annotations this.annotations += annotations
} }
} }
private fun generateAugmentedCallForAugmentedArraySetCall( private fun generateAugmentedCallForAugmentedArraySetCall(
unwrappedReceiver: T, unwrappedReceiver: T,
baseSource: KtSourceElement?,
operation: FirOperation, operation: FirOperation,
rhs: T?, rhs: T?,
convert: T.() -> FirExpression convert: T.() -> FirExpression
@@ -998,6 +1003,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
* a.get(x, y).plusAssign(z) * a.get(x, y).plusAssign(z)
*/ */
return buildFunctionCall { return buildFunctionCall {
source = baseSource?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)
calleeReference = buildSimpleNamedReference { calleeReference = buildSimpleNamedReference {
name = FirOperationNameConventions.ASSIGNMENTS.getValue(operation) name = FirOperationNameConventions.ASSIGNMENTS.getValue(operation)
} }
@@ -1016,6 +1022,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
private fun generateSetGetBlockForAugmentedArraySetCall( private fun generateSetGetBlockForAugmentedArraySetCall(
unwrappedReceiver: T, unwrappedReceiver: T,
baseSource: KtSourceElement?, baseSource: KtSourceElement?,
arrayAccessSource: KtSourceElement?,
operation: FirOperation, operation: FirOperation,
rhs: T?, rhs: T?,
convert: T.() -> FirExpression convert: T.() -> FirExpression
@@ -1037,7 +1044,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
source = null, source = null,
specialName = "<array>", specialName = "<array>",
initializer = baseCall.explicitReceiver ?: buildErrorExpression { initializer = baseCall.explicitReceiver ?: buildErrorExpression {
source = baseSource source = baseSource?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)
diagnostic = ConeSimpleDiagnostic("No receiver for array access", DiagnosticKind.Syntax) 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 += indexVariables
statements += buildFunctionCall { statements += buildFunctionCall {
source = baseSource source = baseSource?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)
explicitReceiver = arrayVariable.toQualifiedAccess() explicitReceiver = arrayVariable.toQualifiedAccess()
calleeReference = buildSimpleNamedReference { calleeReference = buildSimpleNamedReference {
name = OperatorNameConventions.SET name = OperatorNameConventions.SET
@@ -1059,6 +1066,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
} }
val getCall = buildFunctionCall { val getCall = buildFunctionCall {
source = arrayAccessSource?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)
explicitReceiver = arrayVariable.toQualifiedAccess() explicitReceiver = arrayVariable.toQualifiedAccess()
calleeReference = buildSimpleNamedReference { calleeReference = buildSimpleNamedReference {
name = OperatorNameConventions.GET name = OperatorNameConventions.GET