summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-08-02 18:42:01 +0200
committerMartin Odersky <odersky@gmail.com>2012-08-03 13:28:11 +0200
commitf16e2c0874b4ecd4d5f0609f7a1c6a429d11c187 (patch)
tree2ffee893d6958c041a0f0cc475c476a8bf6b20bd /src
parent217aaf7497990cf5cd23bca2bb57b5b6ea708873 (diff)
downloadscala-f16e2c0874b4ecd4d5f0609f7a1c6a429d11c187.tar.gz
scala-f16e2c0874b4ecd4d5f0609f7a1c6a429d11c187.tar.bz2
scala-f16e2c0874b4ecd4d5f0609f7a1c6a429d11c187.zip
Better worksheet support.
We now move instrumentation info to the end of lines where possible so that line and column positions are kept unchanged wrt original source. This is important for error reporting.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/interactive/REPL.scala18
-rw-r--r--src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala22
-rw-r--r--src/compiler/scala/tools/nsc/scratchpad/Mixer.scala7
-rw-r--r--src/library/scala/runtime/WorksheetSupport.scala12
4 files changed, 40 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala
index 6876ea14e0..65e7eb5fc6 100644
--- a/src/compiler/scala/tools/nsc/interactive/REPL.scala
+++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala
@@ -124,9 +124,9 @@ object REPL {
* @param iContents An Array[Char] containing the instrumented source
* @return The name of the instrumented source file
*/
- def writeInstrumented(iFullName: String, iContents: Array[Char]): String = {
+ def writeInstrumented(iFullName: String, suffix: String, iContents: Array[Char]): String = {
val iSimpleName = iFullName drop ((iFullName lastIndexOf '.') + 1)
- val iSourceName = iSimpleName + "$instrumented.scala"
+ val iSourceName = iSimpleName + suffix
val ifile = new FileWriter(iSourceName)
ifile.write(iContents)
ifile.close()
@@ -186,18 +186,20 @@ object REPL {
* and outputs in the right column, or None if the presentation compiler
* does not respond to askInstrumented.
*/
- def instrument(arguments: List[String], line: Int): Option[String] = {
+ def instrument(arguments: List[String], line: Int): Option[(String, String)] = {
val source = toSourceFile(arguments.head)
// strip right hand side comment column and any trailing spaces from all lines
- val strippedSource = new BatchSourceFile(source.file, SourceInserter.stripRight(source.content))
+ val strippedContents = SourceInserter.stripRight(source.content)
+ val strippedSource = new BatchSourceFile(source.file, strippedContents)
println("stripped source = "+strippedSource)
comp.askReload(List(strippedSource), reloadResult)
comp.askInstrumented(strippedSource, line, instrumentedResult)
using(instrumentedResult) {
case (iFullName, iContents) =>
println(s"instrumented source $iFullName = ${iContents.mkString}")
- val iSourceName = writeInstrumented(iFullName, iContents)
- iSourceName
+ val iSourceName = writeInstrumented(iFullName, "$instrumented.scala", iContents)
+ val sSourceName = writeInstrumented(iFullName, "$stripped.scala", strippedContents)
+ (iSourceName, sSourceName)
/*
* val vdirOpt = compileInstrumented(iSourceName, arguments.tail)
runInstrumented(vdirOpt, iFullName, strippedSource.content)
@@ -227,9 +229,9 @@ object REPL {
case List("complete", file, off1) =>
doComplete(makePos(file, off1, off1))
case "instrument" :: arguments =>
- println(instrument(arguments, -1).map(_.mkString))
+ println(instrument(arguments, -1))
case "instrumentTo" :: line :: arguments =>
- println(instrument(arguments, line.toInt).map(_.mkString))
+ println(instrument(arguments, line.toInt))
case List("quit") =>
comp.askShutdown()
exit(1) // Don't use sys yet as this has to run on 2.8.2 also.
diff --git a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala
index f7b1c42fd6..efc393c812 100644
--- a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala
+++ b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala
@@ -3,7 +3,7 @@ package interactive
import scala.reflect.internal.util.{SourceFile, BatchSourceFile, RangePosition}
import collection.mutable.ArrayBuffer
-import reflect.internal.Chars.isLineBreakChar
+import reflect.internal.Chars.{isLineBreakChar, isWhitespace}
trait ScratchPadMaker { self: Global =>
@@ -40,14 +40,28 @@ trait ScratchPadMaker { self: Global =>
toPrint.clear()
}
+ /** The position where to insert an instrumentation statement in front of giuven statement.
+ * This is at the latest `stat.pos.start`. But in order not to mess with column numbers
+ * in position we try to insert it at the end of the preceding line instead.
+ * To be safe, this can be done only if there's only whitespace between that position and
+ * statement's start position.
+ */
+ private def instrumentPos(stat: Tree): Int = {
+ var start = stat.pos.start
+ while (start > 0 && isWhitespace(contents(start - 1))) start -= 1
+ if (start > 0 && isLineBreakChar(contents(start - 1))) start -= 1
+ start
+ }
+
private def addSkip(stat: Tree): Unit = {
- if (stat.pos.start > skipped) applyPendingPatches(stat.pos.start)
+ val ipos = instrumentPos(stat)
+ if (stat.pos.start > skipped) applyPendingPatches(ipos)
if (stat.pos.start >= endOffset)
- patches += Patch(stat.pos.start, ";$stop()")
+ patches += Patch(ipos, ";$stop()")
var end = stat.pos.end
if (end > skipped) {
while (end < contents.length && !isLineBreakChar(contents(end))) end += 1
- patches += Patch(stat.pos.start, ";$skip("+(end-skipped)+"); ")
+ patches += Patch(ipos, ";$skip("+(end-skipped)+"); ")
skipped = end
}
}
diff --git a/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala b/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala
index 46ccc32097..67ff916b11 100644
--- a/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala
+++ b/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala
@@ -23,7 +23,7 @@ class Mixer {
val nextSpace = comments indexOf (' ', idx)
var nextNL = comments indexOf ('\n', nextSpace + 1)
if (nextNL < 0) nextNL = comments.length
- val result =
+ val result =
(new String(comments.slice(idx, nextSpace)).toInt, comments.slice(nextSpace + 1, nextNL))
idx = nextNL + 1
result
@@ -46,7 +46,10 @@ class Mixer {
mixed += '\n'
col = 0
}
- mixed ++= (" " * (sepColumn - col))
+ while (col < sepColumn) {
+ mixed += ' '
+ col += 1
+ }
}
for ((offset, cs) <- parseComments(comments)) {
val sep =
diff --git a/src/library/scala/runtime/WorksheetSupport.scala b/src/library/scala/runtime/WorksheetSupport.scala
index f9ffb9197b..6f2a4d382d 100644
--- a/src/library/scala/runtime/WorksheetSupport.scala
+++ b/src/library/scala/runtime/WorksheetSupport.scala
@@ -18,7 +18,7 @@ object WorksheetSupport {
protected def width = 80 // output width, by default 80 characters
protected def tabInc = 8 // tab increment, by default 8 characters
private var lastFlush: Long = 0L
- private var col = 0
+ private var col = -1
override def write(b: Array[Byte], off: Int, len: Int) = {
for (idx <- off until (off + len min b.length)) writeOne(b(idx))
flush()
@@ -35,16 +35,18 @@ object WorksheetSupport {
}
}
def writeOne(c: Int) {
- if (col == 0)
+ if (col < 0) {
+ col = 0
write((currentOffset+" ").getBytes)
+ }
out.write(c)
col =
- if (c == '\n') 0
+ if (c == '\n') -1
else if (c == '\t') (col / tabInc) * tabInc + tabInc
else col + 1
if (col >= width) writeOne('\n')
}
- def ensureNewLine() = if (col != 0) writeOne('\n')
+ def ensureNewLine() = if (col > 0) writeOne('\n')
}
private val flushedOut = new FlushedOutputStream(System.out)
@@ -73,7 +75,7 @@ object WorksheetSupport {
try op
catch {
case ex: StopException => ;
- case ex => ex.printStackTrace()
+ case ex: Throwable => ex.printStackTrace()
}
}