Refactor host configuration handling and script definition creation

so it is possible now to create custom host configuration with template
and all configurations are handled consistenly.
Also introduce and use new ScriptDefinition class wrapping compilation
and evaluation configurations, that could be consistenly created from a
template.
This commit is contained in:
Ilya Chernikov
2020-05-13 21:44:39 +02:00
parent 255ad47406
commit 4b032a14af
12 changed files with 246 additions and 159 deletions
@@ -15,21 +15,23 @@ import kotlin.script.experimental.host.toScriptSource
import kotlin.script.experimental.jvm.baseClassLoader
import kotlin.script.experimental.jvm.jvm
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate
import kotlin.script.experimental.jvmhost.createJvmScriptDefinitionFromTemplate
fun evalFile(scriptFile: File, cacheDir: File? = null): ResultWithDiagnostics<EvaluationResult> =
withProperty(COMPILED_SCRIPTS_CACHE_DIR_PROPERTY, cacheDir?.absolutePath ?: "") {
val scriptDefinition = createJvmCompilationConfigurationFromTemplate<MainKtsScript>()
val evaluationEnv = ScriptEvaluationConfiguration {
jvm {
baseClassLoader(null)
val scriptDefinition = createJvmScriptDefinitionFromTemplate<MainKtsScript>(
evaluation = {
jvm {
baseClassLoader(null)
}
constructorArgs(emptyArray<String>())
enableScriptsInstancesSharing()
}
constructorArgs(emptyArray<String>())
enableScriptsInstancesSharing()
}
)
BasicJvmScriptingHost().eval(scriptFile.toScriptSource(), scriptDefinition, evaluationEnv)
BasicJvmScriptingHost().eval(
scriptFile.toScriptSource(), scriptDefinition.compilationConfiguration, scriptDefinition.evaluationConfiguration
)
}
@@ -12,26 +12,25 @@ import java.io.File
import javax.script.ScriptEngine
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.fileExtension
import kotlin.script.experimental.api.with
import kotlin.script.experimental.jvm.JvmScriptCompilationConfigurationBuilder
import kotlin.script.experimental.jvm.dependenciesFromCurrentContext
import kotlin.script.experimental.jvm.jvm
import kotlin.script.experimental.jvm.updateClasspath
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContext
import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate
import kotlin.script.experimental.jvmhost.createJvmEvaluationConfigurationFromTemplate
import kotlin.script.experimental.jvmhost.createJvmScriptDefinitionFromTemplate
import kotlin.script.experimental.jvmhost.jsr223.KotlinJsr223ScriptEngineImpl
class KotlinJsr223MainKtsScriptEngineFactory : KotlinJsr223JvmScriptEngineFactoryBase() {
private val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<MainKtsScript>()
private val evaluationConfiguration = createJvmEvaluationConfigurationFromTemplate<MainKtsScript>()
private val scriptDefinition = createJvmScriptDefinitionFromTemplate<MainKtsScript>()
private var lastClassLoader: ClassLoader? = null
private var lastClassPath: List<File>? = null
override fun getExtensions(): List<String> = listOf(compilationConfiguration[ScriptCompilationConfiguration.fileExtension]!!)
override fun getExtensions(): List<String> =
listOf(scriptDefinition.compilationConfiguration[ScriptCompilationConfiguration.fileExtension]!!)
@Synchronized
protected fun JvmScriptCompilationConfigurationBuilder.dependenciesFromCurrentContext() {
private fun JvmScriptCompilationConfigurationBuilder.dependenciesFromCurrentContext() {
val currentClassLoader = Thread.currentThread().contextClassLoader
val classPath = if (lastClassLoader == null || lastClassLoader != currentClassLoader) {
scriptCompilationClasspathFromContext(
@@ -49,12 +48,12 @@ class KotlinJsr223MainKtsScriptEngineFactory : KotlinJsr223JvmScriptEngineFactor
override fun getScriptEngine(): ScriptEngine =
KotlinJsr223ScriptEngineImpl(
this,
ScriptCompilationConfiguration(compilationConfiguration) {
scriptDefinition.compilationConfiguration.with {
jvm {
dependenciesFromCurrentContext()
}
},
evaluationConfiguration
scriptDefinition.evaluationConfiguration
) { ScriptArgsWithTypes(arrayOf(emptyArray<String>()), arrayOf(Array<String>::class)) }
}
@@ -35,7 +35,8 @@ import kotlin.script.experimental.jvmhost.jsr223.jsr223
@KotlinScript(
fileExtension = "main.kts",
compilationConfiguration = MainKtsScriptDefinition::class,
evaluationConfiguration = MainKtsEvaluationConfiguration::class
evaluationConfiguration = MainKtsEvaluationConfiguration::class,
hostConfiguration = MainKtsHostConfiguration::class
)
abstract class MainKtsScript(val args: Array<String>)
@@ -58,26 +59,8 @@ class MainKtsScriptDefinition : ScriptCompilationConfiguration(
jsr223 {
importAllBindings(true)
}
hostConfiguration(ScriptingHostConfiguration {
jvm {
val cacheExtSetting = System.getProperty(COMPILED_SCRIPTS_CACHE_DIR_PROPERTY)
?: System.getenv(COMPILED_SCRIPTS_CACHE_DIR_ENV_VAR)
val cacheBaseDir = when {
cacheExtSetting == null -> System.getProperty("java.io.tmpdir")
?.let(::File)?.takeIf { it.exists() && it.isDirectory }
?.let { File(it, "main.kts.compiled.cache").apply { mkdir() } }
cacheExtSetting.isBlank() -> null
else -> File(cacheExtSetting)
}?.takeIf { it.exists() && it.isDirectory }
if (cacheBaseDir != null)
compilationCache(
CompiledScriptJarsCache { script, scriptCompilationConfiguration ->
File(cacheBaseDir, compiledScriptUniqueName(script, scriptCompilationConfiguration) + ".jar")
}
)
}
})
})
}
)
object MainKtsEvaluationConfiguration : ScriptEvaluationConfiguration(
{
@@ -87,6 +70,28 @@ object MainKtsEvaluationConfiguration : ScriptEvaluationConfiguration(
}
)
class MainKtsHostConfiguration : ScriptingHostConfiguration(
{
jvm {
val cacheExtSetting = System.getProperty(COMPILED_SCRIPTS_CACHE_DIR_PROPERTY)
?: System.getenv(COMPILED_SCRIPTS_CACHE_DIR_ENV_VAR)
val cacheBaseDir = when {
cacheExtSetting == null -> System.getProperty("java.io.tmpdir")
?.let(::File)?.takeIf { it.exists() && it.isDirectory }
?.let { File(it, "main.kts.compiled.cache").apply { mkdir() } }
cacheExtSetting.isBlank() -> null
else -> File(cacheExtSetting)
}?.takeIf { it.exists() && it.isDirectory }
if (cacheBaseDir != null)
compilationCache(
CompiledScriptJarsCache { script, scriptCompilationConfiguration ->
File(cacheBaseDir, compiledScriptUniqueName(script, scriptCompilationConfiguration) + ".jar")
}
)
}
}
)
fun configureConstructorArgsFromMainArgs(context: ScriptEvaluationConfigurationRefinementContext): ResultWithDiagnostics<ScriptEvaluationConfiguration> {
val mainArgs = context.evaluationConfiguration[ScriptEvaluationConfiguration.jvm.mainArguments]
val res = if (context.evaluationConfiguration[ScriptEvaluationConfiguration.constructorArgs] == null && mainArgs != null) {