Skip to content

Improve error/warning error format #6293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
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
28 changes: 18 additions & 10 deletions compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import java.lang.System.{lineSeparator => EOL}

import core.Contexts.Context
import core.Decorators._
import printing.Highlighting.{Blue, Red}
import printing.Highlighting.{Blue, Red, Yellow}
import printing.SyntaxHighlighting
import diagnostic.{ErrorMessageID, Message, MessageContainer}
import diagnostic.messages._
Expand Down Expand Up @@ -42,14 +42,14 @@ trait MessageRendering {
*
* @return (lines before error, lines after error, line numbers offset)
*/
def sourceLines(pos: SourcePosition)(implicit ctx: Context): (List[String], List[String], Int) = {
def sourceLines(pos: SourcePosition, diagnosticLevel: String)(implicit ctx: Context): (List[String], List[String], Int) = {
var maxLen = Int.MinValue
def render(offsetAndLine: (Int, String)): String = {
val (offset, line) = offsetAndLine
val lineNbr = pos.source.offsetToLine(offset)
val prefix = s"${lineNbr + 1} |"
maxLen = math.max(maxLen, prefix.length)
val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix).show
val lnum = hl(diagnosticLevel)(" " * math.max(0, maxLen - prefix.length) + prefix)
lnum + line.stripLineEnd
}

Expand Down Expand Up @@ -78,15 +78,15 @@ trait MessageRendering {
}

/** The column markers aligned under the error */
def columnMarker(pos: SourcePosition, offset: Int)(implicit ctx: Context): String = {
def columnMarker(pos: SourcePosition, offset: Int, diagnosticLevel: String)(implicit ctx: Context): String = {
val prefix = " " * (offset - 1)
val padding = pos.startColumnPadding
val carets = Red {
val carets = hl(diagnosticLevel) {
if (pos.startLine == pos.endLine)
"^" * math.max(1, pos.endColumn - pos.startColumn)
else "^"
}
s"$prefix|$padding${carets.show}"
s"$prefix|$padding$carets"
}

/** The error message (`msg`) aligned under `pos`
Expand All @@ -112,7 +112,7 @@ trait MessageRendering {
* @return separator containing error location and kind
*/
def posStr(pos: SourcePosition, diagnosticLevel: String, message: Message)(implicit ctx: Context): String =
if (pos.exists) Blue({
if (pos.exists) hl(diagnosticLevel)({
val file = s"${pos.source.file.toString}:${pos.line + 1}:${pos.column}"
val errId =
if (message.errorId ne ErrorMessageID.NoExplanationID) {
Expand All @@ -126,7 +126,7 @@ trait MessageRendering {

prefix +
("-" * math.max(ctx.settings.pageWidth.value - stripColor(prefix).length, 0))
}).show else ""
}) else ""

/** Explanation rendered under "Explanation" header */
def explanation(m: Message)(implicit ctx: Context): String = {
Expand All @@ -146,14 +146,22 @@ trait MessageRendering {
val posString = posStr(pos, diagnosticLevel, msg)
if (posString.nonEmpty) sb.append(posString).append(EOL)
if (pos.exists) {
val (srcBefore, srcAfter, offset) = sourceLines(pos)
val marker = columnMarker(pos, offset)
val (srcBefore, srcAfter, offset) = sourceLines(pos, diagnosticLevel)
val marker = columnMarker(pos, offset, diagnosticLevel)
val err = errorMsg(pos, msg.msg, offset)
sb.append((srcBefore ::: marker :: err :: outer(pos, " " * (offset - 1)) ::: srcAfter).mkString(EOL))
} else sb.append(msg.msg)
sb.toString
}

def hl(diagnosticLevel: String)(str: String)(implicit ctx: Context): String = diagnosticLevel match {
case "Info" => Blue(str).show
case "Error" => Red(str).show
case _ =>
assert(diagnosticLevel.contains("Warning"))
Yellow(str).show
}

def diagnosticLevel(cont: MessageContainer): String =
cont match {
case m: Error => "Error"
Expand Down