Refactor scripting infrastructure - convert usages to the new entities

This commit is contained in:
Ilya Chernikov
2019-07-02 11:58:39 +02:00
parent 80ada5113e
commit 4940f64265
11 changed files with 145 additions and 212 deletions
@@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.core.script.scriptCompilationConfiguration
import org.jetbrains.kotlin.idea.core.script.scriptDependencies
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
import kotlin.script.experimental.api.asSuccess
@@ -26,7 +27,7 @@ class FromFileAttributeScriptDependenciesLoader(project: Project) : ScriptDepend
debug(file) { "refined configuration from fileAttributes = $it" }
}
} ?: file.scriptDependencies?.let {
ScriptCompilationConfigurationWrapper.FromLegacy(VirtualFileScriptSource(file), it).apply {
ScriptCompilationConfigurationWrapper.FromLegacy(VirtualFileScriptSource(file), it, file.findScriptDefinition(project)).apply {
debug(file) { "dependencies from fileAttributes = $it" }
}
}?.let {
@@ -1,145 +0,0 @@
/*
* Copyright 2010-2019 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 kotlin.script.experimental.jvmhost.impl
import com.intellij.openapi.fileTypes.LanguageFileType
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.NameUtils
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
import kotlin.reflect.KClass
import kotlin.reflect.KType
import kotlin.reflect.full.starProjectedType
import kotlin.script.dependencies.ScriptContents
import kotlin.script.experimental.api.*
import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.host.getScriptingClass
import kotlin.script.experimental.jvm.impl.BridgeDependenciesResolver
import kotlin.script.experimental.util.getOrError
// A bridge to the current scripting
// mostly copies functionality from KotlinScriptDefinitionAdapterFromNewAPI[Base]
// reusing it requires structural changes that doesn't seem justified now, since the internals of the scripting should be reworked soon anyway
// TODO: either finish refactoring of the scripting internals or reuse KotlinScriptDefinitionAdapterFromNewAPI[Base] here
// NOTE: since KotlinScriptDefinition is not designed to separate static (script definition related) and dynamic (actual script compilation
// configuration) parameters, the implementation is quite hacky, especially for cases as REPL
// TODO: finish refactoring and replace KotlinScriptDefinition with right abstractions
internal class BridgeScriptDefinition(
val scriptCompilationConfiguration: ScriptCompilationConfiguration,
val hostConfiguration: ScriptingHostConfiguration,
dynamicState: BridgeScriptDefinitionDynamicState
) : KotlinScriptDefinition(Any::class) {
val baseClass: KClass<*> by lazy(LazyThreadSafetyMode.PUBLICATION) {
getScriptingClass(scriptCompilationConfiguration.getOrError(ScriptCompilationConfiguration.baseClass))
}
override val template: KClass<*> get() = baseClass
override val name: String
get() = scriptCompilationConfiguration[ScriptCompilationConfiguration.displayName] ?: "Kotlin Script"
override val fileType: LanguageFileType = KotlinFileType.INSTANCE
override fun isScript(fileName: String): Boolean =
fileName.endsWith(".$fileExtension")
override fun getScriptName(script: KtScript): Name {
val fileBasedName = NameUtils.getScriptNameForFile(script.containingKtFile.name)
return Name.identifier(fileBasedName.identifier.removeSuffix(".$fileExtension"))
}
override val fileExtension: String
get() = scriptCompilationConfiguration[ScriptCompilationConfiguration.fileExtension] ?: super.fileExtension
override val acceptedAnnotations = run {
val cl = this::class.java.classLoader
scriptCompilationConfiguration[ScriptCompilationConfiguration.refineConfigurationOnAnnotations]?.annotations
?.map { (cl.loadClass(it.typeName) as Class<out Annotation>).kotlin }
?: emptyList()
}
override val implicitReceivers: List<KType> by lazy(LazyThreadSafetyMode.PUBLICATION) {
scriptCompilationConfiguration[ScriptCompilationConfiguration.implicitReceivers]
.orEmpty()
.map { getScriptingClass(it).starProjectedType }
}
override val providedProperties: List<Pair<String, KType>> by lazy(LazyThreadSafetyMode.PUBLICATION) {
scriptCompilationConfiguration[ScriptCompilationConfiguration.providedProperties]
?.map { (k, v) -> k to getScriptingClass(v).starProjectedType }.orEmpty()
}
override val additionalCompilerArguments: List<String>
get() = scriptCompilationConfiguration[ScriptCompilationConfiguration.compilerOptions]
.orEmpty()
override val dependencyResolver: DependenciesResolver =
BridgeDependenciesResolver(
scriptCompilationConfiguration,
dynamicState::updateConfiguration,
dynamicState::getScriptSource
)
private val scriptingClassGetter by lazy(LazyThreadSafetyMode.PUBLICATION) {
hostConfiguration[ScriptingHostConfiguration.getScriptingClass]
?: throw IllegalArgumentException("Expecting 'getScriptingClass' property in the scripting environment")
}
private fun getScriptingClass(type: KotlinType) =
scriptingClassGetter(
type,
KotlinScriptDefinition::class, // Assuming that the KotlinScriptDefinition class is loaded in the proper classloader
hostConfiguration
)
}
// TODO: consider synchronization, since it is mutable (or finish the refactoring after all)
internal class BridgeScriptDefinitionDynamicState {
private val _sources = linkedSetOf<SourceCode>()
private val _configurations = hashMapOf<SourceCode, ScriptCompilationConfiguration>()
private var _baseScriptCompilationConfiguration: ScriptCompilationConfiguration? = null
val sources: Set<SourceCode> get() = _sources
val configurations: Map<SourceCode, ScriptCompilationConfiguration> get() = _configurations
val baseScriptCompilationConfiguration: ScriptCompilationConfiguration get() = _baseScriptCompilationConfiguration!!
val mainScript: SourceCode get() = sources.first()
val mainScriptCompilationConfiguration: ScriptCompilationConfiguration
get() = configurations[mainScript] ?: baseScriptCompilationConfiguration
fun configureFor(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration) {
_sources.clear()
_sources.add(script)
_configurations.clear()
_baseScriptCompilationConfiguration = scriptCompilationConfiguration
}
fun updateConfiguration(script: SourceCode, updatedConfiguration: ScriptCompilationConfiguration) {
_configurations[script] = updatedConfiguration
updatedConfiguration[ScriptCompilationConfiguration.importScripts]?.let {
_sources.addAll(it)
}
}
fun getScriptSource(scriptContents: ScriptContents): SourceCode? {
val name = scriptContents.file?.name
return sources.find {
// TODO: consider using merged text (likely should be cached)
// on the other hand it may become obsolete when scripting internals will be redesigned properly
(name != null && name == it.scriptFileName(
sources.first(),
mainScriptCompilationConfiguration
)) || it.text == scriptContents.text
}
}
}
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
import kotlin.script.experimental.api.*
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.jvmhost.KJvmCompilerProxy
@@ -35,10 +36,9 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm
getScriptKtFile(script, context.baseScriptCompilationConfiguration, context.environment.project, messageCollector)
.valueOr { return it }
context.scriptCompilationState.configureFor(script, context.baseScriptCompilationConfiguration)
val (sourceFiles, sourceDependencies) = collectRefinedSourcesAndUpdateEnvironment(context, mainKtFile, messageCollector)
val dependenciesProvider = ScriptDependenciesProvider.getInstance(context.environment.project)
val analysisResult = analyze(sourceFiles, context.environment)
if (!analysisResult.shouldGenerateCode) return failure(script, messageCollector, "no code to generate")
@@ -48,7 +48,7 @@ class KJvmCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) : KJvm
val compiledScript =
makeCompiledScript(generationState, script, sourceFiles.first(), sourceDependencies) { ktFile ->
context.scriptCompilationState.configurations.entries.find { ktFile.name == it.key.name }?.value
dependenciesProvider?.getScriptConfigurationResult(ktFile)?.valueOrNull()?.configuration
?: context.baseScriptCompilationConfiguration
}
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.codegen.CompilationErrorHandler
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
import org.jetbrains.kotlin.scripting.repl.ReplCodeAnalyzer
import kotlin.script.experimental.api.*
import kotlin.script.experimental.host.ScriptingHostConfiguration
@@ -118,9 +119,10 @@ class KJvmReplCompilerImpl(val hostConfiguration: ScriptingHostConfiguration) :
history.push(LineId(codeLine), scriptDescriptor)
val dependenciesProvider = ScriptDependenciesProvider.getInstance(context.environment.project)
val compiledScript =
makeCompiledScript(generationState, snippet, sourceFiles.first(), sourceDependencies) { ktFile ->
context.scriptCompilationState.configurations.entries.find { ktFile.name == it.key.name }?.value
dependenciesProvider?.getScriptConfigurationResult(ktFile)?.valueOrNull()?.configuration
?: context.baseScriptCompilationConfiguration
}
@@ -27,12 +27,13 @@ import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
import org.jetbrains.kotlin.scripting.dependencies.ScriptsCompilationDependencies
import org.jetbrains.kotlin.scripting.dependencies.collectScriptsCompilationDependencies
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.SourceCode
import kotlin.script.experimental.api.compilerOptions
import kotlin.script.experimental.api.dependencies
import kotlin.script.experimental.api.valueOrNull
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.jvm.JvmDependency
import kotlin.script.experimental.jvm.jdkHome
@@ -44,8 +45,7 @@ internal class SharedScriptCompilationContext(
val disposable: Disposable,
val baseScriptCompilationConfiguration: ScriptCompilationConfiguration,
val environment: KotlinCoreEnvironment,
val ignoredOptionsReportingState: IgnoredOptionsReportingState,
val scriptCompilationState: BridgeScriptDefinitionDynamicState
val ignoredOptionsReportingState: IgnoredOptionsReportingState
)
internal fun createSharedCompilationContext(
@@ -56,11 +56,9 @@ internal fun createSharedCompilationContext(
): SharedScriptCompilationContext {
val ignoredOptionsReportingState = IgnoredOptionsReportingState()
val scriptCompilationState = BridgeScriptDefinitionDynamicState()
val (initialScriptCompilationConfiguration, kotlinCompilerConfiguration) =
createInitialConfigurations(
scriptCompilationConfiguration, hostConfiguration, scriptCompilationState, messageCollector, ignoredOptionsReportingState
scriptCompilationConfiguration, hostConfiguration, messageCollector, ignoredOptionsReportingState
)
val environment =
KotlinCoreEnvironment.createForProduction(
@@ -68,14 +66,13 @@ internal fun createSharedCompilationContext(
)
return SharedScriptCompilationContext(
disposable, initialScriptCompilationConfiguration, environment, ignoredOptionsReportingState, scriptCompilationState
disposable, initialScriptCompilationConfiguration, environment, ignoredOptionsReportingState
)
}
internal fun createInitialConfigurations(
scriptCompilationConfiguration: ScriptCompilationConfiguration,
hostConfiguration: ScriptingHostConfiguration,
scriptCompilationState: BridgeScriptDefinitionDynamicState,
messageCollector: ScriptDiagnosticsMessageCollector,
ignoredOptionsReportingState: IgnoredOptionsReportingState
): Pair<ScriptCompilationConfiguration, CompilerConfiguration> {
@@ -89,14 +86,7 @@ internal fun createInitialConfigurations(
kotlinCompilerConfiguration.add(
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
ScriptDefinition.FromLegacy(
hostConfiguration,
BridgeScriptDefinition(
scriptCompilationConfiguration,
hostConfiguration,
scriptCompilationState
)
)
ScriptDefinition.FromConfigurations(hostConfiguration, scriptCompilationConfiguration, null)
)
initialScriptCompilationConfiguration[ScriptCompilationConfiguration.compilerOptions]?.let { compilerOptions ->
@@ -217,26 +207,25 @@ internal fun collectRefinedSourcesAndUpdateEnvironment(
sourceFiles.addAll(newSources)
// collectScriptsCompilationDependencies calls resolver for every file, so at this point all updated configurations are collected
context.environment.configuration.updateWithRefinedConfigurations(
context.baseScriptCompilationConfiguration, context.scriptCompilationState.configurations,
messageCollector, context.ignoredOptionsReportingState
)
// collectScriptsCompilationDependencies calls resolver for every file, so at this point all updated configurations are collected in the ScriptDependenciesProvider
context.environment.configuration.updateWithRefinedConfigurations(context, sourceFiles, messageCollector)
return sourceFiles to sourceDependencies
}
private fun CompilerConfiguration.updateWithRefinedConfigurations(
initialScriptCompilationConfiguration: ScriptCompilationConfiguration,
refinedScriptCompilationConfigurations: Map<SourceCode, ScriptCompilationConfiguration>,
messageCollector: ScriptDiagnosticsMessageCollector,
reportingState: IgnoredOptionsReportingState
context: SharedScriptCompilationContext,
sourceFiles: List<KtFile>,
messageCollector: ScriptDiagnosticsMessageCollector
) {
val updatedCompilerOptions = refinedScriptCompilationConfigurations.flatMap {
it.value[ScriptCompilationConfiguration.compilerOptions] ?: emptyList()
val dependenciesProvider = ScriptDependenciesProvider.getInstance(context.environment.project)
val updatedCompilerOptions = sourceFiles.flatMap {
dependenciesProvider?.getScriptConfigurationResult(it)?.valueOrNull()?.configuration?.get(
ScriptCompilationConfiguration.compilerOptions
) ?: emptyList()
}
if (updatedCompilerOptions.isNotEmpty() &&
updatedCompilerOptions != initialScriptCompilationConfiguration[ScriptCompilationConfiguration.compilerOptions]
updatedCompilerOptions != context.baseScriptCompilationConfiguration[ScriptCompilationConfiguration.compilerOptions]
) {
updateWithCompilerOptions(updatedCompilerOptions, messageCollector, reportingState, true)
updateWithCompilerOptions(updatedCompilerOptions, messageCollector, context.ignoredOptionsReportingState, true)
}
}
@@ -21,10 +21,11 @@ import kotlin.script.experimental.jvm.jvm
// TODO: name could be confused with KotlinScriptDefinition, discuss naming
abstract class ScriptDefinition : UserDataHolderBase() {
@Deprecated("Use configurations instead")
abstract val legacyDefinition: KotlinScriptDefinition
abstract val hostConfiguration: ScriptingHostConfiguration
abstract val compilationConfiguration: ScriptCompilationConfiguration
abstract val evaluationConfiguration: ScriptEvaluationConfiguration
abstract val evaluationConfiguration: ScriptEvaluationConfiguration?
abstract fun isScript(fileName: String): Boolean
abstract val fileExtension: String
@@ -43,9 +44,11 @@ abstract class ScriptDefinition : UserDataHolderBase() {
abstract val baseClassType: KotlinType
abstract val compilerOptions: Iterable<String>
@Suppress("DEPRECATION")
inline fun <reified T : KotlinScriptDefinition> asLegacyOrNull(): T? =
if (this is FromLegacy) legacyDefinition as? T else null
@Suppress("OverridingDeprecatedMember", "DEPRECATION")
open class FromLegacy(
override val hostConfiguration: ScriptingHostConfiguration,
override val legacyDefinition: KotlinScriptDefinition
@@ -105,6 +108,7 @@ abstract class ScriptDefinition : UserDataHolderBase() {
abstract class FromConfigurationsBase : ScriptDefinition() {
@Suppress("OverridingDeprecatedMember", "DEPRECATION")
override val legacyDefinition by lazy {
KotlinScriptDefinitionAdapterFromNewAPI(
compilationConfiguration,
@@ -136,13 +140,13 @@ abstract class ScriptDefinition : UserDataHolderBase() {
compilationConfiguration == it.compilationConfiguration && evaluationConfiguration == it.evaluationConfiguration
} == true
override fun hashCode(): Int = compilationConfiguration.hashCode() + 37 * evaluationConfiguration.hashCode()
override fun hashCode(): Int = compilationConfiguration.hashCode() + 37 * (evaluationConfiguration?.hashCode() ?: 0)
}
open class FromConfigurations(
override val hostConfiguration: ScriptingHostConfiguration,
override val compilationConfiguration: ScriptCompilationConfiguration,
override val evaluationConfiguration: ScriptEvaluationConfiguration
override val evaluationConfiguration: ScriptEvaluationConfiguration?
) : FromConfigurationsBase()
open class FromTemplate(
@@ -47,7 +47,7 @@ fun findScriptDefinitionByFileName(project: Project, fileName: String): ScriptDe
return scriptDefinitionProvider.findDefinition(fileName) ?: scriptDefinitionProvider.getDefaultDefinition()
}
private fun VirtualFile.isNonScript(): Boolean =
internal fun VirtualFile.isNonScript(): Boolean =
isDirectory ||
extension == KotlinFileType.EXTENSION ||
extension == JavaClassFileType.INSTANCE.defaultExtension ||
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2019 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.definitions
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationResult
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.valueOr
fun PsiFile.findScriptCompilationConfiguration(): ScriptCompilationConfiguration? {
// Do not use psiFile.script, see comments in findScriptDefinition
if (this !is KtFile/* || this.script == null*/) return null
val file = virtualFile ?: originalFile.virtualFile ?: return null
if (file.isNonScript()) return null
val provider = ScriptDependenciesProvider.getInstance(project)
return provider?.getScriptConfigurationResult(this)?.valueOrError()?.configuration
?: findScriptDefinition()?.compilationConfiguration
}
fun VirtualFile.findScriptCompilationConfiguration(project: Project): ScriptCompilationConfiguration? {
if (!isValid || isNonScript()) return null
// see comments in findScriptDefinition
// we do not need expensive check as in findScriptDefinition here, since it is assumed that this function is called only for known scripts
val provider = ScriptDependenciesProvider.getInstance(project)
return provider?.getScriptConfigurationResult(this)?.valueOrError()?.configuration
?: findScriptDefinition(project)?.compilationConfiguration
}
private fun ScriptCompilationConfigurationResult.valueOrError() = valueOr { failure ->
throw IllegalArgumentException(
"Error retrieving script compilation configuration: ${failure.reports.joinToString { it.message }}",
failure.reports.find { it.exception != null }?.exception
)
}
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider
import org.jetbrains.kotlin.scripting.definitions.ScriptPriorities
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinitionByFileName
import org.jetbrains.kotlin.scripting.definitions.findScriptCompilationConfiguration
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isUnit
@@ -44,7 +44,10 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.io.File
import kotlin.reflect.KClass
import kotlin.reflect.KType
import kotlin.script.experimental.api.valueOrNull
import kotlin.script.experimental.api.*
import kotlin.script.experimental.host.GetScriptingClass
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.host.getScriptingClass
class LazyScriptDescriptor(
@@ -105,14 +108,28 @@ class LazyScriptDescriptor(
override fun getPriority() = priority
// rewrite without using legacyDefinition below
val scriptDefinition: () -> ScriptDefinition = resolveSession.storageManager.createLazyValue {
findScriptDefinitionByFileName(
resolveSession.project,
scriptInfo.script.containingKtFile.name
)
val scriptCompilationConfiguration: () -> ScriptCompilationConfiguration = resolveSession.storageManager.createLazyValue {
scriptInfo.script.containingKtFile.findScriptCompilationConfiguration()
?: throw IllegalArgumentException("Unable to find script compilation configuration for the script ${scriptInfo.script.containingFile}")
}
private val scriptingHostConfiguration: () -> ScriptingHostConfiguration = resolveSession.storageManager.createLazyValue {
scriptCompilationConfiguration()[ScriptCompilationConfiguration.hostConfiguration]
?: throw IllegalArgumentException("Expecting 'hostConfiguration' property in the script compilation configuration for the script ${scriptInfo.script.containingFile}")
}
private val scriptingClassGetter: () -> GetScriptingClass = resolveSession.storageManager.createLazyValue {
scriptingHostConfiguration()[ScriptingHostConfiguration.getScriptingClass]
?: throw IllegalArgumentException("Expecting 'getScriptingClass' property in the scripting host configuration for the script ${scriptInfo.script.containingFile}")
}
fun getScriptingClass(type: KotlinType): KClass<*> =
scriptingClassGetter()(
type,
ScriptDefinition::class, // Assuming that the ScriptDefinition class is loaded in the proper classloader, TODO: consider more reliable way to load or cache classes
scriptingHostConfiguration()
)
override fun substitute(substitutor: TypeSubstitutor) = this
override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R =
@@ -130,16 +147,20 @@ class LazyScriptDescriptor(
override fun getUnsubstitutedPrimaryConstructor() = super.getUnsubstitutedPrimaryConstructor()!!
internal val baseClassDescriptor: () -> ClassDescriptor? = resolveSession.storageManager.createNullableLazyValue {
val template = scriptDefinition().legacyDefinition.template
val baseClass = getScriptingClass(
scriptCompilationConfiguration()[ScriptCompilationConfiguration.baseClass]
?: throw IllegalStateException("Base class is not configured for the script ${scriptInfo.script.containingFile}")
)
findTypeDescriptor(
template,
if (template.qualifiedName?.startsWith("kotlin.script.templates.standard") == true) Errors.MISSING_SCRIPT_STANDARD_TEMPLATE
baseClass,
if (baseClass.qualifiedName?.startsWith("kotlin.script.templates.standard") == true) Errors.MISSING_SCRIPT_STANDARD_TEMPLATE
else Errors.MISSING_SCRIPT_BASE_CLASS
)
}
override fun computeSupertypes() = listOf(baseClassDescriptor()?.defaultType ?: builtIns.anyType)
// TODO: consider passing ScriptSource to avoid psi file fsearching
private inner class ImportedScriptDescriptorsFinder {
val fileManager = VirtualFileManager.getInstance()
@@ -153,7 +174,7 @@ class LazyScriptDescriptor(
return null
}
val vfile = localFS.findFileByPath(importedScriptFile.path)
val vfile = localFS.findFileByPath(importedScriptFile.absolutePath)
?: return errorDescriptor(MISSING_IMPORTED_SCRIPT_FILE)
val psiFile = psiManager.findFile(vfile)
?: return errorDescriptor(MISSING_IMPORTED_SCRIPT_PSI)
@@ -177,8 +198,8 @@ class LazyScriptDescriptor(
}
}
scriptDefinition().legacyDefinition.implicitReceivers.mapNotNullTo(res) { receiver ->
findTypeDescriptor(receiver, Errors.MISSING_SCRIPT_RECEIVER_CLASS)
scriptCompilationConfiguration()[ScriptCompilationConfiguration.implicitReceivers]?.mapNotNullTo(res) { receiver ->
findTypeDescriptor(getScriptingClass(receiver), Errors.MISSING_SCRIPT_RECEIVER_CLASS)
}
res
@@ -224,10 +245,10 @@ class LazyScriptDescriptor(
private val scriptOuterScope: () -> LexicalScope = resolveSession.storageManager.createLazyValue {
var outerScope = super.getOuterScope()
val outerScopeReceivers = implicitReceivers.let {
if (scriptDefinition().legacyDefinition.providedProperties.isEmpty()) {
it
} else {
if (scriptCompilationConfiguration()[ScriptCompilationConfiguration.providedProperties]?.isNotEmpty() == true) {
it + ScriptProvidedPropertiesDescriptor(this)
} else {
it
}
}
for (receiverClassDescriptor in outerScopeReceivers.asReversed()) {
@@ -15,6 +15,9 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.utils.Printer
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.providedProperties
import kotlin.script.experimental.jvm.util.toValidJvmIdentifier
class ScriptProvidedPropertiesDescriptor(script: LazyScriptDescriptor) :
MutableClassDescriptor(
@@ -42,10 +45,9 @@ class ScriptProvidedPropertiesDescriptor(script: LazyScriptDescriptor) :
override fun getUnsubstitutedMemberScope(): MemberScope = memberScope()
val properties: () -> List<ScriptProvidedPropertyDescriptor> = script.resolveSession.storageManager.createLazyValue {
script.scriptDefinition().legacyDefinition.providedProperties.mapNotNull { (name, type) ->
script.findTypeDescriptor(type, Errors.MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS)?.let {
name to it
}
script.scriptCompilationConfiguration()[ScriptCompilationConfiguration.providedProperties].orEmpty().mapNotNull { (name, type) ->
script.findTypeDescriptor(script.getScriptingClass(type), Errors.MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS)
?.let { name.toValidJvmIdentifier() to it }
}.map { (name, classDescriptor) ->
ScriptProvidedPropertyDescriptor(
Name.identifier(name),
@@ -28,14 +28,11 @@ import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.dependencies.ScriptDependencies
import kotlin.script.experimental.host.*
import kotlin.script.experimental.jvm.JvmGetScriptingClass
import kotlin.script.experimental.jvm.*
import kotlin.script.experimental.jvm.compat.mapToDiagnostics
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
import kotlin.script.experimental.jvm.impl.refineWith
import kotlin.script.experimental.jvm.impl.toClassPathOrEmpty
import kotlin.script.experimental.jvm.impl.toDependencies
import kotlin.script.experimental.jvm.jdkHome
import kotlin.script.experimental.jvm.jvm
internal fun VirtualFile.loadAnnotations(
acceptedAnnotations: List<KClass<out Annotation>>,
@@ -147,6 +144,7 @@ abstract class ScriptCompilationConfigurationWrapper(val script: SourceCode) {
get() = configuration?.get(ScriptCompilationConfiguration.importScripts)
?.mapNotNull { (it as? FileBasedScriptSource)?.file }.orEmpty()
@Suppress("OverridingDeprecatedMember")
override val legacyDependencies: ScriptDependencies?
get() = configuration?.toDependencies(dependenciesClassPath)
@@ -156,9 +154,11 @@ abstract class ScriptCompilationConfigurationWrapper(val script: SourceCode) {
override fun hashCode(): Int = super.hashCode() + 23 * (configuration?.hashCode() ?: 1)
}
@Suppress("OverridingDeprecatedMember", "DEPRECATION")
class FromLegacy(
script: SourceCode,
override val legacyDependencies: ScriptDependencies?
override val legacyDependencies: ScriptDependencies?,
val definition: ScriptDefinition?
) : ScriptCompilationConfigurationWrapper(script) {
override val dependenciesClassPath: List<File>
@@ -177,8 +177,23 @@ abstract class ScriptCompilationConfigurationWrapper(val script: SourceCode) {
get() = legacyDependencies?.scripts.orEmpty()
override val configuration: ScriptCompilationConfiguration?
get() = legacyDependencies?.let {
TODO("drop or implement")
get() {
val legacy = legacyDependencies ?: return null
return definition?.compilationConfiguration?.let {
ScriptCompilationConfiguration(it) {
updateClasspath(legacy.classpath)
defaultImports.append(legacy.imports)
importScripts.append(legacy.scripts.map { FileScriptSource(it) })
jvm {
jdkHome.putIfNotNull(legacy.javaHome) // TODO: check if it is correct to supply javaHome as jdkHome
}
if (legacy.sources.isNotEmpty()) {
ide {
dependenciesSources.append(JvmDependency(legacy.sources))
}
}
}
}
}
override fun equals(other: Any?): Boolean =
@@ -190,6 +205,7 @@ abstract class ScriptCompilationConfigurationWrapper(val script: SourceCode) {
typealias ScriptCompilationConfigurationResult = ResultWithDiagnostics<ScriptCompilationConfigurationWrapper>
@Suppress("DEPRECATION")
fun refineScriptCompilationConfiguration(
script: SourceCode,
definition: ScriptDefinition,
@@ -240,7 +256,8 @@ fun refineScriptCompilationConfiguration(
else
ScriptCompilationConfigurationWrapper.FromLegacy(
ktFileSource,
result.dependencies?.adjustByDefinition(definition.legacyDefinition)
result.dependencies?.adjustByDefinition(definition.legacyDefinition),
definition
).asSuccess(result.reports.mapToDiagnostics())
}
}