From 24be4fba1e18a68d3c66ec83a3c9a3ec6d08b928 Mon Sep 17 00:00:00 2001 From: Armin Wiebigke Date: Wed, 4 Sep 2024 20:46:46 +0200 Subject: [PATCH] Add linesIterator implementation `linesIterator` from Scala is not consistent for our cross-compiled versions, so we provide an explicit implementation (copied from Scala 2.13.14 StringOps.scala). --- .../sangria/renderer/QueryRenderer.scala | 5 ++-- .../main/scala/sangria/util/StringUtil.scala | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/modules/core/src/main/scala/sangria/renderer/QueryRenderer.scala b/modules/core/src/main/scala/sangria/renderer/QueryRenderer.scala index b12e86e7..9967daed 100644 --- a/modules/core/src/main/scala/sangria/renderer/QueryRenderer.scala +++ b/modules/core/src/main/scala/sangria/renderer/QueryRenderer.scala @@ -1,8 +1,7 @@ package sangria.renderer -import sangria.ast.AstLocation -import sangria.util.StringUtil.{escapeBlockString, escapeString} import sangria.ast._ +import sangria.util.StringUtil.{escapeBlockString, escapeString, linesIterator} object QueryRenderer { val Pretty: QueryRendererConfig = QueryRendererConfig( @@ -477,7 +476,7 @@ object QueryRenderer { extraIndent: Boolean = true): String = if (node.value.trim.nonEmpty) { val ind = if (extraIndent) indent.incForce.str else indent.strForce - val lines = escapeBlockString(node.value).linesIterator.map { line => + val lines = linesIterator(escapeBlockString(node.value)).map { line => if (line.isEmpty) line // do not output lines with only whitespaces inside else ind + line } diff --git a/modules/core/src/main/scala/sangria/util/StringUtil.scala b/modules/core/src/main/scala/sangria/util/StringUtil.scala index 626b894f..2c6040b6 100644 --- a/modules/core/src/main/scala/sangria/util/StringUtil.scala +++ b/modules/core/src/main/scala/sangria/util/StringUtil.scala @@ -3,6 +3,7 @@ package sangria.util import sangria.since3_0_0 import java.util.Locale +import scala.collection.AbstractIterator import scala.collection.mutable.ListBuffer object StringUtil { @@ -110,6 +111,30 @@ object StringUtil { def charHex(ch: Char): String = Integer.toHexString(ch).toUpperCase(Locale.ENGLISH) + // Redefine `linesIterator`, since the implementation provided by Scala is not consistent for our + // cross-compiled versions + def linesIterator(string: String): Iterator[String] = new AbstractIterator[String] { + def hasNext: Boolean = !done + def next(): String = if (done) Iterator.empty.next() else advance() + + private def isLineBreak(c: Char) = c == '\r' || c == '\n' + private def isWindowsLineBreak(c1: Char, c2: Char) = c1 == '\r' && c2 == '\n' + private[this] val len = string.length + private[this] var index = 0 + @`inline` private def done: Boolean = index >= len + private def advance(): String = { + val start = index + while (!done && !isLineBreak(string.charAt(index))) index += 1 + val end = index + if (!done) { + val c = string.charAt(index) + index += 1 + if (!done && isWindowsLineBreak(c, string.charAt(index))) index += 1 + } + string.substring(start, end) + } + } + /** Produces the value of a block string from its parsed raw value, similar to Coffeescript's * block string, Python's docstring trim or Ruby's strip_heredoc. *