Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions compiler/src/dotty/tools/dotc/config/CliCommand.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package config

import Settings.*
import core.Contexts.*
import printing.Highlighting
import dotty.shaded.fansi

import dotty.tools.dotc.util.chaining.*
import scala.PartialFunction.cond
Expand Down Expand Up @@ -154,10 +154,9 @@ trait CliCommand:
def apply(texts: List[List[(String, String)]])(using Context): String = StringBuilder().tap(columnate(_, texts)).toString

private def columnate(sb: StringBuilder, texts: List[List[(String, String)]])(using Context): Unit =
import Highlighting.*
val colors = Seq(Green(_), Yellow(_), Magenta(_), Cyan(_), Red(_))
val colors: Seq[String => fansi.Str] = Seq(fansi.Color.Green(_), fansi.Color.Yellow(_), fansi.Color.Magenta(_), fansi.Color.Cyan(_), fansi.Color.Red(_))
val nocolor = texts.length == 1
def color(index: Int): String => Highlight = if nocolor then NoColor(_) else colors(index % colors.length)
def color(index: Int): String => fansi.Str = if nocolor then fansi.Str(_) else colors(index % colors.length)
val maxCol = ctx.settings.pageWidth.value
val field1 = maxField.min(texts.flatten.map(_._1.length).filter(_ < maxField).max) // widest field under maxField
val field2 = if field1 + separation + maxField < maxCol then maxCol - field1 - separation else 0 // skinny window -> terminal wrap
Expand All @@ -173,13 +172,13 @@ trait CliCommand:
case i => val (prefix, rest) = fld.splitAt(i) ; prefix :: loopOverField2(rest.trim)
text.split("\n").toList.flatMap(loopOverField2).filter(_.nonEmpty).mkString(EOL + "".padLeft(field1) + separator)
end formatField2
def format(first: String, second: String, index: Int, colorPicker: Int => String => Highlight) =
sb.append(colorPicker(index)(formatField1(first)).show)
def format(first: String, second: String, index: Int, colorPicker: Int => String => fansi.Str) =
sb.append(colorPicker(index)(formatField1(first)).render)
.append(separator)
.append(formatField2(second))
.append(EOL): Unit
def fancy(first: String, second: String, index: Int) = format(first, second, index, color)
def plain(first: String, second: String) = format(first, second, 0, _ => NoColor(_))
def plain(first: String, second: String) = format(first, second, 0, _ => fansi.Str(_))

if heading1.nonEmpty then
plain(heading1, heading2)
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/printing/Formatting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import Texts.*, Types.*, Flags.*, Symbols.*, Contexts.*
import Decorators.*
import reporting.Message
import util.{DiffUtil, SimpleIdentitySet}
import Highlighting.*

