Refactor scripting properties:

- flatten the structure
- add some parameters
- replace iterables with lists
- renaming all scope objects uniformily
also:
- fix passing and usage of script sources
- renamings and other minor improvements
This commit is contained in:
Ilya Chernikov
2018-03-28 12:59:10 +02:00
parent 2ddcc280a9
commit 5058c66e8c
18 changed files with 123 additions and 130 deletions
@@ -27,9 +27,9 @@ abstract class MyScriptWithMavenDeps {
// abstract fun body(vararg args: String): Int // abstract fun body(vararg args: String): Int
} }
val myJvmConfigParams = jvmJavaHomeParams + with(ScriptCompileConfigurationParams) { val myJvmConfigParams = jvmJavaHomeParams + with(ScriptCompileConfigurationProperties) {
listOf( listOf(
scriptSignature to ScriptSignature(MyScriptWithMavenDeps::class, ProvidedDeclarations()), baseClass<MyScriptWithMavenDeps>(),
importedPackages(DependsOn::class.qualifiedName!!, Repository::class.qualifiedName!!), importedPackages(DependsOn::class.qualifiedName!!, Repository::class.qualifiedName!!),
dependencies( dependencies(
JvmDependency( JvmDependency(
@@ -53,10 +53,11 @@ class MyConfigurator(val environment: ChainedPropertyBag) : ScriptCompilationCon
defaultConfiguration.asSuccess() defaultConfiguration.asSuccess()
override suspend fun refineConfiguration( override suspend fun refineConfiguration(
scriptSource: ScriptSource,
configuration: ScriptCompileConfiguration, configuration: ScriptCompileConfiguration,
processedScriptData: ProcessedScriptData processedScriptData: ProcessedScriptData
): ResultWithDiagnostics<ScriptCompileConfiguration> { ): ResultWithDiagnostics<ScriptCompileConfiguration> {
val annotations = processedScriptData.getOrNull(ProcessedScriptDataParams.annotations)?.toList()?.takeIf { it.isNotEmpty() } val annotations = processedScriptData.getOrNull(ProcessedScriptDataProperties.foundAnnotations)?.toList()?.takeIf { it.isNotEmpty() }
?: return configuration.asSuccess() ?: return configuration.asSuccess()
val scriptContents = object : ScriptContents { val scriptContents = object : ScriptContents {
override val annotations: Iterable<Annotation> = annotations override val annotations: Iterable<Annotation> = annotations
@@ -74,8 +75,8 @@ class MyConfigurator(val environment: ChainedPropertyBag) : ScriptCompilationCon
?: return configuration.asSuccess(diagnostics) ?: return configuration.asSuccess(diagnostics)
val newDependency = JvmDependency(resolvedClasspath) val newDependency = JvmDependency(resolvedClasspath)
val updatedDeps = val updatedDeps =
configuration.getOrNull(ScriptCompileConfigurationParams.dependencies)?.plus(newDependency) ?: listOf(newDependency) configuration.getOrNull(ScriptCompileConfigurationProperties.dependencies)?.plus(newDependency) ?: listOf(newDependency)
ChainedPropertyBag(configuration, ScriptCompileConfigurationParams.dependencies(updatedDeps)).asSuccess(diagnostics) ChainedPropertyBag(configuration, ScriptCompileConfigurationProperties.dependencies(updatedDeps)).asSuccess(diagnostics)
} catch (e: Throwable) { } catch (e: Throwable) {
ResultWithDiagnostics.Failure(*diagnostics.toTypedArray(), e.asDiagnostics()) ResultWithDiagnostics.Failure(*diagnostics.toTypedArray(), e.asDiagnostics())
} }
@@ -15,9 +15,9 @@ import kotlin.script.experimental.jvm.*
import kotlin.script.experimental.jvmhost.impl.KJVMCompilerImpl import kotlin.script.experimental.jvmhost.impl.KJVMCompilerImpl
import kotlin.script.experimental.misc.* import kotlin.script.experimental.misc.*
val myJvmConfigParams = jvmJavaHomeParams + with(ScriptCompileConfigurationParams) { val myJvmConfigParams = jvmJavaHomeParams + with(ScriptCompileConfigurationProperties) {
listOf( listOf(
scriptSignature to ScriptSignature(MyScript::class, ProvidedDeclarations()), baseClass<MyScript>(),
dependencies(JvmDependency(scriptCompilationClasspathFromContext("script" /* script library jar name */))) dependencies(JvmDependency(scriptCompilationClasspathFromContext("script" /* script library jar name */)))
) )
} }
@@ -3,10 +3,13 @@
* that can be found in the license/LICENSE.txt file. * that can be found in the license/LICENSE.txt file.
*/ */
@file:Suppress("unused")
package kotlin.script.experimental.api package kotlin.script.experimental.api
object ProcessedScriptDataParams { object ProcessedScriptDataProperties {
val annotations by typedKey<Iterable<Annotation>>() val foundAnnotations by typedKey<List<Annotation>>()
val fragments by typedKey<Iterable<ScriptSourceNamedFragment>>() val foundFragments by typedKey<List<ScriptSourceNamedFragment>>()
} }
@@ -22,6 +22,7 @@ interface ScriptCompilationConfigurator {
suspend fun baseConfiguration(scriptSource: ScriptSource): ResultWithDiagnostics<ScriptCompileConfiguration> suspend fun baseConfiguration(scriptSource: ScriptSource): ResultWithDiagnostics<ScriptCompileConfiguration>
suspend fun refineConfiguration( suspend fun refineConfiguration(
scriptSource: ScriptSource,
configuration: ScriptCompileConfiguration, configuration: ScriptCompileConfiguration,
processedScriptData: ProcessedScriptData = ProcessedScriptData() processedScriptData: ProcessedScriptData = ProcessedScriptData()
): ResultWithDiagnostics<ScriptCompileConfiguration> ): ResultWithDiagnostics<ScriptCompileConfiguration>
@@ -1,34 +0,0 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. 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("unused")
package kotlin.script.experimental.api
import kotlin.reflect.KClass
object ScriptCompileConfigurationParams {
val baseClass by typedKey<KClass<*>>()
val scriptSourceFragments by typedKey<ScriptSourceFragments>()
val scriptSignature by typedKey<ScriptSignature>()
val importedPackages by typedKey<Iterable<String>>()
val restrictions by typedKey<ResolvingRestrictions>()
val importedScripts by typedKey<Iterable<ScriptSource>>()
val dependencies by typedKey<Iterable<ScriptDependency>>()
val compilerOptions by typedKey<Iterable<String>>() // Q: CommonCompilerOptions instead?
val updateConfigurationOnAnnotations by typedKey<Iterable<KClass<out Annotation>>>()
val updateConfigurationOnSections by typedKey<Iterable<String>>()
}
@@ -0,0 +1,39 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. 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("unused")
package kotlin.script.experimental.api
import kotlin.reflect.KClass
import kotlin.reflect.KType
object ScriptCompileConfigurationProperties {
val sourceFragments by typedKey<List<ScriptSourceNamedFragment>>()
val baseClass = ScriptingEnvironmentProperties.baseClass
val scriptBodyTarget by typedKey<ScriptBodyTarget>()
val scriptImplicitReceivers by typedKey<List<KType>>() // in the order from outer to inner scope
val contextVariables by typedKey<Map<String, KType>>() // external variables
val importedPackages by typedKey<List<String>>()
val restrictions by typedKey<List<ResolvingRestrictionRule>>()
val importedScripts by typedKey<List<ScriptSource>>()
val dependencies by typedKey<List<ScriptDependency>>()
val compilerOptions by typedKey<List<String>>() // Q: CommonCompilerOptions instead?
val updateConfigurationOnAnnotations by typedKey<List<KClass<out Annotation>>>()
val updateConfigurationOnSections by typedKey<List<String>>()
}
@@ -22,37 +22,22 @@ interface ScriptSource {
data class ScriptSourceNamedFragment(val name: String?, val range: ScriptSource.Range) data class ScriptSourceNamedFragment(val name: String?, val range: ScriptSource.Range)
open class ScriptSourceFragments( enum class ScriptBodyTarget {
val originalSource: ScriptSource, Constructor,
val fragments: List<ScriptSourceNamedFragment>?) SingleAbstractMethod
open class ProvidedDeclarations(
val implicitReceivers: List<KType> = emptyList(), // previous scripts, etc.
val contextVariables: Map<String, KType> = emptyMap() // external variables
// Q: do we need context constants and/or types here, e.g.
// val contextConstants: Map<String, Any?> // or with KType as well
// val contextTypes: List<KType> // additional (to the classpath) types provided by the environment
// alternatively:
// val contextDeclarations: List<Tuple<DeclarationKind, String?, KType, Any?> // kind, name, type, value
// OR: it should be a HeterogeneousMap too
) {
object Empty : ProvidedDeclarations()
} }
open class ScriptSignature( data class ResolvingRestrictionRule(
val scriptBase: KClass<*>, val action: Action,
val providedDeclarations: ProvidedDeclarations val pattern: String // FQN wildcard
) ) {
enum class Action {
open class ResolvingRestrictions { Allow,
data class Rule( Deny
val allow: Boolean, }
val pattern: String // FQN wildcard
)
val rules: Iterable<Rule> = arrayListOf()
} }
interface ScriptDependency { interface ScriptDependency {
// Q: anything generic here? // Q: anything generic here?
} }
@@ -9,8 +9,8 @@ package kotlin.script.experimental.api
object ScriptDefinitionProperties { object ScriptDefinitionProperties {
val name by typedKey<String>() val name by typedKey<String>() // Name of the script type, by default "Kotlin script"
val fileExtension by typedKey<String>() val fileExtension by typedKey<String>() // default: "kts"
} }
@@ -10,14 +10,13 @@ import kotlin.script.experimental.api.*
class PassThroughCompilationConfigurator(val environment: ChainedPropertyBag) : ScriptCompilationConfigurator { class PassThroughCompilationConfigurator(val environment: ChainedPropertyBag) : ScriptCompilationConfigurator {
override val defaultConfiguration = ScriptCompileConfiguration( override val defaultConfiguration = ScriptCompileConfiguration(environment)
ScriptCompileConfigurationParams.baseClass to environment[ScriptingEnvironmentProperties.baseClass]
)
override suspend fun baseConfiguration(scriptSource: ScriptSource): ResultWithDiagnostics<ScriptCompileConfiguration> = override suspend fun baseConfiguration(scriptSource: ScriptSource): ResultWithDiagnostics<ScriptCompileConfiguration> =
defaultConfiguration.asSuccess() defaultConfiguration.asSuccess()
override suspend fun refineConfiguration( override suspend fun refineConfiguration(
script: ScriptSource,
configuration: ScriptCompileConfiguration, configuration: ScriptCompileConfiguration,
processedScriptData: ProcessedScriptData processedScriptData: ProcessedScriptData
): ResultWithDiagnostics<ScriptCompileConfiguration> = ): ResultWithDiagnostics<ScriptCompileConfiguration> =
@@ -9,8 +9,6 @@ import java.io.File
import java.net.URL import java.net.URL
import kotlin.script.experimental.api.* import kotlin.script.experimental.api.*
fun ScriptSourceFragments.isWholeFile(): Boolean = fragments?.isEmpty() ?: true
fun ScriptSource.getScriptText(): String = when { fun ScriptSource.getScriptText(): String = when {
text != null -> text!! text != null -> text!!
location != null -> location != null ->
@@ -20,13 +18,13 @@ fun ScriptSource.getScriptText(): String = when {
fun getMergedScriptText(script: ScriptSource, configuration: ScriptCompileConfiguration): String { fun getMergedScriptText(script: ScriptSource, configuration: ScriptCompileConfiguration): String {
val originalScriptText = script.getScriptText() val originalScriptText = script.getScriptText()
val sourceFragments = configuration.getOrNull(ScriptCompileConfigurationParams.scriptSourceFragments) val sourceFragments = configuration.getOrNull(ScriptCompileConfigurationProperties.sourceFragments)
return if (sourceFragments == null || sourceFragments.isWholeFile()) { return if (sourceFragments == null || sourceFragments.isEmpty()) {
originalScriptText originalScriptText
} else { } else {
val sb = StringBuilder(originalScriptText.length) val sb = StringBuilder(originalScriptText.length)
var prevFragment: ScriptSourceNamedFragment? = null var prevFragment: ScriptSourceNamedFragment? = null
for (fragment in sourceFragments!!.fragments!!) { for (fragment in sourceFragments) {
val fragmentStartPos = fragment.range.start.absolutePos val fragmentStartPos = fragment.range.start.absolutePos
val fragmentEndPos = fragment.range.end.absolutePos val fragmentEndPos = fragment.range.end.absolutePos
if (fragmentStartPos == null || fragmentEndPos == null) if (fragmentStartPos == null || fragmentEndPos == null)
@@ -15,7 +15,10 @@ import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.* import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
@@ -37,8 +40,8 @@ import kotlin.script.experimental.api.*
import kotlin.script.experimental.dependencies.DependenciesResolver import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.host.getMergedScriptText import kotlin.script.experimental.host.getMergedScriptText
import kotlin.script.experimental.jvm.JvmDependency import kotlin.script.experimental.jvm.JvmDependency
import kotlin.script.experimental.jvm.JvmScriptCompileConfigurationParams import kotlin.script.experimental.jvm.JvmScriptCompileConfigurationProperties
import kotlin.script.experimental.jvm.JvmScriptEvaluationEnvironmentParams import kotlin.script.experimental.jvm.JvmScriptEvaluationEnvironmentProperties
import kotlin.script.experimental.jvm.KJVMCompilerProxy import kotlin.script.experimental.jvm.KJVMCompilerProxy
import kotlin.script.experimental.jvm.impl.BridgeDependenciesResolver import kotlin.script.experimental.jvm.impl.BridgeDependenciesResolver
@@ -49,8 +52,8 @@ class KJVMCompiledScript<out ScriptBase : Any>(
) : CompiledScript<ScriptBase> { ) : CompiledScript<ScriptBase> {
override suspend fun instantiate(scriptEvaluationEnvironment: ScriptEvaluationEnvironment): ResultWithDiagnostics<ScriptBase> = try { override suspend fun instantiate(scriptEvaluationEnvironment: ScriptEvaluationEnvironment): ResultWithDiagnostics<ScriptBase> = try {
val baseClassLoader = scriptEvaluationEnvironment.getOrNull(JvmScriptEvaluationEnvironmentParams.baseClassLoader) val baseClassLoader = scriptEvaluationEnvironment.getOrNull(JvmScriptEvaluationEnvironmentProperties.baseClassLoader)
val dependencies = configuration.getOrNull(ScriptCompileConfigurationParams.dependencies) val dependencies = configuration.getOrNull(ScriptCompileConfigurationProperties.dependencies)
?.flatMap { (it as? JvmDependency)?.classpath?.map { it.toURI().toURL() } ?: emptyList() } ?.flatMap { (it as? JvmDependency)?.classpath?.map { it.toURI().toURL() } ?: emptyList() }
// TODO: previous dependencies and classloaders should be taken into account here // TODO: previous dependencies and classloaders should be taken into account here
val classLoaderWithDeps = val classLoaderWithDeps =
@@ -82,14 +85,14 @@ class KJVMCompilerImpl : KJVMCompilerProxy {
var environment: KotlinCoreEnvironment? = null var environment: KotlinCoreEnvironment? = null
var updatedScriptCompileConfiguration = scriptCompilerConfiguration var updatedScriptCompileConfiguration = scriptCompilerConfiguration
fun updateClasspath(classpath: Iterable<File>) { fun updateClasspath(classpath: List<File>) {
environment!!.updateClasspath(classpath.map(::JvmClasspathRoot)) environment!!.updateClasspath(classpath.map(::JvmClasspathRoot))
val updatedDeps = updatedScriptCompileConfiguration.getOrNull(ScriptCompileConfigurationParams.dependencies)?.plus( val updatedDeps = updatedScriptCompileConfiguration.getOrNull(ScriptCompileConfigurationProperties.dependencies)?.plus(
JvmDependency(classpath) JvmDependency(classpath)
) ?: listOf(JvmDependency(classpath)) ) ?: listOf(JvmDependency(classpath))
updatedScriptCompileConfiguration = ChainedPropertyBag( updatedScriptCompileConfiguration = ChainedPropertyBag(
updatedScriptCompileConfiguration, updatedScriptCompileConfiguration,
ScriptCompileConfigurationParams.dependencies to updatedDeps ScriptCompileConfigurationProperties.dependencies to updatedDeps
) )
} }
@@ -103,13 +106,13 @@ class KJVMCompilerImpl : KJVMCompilerProxy {
put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true) put(JVMConfigurationKeys.RETAIN_OUTPUT_IN_MEMORY, true)
var isModularJava = false var isModularJava = false
scriptCompilerConfiguration.getOrNull(JvmScriptCompileConfigurationParams.javaHomeDir)?.let { scriptCompilerConfiguration.getOrNull(JvmScriptCompileConfigurationProperties.javaHomeDir)?.let {
put(JVMConfigurationKeys.JDK_HOME, it) put(JVMConfigurationKeys.JDK_HOME, it)
isModularJava = CoreJrtFileSystem.isModularJdk(it) isModularJava = CoreJrtFileSystem.isModularJdk(it)
} }
var explicitStdlib = false var explicitStdlib = false
scriptCompilerConfiguration.getOrNull(ScriptCompileConfigurationParams.dependencies)?.let { scriptCompilerConfiguration.getOrNull(ScriptCompileConfigurationProperties.dependencies)?.let {
addJvmClasspathRoots( addJvmClasspathRoots(
it.flatMap { it.flatMap {
(it as JvmDependency).classpath.also { (it as JvmDependency).classpath.also {
@@ -242,9 +245,9 @@ internal class BridgeScriptDefinition(
scriptCompilerConfiguration: ScriptCompileConfiguration, scriptCompilerConfiguration: ScriptCompileConfiguration,
scriptConfigurator: ScriptCompilationConfigurator?, scriptConfigurator: ScriptCompilationConfigurator?,
updateClasspath: (List<File>) -> Unit updateClasspath: (List<File>) -> Unit
) : KotlinScriptDefinition(scriptCompilerConfiguration[ScriptCompileConfigurationParams.scriptSignature].scriptBase as KClass<out Any>) { ) : KotlinScriptDefinition(scriptCompilerConfiguration[ScriptingEnvironmentProperties.baseClass] as KClass<out Any>) {
override val acceptedAnnotations = override val acceptedAnnotations =
scriptCompilerConfiguration.getOrNull(ScriptCompileConfigurationParams.updateConfigurationOnAnnotations)?.toList() ?: emptyList() scriptCompilerConfiguration.getOrNull(ScriptCompileConfigurationProperties.updateConfigurationOnAnnotations)?.toList() ?: emptyList()
override val dependencyResolver: DependenciesResolver = override val dependencyResolver: DependenciesResolver =
BridgeDependenciesResolver(scriptConfigurator, scriptCompilerConfiguration, updateClasspath) BridgeDependenciesResolver(scriptConfigurator, scriptCompilerConfiguration, updateClasspath)
@@ -36,15 +36,14 @@ class BridgeDependenciesResolver(
val diagnostics = arrayListOf<ScriptReport>() val diagnostics = arrayListOf<ScriptReport>()
val processedScriptData = val processedScriptData =
ProcessedScriptData(ProcessedScriptDataParams.annotations to scriptContents.annotations) ProcessedScriptData(ProcessedScriptDataProperties.foundAnnotations to scriptContents.annotations)
val scriptCompilerConfiguration = ChainedPropertyBag(
baseScriptCompilerConfiguration,
ScriptCompileConfigurationParams.scriptSourceFragments to scriptContents.toScriptSourceFragments()
)
val refinedConfiguration = scriptConfigurator?.let { val refinedConfiguration = scriptConfigurator?.let {
val res = scriptConfigurator.refineConfiguration(scriptCompilerConfiguration, processedScriptData) val res = scriptConfigurator.refineConfiguration(
scriptContents.toScriptSource(),
baseScriptCompilerConfiguration,
processedScriptData
)
when (res) { when (res) {
is ResultWithDiagnostics.Failure -> is ResultWithDiagnostics.Failure ->
return@resolveAsync DependenciesResolver.ResolveResult.Failure(res.reports.mapScriptReportsToDiagnostics()) return@resolveAsync DependenciesResolver.ResolveResult.Failure(res.reports.mapScriptReportsToDiagnostics())
@@ -53,12 +52,12 @@ class BridgeDependenciesResolver(
res.value res.value
} }
} }
} ?: scriptCompilerConfiguration } ?: baseScriptCompilerConfiguration
val newClasspath = refinedConfiguration.getOrNull(ScriptCompileConfigurationParams.dependencies) val newClasspath = refinedConfiguration.getOrNull(ScriptCompileConfigurationProperties.dependencies)
?.flatMap { (it as JvmDependency).classpath } ?: emptyList() ?.flatMap { (it as JvmDependency).classpath } ?: emptyList()
if (refinedConfiguration != scriptCompilerConfiguration) { if (refinedConfiguration != baseScriptCompilerConfiguration) {
val oldClasspath = scriptCompilerConfiguration.getOrNull(ScriptCompileConfigurationParams.dependencies) val oldClasspath = baseScriptCompilerConfiguration.getOrNull(ScriptCompileConfigurationProperties.dependencies)
?.flatMap { (it as JvmDependency).classpath } ?: emptyList() ?.flatMap { (it as JvmDependency).classpath } ?: emptyList()
if (newClasspath != oldClasspath) { if (newClasspath != oldClasspath) {
onClasspathUpdated(newClasspath) onClasspathUpdated(newClasspath)
@@ -67,16 +66,14 @@ class BridgeDependenciesResolver(
DependenciesResolver.ResolveResult.Success( DependenciesResolver.ResolveResult.Success(
ScriptDependencies( ScriptDependencies(
classpath = newClasspath, // TODO: maybe it should return only increment from the initial config classpath = newClasspath, // TODO: maybe it should return only increment from the initial config
imports = refinedConfiguration.getOrNull(ScriptCompileConfigurationParams.importedPackages)?.toList() imports = refinedConfiguration.getOrNull(ScriptCompileConfigurationProperties.importedPackages)?.toList()
?: emptyList() ?: emptyList()
), ),
diagnostics diagnostics
) )
} catch (e: Throwable) { } catch (e: Throwable) {
DependenciesResolver.ResolveResult.Failure( DependenciesResolver.ResolveResult.Failure(
ScriptReport( ScriptReport(e.message ?: "unknown error $e")
e.message ?: "unknown error $e"
)
) )
} }
} }
@@ -85,13 +82,9 @@ class BridgeDependenciesResolver(
internal fun List<ScriptDiagnostic>.mapScriptReportsToDiagnostics() = internal fun List<ScriptDiagnostic>.mapScriptReportsToDiagnostics() =
map { ScriptReport(it.message, mapToLegacyScriptReportSeverity(it.severity), mapToLegacyScriptReportPosition(it.location)) } map { ScriptReport(it.message, mapToLegacyScriptReportSeverity(it.severity), mapToLegacyScriptReportPosition(it.location)) }
internal fun ScriptContents.toScriptSourceFragments(): ScriptSourceFragments = internal fun ScriptContents.toScriptSource(): ScriptSource = when {
ScriptSourceFragments( text != null -> text!!.toString().toScriptSource()
when { file != null -> file!!.toScriptSource()
text != null -> text!!.toString().toScriptSource() else -> throw IllegalArgumentException("Unable to convert script contents $this into script source")
file != null -> file!!.toScriptSource() }
else -> throw IllegalArgumentException("Unable to convert script contents $this into script source")
},
null
)
@@ -19,11 +19,10 @@ open class JvmScriptCompiler(
configuration: ScriptCompileConfiguration, configuration: ScriptCompileConfiguration,
configurator: ScriptCompilationConfigurator? configurator: ScriptCompilationConfigurator?
): ResultWithDiagnostics<CompiledScript<*>> { ): ResultWithDiagnostics<CompiledScript<*>> {
val refinedConfiguration = configurator?.refineConfiguration(configuration)?.let { val refinedConfiguration = configurator?.refineConfiguration(script, configuration)?.let {
when (it) { when (it) {
is ResultWithDiagnostics.Failure -> return it is ResultWithDiagnostics.Failure -> return it
is ResultWithDiagnostics.Success -> it.value is ResultWithDiagnostics.Success -> it.value
?: return ResultWithDiagnostics.Failure("Null script compile configuration received".asErrorDiagnostics())
} }
} ?: configuration } ?: configuration
val cached = cache.get(script, refinedConfiguration) val cached = cache.get(script, refinedConfiguration)
@@ -32,7 +31,7 @@ open class JvmScriptCompiler(
return compilerProxy.compile(script, refinedConfiguration, configurator).also { return compilerProxy.compile(script, refinedConfiguration, configurator).also {
if (it is ResultWithDiagnostics.Success) { if (it is ResultWithDiagnostics.Success) {
cache.store(it.value as CompiledScript<*>) cache.store(it.value, refinedConfiguration)
} }
} }
} }
@@ -40,7 +39,7 @@ open class JvmScriptCompiler(
interface CompiledJvmScriptsCache { interface CompiledJvmScriptsCache {
fun get(script: ScriptSource, configuration: ScriptCompileConfiguration): CompiledScript<*>? fun get(script: ScriptSource, configuration: ScriptCompileConfiguration): CompiledScript<*>?
fun store(compiledScript: CompiledScript<*>) fun store(compiledScript: CompiledScript<*>, configuration: ScriptCompileConfiguration)
} }
interface KJVMCompilerProxy { interface KJVMCompilerProxy {
@@ -53,6 +52,6 @@ interface KJVMCompilerProxy {
class DummyCompiledJvmScriptCache : CompiledJvmScriptsCache { class DummyCompiledJvmScriptCache : CompiledJvmScriptsCache {
override fun get(script: ScriptSource, configuration: ScriptCompileConfiguration): CompiledScript<*>? = null override fun get(script: ScriptSource, configuration: ScriptCompileConfiguration): CompiledScript<*>? = null
override fun store(compiledScript: CompiledScript<*>) {} override fun store(compiledScript: CompiledScript<*>, configuration: ScriptCompileConfiguration) {}
} }
@@ -9,7 +9,7 @@ import kotlinx.coroutines.experimental.runBlocking
import kotlin.script.experimental.api.* import kotlin.script.experimental.api.*
import java.io.File import java.io.File
val jvmJavaHomeParams = with(JvmScriptCompileConfigurationParams) { val jvmJavaHomeParams = with(JvmScriptCompileConfigurationProperties) {
listOf(javaHomeDir to File(System.getProperty("java.home"))) listOf(javaHomeDir to File(System.getProperty("java.home")))
} }
@@ -9,9 +9,11 @@ import java.io.File
import kotlin.script.experimental.api.ScriptDependency import kotlin.script.experimental.api.ScriptDependency
import kotlin.script.experimental.api.typedKey import kotlin.script.experimental.api.typedKey
object JvmScriptCompileConfigurationParams { object JvmScriptCompileConfigurationProperties {
val javaHomeDir by typedKey<File>() val javaHomeDir by typedKey<File>()
} }
class JvmDependency(val classpath: Iterable<File>) : ScriptDependency class JvmDependency(val classpath: List<File>) : ScriptDependency {
constructor(vararg classpathEntries: File) : this(classpathEntries.asList())
}
@@ -18,6 +18,6 @@ open class JvmBasicScriptingHost<ScriptBase : Any>(
evaluator: ScriptEvaluator<ScriptBase> evaluator: ScriptEvaluator<ScriptBase>
) : BasicScriptingHost<ScriptBase>(configurationExtractor, compiler, evaluator) ) : BasicScriptingHost<ScriptBase>(configurationExtractor, compiler, evaluator)
object JvmScriptEvaluationEnvironmentParams { object JvmScriptEvaluationEnvironmentProperties {
val baseClassLoader by typedKey<ClassLoader?>() val baseClassLoader by typedKey<ClassLoader?>()
} }
@@ -18,6 +18,9 @@ inline operator fun <reified E> TypedKey<List<E>>.invoke(vararg vs: E): Pair<Typ
@JvmName("invokeIterable") @JvmName("invokeIterable")
inline operator fun <reified E> TypedKey<Iterable<E>>.invoke(vararg vs: E): Pair<TypedKey<Iterable<E>>, Iterable<E>> = this to vs.toList() inline operator fun <reified E> TypedKey<Iterable<E>>.invoke(vararg vs: E): Pair<TypedKey<Iterable<E>>, Iterable<E>> = this to vs.toList()
inline operator fun <reified K, reified V> TypedKey<Map<K, V>>.invoke(vararg vs: Pair<K, V>): Pair<TypedKey<Map<K, V>>, Map<K, V>> =
this to hashMapOf(*vs)
// TODO: make tests from examples below // TODO: make tests from examples below
/* /*
val x = with(kotlin.script.experimental.api.ScriptingEnvironmentProperties) { val x = with(kotlin.script.experimental.api.ScriptingEnvironmentProperties) {
@@ -13,14 +13,15 @@ import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.script.KotlinScriptDefinition import org.jetbrains.kotlin.script.KotlinScriptDefinition
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KType import kotlin.reflect.KType
import kotlin.script.experimental.api.ScriptCompileConfigurationParams import kotlin.script.experimental.api.ScriptCompileConfigurationProperties
import kotlin.script.experimental.api.ScriptDefinition import kotlin.script.experimental.api.ScriptDefinition
import kotlin.script.experimental.api.ScriptDefinitionProperties import kotlin.script.experimental.api.ScriptDefinitionProperties
import kotlin.script.experimental.api.ScriptingEnvironmentProperties
import kotlin.script.experimental.dependencies.DependenciesResolver import kotlin.script.experimental.dependencies.DependenciesResolver
import kotlin.script.experimental.jvm.impl.BridgeDependenciesResolver import kotlin.script.experimental.jvm.impl.BridgeDependenciesResolver
class KotlinScriptDefinitionAdapterFromNewAPI(val scriptDefinition: ScriptDefinition) : class KotlinScriptDefinitionAdapterFromNewAPI(val scriptDefinition: ScriptDefinition) :
KotlinScriptDefinition(scriptDefinition.compilationConfigurator.defaultConfiguration[ScriptCompileConfigurationParams.baseClass]) { KotlinScriptDefinition(scriptDefinition.compilationConfigurator.defaultConfiguration[ScriptingEnvironmentProperties.baseClass]) {
override val name: String get() = scriptDefinition.properties[ScriptDefinitionProperties.name] override val name: String get() = scriptDefinition.properties[ScriptDefinitionProperties.name]
@@ -46,12 +47,12 @@ class KotlinScriptDefinitionAdapterFromNewAPI(val scriptDefinition: ScriptDefini
} }
override val acceptedAnnotations: List<KClass<out Annotation>> by lazy { override val acceptedAnnotations: List<KClass<out Annotation>> by lazy {
scriptDefinition.compilationConfigurator.defaultConfiguration.getOrNull(ScriptCompileConfigurationParams.updateConfigurationOnAnnotations)?.toList() scriptDefinition.compilationConfigurator.defaultConfiguration.getOrNull(ScriptCompileConfigurationProperties.updateConfigurationOnAnnotations)?.toList()
?: emptyList() ?: emptyList()
} }
override val implicitReceivers: List<KType> by lazy { override val implicitReceivers: List<KType> by lazy {
scriptDefinition.compilationConfigurator.defaultConfiguration.getOrNull(ScriptCompileConfigurationParams.scriptSignature)?.providedDeclarations?.implicitReceivers scriptDefinition.compilationConfigurator.defaultConfiguration.getOrNull(ScriptCompileConfigurationProperties.scriptImplicitReceivers)
?: emptyList() ?: emptyList()
} }
} }