From ebe669d3e4e328dcb782d2c538f6d7238c050369 Mon Sep 17 00:00:00 2001 From: Philipp Hanslovsky Date: Mon, 21 Dec 2020 22:36:35 -0500 Subject: [PATCH 1/7] Update dependencies and remove failing tests --- pom.xml | 13 +- .../kotlin/KotlinScriptLanguage.java | 100 +++++++++++++- .../plugins/scripting/kotlin/KotlinTest.java | 128 ------------------ 3 files changed, 97 insertions(+), 144 deletions(-) delete mode 100644 src/test/java/org/scijava/plugins/scripting/kotlin/KotlinTest.java diff --git a/pom.xml b/pom.xml index 49f29bd..86d473f 100644 --- a/pom.xml +++ b/pom.xml @@ -87,6 +87,7 @@ Wisconsin-Madison. org/jetbrains/kotlin/daemon/common/*,kotlinx/coroutines/** + 1.4.21 @@ -111,20 +112,14 @@ Wisconsin-Madison. org.jetbrains.kotlin - kotlin-script-util + kotlin-stdlib ${kotlin.version} org.jetbrains.kotlin - kotlin-script-runtime + kotlin-scripting-jsr223 ${kotlin.version} - runtime - - - org.jetbrains.kotlin - kotlin-scripting-compiler-embeddable - ${kotlin.version} - runtime + diff --git a/src/main/java/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.java b/src/main/java/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.java index d2ab486..706caec 100644 --- a/src/main/java/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.java +++ b/src/main/java/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.java @@ -30,16 +30,16 @@ package org.scijava.plugins.scripting.kotlin; -import java.util.Arrays; -import java.util.List; - -import javax.script.ScriptEngine; - -import org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory; +import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase; import org.scijava.plugin.Plugin; import org.scijava.script.AdaptedScriptLanguage; import org.scijava.script.ScriptLanguage; +import javax.script.*; +import java.io.Reader; +import java.util.Arrays; +import java.util.List; + /** * A SciJava {@link ScriptLanguage} for Kotlin. * @@ -50,7 +50,7 @@ public class KotlinScriptLanguage extends AdaptedScriptLanguage { public KotlinScriptLanguage() { - super(new KotlinJsr223JvmLocalScriptEngineFactory()); + super(new MyScriptEngineFactory()); } @Override @@ -64,4 +64,90 @@ public List getExtensions() { // NB: The wrapped ScriptEngineFactory does not include .kt in its list. return Arrays.asList("kt", "kts"); } + + public static class MyScriptEngineFactory extends KotlinJsr223JvmScriptEngineFactoryBase { + @Override + public ScriptEngine getScriptEngine() { + return new SynchronizedScriptEngine(new ScriptEngineManager().getEngineByExtension("kts")); + } + } + + public static class SynchronizedScriptEngine implements ScriptEngine { + + private final ScriptEngine delegate; + + public SynchronizedScriptEngine(final ScriptEngine delegate) { + this.delegate = delegate; + } + + @Override + public synchronized Object eval(String s, ScriptContext scriptContext) throws ScriptException { + return delegate.eval(s, scriptContext); + } + + @Override + public synchronized Object eval(Reader reader, ScriptContext scriptContext) throws ScriptException { + return delegate.eval(reader, scriptContext); + } + + @Override + public synchronized Object eval(String s) throws ScriptException { + return delegate.eval(s); + } + + @Override + public synchronized Object eval(Reader reader) throws ScriptException { + return delegate.eval(reader); + } + + @Override + public synchronized Object eval(String s, Bindings bindings) throws ScriptException { + return delegate.eval(s, bindings); + } + + @Override + public synchronized Object eval(Reader reader, Bindings bindings) throws ScriptException { + return delegate.eval(reader, bindings); + } + + @Override + public synchronized void put(String s, Object o) { + delegate.put(s, o); + } + + @Override + public synchronized Object get(String s) { + return delegate.get(s); + } + + @Override + public synchronized Bindings getBindings(int i) { + return delegate.getBindings(i); + } + + @Override + public synchronized void setBindings(Bindings bindings, int i) { + delegate.setBindings(bindings, i); + } + + @Override + public synchronized Bindings createBindings() { + return delegate.createBindings(); + } + + @Override + public synchronized ScriptContext getContext() { + return delegate.getContext(); + } + + @Override + public synchronized void setContext(ScriptContext scriptContext) { + delegate.setContext(scriptContext); + } + + @Override + public synchronized ScriptEngineFactory getFactory() { + return delegate.getFactory(); + } + } } diff --git a/src/test/java/org/scijava/plugins/scripting/kotlin/KotlinTest.java b/src/test/java/org/scijava/plugins/scripting/kotlin/KotlinTest.java deleted file mode 100644 index c99da98..0000000 --- a/src/test/java/org/scijava/plugins/scripting/kotlin/KotlinTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * #%L - * JSR-223-compliant Kotlin scripting language plugin. - * %% - * Copyright (C) 2016 - 2019 Board of Regents of the University of - * Wisconsin-Madison. - * %% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * #L% - */ - -package org.scijava.plugins.scripting.kotlin; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.util.concurrent.ExecutionException; - -import javax.script.Bindings; -import javax.script.ScriptContext; -import javax.script.ScriptEngine; -import javax.script.ScriptException; - -import org.junit.Test; -import org.scijava.Context; -import org.scijava.script.AbstractScriptLanguageTest; -import org.scijava.script.ScriptLanguage; -import org.scijava.script.ScriptModule; -import org.scijava.script.ScriptService; - -/** - * Kotlin unit tests. - * - * @author Curtis Rueden - */ -public class KotlinTest extends AbstractScriptLanguageTest { - - @Test - public void testDiscovery() { - assertDiscovered(KotlinScriptLanguage.class); - } - - @Test - public void testBasic() throws InterruptedException, ExecutionException, - IOException, ScriptException - { - final Context context = new Context(ScriptService.class); - final ScriptService scriptService = context.getService(ScriptService.class); - final String script = "1 + 2"; - final ScriptModule m = scriptService.run("add.kt", script, true).get(); - final Object result = m.getReturnValue(); - assertEquals("3", result.toString()); - } - - @Test - public void testLocals() throws ScriptException { - final Context context = new Context(ScriptService.class); - final ScriptService scriptService = context.getService(ScriptService.class); - - final ScriptLanguage language = scriptService.getLanguageByExtension("kt"); - final ScriptEngine engine = language.getScriptEngine(); - assertTrue(engine.getFactory().getNames().contains("kotlin")); - - engine.put("hello", 17); - assertEquals("17", engine.eval("bindings[\"hello\"]").toString()); - assertEquals("17", engine.get("hello").toString()); - - engine.put("foo", "bar"); - assertEquals("bar", engine.eval("bindings[\"foo\"]").toString()); - assertEquals("bar", engine.get("foo").toString()); - // FIXME: You cannot modify or insert a variable in the bindings! -// engine.eval("bindings[\"foo\"] = \"great\""); -// assertEquals("great", engine.eval("bindings[\"foo\"]").toString()); -// assertEquals("great", engine.get("foo").toString()); - - final Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE); - bindings.clear(); - assertNull(engine.get("hello")); - } - - // FIXME: Calling methods on injected instance vars fails with - // "unresolved reference". Nor can we store values into the bindings map! -// @Test -// public void testParameters() throws InterruptedException, ExecutionException, -// IOException, ScriptException -// { -// final Context context = new Context(ScriptService.class); -// final ScriptService scriptService = context.getService(ScriptService.class); -// -// final String script = "" + // -// "// @ScriptService ss\n" + // -// "// @OUTPUT String language\n" + // -// "// @OUTPUT ScriptService ssOut\n" + // -// "println(\"==> \" + bindings[\"ss\"])\n" + // -// "bindings[\"ssOut\"] = bindings[\"ss\"]\n"; -//// "println(\"==> \" + ss.canHandleFile(\"/Users/curtis\"))\n"; -//// "val language = " + // -//// "bindings[\"ss\"].getLanguageByName(\"kotlin\").getLanguageName()\n"; -// final ScriptModule m = scriptService.run("hello.kt", script, true).get(); -// -// final Object actual = m.getOutput("ssOut"); -// final Object expected = -// scriptService.getLanguageByName("kotlin"); -// assertEquals(expected, actual); -// } - -} From d2298436a76d13c5812e480d1c13efb71921c5d5 Mon Sep 17 00:00:00 2001 From: Philipp Hanslovsky Date: Mon, 21 Dec 2020 22:50:39 -0500 Subject: [PATCH 2/7] Rewrite in Kotlin --- .../kotlin/KotlinScriptLanguage.java | 153 ------------------ .../scripting/kotlin/KotlinScriptLanguage.kt | 113 +++++++++++++ 2 files changed, 113 insertions(+), 153 deletions(-) delete mode 100644 src/main/java/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.java create mode 100644 src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt diff --git a/src/main/java/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.java b/src/main/java/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.java deleted file mode 100644 index 706caec..0000000 --- a/src/main/java/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * #%L - * JSR-223-compliant Kotlin scripting language plugin. - * %% - * Copyright (C) 2016 - 2019 Board of Regents of the University of - * Wisconsin-Madison. - * %% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * #L% - */ - -package org.scijava.plugins.scripting.kotlin; - -import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase; -import org.scijava.plugin.Plugin; -import org.scijava.script.AdaptedScriptLanguage; -import org.scijava.script.ScriptLanguage; - -import javax.script.*; -import java.io.Reader; -import java.util.Arrays; -import java.util.List; - -/** - * A SciJava {@link ScriptLanguage} for Kotlin. - * - * @author Curtis Rueden - * @see ScriptEngine - */ -@Plugin(type = ScriptLanguage.class, name = "Kotlin") -public class KotlinScriptLanguage extends AdaptedScriptLanguage { - - public KotlinScriptLanguage() { - super(new MyScriptEngineFactory()); - } - - @Override - public List getNames() { - // NB: The wrapped ScriptEngineFactory does not include Kotlin in its list. - return Arrays.asList("kotlin", "Kotlin"); - } - - @Override - public List getExtensions() { - // NB: The wrapped ScriptEngineFactory does not include .kt in its list. - return Arrays.asList("kt", "kts"); - } - - public static class MyScriptEngineFactory extends KotlinJsr223JvmScriptEngineFactoryBase { - @Override - public ScriptEngine getScriptEngine() { - return new SynchronizedScriptEngine(new ScriptEngineManager().getEngineByExtension("kts")); - } - } - - public static class SynchronizedScriptEngine implements ScriptEngine { - - private final ScriptEngine delegate; - - public SynchronizedScriptEngine(final ScriptEngine delegate) { - this.delegate = delegate; - } - - @Override - public synchronized Object eval(String s, ScriptContext scriptContext) throws ScriptException { - return delegate.eval(s, scriptContext); - } - - @Override - public synchronized Object eval(Reader reader, ScriptContext scriptContext) throws ScriptException { - return delegate.eval(reader, scriptContext); - } - - @Override - public synchronized Object eval(String s) throws ScriptException { - return delegate.eval(s); - } - - @Override - public synchronized Object eval(Reader reader) throws ScriptException { - return delegate.eval(reader); - } - - @Override - public synchronized Object eval(String s, Bindings bindings) throws ScriptException { - return delegate.eval(s, bindings); - } - - @Override - public synchronized Object eval(Reader reader, Bindings bindings) throws ScriptException { - return delegate.eval(reader, bindings); - } - - @Override - public synchronized void put(String s, Object o) { - delegate.put(s, o); - } - - @Override - public synchronized Object get(String s) { - return delegate.get(s); - } - - @Override - public synchronized Bindings getBindings(int i) { - return delegate.getBindings(i); - } - - @Override - public synchronized void setBindings(Bindings bindings, int i) { - delegate.setBindings(bindings, i); - } - - @Override - public synchronized Bindings createBindings() { - return delegate.createBindings(); - } - - @Override - public synchronized ScriptContext getContext() { - return delegate.getContext(); - } - - @Override - public synchronized void setContext(ScriptContext scriptContext) { - delegate.setContext(scriptContext); - } - - @Override - public synchronized ScriptEngineFactory getFactory() { - return delegate.getFactory(); - } - } -} diff --git a/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt b/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt new file mode 100644 index 0000000..712e7a3 --- /dev/null +++ b/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt @@ -0,0 +1,113 @@ +/* + * #%L + * JSR-223-compliant Kotlin scripting language plugin. + * %% + * Copyright (C) 2016 - 2019 Board of Regents of the University of + * Wisconsin-Madison. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.scijava.plugins.scripting.kotlin + +import org.scijava.plugins.scripting.kotlin.KotlinScriptLanguage.MyScriptEngineFactory +import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase +import org.scijava.plugin.Plugin +import org.scijava.plugins.scripting.kotlin.KotlinScriptLanguage.SynchronizedScriptEngine +import org.scijava.script.AdaptedScriptLanguage +import org.scijava.script.ScriptLanguage +import java.io.Reader +import java.util.* +import javax.script.* + +/** + * A SciJava [ScriptLanguage] for Kotlin. + * + * @author Curtis Rueden + * @see ScriptEngine + */ +@Plugin(type = ScriptLanguage::class, name = "Kotlin") +class KotlinScriptLanguage : AdaptedScriptLanguage(MyScriptEngineFactory()) { + // NB: The wrapped ScriptEngineFactory does not include Kotlin in its list. + override fun getNames() = listOf("kotlin", "Kotlin") + + // NB: The wrapped ScriptEngineFactory does not include .kt in its list. + override fun getExtensions() = listOf("kt", "kts") + + class MyScriptEngineFactory : KotlinJsr223JvmScriptEngineFactoryBase() { + override fun getScriptEngine(): ScriptEngine { + return SynchronizedScriptEngine(ScriptEngineManager().getEngineByExtension("kts")) + } + } + + class SynchronizedScriptEngine(private val delegate: ScriptEngine) : ScriptEngine { + @Synchronized + @Throws(ScriptException::class) + override fun eval(s: String, scriptContext: ScriptContext): Any? = delegate.eval(s, scriptContext) + + @Synchronized + @Throws(ScriptException::class) + override fun eval(reader: Reader, scriptContext: ScriptContext): Any? = delegate.eval(reader, scriptContext) + + @Synchronized + @Throws(ScriptException::class) + override fun eval(s: String): Any? = delegate.eval(s) + + @Synchronized + @Throws(ScriptException::class) + override fun eval(reader: Reader): Any? = delegate.eval(reader) + + @Synchronized + @Throws(ScriptException::class) + override fun eval(s: String, bindings: Bindings): Any? = delegate.eval(s, bindings) + + @Synchronized + @Throws(ScriptException::class) + override fun eval(reader: Reader, bindings: Bindings): Any? = delegate.eval(reader, bindings) + + @Synchronized + override fun put(s: String, o: Any) = delegate.put(s, o) + + @Synchronized + override fun get(s: String): Any? = delegate[s] + + @Synchronized + override fun getBindings(i: Int): Bindings? = delegate.getBindings(i) + + @Synchronized + override fun setBindings(bindings: Bindings, i: Int) = delegate.setBindings(bindings, i) + + @Synchronized + override fun createBindings(): Bindings = delegate.createBindings() + + @Synchronized + override fun getContext(): ScriptContext = delegate.context + + @Synchronized + override fun setContext(scriptContext: ScriptContext) { + delegate.context = scriptContext + } + + @Synchronized + override fun getFactory(): ScriptEngineFactory = delegate.factory + } +} \ No newline at end of file From 6c4c5108088531f7f803a74b85faf560863501af Mon Sep 17 00:00:00 2001 From: Philipp Hanslovsky Date: Mon, 21 Dec 2020 22:51:03 -0500 Subject: [PATCH 3/7] Add Hanslovsky as author --- .../org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt b/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt index 712e7a3..5b06ebf 100644 --- a/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt +++ b/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt @@ -43,6 +43,7 @@ import javax.script.* * A SciJava [ScriptLanguage] for Kotlin. * * @author Curtis Rueden + * @author Philipp Hanslovsky * @see ScriptEngine */ @Plugin(type = ScriptLanguage::class, name = "Kotlin") From 291256a901eed46696fb5378e9b7caa768e2975f Mon Sep 17 00:00:00 2001 From: Philipp Hanslovsky Date: Sat, 26 Dec 2020 21:40:03 -0500 Subject: [PATCH 4/7] Add tests --- pom.xml | 1 - .../scripting/kotlin/KotlinScriptLanguage.kt | 7 +- .../plugins/scripting/kotlin/KotlinTest.kt | 112 ++++++++++++++++++ 3 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt diff --git a/pom.xml b/pom.xml index 86d473f..293578b 100644 --- a/pom.xml +++ b/pom.xml @@ -119,7 +119,6 @@ Wisconsin-Madison. org.jetbrains.kotlin kotlin-scripting-jsr223 ${kotlin.version} - diff --git a/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt b/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt index 5b06ebf..e777e68 100644 --- a/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt +++ b/src/main/kotlin/org/scijava/plugins/scripting/kotlin/KotlinScriptLanguage.kt @@ -29,14 +29,11 @@ */ package org.scijava.plugins.scripting.kotlin -import org.scijava.plugins.scripting.kotlin.KotlinScriptLanguage.MyScriptEngineFactory import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase import org.scijava.plugin.Plugin -import org.scijava.plugins.scripting.kotlin.KotlinScriptLanguage.SynchronizedScriptEngine import org.scijava.script.AdaptedScriptLanguage import org.scijava.script.ScriptLanguage import java.io.Reader -import java.util.* import javax.script.* /** @@ -47,14 +44,14 @@ import javax.script.* * @see ScriptEngine */ @Plugin(type = ScriptLanguage::class, name = "Kotlin") -class KotlinScriptLanguage : AdaptedScriptLanguage(MyScriptEngineFactory()) { +class KotlinScriptLanguage : AdaptedScriptLanguage(Factory()) { // NB: The wrapped ScriptEngineFactory does not include Kotlin in its list. override fun getNames() = listOf("kotlin", "Kotlin") // NB: The wrapped ScriptEngineFactory does not include .kt in its list. override fun getExtensions() = listOf("kt", "kts") - class MyScriptEngineFactory : KotlinJsr223JvmScriptEngineFactoryBase() { + class Factory : KotlinJsr223JvmScriptEngineFactoryBase() { override fun getScriptEngine(): ScriptEngine { return SynchronizedScriptEngine(ScriptEngineManager().getEngineByExtension("kts")) } diff --git a/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt b/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt new file mode 100644 index 0000000..44293e2 --- /dev/null +++ b/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt @@ -0,0 +1,112 @@ +/* + * #%L + * JSR-223-compliant Kotlin scripting language plugin. + * %% + * Copyright (C) 2016 - 2019 Board of Regents of the University of + * Wisconsin-Madison. + * %% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * #L% + */ +package org.scijava.plugins.scripting.kotlin + +import org.junit.Assert +import org.junit.Test +import org.scijava.script.AbstractScriptLanguageTest +import org.scijava.script.ScriptLanguage +import java.io.IOException +import java.util.concurrent.ExecutionException +import javax.script.ScriptContext +import javax.script.ScriptEngine +import javax.script.ScriptException +import kotlin.math.E + +/** + * Kotlin unit tests. + * + * @author Curtis Rueden + * @author Philipp Hanslovsky + */ +class KotlinTest : AbstractScriptLanguageTest() { + + // TODO Why is kotlin not discovered by ScriptService? + // It is discovered in ImageJ/Fiji +// val context: Context = Context(ScriptService::class.java) +// val scriptService: ScriptService = context.getService(ScriptService::class.java) +// val kotlinLang: ScriptLanguage = scriptService.getLanguageByName("Kotlin") + val kotlinLang: ScriptLanguage = KotlinScriptLanguage() + val engine: ScriptEngine = kotlinLang.scriptEngine + + @Test + fun testDiscovery() = assertDiscovered(KotlinScriptLanguage::class.java) + + @Test + @Throws(InterruptedException::class, ExecutionException::class, IOException::class, ScriptException::class) + fun `test basic script engine eval`() = Assert.assertEquals(3, engine.eval("1 + 2")) + + + @Test + @Throws(ScriptException::class) + fun `test basic engine eval with bindings`() { + try { + engine.put("Hello", ", SciJava!") + Assert.assertEquals(", SciJava!", engine.eval("Hello")) + Assert.assertEquals(", SciJava!", engine["Hello"]) + + val bindings = engine.createBindings() + bindings["base"] = E + val script = "import kotlin.math.*; base.pow(0)" + Assert.assertThrows(ScriptException::class.java) { engine.eval(script) } + Assert.assertEquals(1.0, engine.eval(script, bindings) as Double, 0.0) + } finally { + engine.getBindings(ScriptContext.ENGINE_SCOPE)?.clear() + Assert.assertNull(engine["Hello"]) + } + } + + // Code copied from original Java test + // FIXME: Calling methods on injected instance vars fails with + // "unresolved reference". Nor can we store values into the bindings map! + // @Test + // public void testParameters() throws InterruptedException, ExecutionException, + // IOException, ScriptException + // { + // final Context context = new Context(ScriptService.class); + // final ScriptService scriptService = context.getService(ScriptService.class); + // + // final String script = "" + // + // "// @ScriptService ss\n" + // + // "// @OUTPUT String language\n" + // + // "// @OUTPUT ScriptService ssOut\n" + // + // "println(\"==> \" + bindings[\"ss\"])\n" + // + // "bindings[\"ssOut\"] = bindings[\"ss\"]\n"; + //// "println(\"==> \" + ss.canHandleFile(\"/Users/curtis\"))\n"; + //// "val language = " + // + //// "bindings[\"ss\"].getLanguageByName(\"kotlin\").getLanguageName()\n"; + // final ScriptModule m = scriptService.run("hello.kt", script, true).get(); + // + // final Object actual = m.getOutput("ssOut"); + // final Object expected = + // scriptService.getLanguageByName("kotlin"); + // assertEquals(expected, actual); + // } +} \ No newline at end of file From 9ba19be01a2fe503f50b1d39552507abad9ea780 Mon Sep 17 00:00:00 2001 From: Philipp Hanslovsky Date: Wed, 3 Mar 2021 23:30:06 -0500 Subject: [PATCH 5/7] Disable manifest-only jar in surefire plugin With this setting, tests pass on command line. TODO: clean-up --- pom.xml | 53 +++++++++++++++++-- .../plugins/scripting/kotlin/KotlinTest.kt | 24 +++++++-- 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 293578b..1995b95 100644 --- a/pom.xml +++ b/pom.xml @@ -87,7 +87,11 @@ Wisconsin-Madison. org/jetbrains/kotlin/daemon/common/*,kotlinx/coroutines/** - 1.4.21 + 1.4.30 + + + + false @@ -110,6 +114,21 @@ Wisconsin-Madison. kotlin-compiler-embeddable ${kotlin.version} + + org.jetbrains.kotlin + kotlin-script-runtime + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-scripting-compiler-embeddable + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-scripting-compiler-impl-embeddable + ${kotlin.version} + org.jetbrains.kotlin kotlin-stdlib @@ -120,13 +139,41 @@ Wisconsin-Madison. kotlin-scripting-jsr223 ${kotlin.version} + + org.jetbrains.kotlin + kotlin-compiler-client-embeddable + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-script-util + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-scripting-jvm-host + ${kotlin.version} + - junit - junit + org.testng + testng + 7.1.0 test + + + + + + + + + + + + org.scijava scijava-common diff --git a/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt b/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt index 44293e2..2e9a8c0 100644 --- a/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt +++ b/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt @@ -29,10 +29,10 @@ */ package org.scijava.plugins.scripting.kotlin -import org.junit.Assert -import org.junit.Test import org.scijava.script.AbstractScriptLanguageTest import org.scijava.script.ScriptLanguage +import org.testng.Assert +import org.testng.annotations.Test import java.io.IOException import java.util.concurrent.ExecutionException import javax.script.ScriptContext @@ -46,18 +46,28 @@ import kotlin.math.E * @author Curtis Rueden * @author Philipp Hanslovsky */ -class KotlinTest : AbstractScriptLanguageTest() { +class KotlinTest { // TODO Why is kotlin not discovered by ScriptService? // It is discovered in ImageJ/Fiji // val context: Context = Context(ScriptService::class.java) // val scriptService: ScriptService = context.getService(ScriptService::class.java) // val kotlinLang: ScriptLanguage = scriptService.getLanguageByName("Kotlin") + init { + Class.forName("org.jetbrains.kotlin.cli.common.environment.UtilKt") + .methods + .also { println(it.map { m -> m.name }) } + .map { it } + .filter { it.name == "setIdeaIoUseFallback" } + .firstOrNull() + ?.let { println("oops"); it.invoke(null) } + ?: println("LOL?") + } val kotlinLang: ScriptLanguage = KotlinScriptLanguage() val engine: ScriptEngine = kotlinLang.scriptEngine - @Test - fun testDiscovery() = assertDiscovered(KotlinScriptLanguage::class.java) +// @Test +// fun testDiscovery() = assertDiscovered(KotlinScriptLanguage::class.java) @Test @Throws(InterruptedException::class, ExecutionException::class, IOException::class, ScriptException::class) @@ -68,9 +78,13 @@ class KotlinTest : AbstractScriptLanguageTest() { @Throws(ScriptException::class) fun `test basic engine eval with bindings`() { try { + println(1) engine.put("Hello", ", SciJava!") + println(2) Assert.assertEquals(", SciJava!", engine.eval("Hello")) + println(3) Assert.assertEquals(", SciJava!", engine["Hello"]) + println(4) val bindings = engine.createBindings() bindings["base"] = E From 667c7298f647d711525215556cefac3094722761 Mon Sep 17 00:00:00 2001 From: Philipp Hanslovsky Date: Thu, 4 Mar 2021 00:02:46 -0500 Subject: [PATCH 6/7] Minimize test dependencies and clean-up test code --- pom.xml | 17 +-- .../plugins/scripting/kotlin/KotlinTest.kt | 101 ++++++------------ 2 files changed, 36 insertions(+), 82 deletions(-) diff --git a/pom.xml b/pom.xml index 1995b95..5d04a4e 100644 --- a/pom.xml +++ b/pom.xml @@ -157,23 +157,10 @@ Wisconsin-Madison. - org.testng - testng - 7.1.0 + junit + junit test - - - - - - - - - - - - org.scijava scijava-common diff --git a/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt b/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt index 2e9a8c0..08b6c5c 100644 --- a/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt +++ b/src/test/kotlin/org/scijava/plugins/scripting/kotlin/KotlinTest.kt @@ -29,10 +29,13 @@ */ package org.scijava.plugins.scripting.kotlin +import org.junit.Assert +import org.junit.BeforeClass +import org.junit.Test +import org.scijava.Context import org.scijava.script.AbstractScriptLanguageTest import org.scijava.script.ScriptLanguage -import org.testng.Assert -import org.testng.annotations.Test +import org.scijava.script.ScriptService import java.io.IOException import java.util.concurrent.ExecutionException import javax.script.ScriptContext @@ -46,81 +49,45 @@ import kotlin.math.E * @author Curtis Rueden * @author Philipp Hanslovsky */ -class KotlinTest { +class KotlinTest : AbstractScriptLanguageTest() { - // TODO Why is kotlin not discovered by ScriptService? - // It is discovered in ImageJ/Fiji -// val context: Context = Context(ScriptService::class.java) -// val scriptService: ScriptService = context.getService(ScriptService::class.java) -// val kotlinLang: ScriptLanguage = scriptService.getLanguageByName("Kotlin") - init { - Class.forName("org.jetbrains.kotlin.cli.common.environment.UtilKt") - .methods - .also { println(it.map { m -> m.name }) } - .map { it } - .filter { it.name == "setIdeaIoUseFallback" } - .firstOrNull() - ?.let { println("oops"); it.invoke(null) } - ?: println("LOL?") - } - val kotlinLang: ScriptLanguage = KotlinScriptLanguage() - val engine: ScriptEngine = kotlinLang.scriptEngine - -// @Test -// fun testDiscovery() = assertDiscovered(KotlinScriptLanguage::class.java) + @Test + fun testDiscovery() = assertDiscovered(KotlinScriptLanguage::class.java) @Test @Throws(InterruptedException::class, ExecutionException::class, IOException::class, ScriptException::class) fun `test basic script engine eval`() = Assert.assertEquals(3, engine.eval("1 + 2")) - @Test @Throws(ScriptException::class) fun `test basic engine eval with bindings`() { - try { - println(1) - engine.put("Hello", ", SciJava!") - println(2) - Assert.assertEquals(", SciJava!", engine.eval("Hello")) - println(3) - Assert.assertEquals(", SciJava!", engine["Hello"]) - println(4) + engine.put("Hello", ", SciJava!") + Assert.assertEquals(", SciJava!", engine.eval("Hello")) + Assert.assertEquals(", SciJava!", engine["Hello"]) - val bindings = engine.createBindings() - bindings["base"] = E - val script = "import kotlin.math.*; base.pow(0)" - Assert.assertThrows(ScriptException::class.java) { engine.eval(script) } - Assert.assertEquals(1.0, engine.eval(script, bindings) as Double, 0.0) - } finally { - engine.getBindings(ScriptContext.ENGINE_SCOPE)?.clear() - Assert.assertNull(engine["Hello"]) - } + val bindings = engine.createBindings() + bindings["base"] = E + val script = "import kotlin.math.*; base.pow(0)" + Assert.assertThrows(ScriptException::class.java) { engine.eval(script) } + Assert.assertEquals(1.0, engine.eval(script, bindings) as Double, 0.0) + + // clear bindings and access variable Hello to cause ScriptException + engine.getBindings(ScriptContext.ENGINE_SCOPE)?.clear() + Assert.assertNull(engine["Hello"]) } - // Code copied from original Java test - // FIXME: Calling methods on injected instance vars fails with - // "unresolved reference". Nor can we store values into the bindings map! - // @Test - // public void testParameters() throws InterruptedException, ExecutionException, - // IOException, ScriptException - // { - // final Context context = new Context(ScriptService.class); - // final ScriptService scriptService = context.getService(ScriptService.class); - // - // final String script = "" + // - // "// @ScriptService ss\n" + // - // "// @OUTPUT String language\n" + // - // "// @OUTPUT ScriptService ssOut\n" + // - // "println(\"==> \" + bindings[\"ss\"])\n" + // - // "bindings[\"ssOut\"] = bindings[\"ss\"]\n"; - //// "println(\"==> \" + ss.canHandleFile(\"/Users/curtis\"))\n"; - //// "val language = " + // - //// "bindings[\"ss\"].getLanguageByName(\"kotlin\").getLanguageName()\n"; - // final ScriptModule m = scriptService.run("hello.kt", script, true).get(); - // - // final Object actual = m.getOutput("ssOut"); - // final Object expected = - // scriptService.getLanguageByName("kotlin"); - // assertEquals(expected, actual); - // } + + companion object { + @BeforeClass + @JvmStatic + fun initKotlinLang() { + val context = Context(ScriptService::class.java) + val scriptService: ScriptService = context.getService(ScriptService::class.java) + _kotlinLang = scriptService.getLanguageByName("Kotlin") + _engine = _kotlinLang.scriptEngine + } + private lateinit var _kotlinLang: ScriptLanguage + private lateinit var _engine: ScriptEngine + val engine get() = _engine + } } \ No newline at end of file From 1264520ace71f288e03d7c04eff43f126e33e3b8 Mon Sep 17 00:00:00 2001 From: Philipp Hanslovsky Date: Thu, 4 Mar 2021 00:06:41 -0500 Subject: [PATCH 7/7] Remove unused Kotlin dependencies --- pom.xml | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/pom.xml b/pom.xml index 5d04a4e..461a0b4 100644 --- a/pom.xml +++ b/pom.xml @@ -114,21 +114,6 @@ Wisconsin-Madison. kotlin-compiler-embeddable ${kotlin.version} - - org.jetbrains.kotlin - kotlin-script-runtime - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-scripting-compiler-embeddable - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-scripting-compiler-impl-embeddable - ${kotlin.version} - org.jetbrains.kotlin kotlin-stdlib @@ -139,21 +124,6 @@ Wisconsin-Madison. kotlin-scripting-jsr223 ${kotlin.version} - - org.jetbrains.kotlin - kotlin-compiler-client-embeddable - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-script-util - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-scripting-jvm-host - ${kotlin.version} -