K2 Scripting: wrap script statements into blocks
(reuse anonymous initializers as block wrappers) so the top-level script elements are all declarations now. Rename the property accordingly ( together with the previous commit). It makes script more similar to the class and thus simplify e.g. control flow analysis and resolve code.
This commit is contained in:
committed by
Space Team
parent
c9aee5bf09
commit
eeb723eb01
@@ -518,19 +518,19 @@ class Fir2IrConverter(
|
||||
addDeclarationToParentIfNeeded(irScript)
|
||||
declarationStorage.withScope(irScript.symbol) {
|
||||
irScript.parent = parent
|
||||
for (scriptStatement in declaration.declarations) {
|
||||
when (scriptStatement) {
|
||||
for (scriptDeclaration in declaration.declarations) {
|
||||
when (scriptDeclaration) {
|
||||
is FirRegularClass -> {
|
||||
registerClassAndNestedClasses(scriptStatement, irScript)
|
||||
processClassAndNestedClassHeaders(scriptStatement)
|
||||
registerClassAndNestedClasses(scriptDeclaration, irScript)
|
||||
processClassAndNestedClassHeaders(scriptDeclaration)
|
||||
}
|
||||
is FirTypeAlias -> classifierStorage.createAndCacheIrTypeAlias(scriptStatement, irScript)
|
||||
is FirTypeAlias -> classifierStorage.createAndCacheIrTypeAlias(scriptDeclaration, irScript)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
for (scriptStatement in declaration.declarations) {
|
||||
if (scriptStatement is FirDeclaration) {
|
||||
processMemberDeclaration(scriptStatement, containingClass = null, irScript, delegateFieldToPropertyMap = null)
|
||||
for (scriptDeclaration in declaration.declarations) {
|
||||
if (scriptDeclaration !is FirAnonymousInitializer) {
|
||||
processMemberDeclaration(scriptDeclaration, containingClass = null, irScript, delegateFieldToPropertyMap = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,8 +255,8 @@ class Fir2IrVisitor(
|
||||
conversionScope.withParent(irScript) {
|
||||
val destructComposites = mutableMapOf<FirVariableSymbol<*>, IrComposite>()
|
||||
for (statement in script.declarations) {
|
||||
val irStatement = if (statement is FirDeclaration) {
|
||||
when {
|
||||
if (statement !is FirAnonymousInitializer) {
|
||||
val irStatement = when {
|
||||
statement is FirProperty && statement.name == SpecialNames.UNDERSCORE_FOR_UNUSED_VAR -> {
|
||||
continue
|
||||
}
|
||||
@@ -311,10 +311,12 @@ class Fir2IrVisitor(
|
||||
statement.accept(this@Fir2IrVisitor, null) as? IrDeclaration
|
||||
}
|
||||
}
|
||||
irScript.statements.add(irStatement!!)
|
||||
} else {
|
||||
statement.toIrStatement()
|
||||
statement.body?.statements?.mapNotNull { it.toIrStatement() }?.let {
|
||||
irScript.statements.addAll(it)
|
||||
}
|
||||
}
|
||||
irScript.statements.add(irStatement!!)
|
||||
}
|
||||
}
|
||||
for (configurator in session.extensionService.fir2IrScriptConfigurators) {
|
||||
|
||||
+71
-40
@@ -1276,50 +1276,81 @@ open class PsiRawFirBuilder(
|
||||
fileName: String,
|
||||
sourceFile: KtSourceFile?,
|
||||
setup: FirScriptBuilder.() -> Unit = {},
|
||||
): FirScript = buildScript {
|
||||
source = script.toFirSourceElement()
|
||||
moduleData = baseModuleData
|
||||
origin = FirDeclarationOrigin.Source
|
||||
name = Name.special("<script-$fileName>")
|
||||
symbol = FirScriptSymbol(context.packageFqName.child(name))
|
||||
withContainerSymbol(symbol) {
|
||||
for (declaration in script.declarations) {
|
||||
when (declaration) {
|
||||
is KtScriptInitializer -> {
|
||||
declaration.body?.let { declarations.add(it.toFirStatement()) }
|
||||
}
|
||||
is KtDestructuringDeclaration -> {
|
||||
val destructuringContainerVar = generateTemporaryVariable(
|
||||
baseModuleData,
|
||||
declaration.toFirSourceElement(),
|
||||
"destruct",
|
||||
declaration.initializer.toFirExpression { ConeSyntaxDiagnostic("Initializer required for destructuring declaration") },
|
||||
origin = FirDeclarationOrigin.Synthetic.ScriptTopLevelDestructuringDeclarationContainer,
|
||||
extractAnnotationsTo = { extractAnnotationsTo(it) }
|
||||
).apply {
|
||||
isDestructuringDeclarationContainerVariable = true
|
||||
}
|
||||
declarations.add(destructuringContainerVar)
|
||||
): FirScript {
|
||||
val scriptName = Name.special("<script-$fileName>")
|
||||
val scriptSymbol = FirScriptSymbol(context.packageFqName.child(scriptName))
|
||||
|
||||
declarations.addDestructuringVariables(
|
||||
moduleData,
|
||||
declaration,
|
||||
destructuringContainerVar,
|
||||
tmpVariable = false,
|
||||
localEntries = false,
|
||||
) {
|
||||
(it as FirProperty).destructuringDeclarationContainerVariable = destructuringContainerVar.symbol
|
||||
return buildScript {
|
||||
source = script.toFirSourceElement()
|
||||
moduleData = baseModuleData
|
||||
origin = FirDeclarationOrigin.Source
|
||||
name = scriptName
|
||||
symbol = scriptSymbol
|
||||
|
||||
val scriptDeclarationsIter = script.declarations.listIterator()
|
||||
withContainerSymbol(symbol) {
|
||||
while (scriptDeclarationsIter.hasNext()) {
|
||||
val declaration = scriptDeclarationsIter.next()
|
||||
val isLast = !scriptDeclarationsIter.hasNext()
|
||||
val declarationSource = declaration.toFirSourceElement()
|
||||
when (declaration) {
|
||||
is KtScriptInitializer -> {
|
||||
val firBlock =
|
||||
if (isLast) {
|
||||
// the last one need to be analyzed in script configurator to decide on result property
|
||||
// therefore no lazy conversion in this case
|
||||
withForcedLocalContext { declaration.body.toFirBlock() }
|
||||
} else {
|
||||
buildOrLazyBlock { withForcedLocalContext { declaration.body.toFirBlock() } }
|
||||
}
|
||||
declarations.add(
|
||||
buildAnonymousInitializer {
|
||||
moduleData = baseModuleData
|
||||
origin = FirDeclarationOrigin.Source
|
||||
source = declarationSource
|
||||
body = firBlock
|
||||
declaration.extractAnnotationsTo(this)
|
||||
}
|
||||
)
|
||||
}
|
||||
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
|
||||
}
|
||||
declarations.add(destructuringContainerVar)
|
||||
|
||||
declarations.addDestructuringVariables(
|
||||
moduleData,
|
||||
declaration,
|
||||
destructuringContainerVar,
|
||||
tmpVariable = false,
|
||||
localEntries = false,
|
||||
) {
|
||||
(it as FirProperty).destructuringDeclarationContainerVariable = destructuringContainerVar.symbol
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val firStatement = declaration.toFirStatement()
|
||||
if (firStatement is FirDeclaration) {
|
||||
declarations.add(firStatement)
|
||||
} else {
|
||||
error("unexpected declaration type in script")
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
declarations.add(declaration.toFirStatement())
|
||||
}
|
||||
}
|
||||
}
|
||||
setup()
|
||||
if (sourceFile != null) {
|
||||
for (configurator in baseSession.extensionService.scriptConfigurators) {
|
||||
with(configurator) { configure(sourceFile) }
|
||||
setup()
|
||||
if (sourceFile != null) {
|
||||
for (configurator in baseSession.extensionService.scriptConfigurators) {
|
||||
with(configurator) { configure(sourceFile) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,28 +37,43 @@ FILE: script.kts
|
||||
^build2 Builder#().apply#(action#)
|
||||
}
|
||||
|
||||
build#(<L> = build@fun <implicit>.<anonymous>(): <implicit> <inline=Unknown> {
|
||||
version# = String(123)
|
||||
local final? class A : R|kotlin/Any| {
|
||||
public? [ContainingClassKey=A] constructor(): R|<local>/A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public? final? fun doo(): R|kotlin/Unit| {
|
||||
init {
|
||||
build#(<L> = build@fun <implicit>.<anonymous>(): <implicit> <inline=Unknown> {
|
||||
version# = String(123)
|
||||
local final? class A : R|kotlin/Any| {
|
||||
public? [ContainingClassKey=A] constructor(): R|<local>/A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public? final? fun doo(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
execute#()
|
||||
}
|
||||
|
||||
execute#()
|
||||
)
|
||||
}
|
||||
)
|
||||
+=(version#, IntegerLiteral(123))
|
||||
|
||||
init {
|
||||
+=(version#, IntegerLiteral(123))
|
||||
}
|
||||
|
||||
public? final? val builder: <implicit> = build#(<L> = build@fun <implicit>.<anonymous>(): <implicit> <inline=Unknown> {
|
||||
version# = String(321)
|
||||
}
|
||||
)
|
||||
public? get(): <implicit>
|
||||
|
||||
println#()
|
||||
builder#.version# = String()
|
||||
builder#.execute#()
|
||||
init {
|
||||
println#()
|
||||
}
|
||||
|
||||
init {
|
||||
builder#.version# = String()
|
||||
}
|
||||
|
||||
init {
|
||||
builder#.execute#()
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ 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.references.FirControlFlowGraphReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirScriptSymbol
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
@@ -30,9 +29,9 @@ abstract class FirScript : FirDeclaration(), FirControlFlowGraphOwner {
|
||||
abstract override val attributes: FirDeclarationAttributes
|
||||
abstract override val controlFlowGraphReference: FirControlFlowGraphReference?
|
||||
abstract val name: Name
|
||||
abstract val declarations: List<FirStatement>
|
||||
abstract val declarations: List<FirDeclaration>
|
||||
abstract override val symbol: FirScriptSymbol
|
||||
abstract val parameters: List<FirVariable>
|
||||
abstract val parameters: List<FirProperty>
|
||||
abstract val contextReceivers: List<FirContextReceiver>
|
||||
abstract val resultPropertyName: Name?
|
||||
|
||||
@@ -47,9 +46,13 @@ abstract class FirScript : FirDeclaration(), FirControlFlowGraphOwner {
|
||||
|
||||
abstract override fun replaceControlFlowGraphReference(newControlFlowGraphReference: FirControlFlowGraphReference?)
|
||||
|
||||
abstract fun replaceDeclarations(newDeclarations: List<FirStatement>)
|
||||
abstract fun replaceDeclarations(newDeclarations: List<FirDeclaration>)
|
||||
|
||||
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirScript
|
||||
|
||||
abstract fun <D> transformDeclarations(transformer: FirTransformer<D>, data: D): FirScript
|
||||
|
||||
abstract fun <D> transformParameters(transformer: FirTransformer<D>, data: D): FirScript
|
||||
|
||||
abstract fun <D> transformContextReceivers(transformer: FirTransformer<D>, data: D): FirScript
|
||||
}
|
||||
|
||||
+3
-4
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
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.name.Name
|
||||
|
||||
@@ -32,9 +31,9 @@ class FirScriptBuilder : FirAnnotationContainerBuilder {
|
||||
lateinit var origin: FirDeclarationOrigin
|
||||
var attributes: FirDeclarationAttributes = FirDeclarationAttributes()
|
||||
lateinit var name: Name
|
||||
val declarations: MutableList<FirStatement> = mutableListOf()
|
||||
val declarations: MutableList<FirDeclaration> = mutableListOf()
|
||||
lateinit var symbol: FirScriptSymbol
|
||||
val parameters: MutableList<FirVariable> = mutableListOf()
|
||||
val parameters: MutableList<FirProperty> = mutableListOf()
|
||||
val contextReceivers: MutableList<FirContextReceiver> = mutableListOf()
|
||||
var resultPropertyName: Name? = null
|
||||
|
||||
@@ -47,7 +46,7 @@ class FirScriptBuilder : FirAnnotationContainerBuilder {
|
||||
origin,
|
||||
attributes,
|
||||
name,
|
||||
declarations.toMutableOrEmpty(),
|
||||
declarations,
|
||||
symbol,
|
||||
parameters,
|
||||
contextReceivers.toMutableOrEmpty(),
|
||||
|
||||
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.MutableOrEmptyList
|
||||
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirScriptSymbol
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
@@ -33,9 +32,9 @@ internal class FirScriptImpl(
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
override val name: Name,
|
||||
override var declarations: MutableOrEmptyList<FirStatement>,
|
||||
override val declarations: MutableList<FirDeclaration>,
|
||||
override val symbol: FirScriptSymbol,
|
||||
override val parameters: MutableList<FirVariable>,
|
||||
override val parameters: MutableList<FirProperty>,
|
||||
override var contextReceivers: MutableOrEmptyList<FirContextReceiver>,
|
||||
override val resultPropertyName: Name?,
|
||||
) : FirScript() {
|
||||
@@ -58,8 +57,8 @@ internal class FirScriptImpl(
|
||||
transformAnnotations(transformer, data)
|
||||
controlFlowGraphReference = controlFlowGraphReference?.transform(transformer, data)
|
||||
transformDeclarations(transformer, data)
|
||||
parameters.transformInplace(transformer, data)
|
||||
contextReceivers.transformInplace(transformer, data)
|
||||
transformParameters(transformer, data)
|
||||
transformContextReceivers(transformer, data)
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -73,6 +72,16 @@ internal class FirScriptImpl(
|
||||
return this
|
||||
}
|
||||
|
||||
override fun <D> transformParameters(transformer: FirTransformer<D>, data: D): FirScriptImpl {
|
||||
parameters.transformInplace(transformer, data)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun <D> transformContextReceivers(transformer: FirTransformer<D>, data: D): FirScriptImpl {
|
||||
contextReceivers.transformInplace(transformer, data)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) {
|
||||
annotations = newAnnotations.toMutableOrEmpty()
|
||||
}
|
||||
@@ -81,7 +90,8 @@ internal class FirScriptImpl(
|
||||
controlFlowGraphReference = newControlFlowGraphReference
|
||||
}
|
||||
|
||||
override fun replaceDeclarations(newDeclarations: List<FirStatement>) {
|
||||
declarations = newDeclarations.toMutableOrEmpty()
|
||||
override fun replaceDeclarations(newDeclarations: List<FirDeclaration>) {
|
||||
declarations.clear()
|
||||
declarations.addAll(newDeclarations)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -494,10 +494,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
|
||||
script.configure {
|
||||
+name
|
||||
+FieldList("declarations", statement, withReplace = true, useMutableOrEmpty = true).withTransform()
|
||||
+declarations.withTransform().withReplace()
|
||||
+symbol("FirScriptSymbol")
|
||||
+fieldList("parameters", variable, withReplace = false)
|
||||
+fieldList(contextReceiver, useMutableOrEmpty = true)
|
||||
+fieldList("parameters", property).withTransform()
|
||||
+fieldList(contextReceiver, useMutableOrEmpty = true).withTransform()
|
||||
+field("resultPropertyName", nameType, nullable = true)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user