From 1898a5e166308bb38d3979f0cf64846fe4210709 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 3 Apr 2025 03:19:33 -0700 Subject: [PATCH] Test chars safely when highlighting The arrow test at lastOffset - 3 is out-of-range when highlighting, which parses a snippet of source. --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 7 +++++-- compiler/test/dotty/tools/utils.scala | 2 ++ tests/neg/i22906.check | 6 ++++++ tests/neg/i22906.scala | 5 +++++ 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 tests/neg/i22906.check create mode 100644 tests/neg/i22906.scala diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 1610362c3323..ec3ec06599e6 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -641,7 +641,7 @@ object Parsers { def inBracesOrIndented[T](body: => T, rewriteWithColon: Boolean = false): T = if in.token == INDENT then val rewriteToBraces = in.rewriteNoIndent - && !testChars(in.lastOffset - 3, " =>") // braces are always optional after `=>` so none should be inserted + && !testCharsSafe(in.lastOffset - 3, " =>") // braces are optional after `=>` so none should be inserted if rewriteToBraces then indentedToBraces(body) else enclosed(INDENT, body) else @@ -744,6 +744,9 @@ object Parsers { str.isEmpty || testChar(from, str.head) && testChars(from + 1, str.tail) + def testCharsSafe(from: Int, str: String): Boolean = + from >= 0 && testChars(from, str) + def skipBlanks(idx: Int, step: Int = 1): Int = if (testChar(idx, c => c == ' ' || c == '\t' || c == Chars.CR)) skipBlanks(idx + step, step) else idx @@ -860,7 +863,7 @@ object Parsers { case _ => false } var canRewrite = allBraces(in.currentRegion) && // test (1) - !testChars(in.lastOffset - 3, " =>") // test(6) + !testCharsSafe(in.lastOffset - 3, " =>") // test(6) def isStartOfSymbolicFunction: Boolean = opStack.headOption.exists { x => diff --git a/compiler/test/dotty/tools/utils.scala b/compiler/test/dotty/tools/utils.scala index c33310acf06e..03e25630c421 100644 --- a/compiler/test/dotty/tools/utils.scala +++ b/compiler/test/dotty/tools/utils.scala @@ -124,6 +124,7 @@ private val toolArg = raw"(?://|/\*| \*) ?(?i:(${ToolName.values.mkString("|")}) private val directiveOptionsArg = raw"//> using options (.*)".r.unanchored private val directiveJavacOptions = raw"//> using javacOpt (.*)".r.unanchored private val directiveTargetOptions = raw"//> using target.platform (jvm|scala-js)".r.unanchored +private val directiveUnsupported = raw"//> using (scala) (.*)".r.unanchored private val directiveUnknown = raw"//> using (.*)".r.unanchored // Inspect the lines for compiler options of the form @@ -141,6 +142,7 @@ def toolArgsParse(lines: List[String], filename: Option[String]): List[(String,S case directiveOptionsArg(args) => List(("scalac", args)) case directiveJavacOptions(args) => List(("javac", args)) case directiveTargetOptions(platform) => List(("target", platform)) + case directiveUnsupported(name, args) => Nil case directiveUnknown(rest) => sys.error(s"Unknown directive: `//> using ${CommandLineParser.tokenize(rest).headOption.getOrElse("''")}`${filename.fold("")(f => s" in file $f")}") case _ => Nil } diff --git a/tests/neg/i22906.check b/tests/neg/i22906.check new file mode 100644 index 000000000000..f2ada0674f5a --- /dev/null +++ b/tests/neg/i22906.check @@ -0,0 +1,6 @@ +Flag -indent set repeatedly +-- Error: tests/neg/i22906.scala:5:15 ---------------------------------------------------------------------------------- +5 | {`1`: Int => 5} // error + | ^ + | parentheses are required around the parameter of a lambda + | This construct can be rewritten automatically under -rewrite -source 3.0-migration. diff --git a/tests/neg/i22906.scala b/tests/neg/i22906.scala new file mode 100644 index 000000000000..f94df913342a --- /dev/null +++ b/tests/neg/i22906.scala @@ -0,0 +1,5 @@ +//> using scala 3.7.0-RC1 +//> using options -rewrite -indent + +def program: Int => Int = + {`1`: Int => 5} // error