From a13d452cd89d891d553d4aa816782a232c2a6bfd Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 11 Jul 2019 17:33:43 +0200 Subject: [PATCH] Implement JSR223 host in the main-kts jar also improve diagnostics on configuration instantiation --- .../host/configurationFromTemplate.kt | 2 +- .../kotlin/mainKts/test/mainKtsJsr223Test.kt | 26 ++++++++ .../tools/kotlin-main-kts/build.gradle.kts | 4 ++ .../services/javax.script.ScriptEngineFactory | 2 + .../KotlinJsr223MainKtsScriptEngineFactory.kt | 60 +++++++++++++++++++ .../org/jetbrains/kotlin/mainKts/scriptDef.kt | 16 ++++- 6 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsJsr223Test.kt create mode 100644 libraries/tools/kotlin-main-kts/resources/META-INF/services/javax.script.ScriptEngineFactory create mode 100644 libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/jsr223/KotlinJsr223MainKtsScriptEngineFactory.kt 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 1f8fa73b0a9..8f316a5a812 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/host/configurationFromTemplate.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/host/configurationFromTemplate.kt @@ -124,6 +124,6 @@ private fun KClass.createInstance(): T { private fun scriptConfigInstance(kclass: KClass): 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) } diff --git a/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsJsr223Test.kt b/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsJsr223Test.kt new file mode 100644 index 00000000000..39b4a7f3ba9 --- /dev/null +++ b/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsJsr223Test.kt @@ -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) + } +} + diff --git a/libraries/tools/kotlin-main-kts/build.gradle.kts b/libraries/tools/kotlin-main-kts/build.gradle.kts index 576b6bbd332..a3473575496 100644 --- a/libraries/tools/kotlin-main-kts/build.gradle.kts +++ b/libraries/tools/kotlin-main-kts/build.gradle.kts @@ -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 { diff --git a/libraries/tools/kotlin-main-kts/resources/META-INF/services/javax.script.ScriptEngineFactory b/libraries/tools/kotlin-main-kts/resources/META-INF/services/javax.script.ScriptEngineFactory new file mode 100644 index 00000000000..22f71f40d46 --- /dev/null +++ b/libraries/tools/kotlin-main-kts/resources/META-INF/services/javax.script.ScriptEngineFactory @@ -0,0 +1,2 @@ +org.jetbrains.kotlin.mainKts.jsr223.KotlinJsr223MainKtsScriptEngineFactory + diff --git a/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/jsr223/KotlinJsr223MainKtsScriptEngineFactory.kt b/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/jsr223/KotlinJsr223MainKtsScriptEngineFactory.kt new file mode 100644 index 00000000000..219b5892f2e --- /dev/null +++ b/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/jsr223/KotlinJsr223MainKtsScriptEngineFactory.kt @@ -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() + private val evaluationConfiguration = createJvmEvaluationConfigurationFromTemplate() + private var lastClassLoader: ClassLoader? = null + private var lastClassPath: List? = null + + override fun getExtensions(): List = 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()), arrayOf(Array::class)) } +} + diff --git a/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/scriptDef.kt b/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/scriptDef.kt index 2584387e4c7..77267e3f343 100644 --- a/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/scriptDef.kt +++ b/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/scriptDef.kt @@ -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 { + override operator fun invoke(context: ScriptConfigurationRefinementContext): ResultWithDiagnostics = + processAnnotations(context).onSuccess { updatedConfiguration -> + configureProvidedPropertiesFromJsr223Context( + ScriptConfigurationRefinementContext(context.script, updatedConfiguration, context.collectedData) + ) + } + + fun processAnnotations(context: ScriptConfigurationRefinementContext): ResultWithDiagnostics { val diagnostics = arrayListOf() fun report(severity: ScriptDependenciesResolver.ReportSeverity, message: String, position: ScriptContents.Position?) {