diff --git a/libraries/scripting/common/src/kotlin/script/experimental/annotations/scriptAnnotations.kt b/libraries/scripting/common/src/kotlin/script/experimental/annotations/scriptAnnotations.kt index c6c2abb56ef..fbaa4e37165 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/annotations/scriptAnnotations.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/annotations/scriptAnnotations.kt @@ -9,6 +9,7 @@ package kotlin.script.experimental.annotations import kotlin.reflect.KClass import kotlin.script.experimental.api.ScriptCompilationConfiguration +import kotlin.script.experimental.api.ScriptEvaluationConfiguration /** * The annotation for declaring a script definition (template) @@ -26,6 +27,8 @@ import kotlin.script.experimental.api.ScriptCompilationConfiguration * default - "kts" * @param compilationConfiguration an object or a class with default constructor containing initial script compilation configuration * default - {@link ScriptCompilationConfiguration#Default} + * @param evaluationConfiguration an object or a class with default constructor containing initial script evaluation configuration + * default - {@link ScriptEvaluationConfiguration#Default} * * Simple usage example: *
@@ -44,6 +47,7 @@ import kotlin.script.experimental.api.ScriptCompilationConfiguration
annotation class KotlinScript(
val displayName: String = "Kotlin script",
val fileExtension: String = "kts",
- val compilationConfiguration: KClass = ScriptCompilationConfiguration.Default::class
+ val compilationConfiguration: KClass = ScriptCompilationConfiguration.Default::class,
+ val evaluationConfiguration: KClass = ScriptEvaluationConfiguration.Default::class
)
diff --git a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt
index ac1b0cfc171..9810b59ff4e 100644
--- a/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt
+++ b/libraries/scripting/common/src/kotlin/script/experimental/api/scriptEvaluation.kt
@@ -17,7 +17,7 @@ interface ScriptEvaluationConfigurationKeys
* The container for script evaluation configuration
* For usages see actual code examples
*/
-class ScriptEvaluationConfiguration(baseEvaluationConfigurations: Iterable, body: Builder.() -> Unit) :
+open class ScriptEvaluationConfiguration(baseEvaluationConfigurations: Iterable, body: Builder.() -> Unit) :
PropertiesCollection(Builder(baseEvaluationConfigurations).apply(body).data) {
constructor(body: Builder.() -> Unit = {}) : this(emptyList(), body)
@@ -30,6 +30,8 @@ class ScriptEvaluationConfiguration(baseEvaluationConfigurations: Iterable,
- scriptEvaluationConfiguration: ScriptEvaluationConfiguration?
+ scriptEvaluationConfiguration: ScriptEvaluationConfiguration = ScriptEvaluationConfiguration.Default
): ResultWithDiagnostics
}
diff --git a/libraries/scripting/common/src/kotlin/script/experimental/host/BasicScriptingHost.kt b/libraries/scripting/common/src/kotlin/script/experimental/host/BasicScriptingHost.kt
index cef092a5337..a2c0efe5ce4 100644
--- a/libraries/scripting/common/src/kotlin/script/experimental/host/BasicScriptingHost.kt
+++ b/libraries/scripting/common/src/kotlin/script/experimental/host/BasicScriptingHost.kt
@@ -39,12 +39,12 @@ abstract class BasicScriptingHost(
*/
open fun eval(
script: SourceCode,
- scriptCompilationConfiguration: ScriptCompilationConfiguration,
- configuration: ScriptEvaluationConfiguration?
+ compilationConfiguration: ScriptCompilationConfiguration,
+ evaluationConfiguration: ScriptEvaluationConfiguration?
): ResultWithDiagnostics =
runInCoroutineContext {
- compiler(script, scriptCompilationConfiguration).onSuccess {
- evaluator(it, configuration)
+ compiler(script, compilationConfiguration).onSuccess {
+ evaluator(it, evaluationConfiguration ?: ScriptEvaluationConfiguration.Default)
}
}
}
diff --git a/libraries/scripting/common/src/kotlin/script/experimental/host/configurationFromTemplate.kt b/libraries/scripting/common/src/kotlin/script/experimental/host/configurationFromTemplate.kt
index 6af633c4ca7..6d1a0e75bd0 100644
--- a/libraries/scripting/common/src/kotlin/script/experimental/host/configurationFromTemplate.kt
+++ b/libraries/scripting/common/src/kotlin/script/experimental/host/configurationFromTemplate.kt
@@ -8,6 +8,7 @@ package kotlin.script.experimental.host
import kotlin.reflect.KClass
import kotlin.script.experimental.annotations.KotlinScript
import kotlin.script.experimental.api.*
+import kotlin.script.experimental.util.PropertiesCollection
private const val ERROR_MSG_PREFIX = "Unable to construct script definition: "
@@ -20,7 +21,7 @@ private const val SCRIPT_RUNTIME_TEMPLATES_PACKAGE = "kotlin.script.templates.st
private abstract class DummyScriptTemplate
/**
- * Creates the compilation configuration from annotated script base class
+ * Creates compilation configuration from annotated script base class
* @param baseClassType the annotated script base class to construct the configuration from
* @param hostConfiguration scripting host configuration properties
* @param contextClass optional context class to extract classloading strategy from
@@ -33,48 +34,70 @@ fun createCompilationConfigurationFromTemplate(
body: ScriptCompilationConfiguration.Builder.() -> Unit = {}
): ScriptCompilationConfiguration {
+ val templateClass: KClass<*> = baseClassType.getTemplateClass(hostConfiguration, contextClass)
+
+ val mainAnnotation: KotlinScript = templateClass.kotlinScriptAnnotation
+
+ return ScriptCompilationConfiguration(scriptConfigInstance(mainAnnotation.compilationConfiguration)) {
+ propertiesFromTemplate(templateClass, baseClassType, mainAnnotation)
+ body()
+ }
+}
+
+/**
+ * Creates evaluation configuration from annotated script base class
+ * @param baseClassType the annotated script base class to construct the configuration from
+ * @param hostConfiguration scripting host configuration properties
+ * @param contextClass optional context class to extract classloading strategy from
+ * @param body optional configuration function to add more properties to the evaluation configuration
+ */
+fun createEvaluationConfigurationFromTemplate(
+ baseClassType: KotlinType,
+ hostConfiguration: ScriptingHostConfiguration,
+ contextClass: KClass<*> = ScriptEvaluationConfiguration::class,
+ body: ScriptEvaluationConfiguration.Builder.() -> Unit = {}
+): ScriptEvaluationConfiguration {
+
+ val templateClass: KClass<*> = baseClassType.getTemplateClass(hostConfiguration, contextClass)
+
+ val mainAnnotation = templateClass.kotlinScriptAnnotation
+
+ return ScriptEvaluationConfiguration(scriptConfigInstance(mainAnnotation.evaluationConfiguration), body = body)
+}
+
+private fun ScriptCompilationConfiguration.Builder.propertiesFromTemplate(
+ templateClass: KClass<*>, baseClassType: KotlinType, mainAnnotation: KotlinScript
+) {
+ if (baseClass() == null) {
+ baseClass(if (templateClass == baseClassType.fromClass) baseClassType else KotlinType(templateClass))
+ }
+ if (fileExtension() == null) {
+ fileExtension(mainAnnotation.fileExtension)
+ }
+ if (displayName() == null) {
+ displayName(mainAnnotation.displayName)
+ }
+}
+
+private val KClass<*>.kotlinScriptAnnotation: KotlinScript
+ get() = findAnnotation()
+ ?: when (this@kotlinScriptAnnotation.qualifiedName) {
+ // transitions to the new scripting API: substituting annotations for standard templates from script-runtime
+ "$SCRIPT_RUNTIME_TEMPLATES_PACKAGE.SimpleScriptTemplate",
+ "$SCRIPT_RUNTIME_TEMPLATES_PACKAGE.ScriptTemplateWithArgs",
+ "$SCRIPT_RUNTIME_TEMPLATES_PACKAGE.ScriptTemplateWithBindings" -> DummyScriptTemplate::class.findAnnotation()
+ else -> null
+ }
+ ?: throw IllegalArgumentException("${ERROR_MSG_PREFIX}Expecting KotlinScript annotation on the ${this}")
+
+private fun KotlinType.getTemplateClass(hostConfiguration: ScriptingHostConfiguration, contextClass: KClass<*>): KClass<*> {
val getScriptingClass = hostConfiguration[ScriptingHostConfiguration.getScriptingClass]
?: throw IllegalArgumentException("${ERROR_MSG_PREFIX}Expecting 'getScriptingClass' parameter in the scripting host configuration")
- val baseClass: KClass<*> =
- try {
- getScriptingClass(baseClassType, contextClass, hostConfiguration)
- } catch (e: Throwable) {
- throw IllegalArgumentException("${ERROR_MSG_PREFIX}Unable to load base class $baseClassType", e)
- }
- val loadedBaseClassType = if (baseClass == baseClassType.fromClass) baseClassType else KotlinType(baseClass)
-
- val mainAnnotation = baseClass.findAnnotation()
- ?: run {
- // transitions to the new scripting API:
- // substituting annotations for standard templates from script-runtime
- when (baseClass.qualifiedName) {
- "$SCRIPT_RUNTIME_TEMPLATES_PACKAGE.SimpleScriptTemplate",
- "$SCRIPT_RUNTIME_TEMPLATES_PACKAGE.ScriptTemplateWithArgs",
- "$SCRIPT_RUNTIME_TEMPLATES_PACKAGE.ScriptTemplateWithBindings" -> DummyScriptTemplate::class
- else -> null
- }?.findAnnotation()
- }
- ?: throw IllegalArgumentException("${ERROR_MSG_PREFIX}Expecting KotlinScript annotation on the $baseClass")
-
- fun scriptConfigInstance(kclass: KClass): ScriptCompilationConfiguration = try {
- kclass.objectInstance ?: kclass.createInstance()
+ return try {
+ getScriptingClass(this, contextClass, hostConfiguration)
} catch (e: Throwable) {
- throw IllegalArgumentException("$ILLEGAL_CONFIG_ANN_ARG: ${e.message}", e)
- }
-
- return ScriptCompilationConfiguration(scriptConfigInstance(mainAnnotation.compilationConfiguration)) {
- if (baseClass() == null) {
- baseClass(loadedBaseClassType)
- }
- if (fileExtension() == null) {
- fileExtension(mainAnnotation.fileExtension)
- }
- if (displayName() == null) {
- displayName(mainAnnotation.displayName)
- }
-
- body()
+ throw IllegalArgumentException("${ERROR_MSG_PREFIX}Unable to load base class ${this}", e)
}
}
@@ -90,3 +113,10 @@ private fun KClass.createInstance(): T {
@Suppress("UNCHECKED_CAST")
return noArgsConstructor.newInstance() as T
}
+
+private fun scriptConfigInstance(kclass: KClass): T = try {
+ kclass.objectInstance ?: kclass.createInstance()
+} catch (e: Throwable) {
+ throw IllegalArgumentException("$ILLEGAL_CONFIG_ANN_ARG: ${e.message}", e)
+}
+
diff --git a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/BasicJvmScriptingHost.kt b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/BasicJvmScriptingHost.kt
index 03c458b5b15..16ab08ad192 100644
--- a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/BasicJvmScriptingHost.kt
+++ b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/BasicJvmScriptingHost.kt
@@ -5,19 +5,30 @@
package kotlin.script.experimental.jvmhost
-import kotlin.script.experimental.api.KotlinType
-import kotlin.script.experimental.api.ScriptCompilationConfiguration
-import kotlin.script.experimental.api.ScriptEvaluator
+import kotlin.script.experimental.api.*
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.host.createCompilationConfigurationFromTemplate
import kotlin.script.experimental.host.BasicScriptingHost
+import kotlin.script.experimental.host.createEvaluationConfigurationFromTemplate
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
open class BasicJvmScriptingHost(
- hostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration,
+ val hostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration,
compiler: JvmScriptCompiler = JvmScriptCompiler(hostConfiguration),
evaluator: ScriptEvaluator = BasicJvmScriptEvaluator()
-) : BasicScriptingHost(compiler, evaluator)
+) : BasicScriptingHost(compiler, evaluator) {
+
+ inline fun evalWithTemplate(
+ script: SourceCode,
+ noinline compilation: ScriptCompilationConfiguration.Builder.() -> Unit = {},
+ noinline evaluation: ScriptEvaluationConfiguration.Builder.() -> Unit = {}
+ ): ResultWithDiagnostics =
+ eval(
+ script,
+ createJvmCompilationConfigurationFromTemplate(hostConfiguration, compilation),
+ createJvmEvaluationConfigurationFromTemplate(hostConfiguration, evaluation)
+ )
+}
inline fun createJvmCompilationConfigurationFromTemplate(
@@ -29,3 +40,13 @@ inline fun createJvmCompilationConfigurationFromTemplate(
ScriptCompilationConfiguration::class,
body
)
+
+inline fun createJvmEvaluationConfigurationFromTemplate(
+ hostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration,
+ noinline body: ScriptEvaluationConfiguration.Builder.() -> Unit = {}
+): ScriptEvaluationConfiguration = createEvaluationConfigurationFromTemplate(
+ KotlinType(T::class),
+ hostConfiguration,
+ ScriptCompilationConfiguration::class,
+ body
+)
diff --git a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptEvaluation.kt b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptEvaluation.kt
index 2470501cba7..ce31d7cdb68 100644
--- a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptEvaluation.kt
+++ b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptEvaluation.kt
@@ -28,11 +28,10 @@ open class BasicJvmScriptEvaluator : ScriptEvaluator {
override suspend operator fun invoke(
compiledScript: CompiledScript<*>,
- scriptEvaluationConfiguration: ScriptEvaluationConfiguration?
+ scriptEvaluationConfiguration: ScriptEvaluationConfiguration
): ResultWithDiagnostics =
try {
- val actualEvalConfiguration = scriptEvaluationConfiguration ?: ScriptEvaluationConfiguration()
- compiledScript.getClass(actualEvalConfiguration).onSuccess { scriptClass ->
+ compiledScript.getClass(scriptEvaluationConfiguration).onSuccess { scriptClass ->
// in the future, when (if) we'll stop to compile everything into constructor
// run as SAM
// return res
@@ -40,14 +39,14 @@ open class BasicJvmScriptEvaluator : ScriptEvaluator {
// for other scripts we need evaluation configuration with actualClassloader set,
// so they are loaded in the same classloader as the "main" script
val updatedEvalConfiguration =
- if (actualEvalConfiguration.containsKey(ScriptEvaluationConfiguration.jvm.actualClassLoader))
- actualEvalConfiguration
+ if (scriptEvaluationConfiguration.containsKey(ScriptEvaluationConfiguration.jvm.actualClassLoader))
+ scriptEvaluationConfiguration
else
- ScriptEvaluationConfiguration(actualEvalConfiguration) {
+ ScriptEvaluationConfiguration(scriptEvaluationConfiguration) {
ScriptEvaluationConfiguration.jvm.actualClassLoader(scriptClass.java.classLoader)
}
- val sharedScripts = actualEvalConfiguration[ScriptEvaluationConfiguration.scriptsInstancesSharingMap]
+ val sharedScripts = scriptEvaluationConfiguration[ScriptEvaluationConfiguration.scriptsInstancesSharingMap]
sharedScripts?.get(scriptClass)?.asSuccess()
?: compiledScript.otherScripts.mapSuccess {
diff --git a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptSaving.kt b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptSaving.kt
index 3ed42180365..95be84054f5 100644
--- a/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptSaving.kt
+++ b/libraries/scripting/jvm-host/src/kotlin/script/experimental/jvmhost/jvmScriptSaving.kt
@@ -20,7 +20,7 @@ open class BasicJvmScriptClassFilesGenerator(val outputDir: File) : ScriptEvalua
override suspend operator fun invoke(
compiledScript: CompiledScript<*>,
- scriptEvaluationConfiguration: ScriptEvaluationConfiguration?
+ scriptEvaluationConfiguration: ScriptEvaluationConfiguration
): ResultWithDiagnostics {
try {
if (compiledScript !is KJvmCompiledScript<*>)
@@ -48,7 +48,7 @@ open class BasicJvmScriptJarGenerator(val outputJar: File) : ScriptEvaluator {
override suspend operator fun invoke(
compiledScript: CompiledScript<*>,
- scriptEvaluationConfiguration: ScriptEvaluationConfiguration?
+ scriptEvaluationConfiguration: ScriptEvaluationConfiguration
): ResultWithDiagnostics {
try {
if (compiledScript !is KJvmCompiledScript<*>)
diff --git a/libraries/scripting/jvm-host/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt b/libraries/scripting/jvm-host/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt
index 686e5905e39..9a52b6b9e77 100644
--- a/libraries/scripting/jvm-host/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt
+++ b/libraries/scripting/jvm-host/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt
@@ -37,6 +37,11 @@ class ScriptingHostTest : TestCase() {
evalScript("println(\"$greeting\")").throwOnFailure()
}
Assert.assertEquals(greeting, output)
+ // another API
+ val output2 = captureOut {
+ BasicJvmScriptingHost().evalWithTemplate("println(\"$greeting\")".toScriptSource()).throwOnFailure()
+ }
+ Assert.assertEquals(greeting, output2)
}
@Test
@@ -276,7 +281,7 @@ class ScriptingHostTest : TestCase() {
runBlocking {
compiler(script.toScriptSource(), scriptCompilationConfiguration).onSuccess {
compiledScript = it
- evaluator(it, null)
+ evaluator(it)
}.throwOnFailure()
}
}.lines()
@@ -296,7 +301,7 @@ class ScriptingHostTest : TestCase() {
val output2 = captureOut {
runBlocking {
- evaluator(cachedScript!!, null).throwOnFailure()
+ evaluator(cachedScript!!).throwOnFailure()
}
}.lines()
Assert.assertEquals(output, output2)