Skip to content

Commit 8dc30f4

Browse files
slothspotallanrenucci
authored andcommitted
Remove old highlighter code and ignore tests with unsupported features
1 parent f1662d6 commit 8dc30f4

File tree

5 files changed

+10
-348
lines changed

5 files changed

+10
-348
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ object Formatting {
8484
case hb: HighlightBuffer =>
8585
hb.toString
8686
case str: String if ctx.settings.color.value != "never" =>
87-
new String(SyntaxHighlighting(str).toArray)
87+
SyntaxHighlighting.highlight(str)(ctx)
8888
case _ => super.showArg(arg)
8989
}
9090
}

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

Lines changed: 1 addition & 343 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ import dotty.tools.dotc.reporting.Reporter
1111
import dotty.tools.dotc.reporting.diagnostic.MessageContainer
1212
import dotty.tools.dotc.util.Positions.Position
1313

14-
import scala.annotation.switch
15-
import scala.collection.mutable.StringBuilder
16-
import util.{Chars, SourceFile}
14+
import util.SourceFile
1715

1816
import scala.collection.mutable
1917

@@ -30,346 +28,6 @@ object SyntaxHighlighting {
3028
val TypeColor = Console.MAGENTA
3129
val AnnotationColor = Console.MAGENTA
3230

33-
private def none(str: String) = str
34-
private def keyword(str: String) = KeywordColor + str + NoColor
35-
private def typeDef(str: String) = TypeColor + str + NoColor
36-
private def literal(str: String) = LiteralColor + str + NoColor
37-
private def valDef(str: String) = ValDefColor + str + NoColor
38-
private def operator(str: String) = TypeColor + str + NoColor
39-
private def annotation(str: String) =
40-
if (str.trim == "@") str else { AnnotationColor + str + NoColor }
41-
private val tripleQs = Console.RED_B + "???" + NoColor
42-
43-
private val keywords: Seq[String] = for {
44-
index <- IF to ERASED // All alpha keywords
45-
} yield tokenString(index)
46-
47-
private val interpolationPrefixes =
48-
'A' :: 'B' :: 'C' :: 'D' :: 'E' :: 'F' :: 'G' :: 'H' :: 'I' :: 'J' :: 'K' ::
49-
'L' :: 'M' :: 'N' :: 'O' :: 'P' :: 'Q' :: 'R' :: 'S' :: 'T' :: 'U' :: 'V' ::
50-
'W' :: 'X' :: 'Y' :: 'Z' :: '$' :: '_' :: 'a' :: 'b' :: 'c' :: 'd' :: 'e' ::
51-
'f' :: 'g' :: 'h' :: 'i' :: 'j' :: 'k' :: 'l' :: 'm' :: 'n' :: 'o' :: 'p' ::
52-
'q' :: 'r' :: 's' :: 't' :: 'u' :: 'v' :: 'w' :: 'x' :: 'y' :: 'z' :: Nil
53-
54-
private val typeEnders =
55-
'{' :: '}' :: ')' :: '(' :: '[' :: ']' :: '=' :: ' ' :: ',' :: '.' :: '|' ::
56-
'&' :: '\n' :: Nil
57-
58-
def apply(chars: Iterable[Char])(implicit ctx: Context): Iterable[Char] = {
59-
if (ctx.settings.color.value != "never") highlight(chars)
60-
else chars
61-
}
62-
63-
def highlight(chars: Iterable[Char]): Iterable[Char] = {
64-
var prev: Char = 0
65-
var remaining = chars.toStream
66-
val newBuf = new StringBuilder
67-
var lastValDefToken = ""
68-
69-
@forceInline def keywordStart =
70-
prev == 0 || prev == ' ' || prev == '{' || prev == '(' ||
71-
prev == '\n' || prev == '[' || prev == ',' || prev == ':' ||
72-
prev == '|' || prev == '&' || prev.isDigit
73-
74-
@forceInline def numberStart(c: Char) =
75-
c.isDigit && (!prev.isLetter || prev == '.' || prev == ' ' || prev == '(' || prev == '\u0000')
76-
77-
def takeChar(): Char = takeChars(1).head
78-
def takeChars(x: Int): Seq[Char] = {
79-
val taken = remaining.take(x)
80-
remaining = remaining.drop(x)
81-
taken
82-
}
83-
84-
while (remaining.nonEmpty) {
85-
val n = takeChar()
86-
if (interpolationPrefixes.contains(n)) {
87-
// Interpolation prefixes are a superset of the keyword start chars
88-
val (prefix, after) = remaining.span(interpolationPrefixes.contains)
89-
if (after.startsWith("\"")) {
90-
newBuf += n ++= prefix
91-
prev = prefix.lastOption.getOrElse(n)
92-
if (remaining.nonEmpty) takeChars(prefix.length + 1) // drop 1 for appendLiteral
93-
appendString('"', after.startsWith("\"\"\""), true)
94-
} else {
95-
if (n.isUpper && (keywordStart || prev == '.')) {
96-
appendWhile(n, !typeEnders.contains(_), typeDef)
97-
} else if (keywordStart) {
98-
append(n, keywords.contains(_), { kw =>
99-
if (kw == "new") typeDef(kw) else keyword(kw)
100-
})
101-
} else {
102-
newBuf += n
103-
prev = n
104-
}
105-
}
106-
} else {
107-
(n: @switch) match {
108-
case '/' =>
109-
if (remaining.nonEmpty) {
110-
remaining.head match {
111-
case '/' =>
112-
takeChar()
113-
eolComment()
114-
case '*' =>
115-
takeChar()
116-
blockComment()
117-
case x =>
118-
newBuf += '/'
119-
}
120-
} else newBuf += '/'
121-
case '=' =>
122-
append('=', _ == "=>", operator)
123-
case '<' =>
124-
append('<', { x => x == "<-" || x == "<:" || x == "<%" }, operator)
125-
case '>' =>
126-
append('>', { x => x == ">:" }, operator)
127-
case '#' =>
128-
if (prev != ' ' && prev != '.') newBuf append operator("#")
129-
else newBuf += n
130-
prev = '#'
131-
case '@' =>
132-
appendWhile('@', !typeEnders.contains(_), annotation)
133-
case '\"' =>
134-
appendString('\"', multiline = remaining.take(2).mkString == "\"\"", false)
135-
case '\'' =>
136-
appendSingleQuote('\'')
137-
case '`' =>
138-
appendTo('`', _ == '`', none)
139-
case _ => {
140-
if (n == '?' && remaining.take(2).mkString == "??") {
141-
takeChars(2)
142-
newBuf append tripleQs
143-
prev = '?'
144-
}
145-
else if (n.isUpper && keywordStart)
146-
appendWhile(n, !typeEnders.contains(_), typeDef)
147-
else if (numberStart(n)) {
148-
def isNumber(c: Char): Boolean =
149-
c.isDigit || c == '\u0000' || (c == '.' && remaining.nonEmpty && remaining.head.isDigit)
150-
appendWhile(n, isNumber, literal)
151-
} else
152-
newBuf += n; prev = n
153-
}
154-
}
155-
}
156-
}
157-
158-
def eolComment() = {
159-
newBuf append (CommentColor + "//")
160-
var curr = '/'
161-
while (curr != '\n' && remaining.nonEmpty) {
162-
curr = takeChar()
163-
newBuf += curr
164-
}
165-
prev = curr
166-
newBuf append NoColor
167-
}
168-
169-
def blockComment() = {
170-
newBuf append (CommentColor + "/*")
171-
var curr = '*'
172-
var open = 1
173-
while (open > 0 && remaining.nonEmpty) {
174-
curr = takeChar()
175-
if (curr == '@') {
176-
appendWhile('@', !typeEnders.contains(_), annotation)
177-
newBuf append CommentColor
178-
}
179-
else newBuf += curr
180-
181-
if (curr == '*' && remaining.nonEmpty) {
182-
curr = takeChar()
183-
newBuf += curr
184-
if (curr == '/') open -= 1
185-
} else if (curr == '/' && remaining.nonEmpty) {
186-
curr = takeChar()
187-
newBuf += curr
188-
if (curr == '*') open += 1
189-
}
190-
191-
if (Chars.isLineBreakChar(curr)) {
192-
newBuf append CommentColor
193-
}
194-
}
195-
prev = curr
196-
newBuf append NoColor
197-
}
198-
199-
def appendString(delim: Char, multiline: Boolean = false, inInterpolation: Boolean) = {
200-
var curr: Char = 0
201-
var continue = true
202-
var closing = 0
203-
newBuf append (LiteralColor + delim)
204-
205-
def shouldInterpolate =
206-
inInterpolation && curr == '$' && prev != '$' && remaining.nonEmpty
207-
208-
def interpolate() = {
209-
val next = takeChar()
210-
if (next == '$') {
211-
newBuf += curr
212-
newBuf += next
213-
prev = '$'
214-
} else if (next == '{') {
215-
var open = 1 // keep track of open blocks
216-
newBuf append (ValDefColor + curr)
217-
newBuf += next
218-
while (remaining.nonEmpty && open > 0) {
219-
var c = takeChar()
220-
newBuf += c
221-
if (c == '}') open -= 1
222-
else if (c == '{') open += 1
223-
}
224-
newBuf append LiteralColor
225-
} else {
226-
newBuf append (ValDefColor + curr)
227-
newBuf += next
228-
var c: Char = 'a'
229-
while (c.isLetterOrDigit && remaining.nonEmpty) {
230-
c = takeChar()
231-
if (c != '"') newBuf += c
232-
}
233-
newBuf append LiteralColor
234-
if (c == '"') {
235-
newBuf += c
236-
continue = false
237-
}
238-
}
239-
closing = 0
240-
}
241-
242-
while (continue && remaining.nonEmpty) {
243-
curr = takeChar()
244-
if (curr == '\\' && remaining.nonEmpty) {
245-
val next = takeChar()
246-
newBuf append (KeywordColor + curr)
247-
if (next == 'u') {
248-
val code = "u" + takeChars(4).mkString
249-
newBuf append code
250-
} else newBuf += next
251-
newBuf append LiteralColor
252-
closing = 0
253-
} else if (shouldInterpolate) {
254-
interpolate()
255-
} else if (curr == delim && multiline) {
256-
closing += 1
257-
if (closing == 3) continue = false
258-
newBuf += curr
259-
} else if (curr == delim) {
260-
continue = false
261-
newBuf += curr
262-
} else {
263-
newBuf += curr
264-
closing = 0
265-
}
266-
267-
if (Chars.isLineBreakChar(curr)) {
268-
newBuf append LiteralColor
269-
}
270-
}
271-
newBuf append NoColor
272-
prev = curr
273-
}
274-
275-
def appendSingleQuote(delim: Char) = remaining.take(3) match {
276-
case chr #:: '\'' #:: _ => // single character
277-
newBuf append LiteralColor
278-
newBuf appendAll s"'$chr'"
279-
newBuf append NoColor
280-
takeChars(2)
281-
prev = '\''
282-
case '\\' #:: chr #:: '\'' #:: _ => // escaped character
283-
newBuf append LiteralColor
284-
newBuf appendAll s"'\\$chr'"
285-
newBuf append NoColor
286-
takeChars(3)
287-
prev = '\''
288-
case _ => appendWhile(delim, !typeEnders.contains(_), literal)
289-
}
290-
291-
def append(c: Char, shouldHL: String => Boolean, highlight: String => String) = {
292-
var curr: Char = 0
293-
val sb = new StringBuilder(s"$c")
294-
295-
def delim(c: Char) = (c: @switch) match {
296-
case ' ' => true
297-
case '\n' => true
298-
case '(' => true
299-
case ')' => true
300-
case '[' => true
301-
case ']' => true
302-
case ':' => true
303-
case '@' => true
304-
case ',' => true
305-
case '.' => true
306-
case _ => false
307-
}
308-
309-
val valDefStarterTokens = "var" :: "val" :: "def" :: "case" :: Nil
310-
311-
/** lastValDefToken is used to check whether we want to show something
312-
* in valDef color or not. There are only a few cases when lastValDefToken
313-
* should be updated, that way we can avoid stopping coloring too early.
314-
* eg.: case A(x, y, z) => ???
315-
* Without this function only x would be colored.
316-
*/
317-
def updateLastToken(currentToken: String): String =
318-
(lastValDefToken, currentToken) match {
319-
case _ if valDefStarterTokens.contains(currentToken) => currentToken
320-
case (("val" | "var"), "=") => currentToken
321-
case ("case", ("=>" | "class" | "object")) => currentToken
322-
case ("def", _) => currentToken
323-
case _ => lastValDefToken
324-
}
325-
326-
while (remaining.nonEmpty && !delim(curr)) {
327-
curr = takeChar()
328-
if (!delim(curr)) sb += curr
329-
}
330-
331-
val str = sb.toString
332-
val toAdd =
333-
if (shouldHL(str))
334-
highlight(str)
335-
else if (valDefStarterTokens.contains(lastValDefToken) && !List("=", "=>").contains(str))
336-
valDef(str)
337-
else str
338-
val suffix = if (delim(curr)) s"$curr" else ""
339-
newBuf append (toAdd + suffix)
340-
lastValDefToken = updateLastToken(str)
341-
prev = curr
342-
}
343-
344-
def appendWhile(c: Char, pred: Char => Boolean, highlight: String => String) = {
345-
var curr: Char = 0
346-
val sb = new StringBuilder(s"$c")
347-
while (remaining.nonEmpty && pred(curr)) {
348-
curr = takeChar()
349-
if (pred(curr)) sb += curr
350-
}
351-
352-
val str = sb.toString
353-
val suffix = if (!pred(curr)) s"$curr" else ""
354-
newBuf append (highlight(str) + suffix)
355-
prev = curr
356-
}
357-
358-
def appendTo(c: Char, pred: Char => Boolean, highlight: String => String) = {
359-
var curr: Char = 0
360-
val sb = new StringBuilder(s"$c")
361-
while (remaining.nonEmpty && !pred(curr)) {
362-
curr = takeChar()
363-
sb += curr
364-
}
365-
366-
newBuf append highlight(sb.toString)
367-
prev = curr
368-
}
369-
370-
newBuf.toIterable
371-
}
372-
37331
private class NoReporter extends Reporter {
37432
override def doReport(m: MessageContainer)(implicit ctx: Context): Unit = ()
37533
}

compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ trait MessageRendering {
6262

6363
val syntax =
6464
if (ctx.settings.color.value != "never")
65-
SyntaxHighlighting(pos.linesSlice).toArray
65+
SyntaxHighlighting.highlight(pos.linesSlice.mkString)(ctx).toArray
6666
else pos.linesSlice
6767
val lines = linesFrom(syntax)
6868
val (before, after) = pos.beforeAndAfterPoint

compiler/src/dotty/tools/repl/ReplDriver.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ class ReplDriver(settings: Array[String],
269269
typeAliases.map("// defined alias " + _.symbol.showUser) ++
270270
defs.map(rendering.renderMethod) ++
271271
vals.map(rendering.renderVal).flatten
272-
).foreach(str => out.println(SyntaxHighlighting(str)))
272+
).foreach(str => out.println(SyntaxHighlighting.highlight(str)(ctx)))
273273

274274
state.copy(valIndex = state.valIndex - vals.count(resAndUnit))
275275
}
@@ -284,7 +284,7 @@ class ReplDriver(settings: Array[String],
284284
x.symbol
285285
}
286286
.foreach { sym =>
287-
out.println(SyntaxHighlighting("// defined " + sym.showUser))
287+
out.println(SyntaxHighlighting.highlight("// defined " + sym.showUser)(ctx))
288288
}
289289

290290

0 commit comments

Comments
 (0)