diff options
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/ILoop.scala | 24 | ||||
-rw-r--r-- | test/files/run/t6502.scala | 26 |
2 files changed, 39 insertions, 11 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 4fd5768b79..4d71e0e09e 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -12,6 +12,7 @@ import scala.annotation.tailrec import Predef.{ println => _, _ } import interpreter.session._ import StdReplTags._ +import scala.tools.asm.ClassReader import scala.util.Properties.{ jdkHome, javaVersion, versionString, javaVmName } import scala.tools.nsc.util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream } import scala.reflect.classTag @@ -633,28 +634,29 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) * the interpreter and replays all interpreter expressions. */ def require(arg: String): Unit = { - class InfoClassLoader extends java.lang.ClassLoader { - def classOf(arr: Array[Byte]): Class[_] = - super.defineClass(null, arr, 0, arr.length) - } - val f = File(arg).normalize - if (f.isDirectory) { - echo("Adding directories to the classpath is not supported. Add a jar instead.") + val jarFile = AbstractFile.getDirectory(new java.io.File(arg)) + if (jarFile == null) { + echo(s"Cannot load '$arg'") return } - val jarFile = AbstractFile.getDirectory(new java.io.File(arg)) - def flatten(f: AbstractFile): Iterator[AbstractFile] = if (f.isClassContainer) f.iterator.flatMap(flatten) else Iterator(f) val entries = flatten(jarFile) - val cloader = new InfoClassLoader - def classNameOf(classFile: AbstractFile): String = cloader.classOf(classFile.toByteArray).getName + def classNameOf(classFile: AbstractFile): String = { + val input = classFile.input + try { + val reader = new ClassReader(input) + reader.getClassName.replace('/', '.') + } finally { + input.close() + } + } def alreadyDefined(clsName: String) = intp.classLoader.tryToLoadClass(clsName).isDefined val exists = entries.filter(_.hasExtension("class")).map(classNameOf).exists(alreadyDefined) diff --git a/test/files/run/t6502.scala b/test/files/run/t6502.scala index 4ce034a482..b0d93ac3fd 100644 --- a/test/files/run/t6502.scala +++ b/test/files/run/t6502.scala @@ -46,6 +46,12 @@ object Test extends StoreReporterDirectTest { } }""" + def app6 = """ + package test6 + class A extends Test { println("created test6.A") } + class Z extends Test { println("created test6.Z") } + trait Test""" + def test1(): Unit = { val jar = "test1.jar" compileCode(app1, jar) @@ -105,11 +111,31 @@ object Test extends StoreReporterDirectTest { println(s"test4 res2: $res2") } + def test5(): Unit = { + val codeToRun = ":require /does/not/exist.jar" + val output = ILoop.run(codeToRun, settings) + assert(!output.contains("NullPointerException"), output) + assert(output.contains("Cannot load '/does/not/exist.jar'"), output) + } + + def test6(): Unit = { + // Avoid java.lang.NoClassDefFoundError triggered by the old appoach of using a Java + // classloader to parse .class files in order to read their names. + val jar = "test6.jar" + compileCode(app6, jar) + val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar", "import test6._; new A; new Z") + val output = ILoop.run(codeToRun, settings) + assert(output.contains("created test6.A"), output) + assert(output.contains("created test6.Z"), output) + } + def show(): Unit = { test1() test2() test3() test4() + test5() + test6() } def toCodeInSeparateLines(lines: String*): String = lines.map(_ + "\n").mkString |