Skip to content

Commit 6d8e627

Browse files
committed
Fix #3814 Correct highlighting issues in REPL
Correct highlighting after "|", ":", "&" characters and after "case", "val", "val" when using extractors.
1 parent 4ca71e0 commit 6d8e627

File tree

5 files changed

+129
-5
lines changed

5 files changed

+129
-5
lines changed

compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ object SyntaxHighlighting {
4242
'q' :: 'r' :: 's' :: 't' :: 'u' :: 'v' :: 'w' :: 'x' :: 'y' :: 'z' :: Nil
4343

4444
private val typeEnders =
45-
'{' :: '}' :: ')' :: '(' :: '[' :: ']' :: '=' :: ' ' :: ',' :: '.' ::
46-
'\n' :: Nil
45+
'{' :: '}' :: ')' :: '(' :: '[' :: ']' :: '=' :: ' ' :: ',' :: '.' :: '|' ::
46+
'&' :: '\n' :: Nil
4747

4848
def apply(chars: Iterable[Char]): Iterable[Char] = {
4949
var prev: Char = 0
@@ -53,7 +53,8 @@ object SyntaxHighlighting {
5353

5454
@inline def keywordStart =
5555
prev == 0 || prev == ' ' || prev == '{' || prev == '(' ||
56-
prev == '\n' || prev == '[' || prev == ','
56+
prev == '\n' || prev == '[' || prev == ',' || prev == ':' ||
57+
prev == '|' || prev == '&'
5758

5859
@inline def numberStart(c: Char) =
5960
c.isDigit && (!prev.isLetter || prev == '.' || prev == ' ' || prev == '(' || prev == '\u0000')
@@ -286,9 +287,20 @@ object SyntaxHighlighting {
286287
case '@' => true
287288
case ',' => true
288289
case '.' => true
290+
case ',' => true
291+
case ')' => true
289292
case _ => false
290293
}
291294

295+
def shouldUpdateLastToken(currentPotentialToken: String): Boolean =
296+
(lastToken, currentPotentialToken) match {
297+
case (_, ("var" | "val" | "def" | "case")) => true
298+
case (("val" | "var"), "=") => true
299+
case ("case", ("=>" | "class" | "object")) => true
300+
case ("def", _) => true
301+
case _ => false
302+
}
303+
292304
while (remaining.nonEmpty && !delim(curr)) {
293305
curr = takeChar()
294306
if (!delim(curr)) sb += curr
@@ -298,12 +310,13 @@ object SyntaxHighlighting {
298310
val toAdd =
299311
if (shouldHL(str))
300312
highlight(str)
301-
else if (("var" :: "val" :: "def" :: "case" :: Nil).contains(lastToken))
313+
else if (("var" :: "val" :: "def" :: "case" :: Nil).contains(lastToken) &&
314+
!List("=", "=>").contains(str))
302315
valDef(str)
303316
else str
304317
val suffix = if (delim(curr)) s"$curr" else ""
305318
newBuf append (toAdd + suffix)
306-
lastToken = str
319+
if (shouldUpdateLastToken(str)) lastToken = str
307320
prev = curr
308321
}
309322

compiler/test-resources/printing/defs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package test
2+
3+
object A {
4+
val a = 123
5+
var b = 123 /*Int*/
6+
var c = "123" // String
7+
var d: Int = 123
8+
var e:Int = 123;e
9+
e
10+
print(a)
11+
123;123
12+
def f = 123
13+
def f1(x: Int) = 123
14+
def f2[T](x: T) = { 123 }
15+
}
16+
result:
17+
package test
18+
19+
object A {
20+
val a = 123
21+
var b = 123 /*Int*/
22+
var c = "123" // String
23+
 var d: Int = 123
24+
var e:Int = 123;e
25+
e
26+
print(a)
27+
123;123
28+
def f = 123
29+
def f1(x: Int) = 123
30+
def f2[T](x: T) = { 123 }
31+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
val aFruit: Fruit = Apple("red", 123)
2+
3+
val Apple(color, weight) = aFruit
4+
5+
sealed trait Fruit
6+
case class Apple(color: String, weight: Double) extends Fruit
7+
case class Orange(weight: Double) extends Fruit
8+
case class Melon(weight: Double) extends Fruit
9+
10+
aFruit match {
11+
case Apple(_, weight) => println(s"apple: $weight kgs")
12+
case o: Orange => println(s"orange ${o.weight} kgs")
13+
case m @ Melon(weight) => println(s"melon: ${m.weight} kgs")
14+
}
15+
result:
16+
val aFruit: Fruit = Apple("red", 123)
17+
18+
val Apple(color, weight) = aFruit
19+
20+
sealed trait Fruit
21+
case class Apple(color: String, weight: Double) extends Fruit
22+
case class Orange(weight: Double) extends Fruit
23+
case class Melon(weight: Double) extends Fruit
24+
25+
aFruit match {
26+
case Apple(_, weight) => println(s"apple: $weight kgs")
27+
case o: Orange => println(s"orange ${o.weight} kgs")
28+
case m @ Melon(weight) => println(s"melon: ${m.weight} kgs")
29+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
type A = String|Int| Long
2+
type B = String |Int| Long
3+
type C = String | Int | Long
4+
type D = String&Int& Long
5+
type E = String &Int& Long
6+
type F = String & Int & Long
7+
fn[String|Char](input)
8+
result:
9+
type A = String|Int| Long
10+
type B = String |Int| Long
11+
type C = String | Int | Long
12+
type D = String&Int& Long
13+
type E = String &Int& Long
14+
type F = String & Int & Long
15+
fn[String|Char](input)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package dotty.tools.dotc.printing
2+
3+
import dotty.tools.io.JFile
4+
import org.junit.Test
5+
import org.junit.Assert.fail
6+
7+
import scala.io.Source
8+
9+
/** Runs all tests contained in `compiler/test-resources/printing/`
10+
* To check test cases, you can use "cat" or "less -r" from bash*/
11+
class SyntaxHighlightingTests {
12+
13+
private def scripts(path: String): Array[JFile] = {
14+
val dir = new JFile(getClass.getResource(path).getPath)
15+
assert(dir.exists && dir.isDirectory, "Couldn't load scripts dir")
16+
dir.listFiles
17+
}
18+
19+
private def testFile(f: JFile): Unit = {
20+
val linesIt = Source.fromFile(f).getLines()
21+
val input = linesIt.takeWhile(_ != "result:").mkString("\n")
22+
val expectedOutput = linesIt.mkString("\n")
23+
val actualOutput = SyntaxHighlighting(input).mkString
24+
25+
if (expectedOutput != actualOutput) {
26+
println("Expected output:")
27+
println(expectedOutput)
28+
println("Actual output:")
29+
println(actualOutput)
30+
31+
fail(s"Error in file $f, expected output did not match actual")
32+
}
33+
}
34+
35+
@Test def syntaxHighlight = scripts("/printing").foreach(testFile)
36+
}

0 commit comments

Comments
 (0)