From c873dc420823b10a8e502a1b7880f47b7f297641 Mon Sep 17 00:00:00 2001 From: Philippus Date: Wed, 14 Nov 2018 21:39:02 +0100 Subject: [PATCH] Take into account leading and trailing line endings --- .../util/parsing/input/OffsetPosition.scala | 15 ++++---- .../parsing/input/OffsetPositionTest.scala | 38 ++++++++++++++++++- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/shared/src/main/scala/scala/util/parsing/input/OffsetPosition.scala b/shared/src/main/scala/scala/util/parsing/input/OffsetPosition.scala index f8c573b0..b24ed35e 100644 --- a/shared/src/main/scala/scala/util/parsing/input/OffsetPosition.scala +++ b/shared/src/main/scala/scala/util/parsing/input/OffsetPosition.scala @@ -34,14 +34,13 @@ case class OffsetPosition(source: CharSequence, offset: Int) extends Position { private def genIndex: Array[Int] = { val lineStarts = new ArrayBuffer[Int] - lineStarts += 0 // first line - for (i <- 1 until source.length) { - if (source.charAt(i - 1) == '\n') // \n or \r\n - lineStarts += i - else if (source.charAt(i - 1) == '\r' && source.charAt(i) != '\n') // \r but not \r\n - lineStarts += i - } - lineStarts += source.length // eof + lineStarts += 0 + for (i <- 0 until source.length) + if (source.charAt(i) == '\n' || + (source.charAt(i) == '\r' && (i == (source.length - 1) || source.charAt(i + 1) != '\n'))) { + lineStarts += (i + 1) + } + lineStarts += source.length lineStarts.toArray } diff --git a/shared/src/test/scala/scala/util/parsing/input/OffsetPositionTest.scala b/shared/src/test/scala/scala/util/parsing/input/OffsetPositionTest.scala index cda8f6f0..76085a83 100644 --- a/shared/src/test/scala/scala/util/parsing/input/OffsetPositionTest.scala +++ b/shared/src/test/scala/scala/util/parsing/input/OffsetPositionTest.scala @@ -18,7 +18,7 @@ class OffsetPositionTest { @Test def lineContentsWithTrailingCRLF: Unit = { - val op = new OffsetPosition("\r\n", 1) + val op = new OffsetPosition("\r\n", 2) assertEquals("", op.lineContents) } @@ -45,4 +45,40 @@ class OffsetPositionTest { val op = new OffsetPosition("foo\r\nbar", 5) assertEquals(2, op.line) } + + @Test + def linesWithTrailingLFs: Unit = { + val op = new OffsetPosition("foo\n\n", 5) + assertEquals(3, op.line) + } + + @Test + def linesWithTrailingCRs: Unit = { + val op = new OffsetPosition("foo\r\r", 5) + assertEquals(3, op.line) + } + + @Test + def linesWithTrailingCRLFs: Unit = { + val op = new OffsetPosition("foo\r\n\r\n", 7) + assertEquals(3, op.line) + } + + @Test + def linesWithLeadingLF: Unit = { + val op = new OffsetPosition("\n", 1) + assertEquals(2, op.line) + } + + @Test + def linesWithLeadingCR: Unit = { + val op = new OffsetPosition("\r", 1) + assertEquals(2, op.line) + } + + @Test + def linesWithLeadingCRLF: Unit = { + val op = new OffsetPosition("\r\n", 2) + assertEquals(2, op.line) + } }