aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bridge/src/main/scala/xsbt/DelegatingReporter.scala44
-rw-r--r--src/dotty/tools/dotc/reporting/ConsoleReporter.scala108
-rw-r--r--src/dotty/tools/dotc/reporting/MessageRendering.scala111
3 files changed, 136 insertions, 127 deletions
diff --git a/bridge/src/main/scala/xsbt/DelegatingReporter.scala b/bridge/src/main/scala/xsbt/DelegatingReporter.scala
index 446ef287e..770d6b2c7 100644
--- a/bridge/src/main/scala/xsbt/DelegatingReporter.scala
+++ b/bridge/src/main/scala/xsbt/DelegatingReporter.scala
@@ -9,12 +9,13 @@ import reporting._
import reporting.diagnostic.MessageContainer
import reporting.diagnostic.messages
import core.Contexts._
-
import xsbti.{Maybe, Position}
final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter
with UniqueMessagePositions
- with HideNonSensicalMessages {
+ with HideNonSensicalMessages
+ with MessageRendering {
+ import MessageContainer._
override def printSummary(implicit ctx: Context): Unit = delegate.printSummary()
@@ -25,36 +26,23 @@ final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter
case _: messages.Warning => xsbti.Severity.Warn
case _ => xsbti.Severity.Info
}
- val pos =
- if (cont.pos.exists) Some(cont.pos)
- else None
-
- val file =
- if (cont.pos.source.file.exists) Option(cont.pos.source.file.file)
- else None
-
- val offset0 = pos.map(_.point)
val position = new Position {
- def line: Maybe[Integer] = maybe(pos.map(_.line))
- def lineContent: String = pos.map(_.lineContent).getOrElse("")
- def offset: Maybe[Integer] = maybeInt(offset0)
- def pointer: Maybe[Integer] = offset
- def pointerSpace: Maybe[String] = maybe(offset0.map(" " * _))
- def sourceFile: Maybe[java.io.File] = maybe(file)
- def sourcePath: Maybe[String] = maybe(file.map(_.getPath))
+ def line: Maybe[Integer] = Maybe.nothing()
+ def lineContent: String = ""
+ def offset: Maybe[Integer] = Maybe.nothing()
+ def pointer: Maybe[Integer] = Maybe.nothing()
+ def pointerSpace: Maybe[String] = Maybe.nothing()
+ def sourceFile: Maybe[java.io.File] = Maybe.nothing()
+ def sourcePath: Maybe[String] = Maybe.nothing()
}
- delegate.log(position, cont.message, severity)
- }
+ val sb = new StringBuilder()
+ sb.append(messageAndPos(cont.contained, cont.pos, diagnosticLevel(cont)))
+ if (ctx.shouldExplain(cont) && cont.contained.explanation.nonEmpty) {
+ sb.append(explanation(cont.contained))
+ }
- private[this] def maybe[T](opt: Option[T]): Maybe[T] = opt match {
- case None => Maybe.nothing[T]
- case Some(s) => Maybe.just[T](s)
- }
- import java.lang.{ Integer => I }
- private[this] def maybeInt(opt: Option[Int]): Maybe[I] = opt match {
- case None => Maybe.nothing[I]
- case Some(s) => Maybe.just[I](s)
+ delegate.log(position, sb.toString(), severity)
}
}
diff --git a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
index da3df6984..99a80982f 100644
--- a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
+++ b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
@@ -2,15 +2,10 @@ package dotty.tools
package dotc
package reporting
-import scala.collection.mutable
import util.SourcePosition
-import core.Contexts._, core.Decorators._
-import Reporter._
-import java.io.{ BufferedReader, IOException, PrintWriter }
-import scala.reflect.internal.util._
-import printing.SyntaxHighlighting._
-import printing.Highlighting._
-import diagnostic.{ Message, MessageContainer, NoExplanation }
+import core.Contexts._
+import java.io.{ BufferedReader, PrintWriter }
+import diagnostic.{ Message, MessageContainer }
import diagnostic.messages._
/**
@@ -19,7 +14,7 @@ import diagnostic.messages._
class ConsoleReporter(
reader: BufferedReader = Console.in,
writer: PrintWriter = new PrintWriter(Console.err, true)
-) extends Reporter with UniqueMessagePositions with HideNonSensicalMessages {
+) extends Reporter with UniqueMessagePositions with HideNonSensicalMessages with MessageRendering {
import MessageContainer._
@@ -29,111 +24,26 @@ class ConsoleReporter(
/** 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 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) = {
- 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) = {
- 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) =
- 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 ""
-
/** Prints the message with the given position indication. */
def printMessageAndPos(msg: Message, pos: SourcePosition, diagnosticLevel: String)(implicit ctx: Context): Boolean = {
- printMessage(posStr(pos, diagnosticLevel, msg))
- if (pos.exists) {
- val (srcBefore, srcAfter, offset) = sourceLines(pos)
- val marker = columnMarker(pos, offset)
- val err = errorMsg(pos, msg.msg, offset)
-
- printMessage((srcBefore ::: marker :: err :: srcAfter).mkString("\n"))
- } else printMessage(msg.msg)
+ printMessage(messageAndPos(msg, pos, diagnosticLevel))
true
}
def printExplanation(m: Message)(implicit ctx: Context): Unit = {
- printMessage(hl"""|
- |${Blue("Explanation")}
- |${Blue("===========")}""".stripMargin)
- printMessage(m.explanation)
- if (m.explanation.lastOption != Some('\n')) printMessage("")
+ printMessage(explanation(m))
}
override def doReport(m: MessageContainer)(implicit ctx: Context): Unit = {
val didPrint = m match {
case m: Error =>
- val didPrint = printMessageAndPos(m.contained, m.pos, "Error")
+ val didPrint = printMessageAndPos(m.contained, m.pos, diagnosticLevel(m))
if (ctx.settings.prompt.value) displayPrompt()
didPrint
case m: ConditionalWarning if !m.enablingOption.value =>
false
- case m: FeatureWarning =>
- printMessageAndPos(m.contained, m.pos, "Feature Warning")
- case m: DeprecationWarning =>
- printMessageAndPos(m.contained, m.pos, "Deprecation Warning")
- case m: UncheckedWarning =>
- printMessageAndPos(m.contained, m.pos, "Unchecked Warning")
- case m: MigrationWarning =>
- printMessageAndPos(m.contained, m.pos, "Migration Warning")
- case m: Warning =>
- printMessageAndPos(m.contained, m.pos, "Warning")
- case m: Info =>
- printMessageAndPos(m.contained, m.pos, "Info")
+ case m =>
+ printMessageAndPos(m.contained, m.pos, diagnosticLevel(m))
}
if (didPrint && ctx.shouldExplain(m))
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"
+ }
+ }
+}