Skip to content

Commit 9edb26a

Browse files
committed
fix-#4405 REPL highlight for StringLiteral
1 parent 5d004dc commit 9edb26a

File tree

1 file changed

+38
-17
lines changed

1 file changed

+38
-17
lines changed

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

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@ object SyntaxHighlighting {
3434
index <- IF to ERASED // All alpha keywords
3535
} yield tokenString(index)
3636

37-
private val interpolationPrefixes =
38-
'A' :: 'B' :: 'C' :: 'D' :: 'E' :: 'F' :: 'G' :: 'H' :: 'I' :: 'J' :: 'K' ::
39-
'L' :: 'M' :: 'N' :: 'O' :: 'P' :: 'Q' :: 'R' :: 'S' :: 'T' :: 'U' :: 'V' ::
40-
'W' :: 'X' :: 'Y' :: 'Z' :: '$' :: '_' :: 'a' :: 'b' :: 'c' :: 'd' :: 'e' ::
41-
'f' :: 'g' :: 'h' :: 'i' :: 'j' :: 'k' :: 'l' :: 'm' :: 'n' :: 'o' :: 'p' ::
42-
'q' :: 'r' :: 's' :: 't' :: 'u' :: 'v' :: 'w' :: 'x' :: 'y' :: 'z' :: Nil
4337

4438
private val typeEnders =
4539
'{' :: '}' :: ')' :: '(' :: '[' :: ']' :: '=' :: ' ' :: ',' :: '.' :: '|' ::
@@ -66,16 +60,44 @@ object SyntaxHighlighting {
6660
taken
6761
}
6862

63+
def isUpper(c: Char) = c.isUpper || c == '_' || c == '$'
64+
65+
def opChar(c:Char) = (c: @switch) match {
66+
case '~' | '!' | '@' | '#' | '%' |
67+
'^' | '*' | '+' | '-' | '<' |
68+
'>' | '?' | ':' | '=' | '&' |
69+
'|' | '\\' | '/' => true
70+
case _ => false
71+
}
72+
73+
def tryInterpolatorPrefix(n: Char, remaining: Stream[Char]): Option[String] = {
74+
if (isUpper(n) || n.isLower) {
75+
val beforeUnderscore = remaining.takeWhile(c =>
76+
c.isUpper || c.isLower || c.isDigit
77+
)
78+
val suffix = remaining.drop(beforeUnderscore.length) match {
79+
case '_' +: afterUnderscore => '_' +: afterUnderscore.drop(1).takeWhile(opChar)
80+
case _ => Seq.empty
81+
}
82+
Some(((n +: beforeUnderscore) ++ suffix).mkString)
83+
} else {
84+
None
85+
}
86+
}
87+
88+
6989
while (remaining.nonEmpty) {
7090
val n = takeChar()
71-
if (interpolationPrefixes.contains(n)) {
72-
// Interpolation prefixes are a superset of the keyword start chars
73-
val next = remaining.take(3).mkString
74-
if (next.startsWith("\"")) {
75-
newBuf += n
76-
prev = n
77-
if (remaining.nonEmpty) takeChar() // drop 1 for appendLiteral
78-
appendString('"', next == "\"\"\"")
91+
92+
val optInterpPrefix = tryInterpolatorPrefix(n, remaining)
93+
if (optInterpPrefix.isDefined) {
94+
val interpPrefix: String = optInterpPrefix.get
95+
val after = remaining.drop(interpPrefix.length - 1).take(3).mkString
96+
if (after.startsWith("\"")) {
97+
newBuf ++= interpPrefix
98+
prev = interpPrefix.last
99+
if (remaining.nonEmpty) takeChars(interpPrefix.length)
100+
appendString('"', after == "\"\"\"", inInterpolation = true)
79101
} else {
80102
if (n.isUpper && (keywordStart || prev == '.')) {
81103
appendWhile(n, !typeEnders.contains(_), typeDef)
@@ -116,7 +138,7 @@ object SyntaxHighlighting {
116138
case '@' =>
117139
appendWhile('@', !typeEnders.contains(_), annotation)
118140
case '\"' =>
119-
appendString('\"', multiline = remaining.take(2).mkString == "\"\"")
141+
appendString('\"', multiline = remaining.take(2).mkString == "\"\"", false)
120142
case '\'' =>
121143
appendSingleQuote('\'')
122144
case '`' =>
@@ -181,11 +203,10 @@ object SyntaxHighlighting {
181203
newBuf append NoColor
182204
}
183205

184-
def appendString(delim: Char, multiline: Boolean = false) = {
206+
def appendString(delim: Char, multiline: Boolean = false, inInterpolation: Boolean) = {
185207
var curr: Char = 0
186208
var continue = true
187209
var closing = 0
188-
val inInterpolation = interpolationPrefixes.contains(prev)
189210
newBuf append (LiteralColor + delim)
190211

191212
def shouldInterpolate =

0 commit comments

Comments
 (0)