Skip to content

Commit 26e98d3

Browse files
authored
Merge pull request #1646 from slothspot/1579
Fix #1579: Adapt the sbt bridge for the new error message
2 parents 0665c4f + e5aade8 commit 26e98d3

File tree

3 files changed

+136
-127
lines changed

3 files changed

+136
-127
lines changed

bridge/src/main/scala/xsbt/DelegatingReporter.scala

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import reporting._
99
import reporting.diagnostic.MessageContainer
1010
import reporting.diagnostic.messages
1111
import core.Contexts._
12-
1312
import xsbti.{Maybe, Position}
1413

1514
final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter
1615
with UniqueMessagePositions
17-
with HideNonSensicalMessages {
16+
with HideNonSensicalMessages
17+
with MessageRendering {
18+
import MessageContainer._
1819

1920
override def printSummary(implicit ctx: Context): Unit = delegate.printSummary()
2021

@@ -25,36 +26,23 @@ final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter
2526
case _: messages.Warning => xsbti.Severity.Warn
2627
case _ => xsbti.Severity.Info
2728
}
28-
val pos =
29-
if (cont.pos.exists) Some(cont.pos)
30-
else None
31-
32-
val file =
33-
if (cont.pos.source.file.exists) Option(cont.pos.source.file.file)
34-
else None
35-
36-
val offset0 = pos.map(_.point)
3729

3830
val position = new Position {
39-
def line: Maybe[Integer] = maybe(pos.map(_.line))
40-
def lineContent: String = pos.map(_.lineContent).getOrElse("")
41-
def offset: Maybe[Integer] = maybeInt(offset0)
42-
def pointer: Maybe[Integer] = offset
43-
def pointerSpace: Maybe[String] = maybe(offset0.map(" " * _))
44-
def sourceFile: Maybe[java.io.File] = maybe(file)
45-
def sourcePath: Maybe[String] = maybe(file.map(_.getPath))
31+
def line: Maybe[Integer] = Maybe.nothing()
32+
def lineContent: String = ""
33+
def offset: Maybe[Integer] = Maybe.nothing()
34+
def pointer: Maybe[Integer] = Maybe.nothing()
35+
def pointerSpace: Maybe[String] = Maybe.nothing()
36+
def sourceFile: Maybe[java.io.File] = Maybe.nothing()
37+
def sourcePath: Maybe[String] = Maybe.nothing()
4638
}
4739

48-
delegate.log(position, cont.message, severity)
49-
}
40+
val sb = new StringBuilder()
41+
sb.append(messageAndPos(cont.contained, cont.pos, diagnosticLevel(cont)))
42+
if (ctx.shouldExplain(cont) && cont.contained.explanation.nonEmpty) {
43+
sb.append(explanation(cont.contained))
44+
}
5045

51-
private[this] def maybe[T](opt: Option[T]): Maybe[T] = opt match {
52-
case None => Maybe.nothing[T]
53-
case Some(s) => Maybe.just[T](s)
54-
}
55-
import java.lang.{ Integer => I }
56-
private[this] def maybeInt(opt: Option[Int]): Maybe[I] = opt match {
57-
case None => Maybe.nothing[I]
58-
case Some(s) => Maybe.just[I](s)
46+
delegate.log(position, sb.toString(), severity)
5947
}
6048
}

src/dotty/tools/dotc/reporting/ConsoleReporter.scala

Lines changed: 9 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,10 @@ package dotty.tools
22
package dotc
33
package reporting
44

5-
import scala.collection.mutable
65
import util.SourcePosition
7-
import core.Contexts._, core.Decorators._
8-
import Reporter._
9-
import java.io.{ BufferedReader, IOException, PrintWriter }
10-
import scala.reflect.internal.util._
11-
import printing.SyntaxHighlighting._
12-
import printing.Highlighting._
13-
import diagnostic.{ Message, MessageContainer, NoExplanation }
6+
import core.Contexts._
7+
import java.io.{ BufferedReader, PrintWriter }
8+
import diagnostic.{ Message, MessageContainer }
149
import diagnostic.messages._
1510

1611
/**
@@ -19,7 +14,7 @@ import diagnostic.messages._
1914
class ConsoleReporter(
2015
reader: BufferedReader = Console.in,
2116
writer: PrintWriter = new PrintWriter(Console.err, true)
22-
) extends Reporter with UniqueMessagePositions with HideNonSensicalMessages {
17+
) extends Reporter with UniqueMessagePositions with HideNonSensicalMessages with MessageRendering {
2318

2419
import MessageContainer._
2520

@@ -29,111 +24,26 @@ class ConsoleReporter(
2924
/** Prints the message. */
3025
def printMessage(msg: String): Unit = { writer.print(msg + "\n"); writer.flush() }
3126

