From 601ffb2db4eb3ee6f50b1a47e20747e5861e074d Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Mon, 7 Aug 2023 15:44:50 +0200 Subject: [PATCH] [LL FIR] transform script body properly Problem: transformSingle for expressions can return another expression, and we should replace the original one with such new expression ^KT-61011 Fixed ^KT-61009 Fixed --- .../LLFirAbstractBodyTargetResolver.kt | 22 +- .../fir/transformers/LLFirBodyLazyResolver.kt | 1 + .../api/fir/util/firCheckResolvedUtils.kt | 10 + .../calls/compoundAssignOnVarScript.txt | 4 +- .../lazyResolve/statementTransformation.kts | 9 + .../lazyResolve/statementTransformation.txt | 193 ++++++++++++++++++ ...ptLazyDeclarationResolveTestGenerated.java | 6 + 7 files changed, 236 insertions(+), 9 deletions(-) create mode 100644 analysis/low-level-api-fir/testdata/lazyResolve/statementTransformation.kts create mode 100644 analysis/low-level-api-fir/testdata/lazyResolve/statementTransformation.txt diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAbstractBodyTargetResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAbstractBodyTargetResolver.kt index 284b9414160..25ee5ba7830 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAbstractBodyTargetResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAbstractBodyTargetResolver.kt @@ -11,14 +11,17 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.LLFirRetu import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isScriptStatement +import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession +import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.transformSingle internal abstract class LLFirAbstractBodyTargetResolver( @@ -27,7 +30,7 @@ internal abstract class LLFirAbstractBodyTargetResolver( private val scopeSession: ScopeSession, resolvePhase: FirResolvePhase, protected val implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession = ImplicitBodyResolveComputationSession(), - isJumpingPhase: Boolean = false + isJumpingPhase: Boolean = false, ) : LLFirTargetResolver(resolveTarget, lockProvider, resolvePhase, isJumpingPhase) { protected fun createReturnTypeCalculator( firResolveContextCollector: FirResolveContextCollector?, @@ -78,12 +81,17 @@ internal abstract class LLFirAbstractBodyTargetResolver( protected fun resolveScript(script: FirScript) { transformer.declarationsTransformer?.withScript(script) { script.parameters.forEach { it.transformSingle(transformer, ResolutionMode.ContextIndependent) } - script.statements.forEach { - if (it.isScriptStatement) { - transformer.firResolveContextCollector?.addStatementContext(it, transformer.context) - it.transformSingle(transformer, ResolutionMode.ContextIndependent) - } - } + script.transformStatements( + transformer = object : FirTransformer() { + override fun transformElement(element: E, data: Any?): E { + if (element !is FirStatement || !element.isScriptStatement) return element + + transformer.firResolveContextCollector?.addStatementContext(element, transformer.context) + return element.transformSingle(transformer, ResolutionMode.ContextIndependent) + } + }, + data = null, + ) script } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt index f0fd2333bcc..707ee099898 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt @@ -74,6 +74,7 @@ internal object LLFirBodyLazyResolver : LLFirLazyResolver(FirResolvePhase.BODY_R checkBodyIsResolved(target) } is FirFunction -> checkBodyIsResolved(target) + is FirScript -> checkStatementsAreResolved(target) } } } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/firCheckResolvedUtils.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/firCheckResolvedUtils.kt index 5546090e0c9..d870a9b7640 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/firCheckResolvedUtils.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/firCheckResolvedUtils.kt @@ -64,6 +64,16 @@ internal fun checkBodyIsResolved(function: FirFunction) { } } +internal fun checkStatementsAreResolved(script: FirScript) { + for (statement in script.statements) { + if (statement.isScriptStatement && statement is FirExpression) { + checkTypeRefIsResolved(statement.typeRef, "script statement", script) { + withFirEntry("expression", statement) + } + } + } +} + internal fun checkExpectForActualIsResolved(memberDeclaration: FirMemberDeclaration) { if (!memberDeclaration.isActual) return diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/compoundAssignOnVarScript.txt b/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/compoundAssignOnVarScript.txt index d4b53e3f4c6..be4b0ca6eb5 100644 --- a/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/compoundAssignOnVarScript.txt +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/compoundAssignOnVarScript.txt @@ -11,7 +11,7 @@ SCRIPT: [ResolvedTo(BODY_RESOLVE)] public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] get(): R|kotlin/Int| public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] set([ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| - +=(R|/i|, Int(1)) + R|/i| = R|/i|.R|kotlin/Int.plus|(Int(1)) FIR FILE: FILE: [ResolvedTo(IMPORTS)] compoundAssignOnVarScript.kts @@ -23,4 +23,4 @@ FILE: [ResolvedTo(IMPORTS)] compoundAssignOnVarScript.kts public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] get(): R|kotlin/Int| public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] set([ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| - +=(R|/i|, Int(1)) \ No newline at end of file + R|/i| = R|/i|.R|kotlin/Int.plus|(Int(1)) \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/statementTransformation.kts b/analysis/low-level-api-fir/testdata/lazyResolve/statementTransformation.kts new file mode 100644 index 00000000000..48e575f8a0a --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/statementTransformation.kts @@ -0,0 +1,9 @@ +// RESOLVE_SCRIPT + +val myProp: () -> Unit = {} + +myProp { + 123 +} + +fun foo() {} \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/statementTransformation.txt b/analysis/low-level-api-fir/testdata/lazyResolve/statementTransformation.txt new file mode 100644 index 00000000000..681861cd53b --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/statementTransformation.txt @@ -0,0 +1,193 @@ +RAW_FIR: +FILE: [ResolvedTo(RAW_FIR)] statementTransformation.kts + context(