diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-01-15 14:11:26 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-01-15 14:11:26 -0800 |
commit | 0f784a53bcce67c760c8c1041d0f4c632fc3e5b3 (patch) | |
tree | fd3bee2bc874b8418ecb3127adcf6d33d23f50fc /src/reflect/scala/reflect/internal/util | |
parent | 0e8984100709658588c67d097452b8606c12d750 (diff) | |
parent | f606d8176e57fbb61495b693bf3cd4e77373fcfb (diff) | |
download | scala-0f784a53bcce67c760c8c1041d0f4c632fc3e5b3.tar.gz scala-0f784a53bcce67c760c8c1041d0f4c632fc3e5b3.tar.bz2 scala-0f784a53bcce67c760c8c1041d0f4c632fc3e5b3.zip |
Merge pull request #3285 from som-snytt/issue/8015-FF-NLs
Count lines by EOLs
Diffstat (limited to 'src/reflect/scala/reflect/internal/util')
-rw-r--r-- | src/reflect/scala/reflect/internal/util/Position.scala | 33 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/util/SourceFile.scala | 44 |
2 files changed, 54 insertions, 23 deletions
diff --git a/src/reflect/scala/reflect/internal/util/Position.scala b/src/reflect/scala/reflect/internal/util/Position.scala index 15cfda26b5..4032ec1157 100644 --- a/src/reflect/scala/reflect/internal/util/Position.scala +++ b/src/reflect/scala/reflect/internal/util/Position.scala @@ -202,12 +202,31 @@ private[util] trait InternalPositionImpl { def line: Int = if (hasSource) source.offsetToLine(point) + 1 else 0 def column: Int = if (hasSource) calculateColumn() else 0 def lineContent: String = if (hasSource) source.lineToString(line - 1) else "" - def lineCarat: String = if (hasSource) " " * (column - 1) + "^" else "" - - def showError(msg: String): String = finalPosition match { - case FakePos(fmsg) => s"$fmsg $msg" - case NoPosition => msg - case pos => s"${pos.line}: $msg\n${pos.lineContent}\n${pos.lineCarat}" + def lineCaret: String = if (hasSource) " " * (column - 1) + "^" else "" + @deprecated("use `lineCaret`", since="2.11.0") + def lineCarat: String = lineCaret + + def showError(msg: String): String = { + def escaped(s: String) = { + def u(c: Int) = f"\\u$c%04x" + def uable(c: Int) = (c < 0x20 && c != '\t') || c == 0x7F + if (s exists (c => uable(c))) { + val sb = new StringBuilder + s foreach (c => sb append (if (uable(c)) u(c) else c)) + sb.toString + } else s + } + def errorAt(p: Pos) = { + def where = p.line + def content = escaped(p.lineContent) + def indicator = p.lineCaret + f"$where: $msg%n$content%n$indicator" + } + finalPosition match { + case FakePos(fmsg) => s"$fmsg $msg" + case NoPosition => msg + case pos => errorAt(pos) + } } def showDebug: String = toString def show = ( @@ -254,7 +273,7 @@ private[util] trait DeprecatedPosition { @deprecated("use `finalPosition`", "2.11.0") def inUltimateSource(source: SourceFile): Position = source positionInUltimateSource this - @deprecated("use `lineCarat`", "2.11.0") + @deprecated("use `lineCaret`", since="2.11.0") def lineWithCarat(maxWidth: Int): (String, String) = ("", "") @deprecated("Use `withSource(source)` and `withShift`", "2.11.0") diff --git a/src/reflect/scala/reflect/internal/util/SourceFile.scala b/src/reflect/scala/reflect/internal/util/SourceFile.scala index 3b6c57e955..9866b043bb 100644 --- a/src/reflect/scala/reflect/internal/util/SourceFile.scala +++ b/src/reflect/scala/reflect/internal/util/SourceFile.scala @@ -16,12 +16,13 @@ import scala.reflect.internal.Chars._ /** abstract base class of a source file used in the compiler */ abstract class SourceFile { - def content : Array[Char] // normalized, must end in SU - def file : AbstractFile - def isLineBreak(idx : Int) : Boolean + def content: Array[Char] // normalized, must end in SU + def file : AbstractFile + def isLineBreak(idx: Int): Boolean + def isEndOfLine(idx: Int): Boolean def isSelfContained: Boolean def length : Int - def position(offset: Int) : Position = { + def position(offset: Int): Position = { assert(offset < length, file + ": " + offset + " >= " + length) Position.offset(this, offset) } @@ -36,8 +37,12 @@ abstract class SourceFile { override def toString() = file.name def path = file.path - def lineToString(index: Int): String = - content drop lineToOffset(index) takeWhile (c => !isLineBreakChar(c.toChar)) mkString "" + def lineToString(index: Int): String = { + val start = lineToOffset(index) + var end = start + while (!isEndOfLine(end)) end += 1 + content.slice(start, end) mkString "" + } @tailrec final def skipWhitespace(offset: Int): Int = @@ -52,6 +57,7 @@ object NoSourceFile extends SourceFile { def content = Array() def file = NoFile def isLineBreak(idx: Int) = false + def isEndOfLine(idx: Int) = false def isSelfContained = true def length = -1 def offsetToLine(offset: Int) = -1 @@ -128,18 +134,24 @@ class BatchSourceFile(val file : AbstractFile, val content0: Array[Char]) extend super.identifier(pos) } - def isLineBreak(idx: Int) = - if (idx >= length) false else { - val ch = content(idx) - // don't identify the CR in CR LF as a line break, since LF will do. - if (ch == CR) (idx + 1 == length) || (content(idx + 1) != LF) - else isLineBreakChar(ch) - } + private def charAtIsEOL(idx: Int)(p: Char => Boolean) = { + // don't identify the CR in CR LF as a line break, since LF will do. + def notCRLF0 = content(idx) != CR || idx + 1 >= length || content(idx + 1) != LF + + idx < length && notCRLF0 && p(content(idx)) + } + + def isLineBreak(idx: Int) = charAtIsEOL(idx)(isLineBreakChar) + + def isEndOfLine(idx: Int) = charAtIsEOL(idx) { + case CR | LF => true + case _ => false + } def calculateLineIndices(cs: Array[Char]) = { val buf = new ArrayBuffer[Int] buf += 0 - for (i <- 0 until cs.length) if (isLineBreak(i)) buf += i + 1 + for (i <- 0 until cs.length) if (isEndOfLine(i)) buf += i + 1 buf += cs.length // sentinel, so that findLine below works smoother buf.toArray } @@ -149,8 +161,8 @@ class BatchSourceFile(val file : AbstractFile, val content0: Array[Char]) extend private var lastLine = 0 - /** Convert offset to line in this source file - * Lines are numbered from 0 + /** Convert offset to line in this source file. + * Lines are numbered from 0. */ def offsetToLine(offset: Int): Int = { val lines = lineIndices |