32-
def stripColor(str: String): String =
33-
str.replaceAll("\u001B\\[[;\\d]*m", "")
34-
35-
def sourceLines(pos: SourcePosition)(implicit ctx: Context): (List[String], List[String], Int) = {
36-
var maxLen = Int.MinValue
37-
def render(xs: List[Int]) =
38-
xs.map(pos.source.offsetToLine(_))
39-
.map { lineNbr =>
40-
val prefix = s"${lineNbr + 1} |"
41-
maxLen = math.max(maxLen, prefix.length)
42-
(prefix, pos.lineContent(lineNbr).stripLineEnd)
43-
}
44-
.map { case (prefix, line) =>
45-
val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix)
46-
hl"$lnum$line"
47-
}
48-
49-
val (before, after) = pos.beforeAndAfterPoint
50-
(render(before), render(after), maxLen)
51-
}
52-
53-
def columnMarker(pos: SourcePosition, offset: Int)(implicit ctx: Context) = {
54-
val prefix = " " * (offset - 1)
55-
val whitespace = " " * pos.startColumn
56-
val carets = Red {
57-
if (pos.startLine == pos.endLine)
58-
"^" * math.max(1, pos.endColumn - pos.startColumn)
59-
else "^"
60-
}
61-
62-
s"$prefix|$whitespace${carets.show}"
63-
}
64-
65-
def errorMsg(pos: SourcePosition, msg: String, offset: Int)(implicit ctx: Context) = {
66-
val leastWhitespace = msg.lines.foldLeft(Int.MaxValue) { (minPad, line) =>
67-
val lineLength = stripColor(line).length
68-
val padding =
69-
math.min(math.max(0, ctx.settings.pageWidth.value - offset - lineLength), offset + pos.startColumn)
70-
71-
if (padding < minPad) padding
72-
else minPad
73-
}
74-
75-
msg.lines
76-
.map { line => " " * (offset - 1) + "|" + (" " * (leastWhitespace - offset)) + line }
77-
.mkString(sys.props("line.separator"))
78-
}
79-
80-
def posStr(pos: SourcePosition, diagnosticLevel: String, message: Message)(implicit ctx: Context) =
81-
if (pos.exists) Blue({
82-
val file = pos.source.file.toString
83-
val errId =
84-
if (message.errorId != NoExplanation.ID)
85-
s"[E${"0" * (3 - message.errorId.toString.length) + message.errorId}] "
86-
else ""
87-
val kind =
88-
if (message.kind == "") diagnosticLevel
89-
else s"${message.kind} $diagnosticLevel"
90-
val prefix = s"-- ${errId}${kind}: $file "
91-
92-
prefix +
93-
("-" * math.max(ctx.settings.pageWidth.value - stripColor(prefix).length, 0))
94-
}).show else ""
95-
9627
/** Prints the message with the given position indication. */
9728
def printMessageAndPos(msg: Message, pos: SourcePosition, diagnosticLevel: String)(implicit ctx: Context): Boolean = {
98-
printMessage(posStr(pos, diagnosticLevel, msg))
99-
if (pos.exists) {
100-
val (srcBefore, srcAfter, offset) = sourceLines(pos)
101-
val marker = columnMarker(pos, offset)
102-
val err = errorMsg(pos, msg.msg, offset)
103-
104-
printMessage((srcBefore ::: marker :: err :: srcAfter).mkString("\n"))
105-
} else printMessage(msg.msg)
29+
printMessage(messageAndPos(msg, pos, diagnosticLevel))
10630
true
10731
}
10832

10933
def printExplanation(m: Message)(implicit ctx: Context): Unit = {
110-
printMessage(hl"""|
111-
|${Blue("Explanation")}
112-
|${Blue("===========")}""".stripMargin)
113-
printMessage(m.explanation)
114-
if (m.explanation.lastOption != Some('\n')) printMessage("")
34+
printMessage(explanation(m))
11535
}
11636

