FIR: Allow selector of safe calls to be a FirStatement

It's necessary to allow a?.b += v be interpreted as a?.(b += v)
But currently FirAssignmentOperatorStatement is not FirQualifiedAccess

^KT-41034 In Progress
This commit is contained in:
Denis.Zharkov
2022-01-18 18:28:25 +03:00
parent c35b8342d8
commit 6f89f1ebf4
20 changed files with 52 additions and 55 deletions
@@ -22,7 +22,7 @@ abstract class FirSafeCallExpression : FirExpression() {
abstract override val annotations: List<FirAnnotation>
abstract val receiver: FirExpression
abstract val checkedSubjectRef: FirExpressionRef<FirCheckedSafeCallSubject>
abstract val regularQualifiedAccess: FirQualifiedAccess
abstract val selector: FirStatement
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitSafeCallExpression(this, data)
@@ -32,11 +32,11 @@ abstract class FirSafeCallExpression : FirExpression() {
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract fun replaceRegularQualifiedAccess(newRegularQualifiedAccess: FirQualifiedAccess)
abstract fun replaceSelector(newSelector: FirStatement)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirSafeCallExpression
abstract fun <D> transformReceiver(transformer: FirTransformer<D>, data: D): FirSafeCallExpression
abstract fun <D> transformRegularQualifiedAccess(transformer: FirTransformer<D>, data: D): FirSafeCallExpression
abstract fun <D> transformSelector(transformer: FirTransformer<D>, data: D): FirSafeCallExpression
}
@@ -13,8 +13,8 @@ import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirSafeCallExpressionImpl
import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -33,7 +33,7 @@ class FirSafeCallExpressionBuilder : FirAnnotationContainerBuilder, FirExpressio
override val annotations: MutableList<FirAnnotation> = mutableListOf()
lateinit var receiver: FirExpression
lateinit var checkedSubjectRef: FirExpressionRef<FirCheckedSafeCallSubject>
lateinit var regularQualifiedAccess: FirQualifiedAccess
lateinit var selector: FirStatement
override fun build(): FirSafeCallExpression {
return FirSafeCallExpressionImpl(
@@ -42,7 +42,7 @@ class FirSafeCallExpressionBuilder : FirAnnotationContainerBuilder, FirExpressio
annotations,
receiver,
checkedSubjectRef,
regularQualifiedAccess,
selector,
)
}
@@ -10,8 +10,8 @@ import org.jetbrains.kotlin.fir.FirExpressionRef
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.*
@@ -26,20 +26,20 @@ internal class FirSafeCallExpressionImpl(
override val annotations: MutableList<FirAnnotation>,
override var receiver: FirExpression,
override val checkedSubjectRef: FirExpressionRef<FirCheckedSafeCallSubject>,
override var regularQualifiedAccess: FirQualifiedAccess,
override var selector: FirStatement,
) : FirSafeCallExpression() {
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
typeRef.accept(visitor, data)
annotations.forEach { it.accept(visitor, data) }
receiver.accept(visitor, data)
regularQualifiedAccess.accept(visitor, data)
selector.accept(visitor, data)
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirSafeCallExpressionImpl {
typeRef = typeRef.transform(transformer, data)
transformAnnotations(transformer, data)
transformReceiver(transformer, data)
transformRegularQualifiedAccess(transformer, data)
transformSelector(transformer, data)
return this
}
@@ -53,8 +53,8 @@ internal class FirSafeCallExpressionImpl(
return this
}
override fun <D> transformRegularQualifiedAccess(transformer: FirTransformer<D>, data: D): FirSafeCallExpressionImpl {
regularQualifiedAccess = regularQualifiedAccess.transform(transformer, data)
override fun <D> transformSelector(transformer: FirTransformer<D>, data: D): FirSafeCallExpressionImpl {
selector = selector.transform(transformer, data)
return this
}
@@ -62,7 +62,7 @@ internal class FirSafeCallExpressionImpl(
typeRef = newTypeRef
}
override fun replaceRegularQualifiedAccess(newRegularQualifiedAccess: FirQualifiedAccess) {
regularQualifiedAccess = newRegularQualifiedAccess
override fun replaceSelector(newSelector: FirStatement) {
selector = newSelector
}
}
@@ -707,7 +707,7 @@ open class FirRenderer(builder: StringBuilder, protected val mode: RenderMode =
override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression) {
safeCallExpression.receiver.accept(this)
print("?.{ ")
safeCallExpression.regularQualifiedAccess.accept(this)
safeCallExpression.selector.accept(this)
print(" }")
}
@@ -506,7 +506,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
// Special node that might be used as a reference to receiver of a safe call after null check
+field("checkedSubjectRef", safeCallCheckedSubjectReferenceType)
// One that uses checkedReceiver as a receiver
+field("regularQualifiedAccess", qualifiedAccess, withReplace = true).withTransform()
+field("selector", statement, withReplace = true).withTransform()
}
checkedSafeCallSubject.configure {