From 125cc6ebfbc9f539945866c10d9d37f7fb683619 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 17 Nov 2016 15:53:40 +0100 Subject: [PATCH] Fix compiled line class loading in repl, fixes #KT-14706 --- .../repl/GenericReplCompiledEvaluator.kt | 19 +++++++++-- .../kotlin/cli/jvm/repl/GenericReplTest.kt | 32 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt index dfe95831f18..2de34e49f80 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompiledEvaluator.kt @@ -38,6 +38,10 @@ open class GenericReplCompiledEvaluator(baseClasspath: Iterable, baseClass return@eval ReplEvalResult.HistoryMismatch(it) } + var mainLineClassName: String? = null + + fun classNameFromPath(path: String) = JvmClassName.byInternalName(path.replaceFirst("\\.class$".toRegex(), "")) + classLoaderLock.read { if (newClasspath.isNotEmpty()) { classLoaderLock.write { @@ -46,11 +50,22 @@ open class GenericReplCompiledEvaluator(baseClasspath: Iterable, baseClass } compiledClasses.filter { it.path.endsWith(".class") } .forEach { - classLoader.addClass(JvmClassName.byInternalName(it.path.replaceFirst("\\.class$".toRegex(), "")), it.bytes) + val className = classNameFromPath(it.path) + if (className.fqNameForClassNameWithoutDollars.shortName().asString() == "Line${codeLine.no}") { + mainLineClassName = className.fqNameForClassNameWithoutDollars.asString() + } + classLoader.addClass(className, it.bytes) } } - val scriptClass = classLoaderLock.read { classLoader.loadClass("Line${codeLine.no}") } + val scriptClass = classLoaderLock.read { + try { + classLoader.loadClass(mainLineClassName!!) + } + catch (e: Exception) { + throw Exception("Error loading class $mainLineClassName: known classes: ${compiledClasses.map { classNameFromPath(it.path).fqNameForClassNameWithoutDollars.asString() }}", e) + } + } val constructorParams: Array> = (compiledLoadedClassesHistory.map { it.second.klass } + diff --git a/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt b/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt index 7d9b85566e2..a21ddace76e 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt @@ -82,6 +82,38 @@ class GenericReplTest : TestCase() { Disposer.dispose(disposable) } + + @Test + fun testRepPackage() { + + val disposable = Disposer.newDisposable() + + val repl = TestRepl(disposable, + listOf(File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-runtime.jar")), + "kotlin.script.templates.standard.ScriptTemplateWithArgs") + + val codeLine1 = ReplCodeLine(0, "package mypackage\n\nval x = 1\nx+2") + val res1 = repl.replCompiler?.compile(codeLine1, emptyList()) + val res1c = res1 as? ReplCompileResult.CompiledClasses + TestCase.assertNotNull("Unexpected compile result: $res1", res1c) + + val res11 = repl.compiledEvaluator.eval(codeLine1, emptyList(), res1c!!.classes, res1c.hasResult, res1c.newClasspath) + val res11e = res11 as? ReplEvalResult.ValueResult + TestCase.assertNotNull("Unexpected eval result: $res11", res11e) + TestCase.assertEquals(3, res11e!!.value) + + val codeLine2 = ReplCodeLine(0, "x+4") + val res2 = repl.replCompiler?.compile(codeLine2, listOf(codeLine1)) + val res2c = res2 as? ReplCompileResult.CompiledClasses + TestCase.assertNotNull("Unexpected compile result: $res2", res2c) + + val res21 = repl.compiledEvaluator.eval(codeLine2, listOf(codeLine1), res2c!!.classes, res2c.hasResult, res2c.newClasspath) + val res21e = res21 as? ReplEvalResult.ValueResult + TestCase.assertNotNull("Unexpected eval result: $res21", res21e) + TestCase.assertEquals(5, res21e!!.value) + + Disposer.dispose(disposable) + } } internal class TestRepl(