From bf0d5b6237d2cec8cfd034cefa558d5b1bf8208b Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Fri, 23 Sep 2016 15:37:36 +0200 Subject: [PATCH] Add basic bindings support to IDEA JSR223 scripting, fix evaluator --- .../repl/GenericReplCompiledEvaluator.kt | 2 +- .../KotlinJvmJsr223ScriptEngine4Idea.kt | 10 +++++++--- ...mJsr223StandardScriptEngineFactory4Idea.kt | 13 ++++++++++--- .../kotlin/idea/repl/IdeaJsr223Test.kt | 19 +++++++++++++++++++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt index c969b2272c6..c72ac1eb521 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt @@ -57,7 +57,7 @@ open class GenericReplCompiledEvaluator(baseClasspath: Iterable, baseClass (compiledLoadedClassesHistory.map { it.second.klass } + (scriptArgs?.asIterable() ?.mapIndexed { i, it -> - it?.javaClass ?: if (i < (scriptArgsTypes?.size ?: 0)) scriptArgsTypes!![i] else Any::class.java + if (i < (scriptArgsTypes?.size ?: 0)) scriptArgsTypes!![i] else it?.javaClass ?: Any::class.java } ?: emptyList() ) diff --git a/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJvmJsr223ScriptEngine4Idea.kt b/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJvmJsr223ScriptEngine4Idea.kt index 35ddd88bf59..a1f5fb45fca 100644 --- a/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJvmJsr223ScriptEngine4Idea.kt +++ b/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJvmJsr223ScriptEngine4Idea.kt @@ -22,7 +22,10 @@ import org.jetbrains.kotlin.cli.common.repl.GenericReplCompiledEvaluator import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult -import org.jetbrains.kotlin.daemon.client.* +import org.jetbrains.kotlin.daemon.client.DaemonReportMessage +import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets +import org.jetbrains.kotlin.daemon.client.KotlinCompilerClient +import org.jetbrains.kotlin.daemon.client.KotlinRemoteReplCompiler import org.jetbrains.kotlin.daemon.common.* import org.jetbrains.kotlin.utils.PathUtil import java.io.File @@ -34,7 +37,7 @@ class KotlinJvmJsr223ScriptEngine4Idea( private val factory: ScriptEngineFactory, templateClasspath: List, templateClassName: String, - scriptArgs: Array?, + getScriptArgs: (ScriptContext) -> Array?, scriptArgsTypes: Array>? ) : AbstractScriptEngine(), ScriptEngine { @@ -63,7 +66,8 @@ class KotlinJvmJsr223ScriptEngine4Idea( } } - val localEvaluator by lazy { GenericReplCompiledEvaluator(emptyList(), Thread.currentThread().contextClassLoader, scriptArgs, scriptArgsTypes) } + // TODO: bindings passing works only once on the first eval, subsequent setContext/setBindings call have no effect. Consider making it dynamic, but take history into account + val localEvaluator by lazy { GenericReplCompiledEvaluator(templateClasspath, Thread.currentThread().contextClassLoader, getScriptArgs(getContext()), scriptArgsTypes) } private var lineCount = 0 diff --git a/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJvmJsr223StandardScriptEngineFactory4Idea.kt b/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJvmJsr223StandardScriptEngineFactory4Idea.kt index d242d54740c..6fbb7badf56 100644 --- a/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJvmJsr223StandardScriptEngineFactory4Idea.kt +++ b/idea/idea-repl/src/org/jetbrains/kotlin/jsr223/KotlinJvmJsr223StandardScriptEngineFactory4Idea.kt @@ -19,6 +19,8 @@ package org.jetbrains.kotlin.jsr223 import com.intellij.openapi.util.Disposer import org.jetbrains.kotlin.cli.common.KotlinVersion import org.jetbrains.kotlin.utils.PathUtil +import javax.script.Bindings +import javax.script.ScriptContext import javax.script.ScriptEngine import javax.script.ScriptEngineFactory @@ -38,9 +40,14 @@ class KotlinJvmJsr223StandardScriptEngineFactory4Idea : ScriptEngineFactory { Disposer.newDisposable(), this, listOf(PathUtil.getKotlinPathsForIdeaPlugin().runtimePath), - "kotlin.script.StandardScriptTemplate", - arrayOf(emptyArray()), - null) + "kotlin.script.ScriptTemplateWithArgsAndBindings", + { ctx -> + val bindings = ctx.getBindings(ScriptContext.ENGINE_SCOPE) + arrayOf( + (bindings[ScriptEngine.ARGV] as? Array<*>) ?: emptyArray(), + bindings) }, + arrayOf(Array::class.java, java.util.Map::class.java) + ) override fun getOutputStatement(toDisplay: String?): String = "print(\"$toDisplay\")" override fun getMethodCallSyntax(obj: String, m: String, vararg args: String): String = "$obj.$m(${args.joinToString()})" diff --git a/idea/tests/org/jetbrains/kotlin/idea/repl/IdeaJsr223Test.kt b/idea/tests/org/jetbrains/kotlin/idea/repl/IdeaJsr223Test.kt index 605cdce99a8..c495eb9b073 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/repl/IdeaJsr223Test.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/repl/IdeaJsr223Test.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.idea.repl import com.intellij.testFramework.PlatformTestCase import org.junit.Test +import javax.script.ScriptContext +import javax.script.ScriptEngine import javax.script.ScriptEngineManager import javax.script.ScriptException import kotlin.test.assertFails @@ -42,4 +44,21 @@ class IdeaJsr223Test : PlatformTestCase() { assertEquals(7, res2) } + @Test + fun testJsr223ScriptWithBindings() { + val semgr = ScriptEngineManager() + + val engine = semgr.getEngineByName("kotlin") + + val bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE) + + bindings.put(ScriptEngine.ARGV, arrayOf("42")) + bindings.put("abc", 13) + + val res1 = engine.eval("2 + args[0].toInt()") + assertEquals(44, res1) + + val res2 = engine.eval("2 + (bindings[\"abc\"] as Int)") + assertEquals(15, res2) + } }