@@ -3,11 +3,19 @@ package dotc
3
3
package printing
4
4
5
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
6
13
7
- import parsing .Tokens ._
8
14
import scala .annotation .switch
9
15
import scala .collection .mutable .StringBuilder
10
- import util .Chars
16
+ import util .{Chars , SourceFile }
17
+
18
+ import scala .collection .mutable
11
19
12
20
/** This object provides functions for syntax highlighting in the REPL */
13
21
object SyntaxHighlighting {
@@ -361,4 +369,85 @@ object SyntaxHighlighting {
361
369
362
370
newBuf.toIterable
363
371
}
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
+ }
364
453
}
0 commit comments