11737
override def doReport(m: MessageContainer)(implicit ctx: Context): Unit = {
11838
val didPrint = m match {
11939
case m: Error =>
120-
val didPrint = printMessageAndPos(m.contained, m.pos, "Error")
40+
val didPrint = printMessageAndPos(m.contained, m.pos, diagnosticLevel(m))
12141
if (ctx.settings.prompt.value) displayPrompt()
12242
didPrint
12343
case m: ConditionalWarning if !m.enablingOption.value =>
12444
false
125-
case m: FeatureWarning =>
126-
printMessageAndPos(m.contained, m.pos, "Feature Warning")
127-
case m: DeprecationWarning =>
128-
printMessageAndPos(m.contained, m.pos, "Deprecation Warning")
129-
case m: UncheckedWarning =>
130-
printMessageAndPos(m.contained, m.pos, "Unchecked Warning")
131-
case m: MigrationWarning =>
132-
printMessageAndPos(m.contained, m.pos, "Migration Warning")
133-
case m: Warning =>
134-
printMessageAndPos(m.contained, m.pos, "Warning")
135-
case m: Info =>
136-
printMessageAndPos(m.contained, m.pos, "Info")
45+
case m =>
46+
printMessageAndPos(m.contained, m.pos, diagnosticLevel(m))
13747
}
13848

13949
if (didPrint && ctx.shouldExplain(m))
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package dotty.tools
2+
package dotc
3+
package reporting
4+
5+
import core.Contexts.Context
6+
import core.Decorators._
7+
import printing.Highlighting.{Blue, Red}
8+
import diagnostic.{Message, MessageContainer, NoExplanation}
9+
import diagnostic.messages._
10+
import util.SourcePosition
11+
12+
import scala.collection.mutable
13+
14+
trait MessageRendering {
15+
def stripColor(str: String): String =
16+
str.replaceAll("\u001B\\[[;\\d]*m", "")
17+
18+
def sourceLines(pos: SourcePosition)(implicit ctx: Context): (List[String], List[String], Int) = {
19+
var maxLen = Int.MinValue
20+
def render(xs: List[Int]) =
21+
xs.map(pos.source.offsetToLine(_))
22+
.map { lineNbr =>
23+
val prefix = s"${lineNbr + 1} |"
24+
maxLen = math.max(maxLen, prefix.length)
25+
(prefix, pos.lineContent(lineNbr).stripLineEnd)
26+
}
27+
.map { case (prefix, line) =>
28+
val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix)
29+
hl"$lnum$line"
30+
}
31+
32+
val (before, after) = pos.beforeAndAfterPoint
33+
(render(before), render(after), maxLen)
34+
}
35+
36+
def columnMarker(pos: SourcePosition, offset: Int)(implicit ctx: Context): String = {
37+
val prefix = " " * (offset - 1)
38+
val whitespace = " " * pos.startColumn
39+
val carets = Red {
40+
if (pos.startLine == pos.endLine)
41+
"^" * math.max(1, pos.endColumn - pos.startColumn)
42+
else "^"
43+
}
44+
45+
s"$prefix|$whitespace${carets.show}"
46+
}
47+
48+
def errorMsg(pos: SourcePosition, msg: String, offset: Int)(implicit ctx: Context): String = {
49+
val leastWhitespace = msg.lines.foldLeft(Int.MaxValue) { (minPad, line) =>
50+
val lineLength = stripColor(line).length
51+
val padding =
52+
math.min(math.max(0, ctx.settings.pageWidth.value - offset - lineLength), offset + pos.startColumn)
53+
54+
if (padding < minPad) padding
55+
else minPad
56+
}
57+
58+
msg.lines
59+
.map { line => " " * (offset - 1) + "|" + (" " * (leastWhitespace - offset)) + line }
60+
.mkString(sys.props("line.separator"))
61+
}
62+
63+
def posStr(pos: SourcePosition, diagnosticLevel: String, message: Message)(implicit ctx: Context): String =
64+
if (pos.exists) Blue({
65+
val file = pos.source.file.toString
66+
val errId =
67+
if (message.errorId != NoExplanation.ID)
68+
s"[E${"0" * (3 - message.errorId.toString.length) + message.errorId}] "
69+
else ""
70+
val kind =
71+
if (message.kind == "") diagnosticLevel
72+
else s"${message.kind} $diagnosticLevel"
73+
val prefix = s"-- ${errId}${kind}: $file "
74+
75+
prefix +
76+
("-" * math.max(ctx.settings.pageWidth.value - stripColor(prefix).length, 0))
77+
}).show else ""
78+
79+
def explanation(m: Message)(implicit ctx: Context): String = {
80+
val sb = new StringBuilder(hl"""|
81+
|${Blue("Explanation")}
82+
|${Blue("===========")}""".stripMargin)
83+
sb.append('\n').append(m.explanation)
84+
if (m.explanation.lastOption != Some('\n')) sb.append('\n')
85+
sb.toString
86+
}
87+
88+
def messageAndPos(msg: Message, pos: SourcePosition, diagnosticLevel: String)(implicit ctx: Context): String = {
89+
val sb = mutable.StringBuilder.newBuilder
90+
sb.append(posStr(pos, diagnosticLevel, msg)).append('\n')
91+
if (pos.exists) {
92+
val (srcBefore, srcAfter, offset) = sourceLines(pos)
93+
val marker = columnMarker(pos, offset)
94+
val err = errorMsg(pos, msg.msg, offset)
95+
sb.append((srcBefore ::: marker :: err :: srcAfter).mkString("\n"))
96+
} else sb.append(msg.msg)
97+
sb.toString
98+
}
99+
100+
def diagnosticLevel(cont: MessageContainer): String = {
101+
cont match {
102+
case m: Error => "Error"
103+
case m: FeatureWarning => "Feature Warning"
104+
case m: DeprecationWarning => "Deprecation Warning"
105+
case m: UncheckedWarning => "Unchecked Warning"
106+
case m: MigrationWarning => "Migration Warning"
107+
case m: Warning => "Warning"
108+
case m: Info => "Info"
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)