summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2015-09-09 15:02:17 +1000
committerJason Zaugg <jzaugg@gmail.com>2015-09-09 15:06:19 +1000
commite3f025c1e4fbef83528ab189b37e13ebdf1b9a72 (patch)
treeec8a296d23b49e1b6156f29f48b78d837a9e0162
parent1c42e6bee90b7c444e973726e01b137584dfaad5 (diff)
downloadscala-e3f025c1e4fbef83528ab189b37e13ebdf1b9a72.tar.gz
scala-e3f025c1e4fbef83528ab189b37e13ebdf1b9a72.tar.bz2
scala-e3f025c1e4fbef83528ab189b37e13ebdf1b9a72.zip
Fix completion for multi-line entries
We need to include the previously entered lines into the code that we presentation compile. Management of this state makes the interpret method non tail recursive, so we could blow the default stack with a multi-line entry of hundreds of lines. I think thats an acceptable limitation.
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala28
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala1
-rw-r--r--src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala7
3 files changed, 20 insertions, 16 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index f934bbe46c..f844029b64 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -764,7 +764,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
* read, go ahead and interpret it. Return the full string
* to be recorded for replay, if any.
*/
- @tailrec final def interpretStartingWith(code: String): Option[String] = {
+ final def interpretStartingWith(code: String): Option[String] = {
// signal completion non-completion input has been received
in.completion.resetVerbosity()
@@ -791,17 +791,21 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
case IR.Incomplete if in.interactive && code.endsWith("\n\n") =>
echo("You typed two blank lines. Starting a new command.")
None
- case IR.Incomplete => in.readLine(paste.ContinuePrompt) match {
- case null =>
- // we know compilation is going to fail since we're at EOF and the
- // parser thinks the input is still incomplete, but since this is
- // a file being read non-interactively we want to fail. So we send
- // it straight to the compiler for the nice error message.
- intp.compileString(code)
- None
-
- case line => interpretStartingWith(s"$code\n$line")
- }
+ case IR.Incomplete =>
+ val saved = intp.partialInput
+ intp.partialInput = code + "\n"
+ try {
+ in.readLine(paste.ContinuePrompt) match {
+ case null =>
+ // we know compilation is going to fail since we're at EOF and the
+ // parser thinks the input is still incomplete, but since this is
+ // a file being read non-interactively we want to fail. So we send
+ // it straight to the compiler for the nice error message.
+ intp.compileString(code)
+ None
+ case line => interpretStartingWith(s"$code\n$line")
+ }
+ } finally intp.partialInput = saved
}
}
}
diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala
index 2085fd4e50..f6f391600b 100644
--- a/src/repl/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala
@@ -80,6 +80,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
private var _isInitialized: Future[Boolean] = null // set up initialization future
private var bindExceptions = true // whether to bind the lastException variable
private var _executionWrapper = "" // code to be wrapped around all lines
+ var partialInput: String = "" // code accumulated in multi-line REPL input
/** We're going to go to some trouble to initialize the compiler asynchronously.
* It's critical that nothing call into it until it's been initialized or we will
diff --git a/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala b/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala
index 81c4fb0b70..3a2177a4cb 100644
--- a/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala
+++ b/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala
@@ -28,10 +28,9 @@ trait PresentationCompilation {
//
// scala> 1
// scala> .toInt
- val line1 = if (Completion.looksLikeInvocation(line)) {
- self.mostRecentVar + line
- } else line
-
+ //
+ // and for multi-line input.
+ val line1 = partialInput + (if (Completion.looksLikeInvocation(line)) { self.mostRecentVar + line } else line)
val compiler = newPresentationCompiler()
val trees = compiler.newUnitParser(line1).parseStats()
val importer = global.mkImporter(compiler)