[FIR] Desugar increment/decrement in body resolve phase

The expression needs to be resolved first to determine if there is a
receiver that needs to be extracted to a temporary variable. Also, the
special case for prefix increment/decrement on local variable without
delegates requires resolution to check if the variable is local.

^KT-56771 Fixed
^KT-56659 Fixed
This commit is contained in:
Kirill Rakhman
2023-02-21 16:24:34 +01:00
committed by Space Team
parent 5ecf9cce25
commit 3b9724d20e
77 changed files with 1171 additions and 553 deletions
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.expressions
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
abstract class FirIncrementDecrementExpression : FirExpression() {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation>
abstract val isPrefix: Boolean
abstract val operationName: Name
abstract val expression: FirExpression
abstract val operationSource: KtSourceElement?
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitIncrementDecrementExpression(this, data)
@Suppress("UNCHECKED_CAST")
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformIncrementDecrementExpression(this, data) as E
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirIncrementDecrementExpression
}
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.expressions.builder
import kotlin.contracts.*
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirIncrementDecrementExpressionImpl
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.name.Name
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
@FirBuilderDsl
class FirIncrementDecrementExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override val annotations: MutableList<FirAnnotation> = mutableListOf()
var isPrefix: Boolean by kotlin.properties.Delegates.notNull<Boolean>()
lateinit var operationName: Name
lateinit var expression: FirExpression
var operationSource: KtSourceElement? = null
override fun build(): FirIncrementDecrementExpression {
return FirIncrementDecrementExpressionImpl(
source,
annotations.toMutableOrEmpty(),
isPrefix,
operationName,
expression,
operationSource,
)
}
@Deprecated("Modification of 'typeRef' has no impact for FirIncrementDecrementExpressionBuilder", level = DeprecationLevel.HIDDEN)
override var typeRef: FirTypeRef
get() = throw IllegalStateException()
set(_) {
throw IllegalStateException()
}
}
@OptIn(ExperimentalContracts::class)
inline fun buildIncrementDecrementExpression(init: FirIncrementDecrementExpressionBuilder.() -> Unit): FirIncrementDecrementExpression {
contract {
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
}
return FirIncrementDecrementExpressionBuilder().apply(init).build()
}
@@ -0,0 +1,61 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.expressions.impl
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.fir.MutableOrEmptyList
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
internal class FirIncrementDecrementExpressionImpl(
override val source: KtSourceElement?,
override var annotations: MutableOrEmptyList<FirAnnotation>,
override val isPrefix: Boolean,
override val operationName: Name,
override var expression: FirExpression,
override val operationSource: KtSourceElement?,
) : FirIncrementDecrementExpression() {
override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
typeRef.accept(visitor, data)
annotations.forEach { it.accept(visitor, data) }
expression.accept(visitor, data)
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirIncrementDecrementExpressionImpl {
typeRef = typeRef.transform(transformer, data)
transformAnnotations(transformer, data)
expression = expression.transform(transformer, data)
return this
}
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirIncrementDecrementExpressionImpl {
annotations.transformInplace(transformer, data)
return this
}
override fun replaceTypeRef(newTypeRef: FirTypeRef) {
typeRef = newTypeRef
}
override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) {
annotations = newAnnotations.toMutableOrEmpty()
}
}
@@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
@@ -214,6 +215,8 @@ abstract class FirDefaultVisitor<out R, in D> : FirVisitor<R, D>() {
override fun visitAssignmentOperatorStatement(assignmentOperatorStatement: FirAssignmentOperatorStatement, data: D): R = visitStatement(assignmentOperatorStatement, data)
override fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression, data: D): R = visitExpression(incrementDecrementExpression, data)
override fun visitAugmentedArraySetCall(augmentedArraySetCall: FirAugmentedArraySetCall, data: D): R = visitStatement(augmentedArraySetCall, data)
override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression, data: D): R = visitExpression(classReferenceExpression, data)
@@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
@@ -214,6 +215,8 @@ abstract class FirDefaultVisitorVoid : FirVisitorVoid() {
override fun visitAssignmentOperatorStatement(assignmentOperatorStatement: FirAssignmentOperatorStatement) = visitStatement(assignmentOperatorStatement)
override fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression) = visitExpression(incrementDecrementExpression)
override fun visitAugmentedArraySetCall(augmentedArraySetCall: FirAugmentedArraySetCall) = visitStatement(augmentedArraySetCall)
override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression) = visitExpression(classReferenceExpression)
@@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
@@ -463,6 +464,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformElement(assignmentOperatorStatement, data)
}
open fun transformIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression, data: D): FirStatement {
return transformElement(incrementDecrementExpression, data)
}
open fun transformEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: D): FirStatement {
return transformElement(equalityOperatorCall, data)
}
@@ -1039,6 +1044,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformAssignmentOperatorStatement(assignmentOperatorStatement, data)
}
final override fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression, data: D): FirStatement {
return transformIncrementDecrementExpression(incrementDecrementExpression, data)
}
final override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: D): FirStatement {
return transformEqualityOperatorCall(equalityOperatorCall, data)
}
@@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
@@ -310,6 +311,8 @@ abstract class FirVisitor<out R, in D> {
open fun visitAssignmentOperatorStatement(assignmentOperatorStatement: FirAssignmentOperatorStatement, data: D): R = visitElement(assignmentOperatorStatement, data)
open fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression, data: D): R = visitElement(incrementDecrementExpression, data)
open fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: D): R = visitElement(equalityOperatorCall, data)
open fun visitWhenExpression(whenExpression: FirWhenExpression, data: D): R = visitElement(whenExpression, data)
@@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirComparisonExpression
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirAssignmentOperatorStatement
import org.jetbrains.kotlin.fir.expressions.FirIncrementDecrementExpression
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
@@ -462,6 +463,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitElement(assignmentOperatorStatement)
}
open fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression) {
visitElement(incrementDecrementExpression)
}
open fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall) {
visitElement(equalityOperatorCall)
}
@@ -1038,6 +1043,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitAssignmentOperatorStatement(assignmentOperatorStatement)
}
final override fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression, data: Nothing?) {
visitIncrementDecrementExpression(incrementDecrementExpression)
}
final override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Nothing?) {
visitEqualityOperatorCall(equalityOperatorCall)
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fakeElement
@@ -14,7 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
@@ -25,15 +26,17 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.name.Name
fun FirVariable.toQualifiedAccess(): FirQualifiedAccessExpression = buildPropertyAccessExpression {
val fakeSource = this@toQualifiedAccess.source?.fakeElement(KtFakeSourceElementKind.ReferenceInAtomicQualifiedAccess)
fun FirVariable.toQualifiedAccess(
fakeSource: KtSourceElement? = source?.fakeElement(KtFakeSourceElementKind.ReferenceInAtomicQualifiedAccess),
typeRef: FirTypeRef = returnTypeRef
): FirQualifiedAccessExpression = buildPropertyAccessExpression {
source = fakeSource
calleeReference = buildResolvedNamedReference {
source = fakeSource
name = this@toQualifiedAccess.name
resolvedSymbol = this@toQualifiedAccess.symbol
}
typeRef = this@toQualifiedAccess.returnTypeRef
this.typeRef = typeRef
}
fun generateTemporaryVariable(
@@ -42,7 +45,7 @@ fun generateTemporaryVariable(
name: Name,
initializer: FirExpression,
typeRef: FirTypeRef? = null,
extractedAnnotations: Collection<FirAnnotation>? = null,
extractedAnnotations: Collection<FirAnnotation>? = null
): FirProperty =
buildProperty {
this.source = source
@@ -56,7 +59,7 @@ fun generateTemporaryVariable(
symbol = FirPropertySymbol(name)
isVar = false
isLocal = true
status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL)
status = FirResolvedDeclarationStatusImpl(Visibilities.Local, Modality.FINAL, EffectiveVisibility.Local)
if (extractedAnnotations != null) {
// LT extracts annotations ahead.
// PSI extracts annotations on demand. Use a similar util in [PsiConversionUtils]
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
class FirRenderer(
@@ -1022,6 +1023,14 @@ class FirRenderer(
print(")")
}
override fun visitIncrementDecrementExpression(incrementDecrementExpression: FirIncrementDecrementExpression) {
annotationRenderer?.render(incrementDecrementExpression)
val operator = if (incrementDecrementExpression.operationName == OperatorNameConventions.INC) "++" else "--"
if (incrementDecrementExpression.isPrefix) print(operator)
incrementDecrementExpression.expression.accept(visitor)
if (!incrementDecrementExpression.isPrefix) print(operator)
}
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall) {
annotationRenderer?.render(equalityOperatorCall)
print(equalityOperatorCall.operation.operator)
@@ -104,6 +104,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
val comparisonExpression by element(Expression, expression)
val typeOperatorCall by element(Expression, expression, call)
val assignmentOperatorStatement by element(Expression, statement)
val incrementDecrementExpression by element(Expression, expression)
val equalityOperatorCall by element(Expression, expression, call)
val whenExpression by element(Expression, expression, resolvable)
val whenBranch by element(Expression)
@@ -317,6 +317,8 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(assignmentOperatorStatement)
impl(incrementDecrementExpression)
impl(equalityOperatorCall) {
default("typeRef", "FirImplicitBooleanTypeRef(null)")
useTypes(implicitBooleanTypeRefType)
@@ -254,6 +254,13 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("rightArgument", expression).withTransform()
}
incrementDecrementExpression.configure {
+booleanField("isPrefix")
+field("operationName", nameType)
+field("expression", expression)
+field("operationSource", sourceElementType, nullable = true)
}
equalityOperatorCall.configure {
+field("operation", operationType)
}