diff options
author | Paul Phillips <paulp@improving.org> | 2011-11-04 08:25:30 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-11-04 08:25:30 +0000 |
commit | 8006cc6760b30274676ae5359c27b49e5cbf5670 (patch) | |
tree | 24fe2d61e0a0068b86e65484ffca97f910d1230c | |
parent | 5df51cc5a6ead1f9d68d1e988cda3a1698daf708 (diff) | |
download | scala-8006cc6760b30274676ae5359c27b49e5cbf5670.tar.gz scala-8006cc6760b30274676ae5359c27b49e5cbf5670.tar.bz2 scala-8006cc6760b30274676ae5359c27b49e5cbf5670.zip |
Fix for some repl bitrot.
Exception handling beset by entropy. Restored some order. The output of
the test may not be stable across platforms, in which case I'll take the
usual step of reverting it, thereby achieving victory over failure by
testing nothing instead of testing something. No review.
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/IMain.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/Line.scala | 24 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/io/Sources.scala | 33 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/util/Exceptional.scala | 2 | ||||
-rw-r--r-- | test/files/run/repl-exceptions.check | 25 | ||||
-rw-r--r-- | test/files/run/repl-exceptions.scala | 12 |
6 files changed, 77 insertions, 27 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index b092574eaf..ff6100e9e8 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -237,12 +237,12 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends /** whether to bind the lastException variable */ private var bindExceptions = true /** takes AnyRef because it may be binding a Throwable or an Exceptional */ - private def withLastExceptionLock[T](body: => T): T = { + private def withLastExceptionLock[T](body: => T, alt: => T): T = { assert(bindExceptions, "withLastExceptionLock called incorrectly.") bindExceptions = false try beQuietDuring(body) - catch logAndDiscard("bindLastException", null.asInstanceOf[T]) + catch logAndDiscard("bindLastException", alt) finally bindExceptions = true } @@ -708,7 +708,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends throw t val unwrapped = unwrap(t) - withLastExceptionLock { + withLastExceptionLock[String]({ if (opt.richExes) { val ex = new LineExceptional(unwrapped) bind[Exceptional]("lastException", ex) @@ -718,7 +718,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends bind[Throwable]("lastException", unwrapped) util.stackTraceString(unwrapped) } - } + }, "" + unwrapped) } // TODO: split it out into a package object and a regular diff --git a/src/compiler/scala/tools/nsc/interpreter/Line.scala b/src/compiler/scala/tools/nsc/interpreter/Line.scala index deec9fcc4e..3062c95dae 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Line.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Line.scala @@ -19,11 +19,11 @@ import Line._ * completed or failed. */ class Line[+T](val code: String, classLoader: ClassLoader, body: => T) { - private var _state: State = Running - private var _result: Any = null - private var _caught: Throwable = null - private val lock = new ReentrantLock() - private val finished = lock.newCondition() + private var _state: State = Running + private var _result: Option[Any] = None + private var _caught: Option[Throwable] = None + private val lock = new ReentrantLock() + private val finished = lock.newCondition() private def withLock[T](body: => T) = { lock.lock() @@ -38,11 +38,8 @@ class Line[+T](val code: String, classLoader: ClassLoader, body: => T) { private def cancel() = if (running) setState(Cancelled) private def runAndSetState[T](body: => T) { - var ex: Throwable = null - - try { _result = body } - catch { case t => ex = t } - finally { setState( if (ex == null) Done else Threw ) } + try { _result = Some(body) ; setState(Done) } + catch { case t => _caught = Some(t) ; setState(Threw) } } // This is where the line thread is created and started. @@ -56,8 +53,11 @@ class Line[+T](val code: String, classLoader: ClassLoader, body: => T) { def success = _state == Done def running = _state == Running - def caught() = { await() ; _caught } - def get() = { await() ; _result } + def caught() = { await() ; _caught.orNull } + def get() = { + await() + _result getOrElse sys.error("Called get with no result. Code: " + code) + } def await() = withLock { while (running) finished.await() } } diff --git a/src/compiler/scala/tools/nsc/io/Sources.scala b/src/compiler/scala/tools/nsc/io/Sources.scala index 35c7a504a5..25d27acae8 100644 --- a/src/compiler/scala/tools/nsc/io/Sources.scala +++ b/src/compiler/scala/tools/nsc/io/Sources.scala @@ -13,6 +13,7 @@ class Sources(val path: String) { def allNames = cache.keys.asScala.toList.sorted def apply(name: String) = get(name) def size = cache.asScala.values map (_.length) sum + def isEmpty = path == "" private var debug = false private def dbg(msg: => Any) = if (debug) Console println msg @@ -20,14 +21,17 @@ class Sources(val path: String) { val dirs = partitioned._1 map (_.toDirectory) val jars = partitioned._2 filter Jar.isJarOrZip map (_.toFile) - val (isDone, force) = { - val f1 = spawn(calculateDirs()) - val f2 = spawn(calculateJars()) - val fn1 = () => { f1.isDone() && f2.isDone() } - val fn2 = () => { f1.get() ; f2.get() ; () } - - (fn1, fn2) - } + val (isDone, force) = ( + if (path == "") (() => true, () => ()) + else { + val f1 = spawn(calculateDirs()) + val f2 = spawn(calculateJars()) + val fn1 = () => { f1.isDone() && f2.isDone() } + val fn2 = () => { f1.get() ; f2.get() ; () } + + (fn1, fn2) + } + ) private def catchZip(body: => Unit): Unit = { try body @@ -62,12 +66,21 @@ trait LowPrioritySourcesImplicits { } object Sources extends LowPrioritySourcesImplicits { + val empty = new Sources("") + private def libraryInits = ClassPath.scalaLibrary.toList flatMap (_.toAbsolute.parents) private def librarySourceDir = libraryInits map (_ / "src") find (_.isDirectory) private def expandedSourceDir = librarySourceDir.toList flatMap (ClassPath expandDir _.path) - val sourcePathProp = sys.props.traceSourcePath.value - val defaultSources = apply(expandedSourceDir :+ sourcePathProp: _*) + private val initialPath = sys.props.traceSourcePath.value + private val initialSources = apply(expandedSourceDir :+ initialPath: _*) + + def defaultSources = { + val path = sys.props.traceSourcePath.value + if (path == "") empty + else if (path == initialPath) initialSources + else apply(expandedSourceDir :+ path: _*) + } def apply(paths: String*): Sources = new Sources(ClassPath.join(paths: _*)) } diff --git a/src/compiler/scala/tools/nsc/util/Exceptional.scala b/src/compiler/scala/tools/nsc/util/Exceptional.scala index 459881bb64..667b7d15a6 100644 --- a/src/compiler/scala/tools/nsc/util/Exceptional.scala +++ b/src/compiler/scala/tools/nsc/util/Exceptional.scala @@ -27,7 +27,7 @@ class Exceptional(val ex: Throwable)(implicit prefs: ScalaPrefs) { /** The result of this will be printed before a context trace. */ def contextPrelude: String = - if (isScanDone) "" + if (isScanDone || prefs.codeSources.isEmpty) "" else "/* Still scanning source path: there may be more momentarily. */\n" /** Frames with surrounding context. */ diff --git a/test/files/run/repl-exceptions.check b/test/files/run/repl-exceptions.check new file mode 100644 index 0000000000..f7ce018422 --- /dev/null +++ b/test/files/run/repl-exceptions.check @@ -0,0 +1,25 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> sys.SystemProperties.traceSourcePath setValue "" +res0: String = null + +scala> def f = sys.error("hi mom") +f: Nothing + +scala> f +[package.error] (package.scala:27) +(access lastException for the full trace) + +scala> lastException.show +/* The repl internal portion of the stack trace is elided. */ +[package.error] (package.scala:27) +[.f] (<console>:7) +[.<init>] (<console>:9) +[.<clinit>] (<console>:-1) + +scala> + +scala> diff --git a/test/files/run/repl-exceptions.scala b/test/files/run/repl-exceptions.scala new file mode 100644 index 0000000000..aaf37c8ae7 --- /dev/null +++ b/test/files/run/repl-exceptions.scala @@ -0,0 +1,12 @@ +import scala.tools.partest.ReplTest +import scala.tools.util.Javap + +object Test extends ReplTest { + override def extraSettings = "-Yrich-exceptions" + def code = """ + |sys.SystemProperties.traceSourcePath setValue "" + |def f = sys.error("hi mom") + |f + |lastException.show + """.stripMargin +} |