Skip to content

Commit bf38d35

Browse files
slothspotallanrenucci
authored andcommitted
Introduce Parser and Scanner based highlighter
1 parent a6da03f commit bf38d35

File tree

1 file changed

+91
-2
lines changed

1 file changed

+91
-2
lines changed

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

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@ package dotc
33
package printing
44

55
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
613

7-
import parsing.Tokens._
814
import scala.annotation.switch
915
import scala.collection.mutable.StringBuilder
10-
import util.Chars
16+
import util.{Chars, SourceFile}
17+
18+
import scala.collection.mutable
1119

1220
/** This object provides functions for syntax highlighting in the REPL */
1321
object SyntaxHighlighting {
@@ -361,4 +369,85 @@ object SyntaxHighlighting {
361369

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

0 commit comments

Comments
 (0)