Skip to content

Commit 9b2ee45

Browse files
committed
Fix scala#3814 Correct highlighting issues in REPL
Correct highlighting after "|", ":", "&" characters and after "case", "val", "val" when using extractors.
1 parent 3365ed3 commit 9b2ee45

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
@@ -43,8 +43,8 @@ object SyntaxHighlighting {
4343
'q' :: 'r' :: 's' :: 't' :: 'u' :: 'v' :: 'w' :: 'x' :: 'y' :: 'z' :: Nil
4444

4545
private val typeEnders =
46-
'{' :: '}' :: ')' :: '(' :: '[' :: ']' :: '=' :: ' ' :: ',' :: '.' ::
47-
'\n' :: Nil
46+
'{' :: '}' :: ')' :: '(' :: '[' :: ']' :: '=' :: ' ' :: ',' :: '.' :: '|' ::
47+
'&' :: '\n' :: Nil
4848

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

5555
@inline def keywordStart =
5656
prev == 0 || prev == ' ' || prev == '{' || prev == '(' ||
57-
prev == '\n' || prev == '[' || prev == ','
57+
prev == '\n' || prev == '[' || prev == ',' || prev == ':' ||
58+
prev == '|' || prev == '&'
5859

5960
@inline def numberStart(c: Char) =
6061
c.isDigit && (!prev.isLetter || prev == '.' || prev == ' ' || prev == '(' || prev == '\u0000')
@@ -284,9 +285,20 @@ object SyntaxHighlighting {
284285
case ':' => true
285286
case '@' => true
286287
case '.' => true
288+
case ',' => true
289+
case ')' => true
287290
case _ => false
288291
}
289292

293+
def shouldUpdateLastToken(currentPotentialToken: String): Boolean =
294+
(lastToken, currentPotentialToken) match {
295+
case (_, ("var" | "val" | "def" | "case")) => true
296+
case (("val" | "var"), "=") => true
297+
case ("case", ("=>" | "class" | "object")) => true
298+
case ("def", _) => true
299+
case _ => false
300+
}
301+
290302
while (remaining.nonEmpty && !delim(curr)) {
291303
curr = takeChar()
292304
if (!delim(curr)) sb += curr
@@ -296,12 +308,13 @@ object SyntaxHighlighting {
296308
val toAdd =
297309
if (shouldHL(str))
298310
highlight(str)
299-
else if (("var" :: "val" :: "def" :: "case" :: Nil).contains(lastToken))
311+
else if (("var" :: "val" :: "def" :: "case" :: Nil).contains(lastToken) &&
312+
!List("=", "=>").contains(str))
300313
valDef(str)
301314
else str
302315
val suffix = if (delim(curr)) s"$curr" else ""
303316
newBuf append (toAdd + suffix)
304-
lastToken = str
317+
if (shouldUpdateLastToken(str)) lastToken = str
305318
prev = curr
306319
}
307320

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)