From 9ca0bdcb807be82bd7724cda84210d9c8e9e3678 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Fri, 9 Feb 2024 19:07:05 +0100 Subject: [PATCH] [FIR] make script destructuring declaration initializer lazy expression This change is required to properly support such declarations in lazy resolution mode as we usually replaced initializers with lazy expressions during the body calculation phase ^KT-62840 --- .../RawFirNonLocalDeclarationBuilder.kt | 15 ++++++--- .../destructionWithNoRValueScript.txt | 4 +-- .../declarations/destructuringScript.txt | 4 +-- .../kotlin/fir/builder/PsiRawFirBuilder.kt | 32 ++++++++++++------- ...DestructuringWithAnnotation.lazyBodies.txt | 6 ++-- 5 files changed, 40 insertions(+), 21 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt index f82e542abe5..763ab7b302f 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt @@ -146,10 +146,17 @@ internal class RawFirNonLocalDeclarationBuilder private constructor( } private inner class VisitorWithReplacement(private val containingClass: FirRegularClass?) : Visitor() { - fun convertDestructuringDeclaration(element: KtDestructuringDeclaration): FirVariable { + fun convertDestructuringDeclaration(element: KtDestructuringDeclaration, containingDeclaration: FirDeclaration?): FirVariable { val replacementDeclaration = replacementApplier?.tryReplace(element) ?: element requireIsInstance(replacementDeclaration) - return buildErrorTopLevelDestructuringDeclaration(replacementDeclaration.toFirSourceElement()) + return if (containingDeclaration is FirScript) { + withContainerSymbol(containingDeclaration.symbol) { + // Annotations from script destructuring declarations are linked to the script itself + buildScriptDestructuringDeclaration(replacementDeclaration) + } + } else { + buildErrorTopLevelDestructuringDeclaration(replacementDeclaration.toFirSourceElement()) + } } fun convertAnonymousInitializer(element: KtAnonymousInitializer, containingDeclaration: FirDeclaration?): FirAnonymousInitializer { @@ -348,7 +355,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor( else -> visitor.convertElement(declarationToBuild, originalDeclaration) } } - is KtDestructuringDeclaration -> visitor.convertDestructuringDeclaration(declarationToBuild) + is KtDestructuringDeclaration -> visitor.convertDestructuringDeclaration(declarationToBuild, containingDeclaration) is KtCodeFragment -> { val firFile = visitor.convertElement(declarationToBuild, originalDeclaration) as FirFile firFile.codeFragment @@ -359,7 +366,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor( } val parent = iterator.next() - if (parent !is FirRegularClass) return moveNext(iterator, containingDeclaration = null) + if (parent !is FirRegularClass) return moveNext(iterator, containingDeclaration = parent) val classOrObject = parent.psi if (classOrObject !is KtClassOrObject) { diff --git a/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructionWithNoRValueScript.txt b/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructionWithNoRValueScript.txt index d5620b3400f..81533820625 100644 --- a/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructionWithNoRValueScript.txt +++ b/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructionWithNoRValueScript.txt @@ -3,7 +3,7 @@ FIR element: FirPropertyImpl FIR source kind: KtRealSourceElementKind FIR element rendered: -[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval : = ERROR_EXPR(Initializer required for destructuring declaration) +[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval : = LAZY_EXPRESSION FIR FILE: FILE: [ResolvedTo(IMPORTS)] destructionWithNoRValueScript.kts @@ -11,7 +11,7 @@ FILE: [ResolvedTo(IMPORTS)] destructionWithNoRValueScript.kts SCRIPT: [ResolvedTo(RAW_FIR)] [ResolvedTo(RAW_FIR)] lval args: R|kotlin/Array| - [ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval : = ERROR_EXPR(Initializer required for destructuring declaration) + [ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval : = LAZY_EXPRESSION public final [ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableKey=/] val o: = R|/|.component1#() diff --git a/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructuringScript.txt b/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructuringScript.txt index d6a88523738..02ccc83d6b4 100644 --- a/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructuringScript.txt +++ b/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructuringScript.txt @@ -3,7 +3,7 @@ FIR element: FirPropertyImpl FIR source kind: KtRealSourceElementKind FIR element rendered: -[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval : = pair# +[ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval : = LAZY_EXPRESSION FIR FILE: FILE: [ResolvedTo(IMPORTS)] destructuringScript.kts @@ -22,7 +22,7 @@ FILE: [ResolvedTo(IMPORTS)] destructuringScript.kts public? final? [ResolvedTo(RAW_FIR)] val pair: = LAZY_EXPRESSION public? [ResolvedTo(RAW_FIR)] get(): - [ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval : = pair# + [ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableMarkerKey=true] lval : = LAZY_EXPRESSION public final [ResolvedTo(RAW_FIR)] [DestructuringDeclarationContainerVariableKey=/] val first: = R|/|.component1#() diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt index 36c9b4d666d..b46911759f2 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt @@ -1280,6 +1280,26 @@ open class PsiRawFirBuilder( } } + protected fun buildScriptDestructuringDeclaration(destructuringDeclaration: KtDestructuringDeclaration): FirVariable { + val initializer = destructuringDeclaration.initializer + val firInitializer = buildOrLazyExpression(initializer?.toFirSourceElement()) { + initializer.toFirExpression { ConeSyntaxDiagnostic("Initializer required for destructuring declaration") } + } + + val destructuringContainerVar = generateTemporaryVariable( + moduleData = baseModuleData, + source = destructuringDeclaration.toFirSourceElement(), + specialName = "destruct", + initializer = firInitializer, + origin = FirDeclarationOrigin.Synthetic.ScriptTopLevelDestructuringDeclarationContainer, + extractAnnotationsTo = { extractAnnotationsTo(it) }, + ).apply { + isDestructuringDeclarationContainerVariable = true + } + + return destructuringContainerVar + } + private fun convertScript( script: KtScript, fileName: String, @@ -1301,7 +1321,6 @@ open class PsiRawFirBuilder( while (scriptDeclarationsIter.hasNext()) { val declaration = scriptDeclarationsIter.next() val isLast = !scriptDeclarationsIter.hasNext() - val declarationSource = declaration.toFirSourceElement() when (declaration) { is KtScriptInitializer -> { val initializer = buildAnonymousInitializer( @@ -1315,16 +1334,7 @@ open class PsiRawFirBuilder( declarations.add(initializer) } is KtDestructuringDeclaration -> { - val destructuringContainerVar = generateTemporaryVariable( - baseModuleData, - declarationSource, - "destruct", - declaration.initializer.toFirExpression { ConeSyntaxDiagnostic("Initializer required for destructuring declaration") }, - origin = FirDeclarationOrigin.Synthetic.ScriptTopLevelDestructuringDeclarationContainer, - extractAnnotationsTo = { extractAnnotationsTo(it) } - ).apply { - isDestructuringDeclarationContainerVariable = true - } + val destructuringContainerVar = buildScriptDestructuringDeclaration(declaration) declarations.add(destructuringContainerVar) declarations.addDestructuringVariables( diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/scriptLevelDestructuringWithAnnotation.lazyBodies.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/scriptLevelDestructuringWithAnnotation.lazyBodies.txt index 4e2eb670b82..9e8f3b8e89a 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/scriptLevelDestructuringWithAnnotation.lazyBodies.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/scriptLevelDestructuringWithAnnotation.lazyBodies.txt @@ -1,15 +1,17 @@ FILE: scriptLevelDestructuringWithAnnotation.kts SCRIPT: - @DestrAnno(LAZY_EXPRESSION) lval : = IntegerLiteral(0).to#(IntegerLiteral(1)) + @DestrAnno(LAZY_EXPRESSION) lval : = LAZY_EXPRESSION @LeftAnno(LAZY_EXPRESSION) public final val a: = R|/|.component1#() @RightAnno(LAZY_EXPRESSION) public final val b: = R|/|.component2#() - @Destr2Anno(LAZY_EXPRESSION) lval : = IntegerLiteral(2).to#(IntegerLiteral(3)) + @Destr2Anno(LAZY_EXPRESSION) lval : = LAZY_EXPRESSION @SecondLeftAnno(LAZY_EXPRESSION) public final val c: = R|/|.component1#() @SecondRightAnno(LAZY_EXPRESSION) public final val d: = R|/|.component2#() + +