[FIR] PsiRawFirBuilder: add missing script configurator

PsiRawFirBuilder#visitScript didn't work because it didn't
have a configurator
Now FirScriptConfiguratorExtension split into two parts:
* File
* Script

^KT-60728
This commit is contained in:
Dmitrii Gridin
2023-07-30 03:29:54 +02:00
committed by Space Team
parent 32e3b67416
commit 35b0cd65e9
3 changed files with 58 additions and 42 deletions
@@ -1127,19 +1127,23 @@ open class PsiRawFirBuilder(
for (declaration in file.declarations) {
declarations += when (declaration) {
is KtScript -> {
requireWithAttachment(file.declarations.size == 1, message = { "Expect the script to be the only declaration in the file" }) {
withEntry("fileName", file.name)
}
convertScript(declaration, this.name) {
for (configurator in baseSession.extensionService.scriptConfigurators) {
with(configurator) { configure(this@buildFile) }
requireWithAttachment(
file.declarations.size == 1,
message = { "Expect the script to be the only declaration in the file" },
) {
withEntry("fileName", file.name)
}
convertScript(declaration, name, sourceFile) {
for (configurator in baseSession.extensionService.scriptConfigurators) {
with(configurator) { configureContainingFile(this@buildFile) }
}
}
}
is KtDestructuringDeclaration -> buildErrorTopLevelDestructuringDeclaration(declaration.toFirSourceElement())
else -> declaration.convert()
}
is KtDestructuringDeclaration -> buildErrorTopLevelDestructuringDeclaration(declaration.toFirSourceElement())
else -> declaration.convert()
}
}
for (danglingModifierList in file.danglingModifierLists) {
declarations += buildErrorTopLevelDeclarationForDanglingModifierList(danglingModifierList)
@@ -1148,7 +1152,12 @@ open class PsiRawFirBuilder(
}
}
private fun convertScript(script: KtScript, fileName: String, setup: FirScriptBuilder.() -> Unit = {}): FirScript {
private fun convertScript(
script: KtScript,
fileName: String,
sourceFile: KtSourceFile?,
setup: FirScriptBuilder.() -> Unit = {},
): FirScript {
return buildScript {
source = script.toFirSourceElement()
moduleData = baseModuleData
@@ -1193,6 +1202,11 @@ open class PsiRawFirBuilder(
}
}
setup()
if (sourceFile != null) {
for (configurator in baseSession.extensionService.scriptConfigurators) {
with(configurator) { configure(sourceFile) }
}
}
}
}
@@ -1212,16 +1226,11 @@ open class PsiRawFirBuilder(
}
}
// TODO: if no original FirScript is passed here, the invalid script could be constructed, consider throwing an error
override fun visitScript(script: KtScript, data: FirElement?): FirElement {
val ktFile = script.containingKtFile
val fileName = ktFile.name
return convertScript(script, fileName) {
(data as? FirScript)?.let {
contextReceivers.addAll(it.contextReceivers)
parameters.addAll(it.parameters)
}
}
val fileForSource = (data as? FirScript)?.psi?.containingFile as? KtFile ?: ktFile
return convertScript(script, fileName, KtPsiSourceFile(fileForSource))
}
protected fun KtEnumEntry.toFirEnumEntry(
@@ -1,10 +1,11 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 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.builder
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.builder.FirFileBuilder
import org.jetbrains.kotlin.fir.declarations.builder.FirScriptBuilder
@@ -27,7 +28,8 @@ abstract class FirScriptConfiguratorExtension(
fun interface Factory : FirExtension.Factory<FirScriptConfiguratorExtension>
abstract fun FirScriptBuilder.configure(fileBuilder: FirFileBuilder)
abstract fun FirScriptBuilder.configureContainingFile(fileBuilder: FirFileBuilder)
abstract fun FirScriptBuilder.configure(sourceFile: KtSourceFile)
}
val FirExtensionService.scriptConfigurators: List<FirScriptConfiguratorExtension> by FirExtensionService.registeredExtensions()
@@ -49,14 +49,35 @@ class FirScriptConfiguratorExtensionImpl(
) : FirScriptConfiguratorExtension(session) {
@OptIn(SymbolInternals::class)
override fun FirScriptBuilder.configure(fileBuilder: FirFileBuilder) {
override fun FirScriptBuilder.configureContainingFile(fileBuilder: FirFileBuilder) {
val sourceFile = fileBuilder.sourceFile ?: return
val configuration = getOrLoadConfiguration(sourceFile) ?: run {
log.warn("Configuration for ${sourceFile.asString()} wasn't found. FirScriptBuilder wasn't configured.")
return
}
val configuration = getOrLoadConfiguration(sourceFile)
?: run {
log.warn("Configuration for ${sourceFile.asString()} wasn't found. FirScriptBuilder wasn't configured.")
return
configuration[ScriptCompilationConfiguration.defaultImports]?.forEach { defaultImport ->
val trimmed = defaultImport.trim()
val endsWithStar = trimmed.endsWith("*")
val stripped = if (endsWithStar) trimmed.substring(0, trimmed.length - 2) else trimmed
val fqName = FqName.fromSegments(stripped.split("."))
fileBuilder.imports += buildImport {
fileBuilder.sourceFile?.project()?.let {
val dummyElement = KtPsiFactory(it, markGenerated = true).createColon()
source = KtFakeSourceElement(dummyElement, KtFakeSourceElementKind.ImplicitImport)
}
importedFqName = fqName
isAllUnder = endsWithStar
}
}
}
@OptIn(SymbolInternals::class)
override fun FirScriptBuilder.configure(sourceFile: KtSourceFile) {
val configuration = getOrLoadConfiguration(sourceFile) ?: run {
log.warn("Configuration for ${sourceFile.asString()} wasn't found. FirScriptBuilder wasn't configured.")
return
}
// TODO: rewrite/extract decision logic for clarity
configuration.getNoDefault(ScriptCompilationConfiguration.baseClass)?.let { baseClass ->
@@ -85,9 +106,11 @@ class FirScriptConfiguratorExtensionImpl(
}
}
}
configuration[ScriptCompilationConfiguration.implicitReceivers]?.forEach { implicitReceiver ->
contextReceivers.add(buildContextReceiverWithFqName(FqName.fromSegments(implicitReceiver.typeName.split("."))))
}
configuration[ScriptCompilationConfiguration.providedProperties]?.forEach { (propertyName, propertyType) ->
val typeRef = buildUserTypeRef {
isMarkedNullable = propertyType.isNullable
@@ -108,24 +131,6 @@ class FirScriptConfiguratorExtensionImpl(
}
)
}
configuration[ScriptCompilationConfiguration.annotationsForSamWithReceivers]?.forEach {
_knownAnnotationsForSamWithReceiver.add(it.typeName)
}
configuration[ScriptCompilationConfiguration.defaultImports]?.forEach { defaultImport ->
val trimmed = defaultImport.trim()
val endsWithStar = trimmed.endsWith("*")
val stripped = if (endsWithStar) trimmed.substring(0, trimmed.length - 2) else trimmed
val fqName = FqName.fromSegments(stripped.split("."))
fileBuilder.imports += buildImport {
fileBuilder.sourceFile?.project()?.let {
val dummyElement = KtPsiFactory(it, markGenerated = true).createColon()
source = KtFakeSourceElement(dummyElement, KtFakeSourceElementKind.ImplicitImport)
}
importedFqName = fqName
isAllUnder = endsWithStar
}
}
configuration[ScriptCompilationConfiguration.annotationsForSamWithReceivers]?.forEach {
_knownAnnotationsForSamWithReceiver.add(it.typeName)