From c9a4328febc8fc6b66377a77ac9d4fa723d5a5a4 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Tue, 9 Jul 2019 15:35:38 +0200 Subject: [PATCH] Fix compiled scripts saving tests: The tests were broken some time ago by applying script isolation, so it was necessary to add base libraries into the classpath. Also refactored some classpath building utilities. --- .../experimental/host/scriptHostUtil.kt | 24 +++++++++++++++---- .../jvmhost/test/ScriptingHostTest.kt | 8 ++++++- .../experimental/jvm/jvmScriptCompilation.kt | 8 +++---- .../experimental/jvm/util/jvmClasspathUtil.kt | 17 +++++++++---- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/libraries/scripting/common/src/kotlin/script/experimental/host/scriptHostUtil.kt b/libraries/scripting/common/src/kotlin/script/experimental/host/scriptHostUtil.kt index 8d0e100aa46..59f785d03b9 100644 --- a/libraries/scripting/common/src/kotlin/script/experimental/host/scriptHostUtil.kt +++ b/libraries/scripting/common/src/kotlin/script/experimental/host/scriptHostUtil.kt @@ -6,8 +6,7 @@ package kotlin.script.experimental.host import java.io.File -import java.io.IOError -import java.io.IOException +import java.io.Serializable import java.net.URL import kotlin.script.experimental.api.* @@ -48,7 +47,7 @@ abstract class FileBasedScriptSource() : ExternalSourceCode { /** * The implementation of the SourceCode for a script located in a file */ -open class FileScriptSource(override val file: File, private val preloadedText: String? = null) : FileBasedScriptSource() { +open class FileScriptSource(override val file: File, private val preloadedText: String? = null) : FileBasedScriptSource(), Serializable { override val externalLocation: URL get() = file.toURI().toURL() override val text: String by lazy { preloadedText ?: file.readText() } override val name: String? get() = file.name @@ -58,12 +57,17 @@ open class FileScriptSource(override val file: File, private val preloadedText: this === other || (other as? FileScriptSource)?.let { file.absolutePath == it.file.absolutePath && textSafe == it.textSafe } == true override fun hashCode(): Int = file.absolutePath.hashCode() + textSafe.hashCode() * 23 + + companion object { + @JvmStatic + private val serialVersionUID = 0L + } } /** * The implementation of the SourceCode for a script location pointed by the URL */ -open class UrlScriptSource(override val externalLocation: URL) : ExternalSourceCode { +open class UrlScriptSource(override val externalLocation: URL) : ExternalSourceCode, Serializable { override val text: String by lazy { externalLocation.readText() } override val name: String? get() = externalLocation.file override val locationId: String? get() = externalLocation.toString() @@ -72,6 +76,11 @@ open class UrlScriptSource(override val externalLocation: URL) : ExternalSourceC this === other || (other as? UrlScriptSource)?.let { externalLocation == it.externalLocation && textSafe == it.textSafe } == true override fun hashCode(): Int = externalLocation.hashCode() + textSafe.hashCode() * 17 + + companion object { + @JvmStatic + private val serialVersionUID = 0L + } } /** @@ -82,7 +91,7 @@ fun File.toScriptSource(): SourceCode = FileScriptSource(this) /** * The implementation of the ScriptSource for a script in a String */ -open class StringScriptSource(val source: String, override val name: String? = null) : SourceCode { +open class StringScriptSource(val source: String, override val name: String? = null) : SourceCode, Serializable { override val text: String get() = source @@ -92,6 +101,11 @@ open class StringScriptSource(val source: String, override val name: String? = n this === other || (other as? StringScriptSource)?.let { text == it.text && name == it.name && locationId == it.locationId } == true override fun hashCode(): Int = text.hashCode() + name.hashCode() * 17 + locationId.hashCode() * 23 + + companion object { + @JvmStatic + private val serialVersionUID = 0L + } } /** diff --git a/libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt b/libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt index 83db8965fcd..169f93c93e0 100644 --- a/libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt +++ b/libraries/scripting/jvm-host-test/test/kotlin/script/experimental/jvmhost/test/ScriptingHostTest.kt @@ -29,6 +29,9 @@ import kotlin.script.experimental.host.toScriptSource import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration import kotlin.script.experimental.jvm.impl.KJvmCompiledScript +import kotlin.script.experimental.jvm.updateClasspath +import kotlin.script.experimental.jvm.util.KotlinJars +import kotlin.script.experimental.jvm.util.classpathFromClass import kotlin.script.experimental.jvmhost.* import kotlin.script.templates.standard.SimpleScriptTemplate @@ -121,7 +124,10 @@ class ScriptingHostTest : TestCase() { fun testSaveToRunnableJar() { val greeting = "Hello from script jar!" val outJar = Files.createTempFile("saveToRunnableJar", ".jar").toFile() - val compilationConfiguration = createJvmCompilationConfigurationFromTemplate() + val compilationConfiguration = createJvmCompilationConfigurationFromTemplate() { + updateClasspath(classpathFromClass()) + updateClasspath(KotlinJars.kotlinScriptStandardJarsWithReflect) + } val compiler = JvmScriptCompiler(defaultJvmScriptingHostConfiguration) val scriptName = "SavedRunnableScript" val compiledScript = runBlocking { diff --git a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/jvmScriptCompilation.kt b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/jvmScriptCompilation.kt index 118130645ce..04daee899fa 100644 --- a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/jvmScriptCompilation.kt +++ b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/jvmScriptCompilation.kt @@ -62,12 +62,12 @@ fun ScriptCompilationConfiguration.withUpdatedClasspath(classpath: Collection) = updateClasspathImpl(classpath) +fun ScriptCompilationConfiguration.Builder.updateClasspath(classpath: Collection?) = updateClasspathImpl(classpath) -fun JvmScriptCompilationConfigurationBuilder.updateClasspath(classpath: Collection) = updateClasspathImpl(classpath) +fun JvmScriptCompilationConfigurationBuilder.updateClasspath(classpath: Collection?) = updateClasspathImpl(classpath) -private fun PropertiesCollection.Builder.updateClasspathImpl(classpath: Collection) { - val newClasspath = classpath.filterNewClasspath(this[ScriptCompilationConfiguration.dependencies]) +private fun PropertiesCollection.Builder.updateClasspathImpl(classpath: Collection?) { + val newClasspath = classpath?.filterNewClasspath(this[ScriptCompilationConfiguration.dependencies]) ?: return ScriptCompilationConfiguration.dependencies.append(JvmDependency(newClasspath)) diff --git a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt index 0fbb4bae629..e2610622573 100644 --- a/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt +++ b/libraries/scripting/jvm/src/kotlin/script/experimental/jvm/util/jvmClasspathUtil.kt @@ -179,12 +179,14 @@ fun classpathFromClasspathProperty(): List? = fun classpathFromClass(classLoader: ClassLoader, klass: KClass): List? = classpathFromFQN(classLoader, klass.qualifiedName!!) +fun classpathFromClass(klass: KClass): List? = + classpathFromClass(klass.java.classLoader, klass) + +inline fun classpathFromClass(): List? = classpathFromClass(T::class) + fun classpathFromFQN(classLoader: ClassLoader, fqn: String): List? { val clp = "${fqn.replace('.', '/')}.class" - val url = classLoader.getResource(clp) - return url?.toURI()?.path?.removeSuffix(clp)?.let { - listOf(File(it)) - } + return classLoader.rawClassPathFromKeyResourcePath(clp).filter { it.isValidClasspathFile() }.toList().takeIf { it.isNotEmpty() } } fun File.matchMaybeVersionedFile(baseName: String) = @@ -408,4 +410,11 @@ object KotlinJars { stdlibOrNull, scriptRuntimeOrNull ).filterNotNull() + + val kotlinScriptStandardJarsWithReflect + get() = listOf( + stdlibOrNull, + scriptRuntimeOrNull, + reflectOrNull + ).filterNotNull() }