From e9f9c8ae9edf9f2ad8b56b2dd2c4b954a88baa03 Mon Sep 17 00:00:00 2001 From: Philippus Date: Thu, 5 Jul 2018 23:55:46 +0200 Subject: [PATCH 1/3] Switch assertEquals parameters, expected goes before actual --- .../scala/scala/util/parsing/input/OffsetPositionTest.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 bbd9c9c4..d2ca696f 100644 --- a/shared/src/test/scala/scala/util/parsing/input/OffsetPositionTest.scala +++ b/shared/src/test/scala/scala/util/parsing/input/OffsetPositionTest.scala @@ -7,12 +7,12 @@ class OffsetPositionTest { @Test def printLineContentsWithTrailingNewLine: Unit = { val op = new OffsetPosition("\n", 1) - assertEquals(op.lineContents, "") + assertEquals("", op.lineContents) } @Test def printLineContentsWithEmptySource: Unit = { val op = new OffsetPosition("", 0) - assertEquals(op.lineContents, "") + assertEquals("", op.lineContents) } } From 77ffd919453b2741ca8a085fea1866cf6ee7121a Mon Sep 17 00:00:00 2001 From: Philippus Date: Fri, 6 Jul 2018 00:00:00 +0200 Subject: [PATCH 2/3] Support '\r' and '\r\n' line endings, closes scala/bug#5669 --- .../util/parsing/input/OffsetPosition.scala | 25 +++++++++----- .../scala/util/parsing/combinator/t5669.scala | 14 ++++++++ .../parsing/input/OffsetPositionTest.scala | 34 +++++++++++++++++-- 3 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 shared/src/test/scala/scala/util/parsing/combinator/t5669.scala 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 cb72ec80..327716fd 100644 --- a/shared/src/main/scala/scala/util/parsing/input/OffsetPosition.scala +++ b/shared/src/main/scala/scala/util/parsing/input/OffsetPosition.scala @@ -34,10 +34,14 @@ case class OffsetPosition(source: CharSequence, offset: Int) extends Position { private def genIndex: Array[Int] = { val lineStarts = new ArrayBuffer[Int] - lineStarts += 0 - for (i <- 0 until source.length) - if (source.charAt(i) == '\n') lineStarts += (i + 1) - lineStarts += source.length + lineStarts += 0 // first line + for (i <- 0 until source.length) { + if (i >= 1 && source.charAt(i - 1) == '\n') // \n or \r\n + lineStarts += i + else if (i >= 1 && source.charAt(i - 1) == '\r' && source.charAt(i) != '\n') // \r but not \r\n + lineStarts += i + } + lineStarts += source.length // eof lineStarts.toArray } @@ -63,11 +67,14 @@ case class OffsetPosition(source: CharSequence, offset: Int) extends Position { def lineContents: String = { val lineStart = index(line - 1) val lineEnd = index(line) - val endIndex = if ( lineStart < lineEnd && source.charAt(lineEnd - 1) == '\n') { - lineEnd - 1 - } else { - lineEnd - } + val endIndex = + if (lineStart < lineEnd - 1 && source.charAt(lineEnd - 2) == '\r' && source.charAt(lineEnd - 1) == '\n') { + lineEnd - 2 + } else if (lineStart < lineEnd && (source.charAt(lineEnd - 1) == '\r' || source.charAt(lineEnd - 1) == '\n')) { + lineEnd - 1 + } else { + lineEnd + } source.subSequence(lineStart, endIndex).toString } diff --git a/shared/src/test/scala/scala/util/parsing/combinator/t5669.scala b/shared/src/test/scala/scala/util/parsing/combinator/t5669.scala new file mode 100644 index 00000000..a03f4d6a --- /dev/null +++ b/shared/src/test/scala/scala/util/parsing/combinator/t5669.scala @@ -0,0 +1,14 @@ +package scala.util.parsing.combinator + +import scala.util.parsing.input.OffsetPosition + +import org.junit.Test +import org.junit.Assert.assertEquals + +class t5669 { + @Test + def test: Unit = { + val op = new OffsetPosition("foo\rbar", 4) + assertEquals(2, op.line) + } +} 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 d2ca696f..cda8f6f0 100644 --- a/shared/src/test/scala/scala/util/parsing/input/OffsetPositionTest.scala +++ b/shared/src/test/scala/scala/util/parsing/input/OffsetPositionTest.scala @@ -5,14 +5,44 @@ import org.junit.Assert.assertEquals class OffsetPositionTest { @Test - def printLineContentsWithTrailingNewLine: Unit = { + def lineContentsWithTrailingLF: Unit = { val op = new OffsetPosition("\n", 1) assertEquals("", op.lineContents) } @Test - def printLineContentsWithEmptySource: Unit = { + def lineContentsWithTrailingCR: Unit = { + val op = new OffsetPosition("\r", 1) + assertEquals("", op.lineContents) + } + + @Test + def lineContentsWithTrailingCRLF: Unit = { + val op = new OffsetPosition("\r\n", 1) + assertEquals("", op.lineContents) + } + + @Test + def lineContentsWithEmptySource: Unit = { val op = new OffsetPosition("", 0) assertEquals("", op.lineContents) } + + @Test + def linesWithLF: Unit = { + val op = new OffsetPosition("foo\nbar", 4) + assertEquals(2, op.line) + } + + @Test + def linesWithCR: Unit = { + val op = new OffsetPosition("foo\rbar", 4) + assertEquals(2, op.line) + } + + @Test + def linesWithCRLF: Unit = { + val op = new OffsetPosition("foo\r\nbar", 5) + assertEquals(2, op.line) + } } From 7fe289713326c3777d147d627d3232a71d31a26f Mon Sep 17 00:00:00 2001 From: Philippus Date: Wed, 11 Jul 2018 16:53:50 +0200 Subject: [PATCH 3/3] Start for loop from 1 --- .../scala/scala/util/parsing/input/OffsetPosition.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 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 327716fd..f8c573b0 100644 --- a/shared/src/main/scala/scala/util/parsing/input/OffsetPosition.scala +++ b/shared/src/main/scala/scala/util/parsing/input/OffsetPosition.scala @@ -35,10 +35,10 @@ 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 <- 0 until source.length) { - if (i >= 1 && source.charAt(i - 1) == '\n') // \n or \r\n + for (i <- 1 until source.length) { + if (source.charAt(i - 1) == '\n') // \n or \r\n lineStarts += i - else if (i >= 1 && source.charAt(i - 1) == '\r' && source.charAt(i) != '\n') // \r but not \r\n + else if (source.charAt(i - 1) == '\r' && source.charAt(i) != '\n') // \r but not \r\n lineStarts += i } lineStarts += source.length // eof