diff options
Diffstat (limited to 'src/dotty/tools/dotc/reporting/ConsoleReporter.scala')
-rw-r--r-- | src/dotty/tools/dotc/reporting/ConsoleReporter.scala | 86 |
1 files changed, 64 insertions, 22 deletions
diff --git a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala index 92eea9fa9..a5979bd5b 100644 --- a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala +++ b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala @@ -8,13 +8,14 @@ import core.Contexts._ import Reporter._ import java.io.{ BufferedReader, IOException, PrintWriter } import scala.reflect.internal.util._ -import diagnostic.Message -import diagnostic.MessageContainer +import printing.SyntaxHighlighting._ +import printing.Highlighting._ +import diagnostic.{ Message, MessageContainer } import diagnostic.messages._ /** - * This class implements a Reporter that displays messages on a text - * console. + * This class implements a more Fancy version (with colors!) of the regular + * `ConsoleReporter` */ class ConsoleReporter( reader: BufferedReader = Console.in, @@ -26,32 +27,72 @@ class ConsoleReporter( /** maximal number of error messages to be printed */ protected def ErrorLimit = 100 - def printSourceLine(pos: SourcePosition) = - printMessage(pos.lineContent.stripLineEnd) - - def printColumnMarker(pos: SourcePosition) = - if (pos.exists) { printMessage(" " * pos.column + "^") } - /** Prints the message. */ def printMessage(msg: String): Unit = { writer.print(msg + "\n"); writer.flush() } + def stripColor(str: String): String = + str.replaceAll("\u001B\\[[;\\d]*m", "") + + def sourceLine(pos: SourcePosition)(implicit ctx: Context): (String, Int) = { + val lineNum = s"${pos.line}:" + (lineNum + hl"${pos.lineContent.stripLineEnd}", lineNum.length) + } + + def columnMarker(pos: SourcePosition, offset: Int)(implicit ctx: Context) = + if (pos.startLine == pos.endLine) { + val whitespace = " " * (pos.column + offset) + val carets = + Red("^" * math.max(1, pos.endColumn - pos.startColumn)) + + whitespace + carets.show + } else { + Red(" " * (pos.column + offset) + "^").show + } + + def errorMsg(pos: SourcePosition, msg: String, offset: Int)(implicit ctx: Context) = { + var hasLongLines = false + val leastWhitespace = msg.lines.foldLeft(Int.MaxValue) { (minPad, line) => + val lineLength = stripColor(line).length + val padding = + math.min(math.max(0, ctx.settings.pageWidth.value - offset - lineLength), offset + pos.startColumn) + + if (padding < minPad) padding + else minPad + } + + msg + .lines + .map { line => " " * leastWhitespace + line } + .mkString(sys.props("line.separator")) + } + + def posStr(pos: SourcePosition, kind: String, errorId: String)(implicit ctx: Context) = + if (pos.exists) Blue({ + val file = pos.source.file.toString + val errId = if (errorId != "") s"[$errorId] " else "" + val prefix = s"-- ${errId}${kind}: $file " + prefix + + ("-" * math.max(ctx.settings.pageWidth.value - stripColor(prefix).length, 0)) + }).show else "" + /** Prints the message with the given position indication. */ def printMessageAndPos(msg: Message, pos: SourcePosition, kind: String)(implicit ctx: Context): Unit = { - val posStr = if (pos.exists) s"$pos: " else "" - printMessage(s"${posStr}${kind}: ${msg.msg}") + printMessage(posStr(pos, kind, msg.errorId)) if (pos.exists) { - printSourceLine(pos) - printColumnMarker(pos) - } + val (src, offset) = sourceLine(pos) + val marker = columnMarker(pos, offset) + val err = errorMsg(pos, msg.msg, offset) + + printMessage(List(src, marker, err).mkString("\n")) + } else printMessage(msg.msg) } - def printExplanation(m: Message)(implicit ctx: Context): Unit = - printMessage( - s"""| - |Explanation - |=========== - |${m.explanation}""".stripMargin - ) + def printExplanation(m: Message)(implicit ctx: Context): Unit = { + printMessage(hl"""| + |${Blue("Explanation")} + |${Blue("===========")}""".stripMargin) + printMessage(m.explanation) + } override def doReport(m: MessageContainer)(implicit ctx: Context): Unit = { m match { @@ -87,3 +128,4 @@ class ConsoleReporter( override def flush()(implicit ctx: Context): Unit = { writer.flush() } } + |