K2 scripting: treat default import similarly to K1

namely, add them to importing scopes directly and according to the
schema used for other implicit imports, rather than adding them
to the regular script file imports. See KT-65982 for explanation.
#KT-65982 fixed
This commit is contained in:
Ilya Chernikov
2024-02-14 17:52:02 +01:00
committed by Space Team
parent 9037975758
commit 266447120d
22 changed files with 282 additions and 102 deletions
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.scripting.compiler.plugin.services.Fir2IrScriptConfiguratorExtensionImpl
import org.jetbrains.kotlin.scripting.compiler.plugin.services.FirScriptConfiguratorExtensionImpl
import org.jetbrains.kotlin.scripting.compiler.plugin.services.FirScriptDefinitionProviderService
import org.jetbrains.kotlin.scripting.compiler.plugin.services.FirScriptResolutionConfigurationExtensionImpl
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
import kotlin.script.experimental.host.ScriptingHostConfiguration
@@ -28,6 +29,7 @@ class FirScriptingCompilerExtensionRegistrar(
}
+FirScriptConfiguratorExtensionImpl.getFactory(hostConfiguration)
+FirScriptResolutionConfigurationExtensionImpl.getFactory(hostConfiguration)
+Fir2IrScriptConfiguratorExtensionImpl.getFactory(hostConfiguration)
}
}
@@ -50,25 +50,7 @@ class FirScriptConfiguratorExtensionImpl(
@Suppress("UNUSED_PARAMETER") hostConfiguration: ScriptingHostConfiguration,
) : FirScriptConfiguratorExtension(session) {
@OptIn(SymbolInternals::class)
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
}
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 {
source = fileBuilder.source?.fakeElement(KtFakeSourceElementKind.ImplicitImport)
importedFqName = fqName
isAllUnder = endsWithStar
}
}
}
@OptIn(SymbolInternals::class)
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2024 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.scripting.compiler.plugin.services
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.declarations.FirScript
import org.jetbrains.kotlin.fir.declarations.builder.buildImport
import org.jetbrains.kotlin.fir.extensions.FirScriptResolutionConfigurationExtension
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.name.FqName
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.defaultImports
import kotlin.script.experimental.host.ScriptingHostConfiguration
class FirScriptResolutionConfigurationExtensionImpl(
session: FirSession,
@Suppress("UNUSED_PARAMETER") hostConfiguration: ScriptingHostConfiguration
) : FirScriptResolutionConfigurationExtension(session) {
override fun getScriptDefaultImports(script: FirScript): List<FirImport> {
val scriptFile = session.firProvider.getFirScriptContainerFile(script.symbol) ?: return emptyList()
val scriptSourceFile = scriptFile.sourceFile?.toSourceCode() ?: return emptyList()
val compilationConfiguration = session.getScriptCompilationConfiguration(scriptSourceFile, getDefault = { null }) ?: return emptyList()
return compilationConfiguration.firImportsFromDefaultImports(script.source?.fakeElement(KtFakeSourceElementKind.ImplicitImport))
}
companion object {
fun getFactory(hostConfiguration: ScriptingHostConfiguration): Factory {
return Factory { session -> FirScriptResolutionConfigurationExtensionImpl(session, hostConfiguration) }
}
}
}
private fun ScriptCompilationConfiguration.firImportsFromDefaultImports(sourceElement: KtSourceElement?): List<FirImport> =
this[ScriptCompilationConfiguration.defaultImports]?.map { 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("."))
buildImport {
source = sourceElement
importedFqName = fqName
isAllUnder = endsWithStar
}
}.orEmpty()