summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala8
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Line.scala24
-rw-r--r--src/compiler/scala/tools/nsc/io/Sources.scala33
-rw-r--r--src/compiler/scala/tools/nsc/util/Exceptional.scala2
-rw-r--r--test/files/run/repl-exceptions.check25
-rw-r--r--test/files/run/repl-exceptions.scala12
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
+}