Skip to content

Commit 764f0c6

Browse files
committed
Introduce Parser and Scanner based highlighter
1 parent 2320ed0 commit 764f0c6

File tree

2 files changed

+94
-3
lines changed

2 files changed

+94
-3
lines changed

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

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,20 @@ package dotty.tools
22
package dotc
33
package printing
44

5-
import parsing.Tokens._
5+
import dotty.tools.dotc.core.Contexts.Context
6+
import dotty.tools.dotc.core.StdNames._
7+
import dotty.tools.dotc.parsing.Parsers.Parser
8+
import dotty.tools.dotc.parsing.Scanners.Scanner
9+
import dotty.tools.dotc.parsing.Tokens._
10+
import dotty.tools.dotc.reporting.Reporter
11+
import dotty.tools.dotc.reporting.diagnostic.MessageContainer
12+
import dotty.tools.dotc.util.Positions.Position
13+
614
import scala.annotation.switch
715
import scala.collection.mutable.StringBuilder
8-
import util.Chars
16+
import util.{Chars, SourceFile}
17+
18+
import scala.collection.mutable
919

1020
/** This object provides functions for syntax highlighting in the REPL */
1121
object SyntaxHighlighting {
@@ -355,4 +365,85 @@ object SyntaxHighlighting {
355365

356366
newBuf.toIterable
357367
}
368+
369+
private class NoReporter extends Reporter {
370+
override def doReport(m: MessageContainer)(implicit ctx: Context): Unit = ()
371+
}
372+
373+
def highlight(in: String)(ctx0: Context): String = {
374+
import dotty.tools.dotc.ast.untpd._
375+
376+
implicit val ctx: Context = ctx0.fresh.setReporter(new NoReporter)
377+
378+
val sf = new SourceFile("<highlighting>", in.toCharArray)
379+
val p = new Parser(sf)
380+
val s = new Scanner(sf)
381+
val trees = p.blockStatSeq()
382+
383+
val outputH = Array.fill(in.length)(NoColor)
384+
385+
def highlightRange(p: Position, color: String): Unit = {
386+
if(p.exists) {
387+
for {
388+
i <- p.start until math.min(p.end, outputH.length)
389+
} outputH(i) = color
390+
}
391+
}
392+
393+
val treeTraverser = new UntypedTreeTraverser {
394+
def traverse(tree: Tree)(implicit ctx: Context): Unit = {
395+
tree match {
396+
case tpe : TypeDef =>
397+
highlightRange(tpe.namePos, TypeColor)
398+
case _ : TypTree =>
399+
highlightRange(tree.pos, TypeColor)
400+
case mod: ModuleDef =>
401+
highlightRange(mod.namePos, TypeColor)
402+
case v : ValOrDefDef =>
403+
highlightRange(v.namePos, ValDefColor)
404+
highlightRange(v.tpt.pos, TypeColor)
405+
case _ : Literal =>
406+
highlightRange(tree.pos, LiteralColor)
407+
case _ =>
408+
}
409+
traverseChildren(tree)
410+
}
411+
}
412+
413+
for {
414+
t <- trees
415+
} {
416+
treeTraverser.traverse(t)
417+
}
418+
419+
val sb = new mutable.StringBuilder()
420+
421+
while(s.token != EOF) {
422+
val isKwd = isKeyword(s.token)
423+
val offsetStart = s.offset
424+
425+
426+
if(s.token == IDENTIFIER && s.name == nme.???) {
427+
highlightRange(Position(s.offset, s.offset + s.name.length), Console.RED_B)
428+
}
429+
s.nextToken()
430+
431+
if(isKwd) {
432+
val offsetEnd = s.lastOffset
433+
highlightRange(Position(offsetStart, offsetEnd), KeywordColor)
434+
}
435+
}
436+
437+
for {
438+
idx <- outputH.indices
439+
} {
440+
if(idx == 0 || outputH(idx-1) != outputH(idx)){
441+
sb.append(outputH(idx))
442+
}
443+
sb.append(in(idx))
444+
}
445+
sb.append(NoColor)
446+
447+
sb.mkString
448+
}
358449
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ private[repl] class AmmoniteReader(out: OutputStream,
105105

106106
def displayTransform(buffer: Vector[Char], cursor: Int): (Ansi.Str, Int) = {
107107
val coloredBuffer =
108-
SyntaxHighlighting(buffer)
108+
SyntaxHighlighting.highlight(buffer.mkString)(ctx)
109109

110110
val ansiBuffer = Ansi.Str.parse(coloredBuffer.toVector)
111111
val (newBuffer, cursorOffset) = SelectionFilter.mangleBuffer(

0 commit comments

Comments
 (0)