Move scripting jvm host tests to a separate project...
to solve problems with testing with direct dependency on proguarded compiler
This commit is contained in:
@@ -10,29 +10,22 @@ dependencies {
|
||||
compile(kotlinStdlib())
|
||||
compile(project(":kotlin-scripting-common"))
|
||||
compile(project(":kotlin-scripting-jvm"))
|
||||
compile(project(":kotlin-scripting-compiler"))
|
||||
compile(project(":kotlin-scripting-compiler-impl"))
|
||||
compileOnly(project(":kotlin-scripting-compiler"))
|
||||
compileOnly(project(":compiler:cli"))
|
||||
compileOnly(project(":kotlin-reflect-api"))
|
||||
compileOnly(intellijCoreDep())
|
||||
runtime(projectRuntimeJar(":kotlin-compiler"))
|
||||
runtime(project(":kotlin-scripting-compiler"))
|
||||
runtime(project(":kotlin-reflect"))
|
||||
runtime(commonDep("org.jetbrains.intellij.deps", "trove4j"))
|
||||
testCompile(projectTests(":compiler:tests-common"))
|
||||
testCompile(commonDep("junit"))
|
||||
testCompile(project(":daemon-common")) // TODO: fix import (workaround for jps build)
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { projectDefault() }
|
||||
"test" {}
|
||||
}
|
||||
|
||||
publish()
|
||||
|
||||
standardPublicJars()
|
||||
|
||||
|
||||
projectTest(parallel = true) {
|
||||
workingDir = rootDir
|
||||
}
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import java.io.InputStream
|
||||
import java.net.URL
|
||||
import java.util.*
|
||||
|
||||
internal class CompiledScriptClassLoader(parent: ClassLoader?, private val entries: Map<String, ByteArray>) : ClassLoader(parent) {
|
||||
class CompiledScriptClassLoader(parent: ClassLoader?, private val entries: Map<String, ByteArray>) : ClassLoader(parent) {
|
||||
|
||||
override fun findClass(name: String): Class<*>? {
|
||||
val classPathName = name.replace('.', '/') + ".class"
|
||||
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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 org.junit.Test
|
||||
import kotlin.script.experimental.api.ResultWithDiagnostics
|
||||
import kotlin.script.experimental.api.implicitReceivers
|
||||
import kotlin.script.experimental.api.providedProperties
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ConstructorArgumentsOrderTest {
|
||||
|
||||
@Test
|
||||
fun testScriptWithProvidedProperties() {
|
||||
val res = evalString<ScriptWithProvidedProperties>("""println(providedString)""") {
|
||||
providedProperties("providedString" to "Hello Provided!")
|
||||
}
|
||||
|
||||
assertTrue(
|
||||
res is ResultWithDiagnostics.Success,
|
||||
"test failed:\n ${res.reports.joinToString("\n ") { it.message + if (it.exception == null) "" else ": ${it.exception}" }}"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testScriptWithImplicitReceiver() {
|
||||
val res = evalString<ScriptWithImplicitReceiver>("""println(receiverString)""") {
|
||||
implicitReceivers(ImplicitReceiverClass("Hello Receiver!"))
|
||||
}
|
||||
|
||||
assertTrue(
|
||||
res is ResultWithDiagnostics.Success,
|
||||
"test failed:\n ${res.reports.joinToString("\n ") { it.message + if (it.exception == null) "" else ": ${it.exception}" }}"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testScriptWithBoth() {
|
||||
val res = evalString<ScriptWithBoth>("""println(providedString + receiverString)""") {
|
||||
providedProperties("providedString" to "Hello")
|
||||
implicitReceivers(ImplicitReceiverClass(" Both!"))
|
||||
}
|
||||
|
||||
assertTrue(
|
||||
res is ResultWithDiagnostics.Success,
|
||||
"test failed:\n ${res.reports.joinToString("\n ") { it.message + if (it.exception == null) "" else ": ${it.exception}" }}"
|
||||
)
|
||||
}
|
||||
}
|
||||
-182
@@ -1,182 +0,0 @@
|
||||
/*
|
||||
* 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 com.intellij.openapi.application.ApplicationManager
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.cli.common.repl.*
|
||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase.resetApplicationToNull
|
||||
import java.io.Closeable
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.script.experimental.jvmhost.repl.JvmReplCompiler
|
||||
import kotlin.script.experimental.jvmhost.repl.JvmReplEvaluator
|
||||
|
||||
// Adapted form GenericReplTest
|
||||
|
||||
// Artificial split into several testsuites, to speed up parallel testing
|
||||
class LegacyReplTest : TestCase() {
|
||||
fun testReplBasics() {
|
||||
LegacyTestRepl().use { repl ->
|
||||
val res1 = repl.replCompiler.check(repl.state, ReplCodeLine(0, 0, "val x ="))
|
||||
TestCase.assertTrue("Unexpected check results: $res1", res1 is ReplCheckResult.Incomplete)
|
||||
|
||||
assertEvalResult(repl, "val l1 = listOf(1 + 2)\nl1.first()", 3)
|
||||
|
||||
assertEvalUnit(repl, "val x = 5")
|
||||
|
||||
assertEvalResult(repl, "x + 2", 7)
|
||||
}
|
||||
}
|
||||
|
||||
fun testReplErrors() {
|
||||
LegacyTestRepl().use { repl ->
|
||||
repl.compileAndEval(repl.nextCodeLine("val x = 10"))
|
||||
|
||||
val res = repl.compileAndEval(repl.nextCodeLine("java.util.fish"))
|
||||
TestCase.assertTrue("Expected compile error", res.first is ReplCompileResult.Error)
|
||||
|
||||
val result = repl.compileAndEval(repl.nextCodeLine("x"))
|
||||
assertEquals(res.second.toString(), 10, (result.second as? ReplEvalResult.ValueResult)?.value)
|
||||
}
|
||||
}
|
||||
|
||||
fun testReplCodeFormat() {
|
||||
LegacyTestRepl().use { repl ->
|
||||
val codeLine0 = ReplCodeLine(0, 0, "val l1 = 1\r\nl1\r\n")
|
||||
val res0 = repl.replCompiler.check(repl.state, codeLine0)
|
||||
val res0c = res0 as? ReplCheckResult.Ok
|
||||
TestCase.assertNotNull("Unexpected compile result: $res0", res0c)
|
||||
}
|
||||
}
|
||||
|
||||
fun testRepPackage() {
|
||||
LegacyTestRepl().use { repl ->
|
||||
assertEvalResult(repl, "package mypackage\n\nval x = 1\nx+2", 3)
|
||||
|
||||
assertEvalResult(repl, "x+4", 5)
|
||||
}
|
||||
}
|
||||
|
||||
fun testReplResultFieldWithFunction() {
|
||||
LegacyTestRepl().use { repl ->
|
||||
assertEvalResultIs<Function0<Int>>(repl, "{ 1 + 2 }")
|
||||
assertEvalResultIs<Function0<Int>>(repl, "res0")
|
||||
assertEvalResult(repl, "res0()", 3)
|
||||
}
|
||||
}
|
||||
|
||||
fun testReplResultField() {
|
||||
LegacyTestRepl().use { repl ->
|
||||
assertEvalResult(repl, "5 * 4", 20)
|
||||
assertEvalResult(repl, "res0 + 3", 23)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Artificial split into several testsuites, to speed up parallel testing
|
||||
class LegacyReplTestLong1 : TestCase() {
|
||||
|
||||
fun test256Evals() {
|
||||
LegacyTestRepl().use { repl ->
|
||||
repl.compileAndEval(ReplCodeLine(0, 0, "val x0 = 0"))
|
||||
|
||||
val evals = 256
|
||||
for (i in 1..evals) {
|
||||
repl.compileAndEval(ReplCodeLine(i, 0, "val x$i = x${i-1} + 1"))
|
||||
}
|
||||
|
||||
val res = repl.compileAndEval(ReplCodeLine(evals + 1, 0, "x$evals"))
|
||||
assertEquals(res.second.toString(), evals, (res.second as? ReplEvalResult.ValueResult)?.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Artificial split into several testsuites, to speed up parallel testing
|
||||
class LegacyReplTestLong2 : TestCase() {
|
||||
|
||||
fun testReplSlowdownKt22740() {
|
||||
LegacyTestRepl().use { repl ->
|
||||
repl.compileAndEval(ReplCodeLine(0, 0, "class Test<T>(val x: T) { fun <R> map(f: (T) -> R): R = f(x) }".trimIndent()))
|
||||
|
||||
// We expect that analysis time is not exponential
|
||||
for (i in 1..60) {
|
||||
repl.compileAndEval(ReplCodeLine(i, 0, "fun <T> Test<T>.map(f: (T) -> Double): List<Double> = listOf(f(this.x))"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class LegacyTestRepl : Closeable {
|
||||
val application = ApplicationManager.getApplication()
|
||||
|
||||
val currentLineCounter = AtomicInteger()
|
||||
|
||||
fun nextCodeLine(code: String): ReplCodeLine = ReplCodeLine(currentLineCounter.getAndIncrement(), 0, code)
|
||||
|
||||
val replCompiler: JvmReplCompiler by lazy {
|
||||
JvmReplCompiler(simpleScriptompilationConfiguration)
|
||||
}
|
||||
|
||||
val compiledEvaluator: ReplEvaluator by lazy {
|
||||
JvmReplEvaluator(simpleScriptEvaluationConfiguration)
|
||||
}
|
||||
|
||||
val state by lazy {
|
||||
val stateLock = ReentrantReadWriteLock()
|
||||
AggregatedReplStageState(replCompiler.createState(stateLock), compiledEvaluator.createState(stateLock), stateLock)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
state.dispose()
|
||||
resetApplicationToNull(application)
|
||||
}
|
||||
}
|
||||
|
||||
private fun LegacyTestRepl.compileAndEval(codeLine: ReplCodeLine): Pair<ReplCompileResult, ReplEvalResult?> {
|
||||
|
||||
val compRes = replCompiler.compile(state, codeLine)
|
||||
|
||||
val evalRes = (compRes as? ReplCompileResult.CompiledClasses)?.let {
|
||||
|
||||
compiledEvaluator.eval(state, it)
|
||||
}
|
||||
return compRes to evalRes
|
||||
}
|
||||
|
||||
private fun assertEvalUnit(repl: LegacyTestRepl, line: String) {
|
||||
val compiledClasses = checkCompile(repl, line)
|
||||
|
||||
val evalResult = repl.compiledEvaluator.eval(repl.state, compiledClasses!!)
|
||||
val unitResult = evalResult as? ReplEvalResult.UnitResult
|
||||
TestCase.assertNotNull("Unexpected eval result: $evalResult", unitResult)
|
||||
}
|
||||
|
||||
private fun<R> assertEvalResult(repl: LegacyTestRepl, line: String, expectedResult: R) {
|
||||
val compiledClasses = checkCompile(repl, line)
|
||||
|
||||
val evalResult = repl.compiledEvaluator.eval(repl.state, compiledClasses!!)
|
||||
val valueResult = evalResult as? ReplEvalResult.ValueResult
|
||||
TestCase.assertNotNull("Unexpected eval result: $evalResult", valueResult)
|
||||
TestCase.assertEquals(expectedResult, valueResult!!.value)
|
||||
}
|
||||
|
||||
private inline fun<reified R> assertEvalResultIs(repl: LegacyTestRepl, line: String) {
|
||||
val compiledClasses = checkCompile(repl, line)
|
||||
|
||||
val evalResult = repl.compiledEvaluator.eval(repl.state, compiledClasses!!)
|
||||
val valueResult = evalResult as? ReplEvalResult.ValueResult
|
||||
TestCase.assertNotNull("Unexpected eval result: $evalResult", valueResult)
|
||||
TestCase.assertTrue(valueResult!!.value is R)
|
||||
}
|
||||
|
||||
private fun checkCompile(repl: LegacyTestRepl, line: String): ReplCompileResult.CompiledClasses? {
|
||||
val codeLine = repl.nextCodeLine(line)
|
||||
val compileResult = repl.replCompiler.compile(repl.state, codeLine)
|
||||
val compiledClasses = compileResult as? ReplCompileResult.CompiledClasses
|
||||
TestCase.assertNotNull("Unexpected compile result: $compileResult", compiledClasses)
|
||||
return compiledClasses
|
||||
}
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* 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 kotlinx.coroutines.runBlocking
|
||||
import org.jetbrains.kotlin.cli.common.repl.BasicReplStageHistory
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import kotlin.script.experimental.annotations.KotlinScript
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.host.toScriptSource
|
||||
import kotlin.script.experimental.jvm.*
|
||||
import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate
|
||||
import kotlin.script.experimental.jvmhost.impl.KJvmReplCompilerImpl
|
||||
|
||||
class ReplTest : TestCase() {
|
||||
|
||||
companion object {
|
||||
const val TEST_DATA_DIR = "libraries/scripting/jvm-host/testData"
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCompileAndEval() {
|
||||
val out = captureOut {
|
||||
chechEvaluateInReplNoErrors(
|
||||
simpleScriptompilationConfiguration,
|
||||
simpleScriptEvaluationConfiguration,
|
||||
sequenceOf(
|
||||
"val x = 3",
|
||||
"x + 4",
|
||||
"println(\"x = \$x\")"
|
||||
),
|
||||
sequenceOf(null, 7, null)
|
||||
)
|
||||
}
|
||||
Assert.assertEquals("x = 3", out)
|
||||
}
|
||||
|
||||
fun evaluateInRepl(
|
||||
compilationConfiguration: ScriptCompilationConfiguration,
|
||||
evaluationConfiguration: ScriptEvaluationConfiguration,
|
||||
snippets: Sequence<String>
|
||||
): Sequence<ResultWithDiagnostics<EvaluationResult>> {
|
||||
val replCompilerProxy = KJvmReplCompilerImpl(defaultJvmScriptingHostConfiguration)
|
||||
val compilationState = replCompilerProxy.createReplCompilationState(compilationConfiguration)
|
||||
val compilationHistory = BasicReplStageHistory<ScriptDescriptor>()
|
||||
val replEvaluator = BasicJvmScriptEvaluator()
|
||||
var currentEvalConfig = evaluationConfiguration
|
||||
return snippets.mapIndexed { snippetNo, snippetText ->
|
||||
val snippetSource = snippetText.toScriptSource("Line_$snippetNo.simplescript.kts")
|
||||
val snippetId = ReplSnippetIdImpl(snippetNo, 0, snippetSource)
|
||||
replCompilerProxy.compileReplSnippet(compilationState, snippetSource, snippetId, compilationHistory)
|
||||
.onSuccess {
|
||||
runBlocking {
|
||||
replEvaluator(it, currentEvalConfig)
|
||||
}
|
||||
}
|
||||
.onSuccess {
|
||||
val snippetInstance = when (val retVal = it.returnValue) {
|
||||
is ResultValue.Value -> retVal.scriptInstance
|
||||
is ResultValue.UnitValue -> retVal.scriptInstance
|
||||
else -> throw IllegalStateException("Expecting value with script instance, got $it")
|
||||
}
|
||||
currentEvalConfig = ScriptEvaluationConfiguration(currentEvalConfig) {
|
||||
previousSnippets.append(snippetInstance)
|
||||
jvm {
|
||||
baseClassLoader(snippetInstance::class.java.classLoader)
|
||||
}
|
||||
}
|
||||
it.asSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun chechEvaluateInReplNoErrors(
|
||||
compilationConfiguration: ScriptCompilationConfiguration,
|
||||
evaluationConfiguration: ScriptEvaluationConfiguration,
|
||||
snippets: Sequence<String>,
|
||||
expected: Sequence<Any?>
|
||||
) {
|
||||
val expectedIter = expected.iterator()
|
||||
evaluateInRepl(compilationConfiguration, evaluationConfiguration, snippets).forEachIndexed { index, res ->
|
||||
when (res) {
|
||||
is ResultWithDiagnostics.Failure -> Assert.fail("#$index: Expected result, got $res")
|
||||
is ResultWithDiagnostics.Success -> {
|
||||
val expectedVal = expectedIter.next()
|
||||
val resVal = res.value.returnValue
|
||||
if (resVal is ResultValue.Value && resVal.type.isNotBlank()) // TODO: the latter check is temporary while the result is used to return the instance too
|
||||
Assert.assertEquals("#$index: Expected $expectedVal, got $resVal", expectedVal, resVal.value)
|
||||
else
|
||||
Assert.assertTrue("#$index: Expected $expectedVal, got Unit", expectedVal == null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@KotlinScript(fileExtension = "simplescript.kts")
|
||||
abstract class SimpleScript
|
||||
|
||||
val simpleScriptompilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScript> {
|
||||
jvm {
|
||||
dependenciesFromCurrentContext(wholeClasspath = true)
|
||||
}
|
||||
}
|
||||
|
||||
val simpleScriptEvaluationConfiguration = ScriptEvaluationConfiguration()
|
||||
-548
@@ -1,548 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 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 kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import java.io.*
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.file.Files
|
||||
import java.security.MessageDigest
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.jar.JarFile
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.host.BasicScriptingHost
|
||||
import kotlin.script.experimental.host.FileScriptSource
|
||||
import kotlin.script.experimental.host.toScriptSource
|
||||
import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator
|
||||
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
|
||||
import kotlin.script.experimental.jvmhost.*
|
||||
import kotlin.script.experimental.jvmhost.impl.CompiledScriptClassLoader
|
||||
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
|
||||
import kotlin.script.templates.standard.SimpleScriptTemplate
|
||||
|
||||
class ScriptingHostTest : TestCase() {
|
||||
|
||||
companion object {
|
||||
const val TEST_DATA_DIR = "libraries/scripting/jvm-host/testData"
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSimpleUsage() {
|
||||
val greeting = "Hello from script!"
|
||||
val output = captureOut {
|
||||
evalScript("println(\"$greeting\")").throwOnFailure()
|
||||
}
|
||||
Assert.assertEquals(greeting, output)
|
||||
// another API
|
||||
val output2 = captureOut {
|
||||
BasicJvmScriptingHost().evalWithTemplate<SimpleScriptTemplate>("println(\"$greeting\")".toScriptSource()).throwOnFailure()
|
||||
}
|
||||
Assert.assertEquals(greeting, output2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSaveToClasses() {
|
||||
val greeting = "Hello from script classes!"
|
||||
val outDir = Files.createTempDirectory("saveToClassesOut").toFile()
|
||||
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate>()
|
||||
val host = BasicJvmScriptingHost(evaluator = BasicJvmScriptClassFilesGenerator(outDir))
|
||||
host.eval("println(\"$greeting\")".toScriptSource(name = "SavedScript.kts"), compilationConfiguration, null).throwOnFailure()
|
||||
val classloader = URLClassLoader(arrayOf(outDir.toURI().toURL()), ScriptingHostTest::class.java.classLoader)
|
||||
val scriptClass = classloader.loadClass("SavedScript")
|
||||
val output = captureOut {
|
||||
scriptClass.newInstance()
|
||||
}
|
||||
Assert.assertEquals(greeting, output)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSaveToJar() {
|
||||
val greeting = "Hello from script jar!"
|
||||
val outJar = Files.createTempFile("saveToJar", ".jar").toFile()
|
||||
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate>()
|
||||
val host = BasicJvmScriptingHost(evaluator = BasicJvmScriptJarGenerator(outJar))
|
||||
host.eval("println(\"$greeting\")".toScriptSource(name = "SavedScript.kts"), compilationConfiguration, null).throwOnFailure()
|
||||
val classloader = URLClassLoader(arrayOf(outJar.toURI().toURL()), ScriptingHostTest::class.java.classLoader)
|
||||
val scriptClass = classloader.loadClass("SavedScript")
|
||||
val output = captureOut {
|
||||
scriptClass.newInstance()
|
||||
}
|
||||
Assert.assertEquals(greeting, output)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSaveToRunnableJar() {
|
||||
val greeting = "Hello from script jar!"
|
||||
val outJar = Files.createTempFile("saveToRunnableJar", ".jar").toFile()
|
||||
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate>()
|
||||
val compiler = JvmScriptCompiler(defaultJvmScriptingHostConfiguration)
|
||||
val scriptName = "SavedRunnableScript"
|
||||
val compiledScript = runBlocking {
|
||||
compiler("println(\"$greeting\")".toScriptSource(name = "$scriptName.kts"), compilationConfiguration).throwOnFailure()
|
||||
.resultOrNull()!!
|
||||
}
|
||||
val saver = BasicJvmScriptJarGenerator(outJar)
|
||||
runBlocking {
|
||||
saver(compiledScript, ScriptEvaluationConfiguration.Default).throwOnFailure()
|
||||
}
|
||||
|
||||
val classpathFromJar = run {
|
||||
val manifest = JarFile(outJar).manifest
|
||||
manifest.mainAttributes.getValue("Class-Path").split(" ") // TODO: quoted paths
|
||||
.map { File(it).toURI().toURL() }
|
||||
} + outJar.toURI().toURL()
|
||||
|
||||
fun checkInvokeMain(baseClassLoader: ClassLoader?) {
|
||||
val classloader = URLClassLoader(classpathFromJar.toTypedArray(), baseClassLoader)
|
||||
val scriptClass = classloader.loadClass(scriptName)
|
||||
val mainMethod = scriptClass.methods.find { it.name == "main" }
|
||||
Assert.assertNotNull(mainMethod)
|
||||
val output = captureOutAndErr {
|
||||
mainMethod!!.invoke(null, emptyArray<String>())
|
||||
}.toList().filterNot(String::isEmpty).joinToString("\n")
|
||||
Assert.assertEquals(greeting, output)
|
||||
}
|
||||
|
||||
checkInvokeMain(null) // isolated
|
||||
checkInvokeMain(Thread.currentThread().contextClassLoader)
|
||||
|
||||
val javaExecutable = File(File(System.getProperty("java.home"), "bin"), "java")
|
||||
val args = listOf(javaExecutable.absolutePath, "-jar", outJar.path)
|
||||
val processBuilder = ProcessBuilder(args)
|
||||
processBuilder.redirectErrorStream(true)
|
||||
val outputFromProcess = run {
|
||||
val process = processBuilder.start()
|
||||
process.waitFor(10, TimeUnit.SECONDS)
|
||||
val out = process.inputStream.reader().readText()
|
||||
if (process.isAlive) {
|
||||
process.destroyForcibly()
|
||||
"Error: timeout, killing script process\n$out"
|
||||
} else {
|
||||
out
|
||||
}
|
||||
}.trim()
|
||||
Assert.assertEquals(greeting, outputFromProcess)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSimpleRequire() {
|
||||
val greeting = "Hello from required!"
|
||||
val script = "val subj = RequiredClass().value\nprintln(\"Hello from \$subj!\")"
|
||||
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate> {
|
||||
importScripts(File(TEST_DATA_DIR, "importTest/requiredSrc.kt").toScriptSource())
|
||||
}
|
||||
val output = captureOut {
|
||||
BasicJvmScriptingHost().eval(script.toScriptSource(), compilationConfiguration, null).throwOnFailure()
|
||||
}
|
||||
Assert.assertEquals(greeting, output)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSimpleImport() {
|
||||
val greeting = listOf("Hello from helloWithVal script!", "Hello from imported helloWithVal script!")
|
||||
val script = "println(\"Hello from imported \$helloScriptName script!\")"
|
||||
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate> {
|
||||
makeSimpleConfigurationWithTestImport()
|
||||
}
|
||||
val output = captureOut {
|
||||
BasicJvmScriptingHost().eval(script.toScriptSource(), compilationConfiguration, null).throwOnFailure()
|
||||
}.lines()
|
||||
Assert.assertEquals(greeting, output)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDiamondImportWithoutSharing() {
|
||||
val greeting = listOf("Hi from common", "Hi from middle", "Hi from common", "sharedVar == 3")
|
||||
val output = doDiamondImportTest()
|
||||
Assert.assertEquals(greeting, output)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDiamondImportWithSharing() {
|
||||
val greeting = listOf("Hi from common", "Hi from middle", "sharedVar == 5")
|
||||
val output = doDiamondImportTest(
|
||||
ScriptEvaluationConfiguration {
|
||||
enableScriptsInstancesSharing()
|
||||
}
|
||||
)
|
||||
Assert.assertEquals(greeting, output)
|
||||
}
|
||||
|
||||
private fun doDiamondImportTest(evaluationConfiguration: ScriptEvaluationConfiguration? = null): List<String> {
|
||||
val mainScript = "sharedVar += 1\nprintln(\"sharedVar == \$sharedVar\")".toScriptSource("main.kts")
|
||||
val middleScript = File(TEST_DATA_DIR, "importTest/diamondImportMiddle.kts").toScriptSource()
|
||||
val commonScript = File(TEST_DATA_DIR, "importTest/diamondImportCommon.kts").toScriptSource()
|
||||
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate> {
|
||||
refineConfiguration {
|
||||
beforeCompiling { ctx ->
|
||||
when (ctx.script.name) {
|
||||
"main.kts" -> ScriptCompilationConfiguration(ctx.compilationConfiguration) {
|
||||
importScripts(middleScript, commonScript)
|
||||
}
|
||||
"diamondImportMiddle.kts" -> ScriptCompilationConfiguration(ctx.compilationConfiguration) {
|
||||
importScripts(commonScript)
|
||||
}
|
||||
else -> ctx.compilationConfiguration
|
||||
}.asSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
val output = captureOut {
|
||||
BasicJvmScriptingHost().eval(mainScript, compilationConfiguration, evaluationConfiguration).throwOnFailure()
|
||||
}.lines()
|
||||
return output
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testImportError() {
|
||||
val script = "println(\"Hello from imported \$helloScriptName script!\")"
|
||||
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate> {
|
||||
refineConfiguration {
|
||||
beforeCompiling { ctx ->
|
||||
ScriptCompilationConfiguration(ctx.compilationConfiguration) {
|
||||
importScripts(File(TEST_DATA_DIR, "missing_script.kts").toScriptSource())
|
||||
}.asSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
val res = BasicJvmScriptingHost().eval(script.toScriptSource(), compilationConfiguration, null)
|
||||
assertTrue(res is ResultWithDiagnostics.Failure)
|
||||
val report = res.reports.find { it.message.startsWith("Source file or directory not found") }
|
||||
assertNotNull(report)
|
||||
assertEquals("/script.kts", report?.sourcePath)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCompileOptionsLanguageVersion() {
|
||||
val script = "typealias MyInt = Int\nval x: MyInt = 3"
|
||||
val compilationConfiguration1 = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate> {
|
||||
compilerOptions("-language-version", "1.0")
|
||||
}
|
||||
val res = BasicJvmScriptingHost().eval(script.toScriptSource(), compilationConfiguration1, null)
|
||||
assertTrue(res is ResultWithDiagnostics.Failure)
|
||||
res.reports.find { it.message.startsWith("The feature \"type aliases\" is only available since language version 1.1") }
|
||||
?: fail("Error report about language version not found. Reported:\n ${res.reports.joinToString("\n ") { it.message }}")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCompileOptionsNoStdlib() {
|
||||
val script = "println(\"Hi\")"
|
||||
|
||||
val res1 = evalScriptWithConfiguration(script) {
|
||||
compilerOptions("-no-stdlib")
|
||||
}
|
||||
assertTrue(res1 is ResultWithDiagnostics.Failure)
|
||||
res1.reports.find { it.message.startsWith("Unresolved reference: println") }
|
||||
?: fail("Expected unresolved reference report. Reported:\n ${res1.reports.joinToString("\n ") { it.message }}")
|
||||
|
||||
val res2 = evalScriptWithConfiguration(script) {
|
||||
refineConfiguration {
|
||||
beforeCompiling { ctx ->
|
||||
ScriptCompilationConfiguration(ctx.compilationConfiguration) {
|
||||
compilerOptions("-no-stdlib")
|
||||
}.asSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
// -no-stdlib in refined configuration has no effect
|
||||
assertTrue(res2 is ResultWithDiagnostics.Success)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIgnoredOptionsWarning() {
|
||||
val script = "println(\"Hi\")"
|
||||
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate> {
|
||||
compilerOptions("-version", "-d", "destDir", "-Xreport-perf", "-no-reflect")
|
||||
refineConfiguration {
|
||||
beforeCompiling { ctx ->
|
||||
ScriptCompilationConfiguration(ctx.compilationConfiguration) {
|
||||
compilerOptions.append("-no-jdk", "-version", "-no-stdlib", "-Xdump-perf", "-no-inline")
|
||||
}.asSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
val res = BasicJvmScriptingHost().eval(script.toScriptSource(), compilationConfiguration, null)
|
||||
assertTrue(res is ResultWithDiagnostics.Success)
|
||||
assertNotNull(res.reports.find { it.message == "The following compiler arguments are ignored on script compilation: -version, -d, -Xreport-perf" })
|
||||
assertNotNull(res.reports.find { it.message == "The following compiler arguments are ignored on script compilation: -Xdump-perf" })
|
||||
assertNotNull(res.reports.find { it.message == "The following compiler arguments are ignored when configured from refinement callbacks: -no-jdk, -no-stdlib" })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMemoryCache() {
|
||||
val script = "val x = 1\nprintln(\"x = \$x\")"
|
||||
val expectedOutput = listOf("x = 1")
|
||||
val cache = SimpleMemoryScriptsCache()
|
||||
checkWithCache(cache, script, expectedOutput)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSimpleImportWithMemoryCache() {
|
||||
val script = "println(\"Hello from imported \$helloScriptName script!\")"
|
||||
val expectedOutput = listOf("Hello from helloWithVal script!", "Hello from imported helloWithVal script!")
|
||||
val cache = SimpleMemoryScriptsCache()
|
||||
checkWithCache(cache, script, expectedOutput) { makeSimpleConfigurationWithTestImport() }
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testFileCache() {
|
||||
val script = "val x = 1\nprintln(\"x = \$x\")"
|
||||
val expectedOutput = listOf("x = 1")
|
||||
val cacheDir = Files.createTempDirectory("scriptingTestCache").toFile()
|
||||
try {
|
||||
val cache = FileBasedScriptCache(cacheDir)
|
||||
Assert.assertTrue(cache.baseDir.listFiles().isEmpty())
|
||||
|
||||
checkWithCache(cache, script, expectedOutput)
|
||||
} finally {
|
||||
cacheDir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSimpleImportWithFileCache() {
|
||||
val script = "println(\"Hello from imported \$helloScriptName script!\")"
|
||||
val expectedOutput = listOf("Hello from helloWithVal script!", "Hello from imported helloWithVal script!")
|
||||
val cacheDir = Files.createTempDirectory("scriptingTestCache").toFile()
|
||||
try {
|
||||
val cache = FileBasedScriptCache(cacheDir)
|
||||
Assert.assertTrue(cache.baseDir.listFiles().isEmpty())
|
||||
|
||||
checkWithCache(cache, script, expectedOutput) { makeSimpleConfigurationWithTestImport() }
|
||||
} finally {
|
||||
cacheDir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkWithCache(
|
||||
cache: ScriptingCacheWithCounters, script: String, expectedOutput: List<String>,
|
||||
configurationBuilder: ScriptCompilationConfiguration.Builder.() -> Unit = {}
|
||||
) {
|
||||
val compiler = JvmScriptCompiler(defaultJvmScriptingHostConfiguration, cache = cache)
|
||||
val evaluator = BasicJvmScriptEvaluator()
|
||||
val host = BasicJvmScriptingHost(compiler = compiler, evaluator = evaluator)
|
||||
|
||||
val scriptCompilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate>(body = configurationBuilder)
|
||||
|
||||
Assert.assertEquals(0, cache.storedScripts)
|
||||
var compiledScript: CompiledScript<*>? = null
|
||||
val output = captureOut {
|
||||
runBlocking {
|
||||
compiler(script.toScriptSource(), scriptCompilationConfiguration).onSuccess {
|
||||
compiledScript = it
|
||||
evaluator(it)
|
||||
}.throwOnFailure()
|
||||
}
|
||||
}.lines()
|
||||
Assert.assertEquals(expectedOutput, output)
|
||||
Assert.assertEquals(1, cache.storedScripts)
|
||||
Assert.assertEquals(0, cache.retrievedScripts)
|
||||
|
||||
val cachedScript = cache.get(script.toScriptSource(), scriptCompilationConfiguration)
|
||||
Assert.assertNotNull(cachedScript)
|
||||
Assert.assertEquals(1, cache.retrievedScripts)
|
||||
|
||||
val compiledScriptClassRes = runBlocking { compiledScript!!.getClass(null) }
|
||||
val cachedScriptClassRes = runBlocking { cachedScript!!.getClass(null) }
|
||||
|
||||
val compiledScriptClass = compiledScriptClassRes.resultOrNull()
|
||||
val cachedScriptClass = cachedScriptClassRes.resultOrNull()
|
||||
|
||||
Assert.assertEquals(compiledScriptClass!!.qualifiedName, cachedScriptClass!!.qualifiedName)
|
||||
Assert.assertEquals(compiledScriptClass!!.supertypes, cachedScriptClass!!.supertypes)
|
||||
|
||||
val output2 = captureOut {
|
||||
runBlocking {
|
||||
evaluator(cachedScript!!).throwOnFailure()
|
||||
}
|
||||
}.lines()
|
||||
Assert.assertEquals(output, output2)
|
||||
|
||||
val output3 = captureOut { evalScriptWithConfiguration(script, host, configurationBuilder).throwOnFailure() }.lines()
|
||||
Assert.assertEquals(2, cache.retrievedScripts)
|
||||
Assert.assertEquals(output, output3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCompiledScriptClassLoader() {
|
||||
val script = "val x = 1"
|
||||
val scriptCompilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate>()
|
||||
val compiler = JvmScriptCompiler(defaultJvmScriptingHostConfiguration)
|
||||
val compiledScript = runBlocking {
|
||||
val res = compiler(script.toScriptSource(), scriptCompilationConfiguration).throwOnFailure()
|
||||
(res as ResultWithDiagnostics.Success<CompiledScript<*>>).value
|
||||
}
|
||||
val compiledScriptClass = runBlocking { compiledScript.getClass(null).throwOnFailure().resultOrNull()!! as KClass<*> }
|
||||
val classLoader = compiledScriptClass.java.classLoader
|
||||
|
||||
Assert.assertTrue(classLoader is CompiledScriptClassLoader)
|
||||
val anotherClass = classLoader.loadClass(compiledScriptClass.qualifiedName)
|
||||
|
||||
Assert.assertEquals(compiledScriptClass.java, anotherClass)
|
||||
|
||||
val classResourceName = compiledScriptClass.qualifiedName!!.replace('.', '/') + ".class"
|
||||
val classAsResourceUrl = classLoader.getResource(classResourceName)
|
||||
val classAssResourceStream = classLoader.getResourceAsStream(classResourceName)
|
||||
|
||||
Assert.assertNotNull(classAsResourceUrl)
|
||||
Assert.assertNotNull(classAssResourceStream)
|
||||
|
||||
val classAsResourceData = classAsResourceUrl.openConnection().getInputStream().readBytes()
|
||||
val classAsResourceStreamData = classAssResourceStream.readBytes()
|
||||
|
||||
Assert.assertArrayEquals(classAsResourceData, classAsResourceStreamData)
|
||||
|
||||
// TODO: consider testing getResources as well
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> ResultWithDiagnostics<T>.throwOnFailure(): ResultWithDiagnostics<T> = apply {
|
||||
if (this is ResultWithDiagnostics.Failure) {
|
||||
val firstExceptionFromReports = reports.find { it.exception != null }?.exception
|
||||
throw Exception(
|
||||
"Compilation/evaluation failed:\n ${reports.joinToString("\n ") { it.exception?.toString() ?: it.message }}",
|
||||
firstExceptionFromReports
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun evalScript(script: String, host: BasicScriptingHost = BasicJvmScriptingHost()): ResultWithDiagnostics<*> =
|
||||
evalScriptWithConfiguration(script, host)
|
||||
|
||||
private fun evalScriptWithConfiguration(
|
||||
script: String,
|
||||
host: BasicScriptingHost = BasicJvmScriptingHost(),
|
||||
body: ScriptCompilationConfiguration.Builder.() -> Unit = {}
|
||||
): ResultWithDiagnostics<EvaluationResult> {
|
||||
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate>(body = body)
|
||||
return host.eval(script.toScriptSource(), compilationConfiguration, null)
|
||||
}
|
||||
|
||||
|
||||
private interface ScriptingCacheWithCounters : CompiledJvmScriptsCache {
|
||||
|
||||
val storedScripts: Int
|
||||
val retrievedScripts: Int
|
||||
}
|
||||
|
||||
private class SimpleMemoryScriptsCache : ScriptingCacheWithCounters {
|
||||
|
||||
internal val data = hashMapOf<Pair<SourceCode, ScriptCompilationConfiguration>, CompiledScript<*>>()
|
||||
|
||||
private var _storedScripts = 0
|
||||
private var _retrievedScripts = 0
|
||||
|
||||
override val storedScripts: Int
|
||||
get() = _storedScripts
|
||||
|
||||
override val retrievedScripts: Int
|
||||
get() = _retrievedScripts
|
||||
|
||||
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>? =
|
||||
data[script to scriptCompilationConfiguration]?.also { _retrievedScripts++ }
|
||||
|
||||
override fun store(
|
||||
compiledScript: CompiledScript<*>,
|
||||
script: SourceCode,
|
||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||
) {
|
||||
data[script to scriptCompilationConfiguration] = compiledScript
|
||||
_storedScripts++
|
||||
}
|
||||
}
|
||||
|
||||
private fun ScriptCompilationConfiguration.Builder.makeSimpleConfigurationWithTestImport() {
|
||||
refineConfiguration {
|
||||
beforeCompiling { ctx ->
|
||||
val importedScript = File(ScriptingHostTest.TEST_DATA_DIR, "importTest/helloWithVal.kts")
|
||||
if ((ctx.script as? FileScriptSource)?.file?.canonicalFile == importedScript.canonicalFile) {
|
||||
ctx.compilationConfiguration
|
||||
} else {
|
||||
ScriptCompilationConfiguration(ctx.compilationConfiguration) {
|
||||
importScripts(importedScript.toScriptSource())
|
||||
}
|
||||
}.asSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun File.readCompiledScript(scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*> {
|
||||
return inputStream().use { fs ->
|
||||
ObjectInputStream(fs).use {
|
||||
it.readObject() as KJvmCompiledScript<*>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ByteArray.toHexString(): String = joinToString("", transform = { "%02x".format(it) })
|
||||
|
||||
|
||||
private class FileBasedScriptCache(val baseDir: File) : ScriptingCacheWithCounters {
|
||||
|
||||
internal fun uniqueHash(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): String {
|
||||
val digestWrapper = MessageDigest.getInstance("MD5")
|
||||
digestWrapper.update(script.text.toByteArray())
|
||||
scriptCompilationConfiguration.entries().sortedBy { it.key.name }.forEach {
|
||||
digestWrapper.update(it.key.name.toByteArray())
|
||||
digestWrapper.update(it.value.toString().toByteArray())
|
||||
}
|
||||
return digestWrapper.digest().toHexString()
|
||||
}
|
||||
|
||||
override fun get(script: SourceCode, scriptCompilationConfiguration: ScriptCompilationConfiguration): CompiledScript<*>? {
|
||||
val file = File(baseDir, uniqueHash(script, scriptCompilationConfiguration))
|
||||
return if (!file.exists()) null else file.readCompiledScript(scriptCompilationConfiguration)?.also { _retrievedScripts++ }
|
||||
}
|
||||
|
||||
override fun store(
|
||||
compiledScript: CompiledScript<*>,
|
||||
script: SourceCode,
|
||||
scriptCompilationConfiguration: ScriptCompilationConfiguration
|
||||
) {
|
||||
val file = File(baseDir, uniqueHash(script, scriptCompilationConfiguration))
|
||||
file.outputStream().use { fs ->
|
||||
ObjectOutputStream(fs).use { os ->
|
||||
os.writeObject(compiledScript)
|
||||
}
|
||||
}
|
||||
_storedScripts++
|
||||
}
|
||||
|
||||
private var _storedScripts = 0
|
||||
private var _retrievedScripts = 0
|
||||
|
||||
override val storedScripts: Int
|
||||
get() = _storedScripts
|
||||
|
||||
override val retrievedScripts: Int
|
||||
get() = _retrievedScripts
|
||||
}
|
||||
|
||||
internal fun captureOut(body: () -> Unit): String = captureOutAndErr(body).first
|
||||
|
||||
internal fun captureOutAndErr(body: () -> Unit): Pair<String, String> {
|
||||
val outStream = ByteArrayOutputStream()
|
||||
val errStream = ByteArrayOutputStream()
|
||||
val prevOut = System.out
|
||||
val prevErr = System.err
|
||||
System.setOut(PrintStream(outStream))
|
||||
System.setErr(PrintStream(errStream))
|
||||
try {
|
||||
body()
|
||||
} finally {
|
||||
System.out.flush()
|
||||
System.err.flush()
|
||||
System.setOut(prevOut)
|
||||
System.setErr(prevErr)
|
||||
}
|
||||
return outStream.toString().trim() to errStream.toString().trim()
|
||||
}
|
||||
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* 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 kotlin.script.experimental.annotations.KotlinScript
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.host.toScriptSource
|
||||
import kotlin.script.experimental.jvm.dependenciesFromCurrentContext
|
||||
import kotlin.script.experimental.jvm.jvm
|
||||
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
|
||||
import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate
|
||||
|
||||
@KotlinScript(fileExtension = "withboth.kts", compilationConfiguration = ReceiverAndPropertiesConfiguration::class)
|
||||
abstract class ScriptWithBoth
|
||||
|
||||
@KotlinScript(fileExtension = "withproperties.kts", compilationConfiguration = ProvidedPropertiesConfiguration::class)
|
||||
abstract class ScriptWithProvidedProperties
|
||||
|
||||
@KotlinScript(fileExtension = "withreceiver.kts", compilationConfiguration = ImplicitReceiverConfiguration::class)
|
||||
abstract class ScriptWithImplicitReceiver
|
||||
|
||||
object ReceiverAndPropertiesConfiguration : ScriptCompilationConfiguration(
|
||||
{
|
||||
jvm { dependenciesFromCurrentContext(wholeClasspath = true) }
|
||||
|
||||
providedProperties("providedString" to String::class)
|
||||
|
||||
implicitReceivers(ImplicitReceiverClass::class)
|
||||
}
|
||||
)
|
||||
|
||||
object ProvidedPropertiesConfiguration : ScriptCompilationConfiguration(
|
||||
{
|
||||
jvm { dependenciesFromCurrentContext(wholeClasspath = true) }
|
||||
|
||||
providedProperties("providedString" to String::class)
|
||||
}
|
||||
)
|
||||
|
||||
object ImplicitReceiverConfiguration : ScriptCompilationConfiguration(
|
||||
{
|
||||
jvm { dependenciesFromCurrentContext(wholeClasspath = true) }
|
||||
|
||||
implicitReceivers(ImplicitReceiverClass::class)
|
||||
}
|
||||
)
|
||||
|
||||
class ImplicitReceiverClass(val receiverString: String)
|
||||
|
||||
inline fun <reified T : Any> evalString(
|
||||
source: String,
|
||||
noinline configure: ScriptEvaluationConfiguration.Builder.() -> Unit
|
||||
): ResultWithDiagnostics<EvaluationResult> {
|
||||
val actualConfiguration = createJvmCompilationConfigurationFromTemplate<T>()
|
||||
return BasicJvmScriptingHost()
|
||||
.eval(source.toScriptSource(), actualConfiguration, ScriptEvaluationConfiguration(configure))
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
println("Hi from common")
|
||||
|
||||
var sharedVar = 2
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
println("Hi from middle")
|
||||
|
||||
sharedVar *= 2
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
val helloScriptName = "helloWithVal"
|
||||
|
||||
println("Hello from $helloScriptName script!")
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
class RequiredClass {
|
||||
|
||||
val value = "required"
|
||||
}
|
||||
Reference in New Issue
Block a user