Implement script dependencies resolution directly from classloader

#KT-27956 fixed
This commit is contained in:
Ilya Chernikov
2019-09-11 14:16:25 +02:00
parent f8db150a2b
commit 61d517fb31
9 changed files with 199 additions and 30 deletions
@@ -38,6 +38,7 @@ sourceSets {
}
projectTest(parallel = true) {
dependsOn(":dist")
workingDir = rootDir
}
@@ -0,0 +1,57 @@
/*
* 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 kotlin.script.experimental.jvmhost.test
import junit.framework.TestCase
import org.junit.Test
import java.io.File
import kotlin.script.experimental.api.ResultValue
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.dependencies
import kotlin.script.experimental.api.valueOrThrow
import kotlin.script.experimental.host.toScriptSource
import kotlin.script.experimental.jvm.JvmDependency
import kotlin.script.experimental.jvm.JvmDependencyFromClassLoader
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
class ResolveFromClassloaderTest : TestCase() {
@Test
fun testResolveFromClassloader() {
val script = "${ShouldBeVisibleFromScript::class.java.name}().x".toScriptSource()
val compilationConfiguration = ScriptCompilationConfiguration {
dependencies(JvmDependencyFromClassLoader { ShouldBeVisibleFromScript::class.java.classLoader })
}
val res = BasicJvmScriptingHost().eval(script, compilationConfiguration, null).valueOrThrow().returnValue as ResultValue.Value
assertEquals(42, res.value)
}
@Test
fun testResolveFromClassloaderAndClassPath() {
val script = """
org.jetbrains.kotlin.mainKts.MainKtsConfigurator()
${ShouldBeVisibleFromScript::class.java.name}().x
""".trimIndent().toScriptSource()
val classpath = listOf(
File("dist/kotlinc/lib/kotlin-main-kts.jar").also {
assertTrue("kotlin-main-kts.jar not found, run dist task: ${it.absolutePath}", it.exists())
}
)
val compilationConfiguration = ScriptCompilationConfiguration {
dependencies(
JvmDependencyFromClassLoader { ShouldBeVisibleFromScript::class.java.classLoader },
JvmDependency(classpath)
)
}
val res = BasicJvmScriptingHost().eval(script, compilationConfiguration, null).valueOrThrow().returnValue as ResultValue.Value
assertEquals(42, res.value)
}
}
@Suppress("unused")
class ShouldBeVisibleFromScript {
val x = 42
}
@@ -97,7 +97,7 @@ internal fun ScriptContents.toScriptSource(): SourceCode = when {
else -> throw IllegalArgumentException("Unable to convert script contents $this into script source")
}
fun List<ScriptDependency>?.toClassPathOrEmpty() = this?.flatMap { (it as JvmDependency).classpath } ?: emptyList()
fun List<ScriptDependency>?.toClassPathOrEmpty() = this?.flatMap { (it as? JvmDependency)?.classpath ?: emptyList() } ?: emptyList()
internal fun List<SourceCode>?.toFilesOrEmpty() = this?.map {
val externalSource = it as? ExternalSourceCode
@@ -19,6 +19,12 @@ data class JvmDependency(val classpath: List<File>) : ScriptDependency {
companion object { private const val serialVersionUID: Long = 1L }
}
typealias ClassLoaderByConfiguration = (ScriptCompilationConfiguration) -> ClassLoader
class JvmDependencyFromClassLoader(val classLoaderGetter: ClassLoaderByConfiguration) : ScriptDependency {
fun getClassLoader(configuration: ScriptCompilationConfiguration): ClassLoader = classLoaderGetter(configuration)
}
interface JvmScriptCompilationConfigurationKeys
open class JvmScriptCompilationConfigurationBuilder : PropertiesCollection.Builder(), JvmScriptCompilationConfigurationKeys {