From a3a15509335e50711686a0bb9702f947adfe2fa2 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Tue, 8 Nov 2022 10:42:10 +0100 Subject: [PATCH] K2 scripting: add initial scripting support to K2 frontend --- .../expression/FirOptInUsageBaseChecker.kt | 2 +- .../kotlin/fir/resolve/calls/FirReceivers.kt | 26 ++++-- .../scopes/impl/FirScriptDeclarationsScope.kt | 84 +++++++++++++++++++ .../kotlin/fir/builder/RawFirBuilder.kt | 31 ++++++- .../fir/resolve/dfa/FirDataFlowAnalyzer.kt | 11 +++ .../dfa/cfg/ControlFlowGraphBuilder.kt | 16 ++++ .../dfa/cfg/ControlFlowGraphNodeBuilder.kt | 6 ++ .../body/resolve/BodyResolveContext.kt | 31 +++++++ ...bstractBodyResolveTransformerDispatcher.kt | 4 + .../FirDeclarationsResolveTransformer.kt | 12 +++ ...actContractResolveTransformerDispatcher.kt | 4 + ...irAnnotationArgumentsResolveTransformer.kt | 4 + .../kotlin/fir/declarations/ScriptScopes.kt | 33 ++++++++ .../kotlin/fir/resolve/dfa/cfg/CFGNode.kt | 14 ++++ .../fir/resolve/dfa/cfg/CFGNodeRenderer.kt | 3 + .../dfa/cfg/ControlFlowGraphVisitor.kt | 10 +++ .../kotlin/fir/declarations/FirScript.kt | 45 ++++++++++ .../declarations/builder/FirScriptBuilder.kt | 68 +++++++++++++++ .../fir/declarations/impl/FirScriptImpl.kt | 71 ++++++++++++++++ .../kotlin/fir/visitors/FirDefaultVisitor.kt | 3 + .../fir/visitors/FirDefaultVisitorVoid.kt | 3 + .../kotlin/fir/visitors/FirTransformer.kt | 9 ++ .../kotlin/fir/visitors/FirVisitor.kt | 3 + .../kotlin/fir/visitors/FirVisitorVoid.kt | 9 ++ .../fir/symbols/impl/FirScriptSymbol.kt | 12 +++ .../fir/tree/generator/FirTreeBuilder.kt | 1 + .../fir/tree/generator/NodeConfigurator.kt | 7 ++ 27 files changed, 513 insertions(+), 9 deletions(-) create mode 100644 compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirScriptDeclarationsScope.kt create mode 100644 compiler/fir/semantics/src/org/jetbrains/kotlin/fir/declarations/ScriptScopes.kt create mode 100644 compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirScript.kt create mode 100644 compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirScriptBuilder.kt create mode 100644 compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirScriptImpl.kt create mode 100644 compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirScriptSymbol.kt diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt index ec46ade2a93..00c220bd7c8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageBaseChecker.kt @@ -153,7 +153,7 @@ object FirOptInUsageBaseChecker { fir.loadCallableSpecificExperimentalities(this, context, visited, fromSetter, dispatchReceiverType, result) is FirClassLikeDeclaration -> fir.loadClassLikeSpecificExperimentalities(this, context, visited, result) - is FirAnonymousInitializer, is FirFile, is FirTypeParameter -> {} + is FirAnonymousInitializer, is FirFile, is FirTypeParameter, is FirScript -> {} } fir.loadExperimentalitiesFromAnnotationTo(session, result, fromSupertype) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt index 5d75d2d49d9..7560b108074 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/calls/FirReceivers.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirScriptSymbol import org.jetbrains.kotlin.fir.types.ConeErrorType import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef @@ -221,6 +222,9 @@ sealed class ContextReceiverValue>( boundSymbol, type, useSiteSession, scopeSession, mutable, contextReceiverNumber, ) { abstract override fun createSnapshot(): ContextReceiverValue + + override val isContextReceiver: Boolean + get() = true } class ContextReceiverValueForCallable( @@ -236,9 +240,6 @@ class ContextReceiverValueForCallable( ) { override fun createSnapshot(): ContextReceiverValue> = ContextReceiverValueForCallable(boundSymbol, type, labelName, useSiteSession, scopeSession, mutable = false, contextReceiverNumber) - - override val isContextReceiver: Boolean - get() = true } class ContextReceiverValueForClass( @@ -254,7 +255,20 @@ class ContextReceiverValueForClass( ) { override fun createSnapshot(): ContextReceiverValue> = ContextReceiverValueForClass(boundSymbol, type, labelName, useSiteSession, scopeSession, mutable = false, contextReceiverNumber) - - override val isContextReceiver: Boolean - get() = true } + +class ImplicitReceiverValueForScript( + boundSymbol: FirScriptSymbol, + type: ConeKotlinType, + labelName: Name?, + useSiteSession: FirSession, + scopeSession: ScopeSession, + mutable: Boolean = true, + contextReceiverNumber: Int, +) : ContextReceiverValue( + boundSymbol, type, labelName, useSiteSession, scopeSession, mutable, contextReceiverNumber +) { + override fun createSnapshot(): ContextReceiverValue = + ImplicitReceiverValueForScript(boundSymbol, type, labelName, useSiteSession, scopeSession, mutable = false, contextReceiverNumber) +} + diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirScriptDeclarationsScope.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirScriptDeclarationsScope.kt new file mode 100644 index 00000000000..307e0d5a0ef --- /dev/null +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirScriptDeclarationsScope.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2022 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.scopes.impl + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap +import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope +import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.SpecialNames + +class FirScriptDeclarationsScope( + val useSiteSession: FirSession, + val script: FirScript, +) : FirContainingNamesAwareScope() { + + private val callablesIndex: Map>> = run { + val result = mutableMapOf>>() + loop@ for (statement in script.statements) { + if (statement is FirCallableDeclaration) { + val name = when (statement) { + is FirVariable -> if (statement.isSynthetic) continue@loop else statement.name + is FirSimpleFunction -> statement.name + // TODO: destructuring decl + else -> continue@loop + } + result.getOrPut(name) { mutableListOf() } += statement.symbol + } + } + result + } + + private val classIndex: Map = run { + val result = mutableMapOf() + for (declaration in script.statements) { + if (declaration is FirRegularClass) { + result[declaration.name] = declaration.symbol + } + } + result + } + + override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) { + if (name == SpecialNames.INIT) return + processCallables(name, processor) + } + + override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { + processCallables(name, processor) + } + + private inline fun > processCallables( + name: Name, + processor: (D) -> Unit + ) { + val symbols = callablesIndex[name] ?: emptyList() + for (symbol in symbols) { + if (symbol is D) { + processor(symbol) + } + } + } + + override fun getCallableNames(): Set { + return callablesIndex.keys + } + + override fun processClassifiersByNameWithSubstitution( + name: Name, + processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit + ) { + val matchedClass = classIndex[name] ?: return + val substitution = matchedClass.typeParameterSymbols.associateWith { it.toConeType() } + processor(matchedClass, ConeSubstitutorByMap(substitution, useSiteSession)) + } + + override fun getClassifierNames(): Set = classIndex.keys +} \ No newline at end of file diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 607f68e9f89..5ab57421841 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -992,8 +992,10 @@ open class RawFirBuilder( } for (declaration in file.declarations) { declarations += when (declaration) { - // TODO: scripts aren't supported yet - is KtScript -> continue + is KtScript -> { + require(file.declarations.size == 1) { "Expect the script to be the only declaration in the file $name" } + convertScript(declaration, this) + } is KtDestructuringDeclaration -> buildErrorTopLevelDestructuringDeclaration(declaration.toFirSourceElement()) else -> declaration.convert() } @@ -1001,6 +1003,30 @@ open class RawFirBuilder( } } + private fun convertScript(script: KtScript, containingFile: FirFileBuilder,): FirScript { + return buildScript { + source = script.toFirSourceElement() + moduleData = baseModuleData + origin = FirDeclarationOrigin.Source + name = Name.special("") + symbol = FirScriptSymbol(context.packageFqName.child(name)) + for (declaration in script.declarations) { + when (declaration) { + is KtScriptInitializer -> { + declaration.body?.let { statements.add(it.toFirStatement()) } + } + else -> { + statements.add(declaration.toFirStatement()) + } + } + } + } + } + + override fun visitScript(script: KtScript, data: Unit?): FirElement { + error("should not be here") + } + protected fun KtEnumEntry.toFirEnumEntry( delegatedEnumSelfTypeRef: FirResolvedTypeRef, ownerClassHasDefaultConstructor: Boolean @@ -2145,6 +2171,7 @@ open class RawFirBuilder( return (parent.parent as? KtExpression)?.usedAsExpression ?: true } } + if (parent is KtScriptInitializer) return false // Here we check that when used is a single statement of a loop if (parent !is KtContainerNodeForControlStructureBody) return true val type = parent.parent.elementType diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt index a257d677943..6fd51b3d056 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt @@ -308,6 +308,17 @@ abstract class FirDataFlowAnalyzer( graphBuilder.exitAnonymousObjectExpression(anonymousObjectExpression).mergeIncomingFlow() } + // ----------------------------------- Scripts ------------------------------------------ + + fun enterScript(script: FirScript) { + val res = graphBuilder.enterScript(script) + res.mergeIncomingFlow() + } + + fun exitScript(script: FirScript) { + graphBuilder.exitScript(script) + } + // ----------------------------------- Value parameters (and it's defaults) ----------------------------------- fun enterValueParameter(valueParameter: FirValueParameter) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt index 27031dedc4e..43cb05efcc6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt @@ -515,6 +515,22 @@ class ControlFlowGraphBuilder { } } + fun enterScript(script: FirScript): ScriptEnterNode { + pushGraph( + ControlFlowGraph(null, "SCRIPT_GRAPH", ControlFlowGraph.Kind.Function), + mode = Mode.Body + ) + val enterNode = createScriptEnterNode(script) + lastNodes.push(enterNode) + return enterNode + } + + fun exitScript(script: FirScript): ScriptExitNode { + return createScriptExitNode(script).also { + addNewSimpleNodeIfPossible(it) + } + } + private fun visitLocalClassFunctions(klass: FirClass, node: CFGNodeWithSubgraphs<*>) { klass.declarations.filterIsInstance().forEach { function -> val functionGraph = function.controlFlowGraphReference?.controlFlowGraph diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt index 933885e66ff..a4e3fd108dc 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphNodeBuilder.kt @@ -235,6 +235,12 @@ fun ControlFlowGraphBuilder.createAnonymousObjectExitNode(fir: FirAnonymousObjec fun ControlFlowGraphBuilder.createAnonymousObjectExpressionExitNode(fir: FirAnonymousObjectExpression): AnonymousObjectExpressionExitNode = AnonymousObjectExpressionExitNode(currentGraph, fir, levelCounter, createId()) +fun ControlFlowGraphBuilder.createScriptEnterNode(fir: FirScript): ScriptEnterNode = + ScriptEnterNode(currentGraph, fir, levelCounter, createId()) + +fun ControlFlowGraphBuilder.createScriptExitNode(fir: FirScript): ScriptExitNode = + ScriptExitNode(currentGraph, fir, levelCounter, createId()) + fun ControlFlowGraphBuilder.createUnionFunctionCallArgumentsNode(fir: FirElement): UnionFunctionCallArgumentsNode = UnionFunctionCallArgumentsNode(currentGraph, fir, levelCounter, createId()) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt index f9c31816f2d..34eb9624260 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt @@ -492,6 +492,37 @@ class BodyResolveContext( } } + fun withScopesForScript( + owner: FirScript, + holder: SessionHolder, + f: () -> T + ): T { + val towerElementsForScript = holder.collectTowerDataElementsForScript(owner) + + val base = towerDataContext.addNonLocalTowerDataElements(emptyList()) + val statics = base + .addNonLocalScopeIfNotNull(towerElementsForScript.staticScope) + + val forMembersResolution = + statics + .addContextReceiverGroup(towerElementsForScript.implicitReceivers) + + val newContexts = FirRegularTowerDataContexts( + regular = forMembersResolution, + forClassHeaderAnnotations = base, + forNestedClasses = forMembersResolution, + forCompanionObject = statics, + forConstructorHeaders = null, + forEnumEntries = null, + primaryConstructorPureParametersScope = null, + primaryConstructorAllParametersScope = null + ) + + return withTowerDataContexts(newContexts) { + f() + } + } + @OptIn(PrivateForInline::class) inline fun withWhenSubjectType( subjectType: ConeKotlinType?, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformerDispatcher.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformerDispatcher.kt index 89654121459..69cdbc4e348 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformerDispatcher.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformerDispatcher.kt @@ -57,6 +57,10 @@ abstract class FirAbstractBodyResolveTransformerDispatcher( } } + override fun transformScript(script: FirScript, data: ResolutionMode): FirScript { + return declarationsTransformer.transformScript(script, data) + } + override fun transformElement(element: E, data: ResolutionMode): E { @Suppress("UNCHECKED_CAST") return (element.transformChildren(this, data) as E) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 9d9c257c04f..34a6708d30e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -507,6 +507,18 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve } } + override fun transformScript(script: FirScript, data: ResolutionMode): FirScript { + if (implicitTypeOnly) return script + dataFlowAnalyzer.enterScript(script) + val result = context.withScopesForScript(script, components) { + transformDeclarationContent(script, data) as FirScript + } + + dataFlowAnalyzer.exitScript(script) + + return result + } + override fun transformTypeAlias(typeAlias: FirTypeAlias, data: ResolutionMode): FirTypeAlias { if (typeAlias.isLocal && typeAlias !in context.targetedLocalClasses) { return typeAlias.runAllPhasesForLocalClass( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt index 26184876bdd..0c1a195cb43 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirAbstractContractResolveTransformerDispatcher.kt @@ -90,6 +90,10 @@ abstract class FirAbstractContractResolveTransformerDispatcher( } } + override fun transformScript(script: FirScript, data: ResolutionMode): FirScript { + return script + } + override fun transformProperty(property: FirProperty, data: ResolutionMode): FirProperty { if ( property.getter?.hasContractToResolve != true && property.setter?.hasContractToResolve != true || diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt index d06cba4ea9b..5a514de77ed 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt @@ -132,6 +132,10 @@ private class FirDeclarationsResolveTransformerForArgumentAnnotations( typeAlias.transformAnnotations(transformer, data) return typeAlias } + + override fun transformScript(script: FirScript, data: ResolutionMode): FirScript { + return script + } } private class FirExpressionsResolveTransformerForSpecificAnnotations( diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/declarations/ScriptScopes.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/declarations/ScriptScopes.kt new file mode 100644 index 00000000000..00b484c3c24 --- /dev/null +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/declarations/ScriptScopes.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2022 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.declarations + +import org.jetbrains.kotlin.fir.labelName +import org.jetbrains.kotlin.fir.resolve.SessionHolder +import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValueForScript +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.impl.FirScriptDeclarationsScope +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.coneType + +class TowerElementsForScript( + val implicitReceivers: List, + val staticScope: FirScope?, +) + +fun SessionHolder.collectTowerDataElementsForScript(owner: FirScript): TowerElementsForScript { + val contextReceivers = owner.contextReceivers.mapIndexed { index, receiver -> + ImplicitReceiverValueForScript( + owner.symbol, receiver.typeRef.coneType, receiver.labelName, session, scopeSession, + contextReceiverNumber = index, + ) + } + + return TowerElementsForScript( + contextReceivers, + FirScriptDeclarationsScope(session, owner), + ) +} diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt index 16749844236..fe372bb4312 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNode.kt @@ -303,6 +303,20 @@ class AnonymousObjectExpressionExitNode(owner: ControlFlowGraph, override val fi } } +// ----------------------------------- Scripts ------------------------------------------ + +class ScriptEnterNode(owner: ControlFlowGraph, override val fir: FirScript, level: Int, id: Int) : CFGNode(owner, level, id) { + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { + return visitor.visitScriptEnterNode(this, data) + } +} + +class ScriptExitNode(owner: ControlFlowGraph, override val fir: FirScript, level: Int, id: Int) : CFGNode(owner, level, id) { + override fun accept(visitor: ControlFlowGraphVisitor, data: D): R { + return visitor.visitScriptExitNode(this, data) + } +} + // ----------------------------------- Initialization ----------------------------------- class PartOfClassInitializationNode(owner: ControlFlowGraph, override val fir: FirControlFlowGraphOwner, level: Int, id: Int) : CFGNodeWithCfgOwner(owner, level, id) { diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt index 769cbd160f1..c46d359261b 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt @@ -112,6 +112,9 @@ fun CFGNode<*>.render(): String = is AnonymousObjectExitNode -> "Exit anonymous object" is AnonymousObjectExpressionExitNode -> "Exit anonymous object expression" + is ScriptEnterNode -> "Enter class ${fir.name}" + is ScriptExitNode -> "Exit class ${fir.name}" + is ContractDescriptionEnterNode -> "Enter contract description" is EnterDefaultArgumentsNode -> "Enter default value of ${fir.name}" diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt index 4ea6228ec11..7587ea5f24e 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphVisitor.kt @@ -80,6 +80,16 @@ abstract class ControlFlowGraphVisitor { return visitNode(node, data) } + // ----------------------------------- Scripts ------------------------------------------ + + open fun visitScriptEnterNode(node: ScriptEnterNode, data: D): R { + return visitNode(node, data) + } + + open fun visitScriptExitNode(node: ScriptExitNode, data: D): R { + return visitNode(node, data) + } + // ----------------------------------- Initialization ----------------------------------- open fun visitPartOfClassInitializationNode(node: PartOfClassInitializationNode, data: D): R { diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirScript.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirScript.kt new file mode 100644 index 00000000000..ef4c33f4bfd --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirScript.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2022 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.declarations + +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.symbols.impl.FirScriptSymbol +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.fir.visitors.* + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +abstract class FirScript : FirDeclaration() { + abstract override val source: KtSourceElement? + abstract override val annotations: List + abstract override val moduleData: FirModuleData + abstract override val resolvePhase: FirResolvePhase + abstract override val origin: FirDeclarationOrigin + abstract override val attributes: FirDeclarationAttributes + abstract val name: Name + abstract val statements: List + abstract override val symbol: FirScriptSymbol + abstract val contextReceivers: List + + override fun accept(visitor: FirVisitor, data: D): R = visitor.visitScript(this, data) + + @Suppress("UNCHECKED_CAST") + override fun transform(transformer: FirTransformer, data: D): E = + transformer.transformScript(this, data) as E + + abstract override fun replaceResolvePhase(newResolvePhase: FirResolvePhase) + + abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirScript + + abstract fun transformStatements(transformer: FirTransformer, data: D): FirScript +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirScriptBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirScriptBuilder.kt new file mode 100644 index 00000000000..dbd3e0ad2cc --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirScriptBuilder.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2022 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.declarations.builder + +import kotlin.contracts.* +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder +import org.jetbrains.kotlin.fir.builder.FirBuilderDsl +import org.jetbrains.kotlin.fir.declarations.FirContextReceiver +import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.declarations.FirScript +import org.jetbrains.kotlin.fir.declarations.impl.FirScriptImpl +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.symbols.impl.FirScriptSymbol +import org.jetbrains.kotlin.fir.visitors.* +import org.jetbrains.kotlin.name.Name + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +@FirBuilderDsl +class FirScriptBuilder : FirAnnotationContainerBuilder { + override var source: KtSourceElement? = null + override val annotations: MutableList = mutableListOf() + lateinit var moduleData: FirModuleData + var resolvePhase: FirResolvePhase = FirResolvePhase.RAW_FIR + lateinit var origin: FirDeclarationOrigin + var attributes: FirDeclarationAttributes = FirDeclarationAttributes() + lateinit var name: Name + val statements: MutableList = mutableListOf() + lateinit var symbol: FirScriptSymbol + val contextReceivers: MutableList = mutableListOf() + + override fun build(): FirScript { + return FirScriptImpl( + source, + annotations, + moduleData, + resolvePhase, + origin, + attributes, + name, + statements, + symbol, + contextReceivers, + ) + } + +} + +@OptIn(ExperimentalContracts::class) +inline fun buildScript(init: FirScriptBuilder.() -> Unit): FirScript { + contract { + callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE) + } + return FirScriptBuilder().apply(init).build() +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirScriptImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirScriptImpl.kt new file mode 100644 index 00000000000..14c7563c727 --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirScriptImpl.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2010-2022 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.declarations.impl + +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.fir.declarations.FirContextReceiver +import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.declarations.FirScript +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.symbols.impl.FirScriptSymbol +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.fir.visitors.* + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +internal class FirScriptImpl( + override val source: KtSourceElement?, + override val annotations: MutableList, + override val moduleData: FirModuleData, + @Volatile + override var resolvePhase: FirResolvePhase, + override val origin: FirDeclarationOrigin, + override val attributes: FirDeclarationAttributes, + override val name: Name, + override val statements: MutableList, + override val symbol: FirScriptSymbol, + override val contextReceivers: MutableList, +) : FirScript() { + init { + symbol.bind(this) + } + + override fun acceptChildren(visitor: FirVisitor, data: D) { + annotations.forEach { it.accept(visitor, data) } + statements.forEach { it.accept(visitor, data) } + contextReceivers.forEach { it.accept(visitor, data) } + } + + override fun transformChildren(transformer: FirTransformer, data: D): FirScriptImpl { + transformAnnotations(transformer, data) + transformStatements(transformer, data) + contextReceivers.transformInplace(transformer, data) + return this + } + + override fun transformAnnotations(transformer: FirTransformer, data: D): FirScriptImpl { + annotations.transformInplace(transformer, data) + return this + } + + override fun transformStatements(transformer: FirTransformer, data: D): FirScriptImpl { + statements.transformInplace(transformer, data) + return this + } + + override fun replaceResolvePhase(newResolvePhase: FirResolvePhase) { + resolvePhase = newResolvePhase + } +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt index e06c0eaf363..e27a82aee1d 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor import org.jetbrains.kotlin.fir.declarations.FirBackingField import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirScript import org.jetbrains.kotlin.fir.FirPackageDirective import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression @@ -170,6 +171,8 @@ abstract class FirDefaultVisitor : FirVisitor() { override fun visitFile(file: FirFile, data: D): R = visitDeclaration(file, data) + override fun visitScript(script: FirScript, data: D): R = visitDeclaration(script, data) + override fun visitAnonymousFunctionExpression(anonymousFunctionExpression: FirAnonymousFunctionExpression, data: D): R = visitExpression(anonymousFunctionExpression, data) override fun visitAnonymousObjectExpression(anonymousObjectExpression: FirAnonymousObjectExpression, data: D): R = visitExpression(anonymousObjectExpression, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt index e9139487717..e70c76247ea 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor import org.jetbrains.kotlin.fir.declarations.FirBackingField import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirScript import org.jetbrains.kotlin.fir.FirPackageDirective import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression @@ -170,6 +171,8 @@ abstract class FirDefaultVisitorVoid : FirVisitorVoid() { override fun visitFile(file: FirFile) = visitDeclaration(file) + override fun visitScript(script: FirScript) = visitDeclaration(script) + override fun visitAnonymousFunctionExpression(anonymousFunctionExpression: FirAnonymousFunctionExpression) = visitExpression(anonymousFunctionExpression) override fun visitAnonymousObjectExpression(anonymousObjectExpression: FirAnonymousObjectExpression) = visitExpression(anonymousObjectExpression) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt index c1e49bb1564..70e4d586226 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor import org.jetbrains.kotlin.fir.declarations.FirBackingField import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirScript import org.jetbrains.kotlin.fir.FirPackageDirective import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression @@ -305,6 +306,10 @@ abstract class FirTransformer : FirVisitor() { return transformElement(file, data) } + open fun transformScript(script: FirScript, data: D): FirScript { + return transformElement(script, data) + } + open fun transformPackageDirective(packageDirective: FirPackageDirective, data: D): FirPackageDirective { return transformElement(packageDirective, data) } @@ -857,6 +862,10 @@ abstract class FirTransformer : FirVisitor() { return transformFile(file, data) } + final override fun visitScript(script: FirScript, data: D): FirScript { + return transformScript(script, data) + } + final override fun visitPackageDirective(packageDirective: FirPackageDirective, data: D): FirPackageDirective { return transformPackageDirective(packageDirective, data) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt index db321a2c9e3..8fcdf0361fc 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor import org.jetbrains.kotlin.fir.declarations.FirBackingField import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirScript import org.jetbrains.kotlin.fir.FirPackageDirective import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression @@ -228,6 +229,8 @@ abstract class FirVisitor { open fun visitFile(file: FirFile, data: D): R = visitElement(file, data) + open fun visitScript(script: FirScript, data: D): R = visitElement(script, data) + open fun visitPackageDirective(packageDirective: FirPackageDirective, data: D): R = visitElement(packageDirective, data) open fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: D): R = visitElement(anonymousFunction, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt index 46edb374931..24193c839b9 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt @@ -44,6 +44,7 @@ import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor import org.jetbrains.kotlin.fir.declarations.FirBackingField import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirScript import org.jetbrains.kotlin.fir.FirPackageDirective import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression @@ -304,6 +305,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitElement(file) } + open fun visitScript(script: FirScript) { + visitElement(script) + } + open fun visitPackageDirective(packageDirective: FirPackageDirective) { visitElement(packageDirective) } @@ -856,6 +861,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitFile(file) } + final override fun visitScript(script: FirScript, data: Nothing?) { + visitScript(script) + } + final override fun visitPackageDirective(packageDirective: FirPackageDirective, data: Nothing?) { visitPackageDirective(packageDirective) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirScriptSymbol.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirScriptSymbol.kt new file mode 100644 index 00000000000..c4845410af9 --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirScriptSymbol.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2022 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.symbols.impl + +import org.jetbrains.kotlin.fir.declarations.FirScript +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.name.FqName + +class FirScriptSymbol(val fqName: FqName) : FirBasedSymbol() diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt index 8b520d63996..2d7fcd9c824 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt @@ -60,6 +60,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() { val backingField by element(Declaration, variable, typeParametersOwner, statement) val constructor by element(Declaration, function, typeParameterRefsOwner) val file by element(Declaration, declaration) + val script by element(Declaration, declaration) val packageDirective by element(Other) val anonymousFunction by element(Declaration, function, typeParametersOwner) diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index 0b8b5519efb..93ab5165493 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -451,6 +451,13 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild +symbol("FirFileSymbol") } + script.configure { + +name + +fieldList(statement).withTransform() + +symbol("FirScriptSymbol") + +fieldList(contextReceiver) + } + packageDirective.configure { +field("packageFqName", fqNameType) }