Skip to content

Avoid crasher when first token of a program is in error #695

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dotty/tools/backend/jvm/DottyBackendInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{

implicit def positionHelper(a: Position): PositionHelper = new PositionHelper {
def isDefined: Boolean = a.exists
def line: Int = sourcePos(a).line
def line: Int = sourcePos(a).line + 1
def finalPosition: Position = a
}

Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ object Parsers {
case _ =>
if (mustStartStat &&
in.isAfterLineEnd() &&
isLeqIndented(in.offset, lastStatOffset))
isLeqIndented(in.offset, lastStatOffset max 0))
return
}
in.nextToken()
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/reporting/ConsoleReporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class ConsoleReporter(
printMessage(pos.lineContents.stripLineEnd)

def printColumnMarker(pos: SourcePosition) =
if (pos.exists) { printMessage(" " * (pos.column - 1) + "^") }
if (pos.exists) { printMessage(" " * pos.column + "^") }

/** Prints the message. */
def printMessage(msg: String): Unit = { writer.print(msg + "\n"); writer.flush() }
Expand Down
17 changes: 12 additions & 5 deletions src/dotty/tools/dotc/util/SourceFile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ case class SourceFile(file: AbstractFile, content: Array[Char]) {
def positionInUltimateSource(position: SourcePosition): SourcePosition =
SourcePosition(underlying, position.pos shift start)

def isLineBreak(idx: Int) =
private 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)
}

def calculateLineIndices(cs: Array[Char]) = {
private def calculateLineIndices(cs: Array[Char]) = {
val buf = new ArrayBuffer[Int]
buf += 0
for (i <- 0 until cs.length) if (isLineBreak(i)) buf += i + 1
Expand All @@ -103,22 +103,29 @@ case class SourceFile(file: AbstractFile, content: Array[Char]) {
lastLine
}

def startOfLine(offset: Int): Int = lineToOffset(offsetToLine(offset))
/** The index of the first character of the line containing position `offset` */
def startOfLine(offset: Int): Int = {
require(offset >= 0)
lineToOffset(offsetToLine(offset))
}

/** The start index of the line following the one containing position `offset` */
def nextLine(offset: Int): Int =
lineToOffset(offsetToLine(offset) + 1 min lineIndices.length - 1)

/** The contents of the line containing position `offset` */
def lineContents(offset: Int): String =
content.slice(startOfLine(offset), nextLine(offset)).mkString

/** The column corresponding to `offset`, starting at 0 */
def column(offset: Int): Int = {
var idx = startOfLine(offset)
var col = 0
while (idx != offset) {
col += (if (content(idx) == '\t') tabInc - col % tabInc else 1)
col += (if (content(idx) == '\t') (tabInc - col) % tabInc else 1)
idx += 1
}
col + 1
col
}

override def toString = file.toString
Expand Down
4 changes: 4 additions & 0 deletions src/dotty/tools/dotc/util/SourcePosition.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ case class SourcePosition(source: SourceFile, pos: Position) {
def exists = pos.exists

def lineContents: String = source.lineContents(point)

/** The line of the position, starting at 0 */
def line: Int = source.offsetToLine(point)

/** The column of the position, starting at 0 */
def column: Int = source.column(point)

override def toString =
Expand Down
1 change: 1 addition & 0 deletions test/dotc/tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ class tests extends CompilerTest {
@Test def neg_shadowedImplicits = compileFile(negDir, "arrayclone-new", xerrors = 2)
@Test def neg_traitParamsTyper = compileFile(negDir, "traitParamsTyper", xerrors = 5)
@Test def neg_traitParamsMixin = compileFile(negDir, "traitParamsMixin", xerrors = 2)
@Test def neg_firstError = compileFile(negDir, "firstError", xerrors = 3)

@Test def run_all = runFiles(runDir)

Expand Down
4 changes: 4 additions & 0 deletions tests/neg/firstError.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.

\u890u3084eu

6 changes: 3 additions & 3 deletions tests/run/origins.check
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

>> Origins tag 'boop' logged 65 calls from 3 distinguished sources.

50 Test$.$anonfun$f3$1(origins.scala:21)
10 Test$.$anonfun$f2$1(origins.scala:20)
5 Test$.$anonfun$f1$1(origins.scala:19)
50 Test$.$anonfun$f3$1(origins.scala:22)
10 Test$.$anonfun$f2$1(origins.scala:21)
5 Test$.$anonfun$f1$1(origins.scala:20)