object Formatting {

Expand Down Expand Up @@ -156,6 +155,8 @@ object Formatting {
given Show[util.Spans.Span] = ShowAny
given Show[tasty.TreeUnpickler#OwnerTree] = ShowAny
given Show[typer.ForceDegree.Value] = ShowAny
given Show[dotty.shaded.fansi.Str] with
def show(x: dotty.shaded.fansi.Str) = x.render
end Show
end ShownDef
export ShownDef.{ Show, Shown }
Expand Down
72 changes: 0 additions & 72 deletions compiler/src/dotty/tools/dotc/printing/Highlighting.scala

This file was deleted.

10 changes: 6 additions & 4 deletions compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Variances.varianceSign
import util.{Chars, SourcePosition}
import scala.util.control.NonFatal
import scala.annotation.switch
import dotty.shaded.fansi
import config.{Config, Feature}
import ast.{tpd, untpd}
import cc.*
Expand Down Expand Up @@ -846,9 +847,10 @@ class PlainPrinter(_ctx: Context) extends Printer {
protected def literalText(text: Text): Text = coloredText(text, SyntaxHighlighting.LiteralColor)
protected def stringText(text: Text): Text = coloredText(text, SyntaxHighlighting.StringColor)

protected def coloredStr(text: String, color: String): String =
if (ctx.useColors) color + text + SyntaxHighlighting.NoColor else text
protected def coloredText(text: Text, color: String): Text =
if (ctx.useColors) color ~ text ~ SyntaxHighlighting.NoColor else text
protected def coloredStr(text: String, color: dotty.shaded.fansi.Attrs): String =
if (ctx.useColors) color(text).render else text
protected def coloredText(text: Text, color: dotty.shaded.fansi.Attrs): Text =
if (ctx.useColors) fansi.Attrs.emitAnsiCodes(0, color.applyMask) ~ text ~ fansi.Attrs.emitAnsiCodes(color.applyMask, 0)
else text
}

4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/printing/ReplPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@ class ReplPrinter(_ctx: Context) extends RefinedPrinter(_ctx) {

// We don't want the colors coming from RefinedPrinter as the REPL uses its
// own syntax coloring mechanism.
override def coloredStr(text: String, color: String): String = text
override def coloredText(text: Text, color: String): Text = text
override def coloredStr(text: String, color: dotty.shaded.fansi.Attrs): String = text
override def coloredText(text: Text, color: dotty.shaded.fansi.Attrs): Text = text
}
50 changes: 20 additions & 30 deletions compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import dotty.tools.dotc.reporting.Reporter
import dotty.tools.dotc.util.Spans.Span
import dotty.tools.dotc.util.SourceFile

import java.util.Arrays
import dotty.shaded.fansi
import scala.collection.mutable.ArrayBuffer

/** This object provides functions for syntax highlighting in the REPL */
object SyntaxHighlighting {
Expand All @@ -23,14 +24,14 @@ object SyntaxHighlighting {
private inline val debug = true

// Keep in sync with SyntaxHighlightingTests
val NoColor: String = Console.RESET
val CommentColor: String = Console.BLUE
val KeywordColor: String = Console.YELLOW
val ValDefColor: String = Console.CYAN
val LiteralColor: String = Console.GREEN
val StringColor: String = Console.GREEN
val TypeColor: String = Console.MAGENTA
val AnnotationColor: String = Console.MAGENTA
val NoColor: fansi.Attrs = fansi.Attrs.Empty
val CommentColor: fansi.Attrs = fansi.Color.Blue
val KeywordColor: fansi.Attrs = fansi.Color.Yellow
val ValDefColor: fansi.Attrs = fansi.Color.Cyan
val LiteralColor: fansi.Attrs = fansi.Color.Green
val StringColor: fansi.Attrs = fansi.Color.Green
val TypeColor: fansi.Attrs = fansi.Color.Magenta
val AnnotationColor: fansi.Attrs = fansi.Color.Magenta

def highlight(in: String)(using Context): String = {
def freshCtx = ctx.fresh.setReporter(Reporter.NoReporter)
Expand All @@ -41,18 +42,20 @@ object SyntaxHighlighting {
given Context = freshCtx
.setCompilationUnit(CompilationUnit(source, mustExist = false)(using freshCtx))

val colorAt = Array.fill(in.length)(NoColor)
// Buffer to collect all highlight ranges for fansi.Str.overlayAll
val ranges = ArrayBuffer[(fansi.Attrs, Int, Int)]()

def highlightRange(from: Int, to: Int, color: String) =
Arrays.fill(colorAt.asInstanceOf[Array[AnyRef]], from, to, color)
def highlightRange(from: Int, to: Int, attrs: fansi.Attrs) =
if (attrs != fansi.Attrs.Empty)
ranges += ((attrs, from, to))

def highlightPosition(span: Span, color: String) = if (span.exists)
def highlightPosition(span: Span, attrs: fansi.Attrs) = if (span.exists)
if (span.start < 0 || span.end > in.length) {
if (debug)
println(s"Trying to highlight erroneous position $span. Input size: ${in.length}")
}
else
highlightRange(span.start, span.end, color)
highlightRange(span.start, span.end, attrs)

val scanner = new Scanner(source)
while (scanner.token != EOF) {
Expand All @@ -78,7 +81,7 @@ object SyntaxHighlighting {
highlightRange(start, end, KeywordColor)

case IDENTIFIER if name == nme.??? =>
highlightRange(start, end, Console.RED_B)
highlightRange(start, end, fansi.Back.Red)

case IDENTIFIER if name.head.isUpper && name.exists(!_.isUpper) =>
highlightRange(start, end, KeywordColor)
Expand Down Expand Up @@ -133,21 +136,8 @@ object SyntaxHighlighting {
val trees = parser.blockStatSeq()
TreeHighlighter.highlight(trees)


val highlighted = new StringBuilder()

for (idx <- colorAt.indices) {
val prev = if (idx == 0) NoColor else colorAt(idx - 1)
val curr = colorAt(idx)
if (curr != prev)
highlighted.append(curr)
highlighted.append(in(idx))
}

if (colorAt.last != NoColor)
highlighted.append(NoColor)

highlighted.toString
// Apply all color ranges at once using fansi.Str.overlayAll
fansi.Str(in).overlayAll(ranges.toSeq).render
catch
case e: StackOverflowError =>
in
Expand Down
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/reporting/Message.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import printing.Formatting.hl
import config.SourceVersion
import cc.CaptureSet
import cc.Capabilities.*
import dotty.shaded.fansi

import scala.annotation.threadUnsafe

Expand Down Expand Up @@ -386,6 +387,10 @@ abstract class Message(val errorId: ErrorMessageID)(using Context) { self =>

def withoutDisambiguation(): this.type = withDisambiguation(Disambiguation.None)

private def stripFansiColorsIfNecessary(str: String)(using Context): String =
if ctx.useColors then str
else fansi.Str(str).plainText

private def inMessageContext(disambiguate: Disambiguation)(op: Context ?=> String): String =
if ctx eq NoContext then op
else
Expand All @@ -397,7 +402,7 @@ abstract class Message(val errorId: ErrorMessageID)(using Context) { self =>
if !ctx1.property(MessageLimiter).isDefined then
ctx1.setProperty(MessageLimiter, ErrorMessageLimiter())
ctx1
op(using msgContext)
stripFansiColorsIfNecessary(op(using msgContext))

/** The message to report. <nonsensical> tags are filtered out */
@threadUnsafe lazy val message: String =
Expand Down
16 changes: 9 additions & 7 deletions compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import java.lang.System.{lineSeparator => EOL}
import core.Contexts.*
import core.Decorators.*
import io.AbstractFile
import printing.Highlighting.{Blue, Red, Yellow}
import printing.SyntaxHighlighting
import dotty.shaded.fansi
import Diagnostic.*
import util.{SourcePosition, NoSourcePosition}
import util.Chars.{ LF, CR, FF, SU }
Expand Down Expand Up @@ -205,8 +205,8 @@ trait MessageRendering {
def explanation(m: Message)(using Context): String = {
val sb = new StringBuilder(
s"""|
|${Blue("Explanation").show}
|${Blue("===========").show}""".stripMargin
|${if ctx.useColors then fansi.Color.Blue("Explanation").render else "Explanation"}
|${if ctx.useColors then fansi.Color.Blue("===========").render else "==========="}""".stripMargin
)
sb.append(EOL).append(m.explanation)
if (!m.explanation.endsWith(EOL)) sb.append(EOL)
Expand Down Expand Up @@ -305,10 +305,12 @@ trait MessageRendering {
}

private def hl(str: String)(using Context, Level): String =
summon[Level].value match
case interfaces.Diagnostic.ERROR => Red(str).show
case interfaces.Diagnostic.WARNING => Yellow(str).show
case interfaces.Diagnostic.INFO => Blue(str).show
if ctx.useColors then
summon[Level].value match
case interfaces.Diagnostic.ERROR => fansi.Color.Red(str).render
case interfaces.Diagnostic.WARNING => fansi.Color.Yellow(str).render
case interfaces.Diagnostic.INFO => fansi.Color.Blue(str).render
else str

private def diagnosticLevel(dia: Diagnostic): String =
dia match {
Expand Down
Loading
Loading