summaryrefslogtreecommitdiff
path: root/src/repl/scala/tools
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2015-01-15 21:48:47 +1000
committerJason Zaugg <jzaugg@gmail.com>2015-01-16 11:36:49 +1000
commit09ce5c32f1db71ccaa5d4b22076d9ec606ad5ec9 (patch)
treed7188ff810f1d9a2cc6eb2faad18ebd40a0ac587 /src/repl/scala/tools
parent05612399f78f34cb01fb31070eacf4a51b489dfb (diff)
downloadscala-09ce5c32f1db71ccaa5d4b22076d9ec606ad5ec9.tar.gz
scala-09ce5c32f1db71ccaa5d4b22076d9ec606ad5ec9.tar.bz2
scala-09ce5c32f1db71ccaa5d4b22076d9ec606ad5ec9.zip
SI-6502 More robust REPL :require
- handle missing files gracefully (rather than NPE) - read the class name with ASM, rather than with a dummy classloader. The dummy classloader is prone to throwing `LinkageError`s, as reported in the comments of SI-6502. Manual test of the original report: ``` % qscala Welcome to Scala version 2.11.5-20150115-183424-155dbf3fdf (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25). Type in expressions to have them evaluated. Type :help for more information. scala> :require does/not/exist Cannot read: does/not/exist scala> classOf[org.junit.Test] <console>:8: error: object junit is not a member of package org classOf[org.junit.Test] ^ scala> :require /Users/jason/.m2/repository/junit/junit/4.11/junit-4.11.jar Added '/Users/jason/.m2/repository/junit/junit/4.11/junit-4.11.jar' to classpath. scala> classOf[org.junit.Test] res1: Class[org.junit.Test] = interface org.junit.Test ``` I have commited an automated test that is a minimization of this one.
Diffstat (limited to 'src/repl/scala/tools')
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala24
1 files changed, 13 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)