aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/reporting/MessageRendering.scala
diff options
context:
space:
mode:
authorDmitry Melnichenko <dmytro.i.am@gmail.com>2016-10-31 21:01:10 +0200
committerDmitry Melnichenko <dmytro.i.am@gmail.com>2016-11-04 00:24:00 +0200
commite5aade87a9d7fb6c0319920c81ef3ee9f146bba1 (patch)
tree6ff4c377b2c3d2d6dfcef4ffc005691c8f3836fc /src/dotty/tools/dotc/reporting/MessageRendering.scala
parent01ae7ddfd4956660ed4897f5d2773587f845204c (diff)
downloaddotty-e5aade87a9d7fb6c0319920c81ef3ee9f146bba1.tar.gz
dotty-e5aade87a9d7fb6c0319920c81ef3ee9f146bba1.tar.bz2
dotty-e5aade87a9d7fb6c0319920c81ef3ee9f146bba1.zip
#1579 Adapt the sbt bridge for the new error message
Diffstat (limited to 'src/dotty/tools/dotc/reporting/MessageRendering.scala')
-rw-r--r--src/dotty/tools/dotc/reporting/MessageRendering.scala111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/reporting/MessageRendering.scala b/src/dotty/tools/dotc/reporting/MessageRendering.scala
new file mode 100644
index 000000000..6d9e45a6e
--- /dev/null
+++ b/src/dotty/tools/dotc/reporting/MessageRendering.scala
@@ -0,0 +1,111 @@
+package dotty.tools
+package dotc
+package reporting
+
+import core.Contexts.Context
+import core.Decorators._
+import printing.Highlighting.{Blue, Red}
+import diagnostic.{Message, MessageContainer, NoExplanation}
+import diagnostic.messages._
+import util.SourcePosition
+
+import scala.collection.mutable
+
+trait MessageRendering {
+ def stripColor(str: String): String =
+ str.replaceAll("\u001B\\[[;\\d]*m", "")
+
+ def sourceLines(pos: SourcePosition)(implicit ctx: Context): (List[String], List[String], Int) = {
+ var maxLen = Int.MinValue
+ def render(xs: List[Int]) =
+ xs.map(pos.source.offsetToLine(_))
+ .map { lineNbr =>
+ val prefix = s"${lineNbr + 1} |"
+ maxLen = math.max(maxLen, prefix.length)
+ (prefix, pos.lineContent(lineNbr).stripLineEnd)
+ }
+ .map { case (prefix, line) =>
+ val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix)
+ hl"$lnum$line"
+ }
+
+ val (before, after) = pos.beforeAndAfterPoint
+ (render(before), render(after), maxLen)
+ }
+
+ def columnMarker(pos: SourcePosition, offset: Int)(implicit ctx: Context): String = {
+ val prefix = " " * (offset - 1)
+ val whitespace = " " * pos.startColumn
+ val carets = Red {
+ if (pos.startLine == pos.endLine)
+ "^" * math.max(1, pos.endColumn - pos.startColumn)
+ else "^"
+ }
+
+ s"$prefix|$whitespace${carets.show}"
+ }
+
+ def errorMsg(pos: SourcePosition, msg: String, offset: Int)(implicit ctx: Context): String = {
+ 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 => " " * (offset - 1) + "|" + (" " * (leastWhitespace - offset)) + line }
+ .mkString(sys.props("line.separator"))
+ }
+
+ def posStr(pos: SourcePosition, diagnosticLevel: String, message: Message)(implicit ctx: Context): String =
+ if (pos.exists) Blue({
+ val file = pos.source.file.toString
+ val errId =
+ if (message.errorId != NoExplanation.ID)
+ s"[E${"0" * (3 - message.errorId.toString.length) + message.errorId}] "
+ else ""
+ val kind =
+ if (message.kind == "") diagnosticLevel
+ else s"${message.kind} $diagnosticLevel"
+ val prefix = s"-- ${errId}${kind}: $file "
+
+ prefix +
+ ("-" * math.max(ctx.settings.pageWidth.value - stripColor(prefix).length, 0))
+ }).show else ""
+
+ def explanation(m: Message)(implicit ctx: Context): String = {
+ val sb = new StringBuilder(hl"""|
+ |${Blue("Explanation")}
+ |${Blue("===========")}""".stripMargin)
+ sb.append('\n').append(m.explanation)
+ if (m.explanation.lastOption != Some('\n')) sb.append('\n')
+ sb.toString
+ }
+
+ def messageAndPos(msg: Message, pos: SourcePosition, diagnosticLevel: String)(implicit ctx: Context): String = {
+ val sb = mutable.StringBuilder.newBuilder
+ sb.append(posStr(pos, diagnosticLevel, msg)).append('\n')
+ if (pos.exists) {
+ val (srcBefore, srcAfter, offset) = sourceLines(pos)
+ val marker = columnMarker(pos, offset)
+ val err = errorMsg(pos, msg.msg, offset)
+ sb.append((srcBefore ::: marker :: err :: srcAfter).mkString("\n"))
+ } else sb.append(msg.msg)
+ sb.toString
+ }
+
+ def diagnosticLevel(cont: MessageContainer): String = {
+ cont match {
+ case m: Error => "Error"
+ case m: FeatureWarning => "Feature Warning"
+ case m: DeprecationWarning => "Deprecation Warning"
+ case m: UncheckedWarning => "Unchecked Warning"
+ case m: MigrationWarning => "Migration Warning"
+ case m: Warning => "Warning"
+ case m: Info => "Info"
+ }
+ }
+}