diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index 2b4acfe6a9c..ca99336e0d4 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -105,6 +105,7 @@ class DeclarationsConverter( CLASS -> firStatements += convertClass(it) as FirStatement FUN -> firStatements += convertFunctionDeclaration(it) as FirStatement PROPERTY -> firStatements += convertPropertyDeclaration(it) as FirStatement + DESTRUCTURING_DECLARATION -> firStatements += convertDestructingDeclaration(it).toFirDestructingDeclaration(session) TYPEALIAS -> firStatements += convertTypeAlias(it) as FirStatement OBJECT_DECLARATION -> firStatements += convertClass(it) as FirStatement CLASS_INITIALIZER -> firStatements += convertAnonymousInitializer(it) as FirStatement @@ -676,7 +677,6 @@ class DeclarationsConverter( * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseProperty */ private fun convertPropertyDeclaration(property: LighterASTNode): FirDeclaration { - //TODO DESTRUCTURING_DECLARATION var modifiers = Modifier(session) lateinit var identifier: String val firTypeParameters = mutableListOf() @@ -718,7 +718,9 @@ class DeclarationsConverter( isVar, firExpression, delegate = firDelegateExpression - ) + ).apply { + annotations += modifiers.annotations + } } else { FirMemberPropertyImpl( session, @@ -753,14 +755,16 @@ class DeclarationsConverter( private fun convertDestructingDeclaration(destructingDeclaration: LighterASTNode): DestructuringDeclaration { var isVar = false val entries = mutableListOf() + var firExpression: FirExpression? = null destructingDeclaration.forEachChildren { when (it.tokenType) { VAR_KEYWORD -> isVar = true DESTRUCTURING_DECLARATION_ENTRY -> entries += convertDestructingDeclarationEntry(it) + else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it) } } - return DestructuringDeclaration(isVar, entries) + return DestructuringDeclaration(isVar, entries, firExpression) } /** diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt index a25361babfc..5076a239a28 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/fir/DestructuringDeclaration.kt @@ -5,9 +5,29 @@ package org.jetbrains.kotlin.fir.lightTree.fir +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.builder.generateTemporaryVariable +import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall +import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirVariable +import org.jetbrains.kotlin.fir.expressions.impl.FirErrorExpressionImpl +import org.jetbrains.kotlin.fir.lightTree.converter.utils.generateDestructuringBlock data class DestructuringDeclaration( val isVar: Boolean, - val entries: List -) \ No newline at end of file + val entries: List, + val initializer: FirExpression? +) { + fun toFirDestructingDeclaration(session: FirSession): FirExpression { + val baseVariable = generateTemporaryVariable( + session, null, "destruct", + initializer ?: FirErrorExpressionImpl(session, null, "Destructuring declaration without initializer") + ) + return generateDestructuringBlock( + session, + this, + baseVariable, + tmpVariable = true + ) + } +} \ No newline at end of file diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt index b29c59017c1..39ff7e5bd1c 100644 --- a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt @@ -19,16 +19,14 @@ import org.jetbrains.kotlin.psi.KtLambdaExpression class FirPartialTransformer( private val visitAnonymousFunction: Boolean = false, private val visitLambdaExpression: Boolean = false, - private val visitNamedFunction: Boolean = false, - private val visitMemberDeclaration: Boolean = false, + private val visitLocalMembers: Boolean = false, private val visitVariable: Boolean = false, private val visitAnnotation: Boolean = false, private val visitTypeOperatorCall: Boolean = false, private val visitArrayOfCall: Boolean = false, private val visitFunctionCall: Boolean = false, private val visitGetClassCall: Boolean = false, - private val visitBreakExpression: Boolean = false, - private val visitContinueExpression: Boolean = false, + private val visitLoopJump: Boolean = false, private val visitReturnExpression: Boolean = false, private val visitThrowExpression: Boolean = false, private val visitLoops: Boolean = false, @@ -38,8 +36,7 @@ class FirPartialTransformer( private val visitTryExpression: Boolean = false, private val visitWhenExpression: Boolean = false, private val visitLambdaArgumentExpression: Boolean = false, - private val visitAnonymousObject: Boolean = false, - private val visitAssignment: Boolean = false + private val visitAnonymousObject: Boolean = false ) : FirAbstractTreeTransformer() { override fun transformAnonymousFunction( anonymousFunction: FirAnonymousFunction, @@ -55,7 +52,7 @@ class FirPartialTransformer( } override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Nothing?): CompositeTransformResult { - return if (!visitNamedFunction && namedFunction is FirAbstractCallableMember && namedFunction.visibility == Visibilities.LOCAL) { + return if (!visitLocalMembers && namedFunction is FirAbstractCallableMember && namedFunction.visibility == Visibilities.LOCAL) { DummyFirDeclaration().compose() } else { (namedFunction.transformChildren(this, data) as FirNamedFunction).compose() @@ -66,7 +63,7 @@ class FirPartialTransformer( memberDeclaration: FirMemberDeclaration, data: Nothing? ): CompositeTransformResult { - return if (!visitMemberDeclaration && memberDeclaration.visibility == Visibilities.LOCAL) { + return if (!visitLocalMembers && memberDeclaration.visibility == Visibilities.LOCAL) { DummyFirDeclaration().compose() } else { (memberDeclaration.transformChildren(this, data) as FirMemberDeclaration).compose() @@ -130,7 +127,7 @@ class FirPartialTransformer( } override fun transformBreakExpression(breakExpression: FirBreakExpression, data: Nothing?): CompositeTransformResult { - return if (visitBreakExpression) { + return if (visitLoopJump) { (breakExpression.transformChildren(this, data) as FirBreakExpression).compose() } else { DummyFirStatement().compose() @@ -141,7 +138,7 @@ class FirPartialTransformer( continueExpression: FirContinueExpression, data: Nothing? ): CompositeTransformResult { - return if (visitContinueExpression) { + return if (visitLoopJump) { (continueExpression.transformChildren(this, data) as FirContinueExpression).compose() } else { DummyFirStatement().compose() @@ -257,7 +254,7 @@ class FirPartialTransformer( } override fun transformAssignment(assignment: FirAssignment, data: Nothing?): CompositeTransformResult { - return if (visitAssignment) { + return if (visitVariable) { (assignment.transformChildren(this, data) as FirAssignment).compose() } else { DummyFirStatement().compose() diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt index d66de2031ad..3aef4aef624 100644 --- a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt @@ -59,16 +59,14 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { stubMode: Boolean, visitAnonymousFunction: Boolean = false, visitLambdaExpression: Boolean = false, - visitNamedFunction: Boolean = false, - visitMemberDeclaration: Boolean = false, + visitLocalMembers: Boolean = false, visitVariable: Boolean = false, visitAnnotation: Boolean = false, visitTypeOperatorCall: Boolean = false, visitArrayOfCall: Boolean = false, visitFunctionCall: Boolean = false, visitGetClassCall: Boolean = false, - visitBreakExpression: Boolean = false, - visitContinueExpression: Boolean = false, + visitLoopJump: Boolean = false, visitReturnExpression: Boolean = false, visitThrowExpression: Boolean = false, visitLoops: Boolean = false, @@ -78,22 +76,19 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { visitTryExpression: Boolean = false, visitWhenExpression: Boolean = false, visitLambdaArgumentExpression: Boolean = false, - visitAnonymousObject: Boolean = false, - visitAssignment: Boolean = false + visitAnonymousObject: Boolean = false ) { val firVisitor = FirPartialTransformer( visitAnonymousFunction = visitAnonymousFunction, visitLambdaExpression = visitLambdaExpression, - visitNamedFunction = visitNamedFunction, - visitMemberDeclaration = visitMemberDeclaration, + visitLocalMembers = visitLocalMembers, visitVariable = visitVariable, visitAnnotation = visitAnnotation, visitTypeOperatorCall = visitTypeOperatorCall, visitArrayOfCall = visitArrayOfCall, visitFunctionCall = visitFunctionCall, visitGetClassCall = visitGetClassCall, - visitBreakExpression = visitBreakExpression, - visitContinueExpression = visitContinueExpression, + visitLoopJump = visitLoopJump, visitReturnExpression = visitReturnExpression, visitThrowExpression = visitThrowExpression, visitLoops = visitLoops, @@ -103,8 +98,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { visitTryExpression = visitTryExpression, visitWhenExpression = visitWhenExpression, visitLambdaArgumentExpression = visitLambdaArgumentExpression, - visitAnonymousObject = visitAnonymousObject, - visitAssignment = visitAssignment + visitAnonymousObject = visitAnonymousObject ) val lightTreeConverter = LightTree2Fir(stubMode, myProject) compareBase { file -> @@ -186,8 +180,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { fun testLocalMembers() { compare( stubMode = false, - visitNamedFunction = true, - visitMemberDeclaration = true, + visitLocalMembers = true, visitAnnotation = true, visitTypeOperatorCall = true, visitArrayOfCall = true, @@ -202,8 +195,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { fun testReturn() { compare( stubMode = false, - visitNamedFunction = true, - visitMemberDeclaration = true, + visitLocalMembers = true, visitAnnotation = true, visitTypeOperatorCall = true, visitArrayOfCall = true, @@ -221,8 +213,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { stubMode = false, visitAnonymousFunction = true, visitLambdaExpression = true, - visitNamedFunction = true, - visitMemberDeclaration = true, + visitLocalMembers = true, visitAnnotation = true, visitTypeOperatorCall = true, visitArrayOfCall = true, @@ -240,8 +231,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { stubMode = false, visitAnonymousFunction = true, visitLambdaExpression = true, - visitNamedFunction = true, - visitMemberDeclaration = true, + visitLocalMembers = true, visitAnnotation = true, visitTypeOperatorCall = true, visitArrayOfCall = true, @@ -260,8 +250,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { stubMode = false, visitAnonymousFunction = true, visitLambdaExpression = true, - visitNamedFunction = true, - visitMemberDeclaration = true, + visitLocalMembers = true, visitAnnotation = true, visitTypeOperatorCall = true, visitArrayOfCall = true, @@ -288,4 +277,20 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() { visitQualifiedAccessExpression = true ) } + + fun testVariables() { + compare( + stubMode = false, + visitAnonymousFunction = true, + visitLambdaExpression = true, + visitLocalMembers = true, + visitVariable = true, + visitAnnotation = true, + visitFunctionCall = true, + visitLoops = true, + visitConstExpression = true, + visitQualifiedAccessExpression = true, + visitAnonymousObject = true + ) + } } diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt index 755e4f9b078..eca0cb1e79c 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt @@ -469,7 +469,7 @@ fun generateTemporaryVariable( symbol.bind(this) } -internal fun generateTemporaryVariable( +fun generateTemporaryVariable( session: FirSession, psi: PsiElement?, specialName: String, initializer: FirExpression ): FirVariable<*> = generateTemporaryVariable(session, psi, Name.special("<$specialName>"), initializer)