Implement JSR223 host in the main-kts jar

also improve diagnostics on configuration instantiation
This commit is contained in:
Ilya Chernikov
2019-07-11 17:33:43 +02:00
parent 0108a76e99
commit a13d452cd8
6 changed files with 108 additions and 2 deletions
@@ -124,6 +124,6 @@ private fun <T : Any> KClass<T>.createInstance(): T {
private fun <T : PropertiesCollection> scriptConfigInstance(kclass: KClass<out T>): T = try {
kclass.objectInstance ?: kclass.createInstance()
} catch (e: Throwable) {
throw IllegalArgumentException("$ILLEGAL_CONFIG_ANN_ARG: ${e.message}", e)
throw IllegalArgumentException("$ILLEGAL_CONFIG_ANN_ARG: ${e.message + if (e.cause != null) " (${e.cause})" else ""}", e)
}
@@ -0,0 +1,26 @@
import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback
import org.junit.Assert
import org.junit.Test
import javax.script.ScriptEngineManager
/*
* 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.
*/
class MainKtsJsr223Test {
init {
setIdeaIoUseFallback()
}
@Test
fun testSimpleEval() {
val engine = ScriptEngineManager().getEngineByExtension("main.kts")!!
val res1 = engine.eval("val x = 3")
Assert.assertNull(res1)
val res2 = engine.eval("x + 2")
Assert.assertEquals(5, res2)
}
}
@@ -15,6 +15,7 @@ val proguardLibraryJars by configurations.creating
val projectsDependencies = listOf(
":kotlin-scripting-common",
":kotlin-scripting-jvm",
":kotlin-scripting-jvm-host",
":kotlin-script-util",
":kotlin-script-runtime"
)
@@ -26,8 +27,10 @@ dependencies {
testCompile(project(it))
}
compileOnly("org.apache.ivy:ivy:2.4.0")
compileOnly(project(":compiler:cli-common"))
runtime(project(":kotlin-compiler-embeddable"))
runtime(project(":kotlin-scripting-compiler-embeddable"))
runtime(project(":kotlin-scripting-jvm-host-embeddable"))
runtime(project(":kotlin-reflect"))
embedded("org.apache.ivy:ivy:2.4.0")
embedded(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) { isTransitive = false }
@@ -36,6 +39,7 @@ dependencies {
toolsJar()))
proguardLibraryJars(kotlinStdlib())
proguardLibraryJars(project(":kotlin-reflect"))
proguardLibraryJars(project(":kotlin-compiler"))
}
sourceSets {
@@ -0,0 +1,2 @@
org.jetbrains.kotlin.mainKts.jsr223.KotlinJsr223MainKtsScriptEngineFactory
@@ -0,0 +1,60 @@
/*
* 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.mainKts.jsr223
import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase
import org.jetbrains.kotlin.cli.common.repl.ScriptArgsWithTypes
import org.jetbrains.kotlin.mainKts.MainKtsScript
import java.io.File
import javax.script.ScriptEngine
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.fileExtension
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.jsr223.KotlinJsr223ScriptEngineImpl
class KotlinJsr223MainKtsScriptEngineFactory : KotlinJsr223JvmScriptEngineFactoryBase() {
private val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<MainKtsScript>()
private val evaluationConfiguration = createJvmEvaluationConfigurationFromTemplate<MainKtsScript>()
private var lastClassLoader: ClassLoader? = null
private var lastClassPath: List<File>? = null
override fun getExtensions(): List<String> = listOf(compilationConfiguration[ScriptCompilationConfiguration.fileExtension]!!)
@Synchronized
protected fun JvmScriptCompilationConfigurationBuilder.dependenciesFromCurrentContext() {
val currentClassLoader = Thread.currentThread().contextClassLoader
val classPath = if (lastClassLoader == null || lastClassLoader != currentClassLoader) {
scriptCompilationClasspathFromContext(
classLoader = currentClassLoader,
wholeClasspath = true,
unpackJarCollections = true
).also {
lastClassLoader = currentClassLoader
lastClassPath = it
}
} else lastClassPath!!
updateClasspath(classPath)
}
override fun getScriptEngine(): ScriptEngine =
KotlinJsr223ScriptEngineImpl(
this,
ScriptCompilationConfiguration(compilationConfiguration) {
jvm {
dependenciesFromCurrentContext()
}
},
evaluationConfiguration
) { ScriptArgsWithTypes(arrayOf(emptyArray<String>()), arrayOf(Array<String>::class)) }
}
@@ -21,6 +21,9 @@ import kotlin.script.experimental.jvm.compat.mapLegacyScriptPosition
import kotlin.script.experimental.jvm.dependenciesFromClassContext
import kotlin.script.experimental.jvm.jvm
import kotlin.script.experimental.jvm.updateClasspath
import kotlin.script.experimental.jvmhost.jsr223.configureProvidedPropertiesFromJsr223Context
import kotlin.script.experimental.jvmhost.jsr223.importAllBindings
import kotlin.script.experimental.jvmhost.jsr223.jsr223
@Suppress("unused")
@KotlinScript(
@@ -42,18 +45,29 @@ object MainKtsScriptDefinition : ScriptCompilationConfiguration(
ide {
acceptedLocations(ScriptAcceptedLocation.Everywhere)
}
jsr223 {
importAllBindings(true)
}
})
object MainKtsEvaluationConfiguration : ScriptEvaluationConfiguration(
{
scriptsInstancesSharing(true)
refineConfigurationBeforeEvaluate(::configureProvidedPropertiesFromJsr223Context)
}
)
class MainKtsConfigurator : RefineScriptCompilationConfigurationHandler {
private val resolver = FilesAndIvyResolver()
override operator fun invoke(context: ScriptConfigurationRefinementContext): ResultWithDiagnostics<ScriptCompilationConfiguration> {
override operator fun invoke(context: ScriptConfigurationRefinementContext): ResultWithDiagnostics<ScriptCompilationConfiguration> =
processAnnotations(context).onSuccess { updatedConfiguration ->
configureProvidedPropertiesFromJsr223Context(
ScriptConfigurationRefinementContext(context.script, updatedConfiguration, context.collectedData)
)
}
fun processAnnotations(context: ScriptConfigurationRefinementContext): ResultWithDiagnostics<ScriptCompilationConfiguration> {
val diagnostics = arrayListOf<ScriptDiagnostic>()
fun report(severity: ScriptDependenciesResolver.ReportSeverity, message: String, position: ScriptContents.Position?) {