Skip to content

Commit dd8af22

Browse files
committed
Refactoring of message filtering
The previous pipeline forgot to filter out <nonsensical> tags in most situations
1 parent 1586531 commit dd8af22

File tree

14 files changed

+73
-77
lines changed

14 files changed

+73
-77
lines changed

compiler/src/dotty/tools/dotc/printing/Formatting.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Texts._, Types._, Flags._, Symbols._, Contexts._
66
import collection.mutable
77
import Decorators._
88
import scala.util.control.NonFatal
9-
import reporting.Diagnostic
9+
import reporting.Message
1010
import util.DiffUtil
1111
import Highlighting._
1212

@@ -88,7 +88,7 @@ object Formatting {
8888
}
8989

9090
private def wrapNonSensical(arg: Any, str: String)(implicit ctx: Context): String = {
91-
import Diagnostic._
91+
import Message._
9292
def isSensical(arg: Any): Boolean = arg match {
9393
case tpe: Type =>
9494
tpe.exists && !tpe.isErroneous

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
170170
(" <: " ~ toText(bound) provided !bound.isAny)
171171
}.close
172172
case tp: ErrorType =>
173-
s"<error ${tp.msg.msg}>"
173+
s"<error ${tp.msg.rawMessage}>"
174174
case tp: WildcardType =>
175175
if (tp.optBounds.exists) "<?" ~ toTextRHS(tp.bounds) ~ ">" else "<?>"
176176
case NoType =>

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@ class ConsoleReporter(
2323
def doReport(dia: Diagnostic)(implicit ctx: Context): Unit = {
2424
val didPrint = dia match {
2525
case dia: Error =>
26-
printMessage(messageAndPos(dia.contained, dia.pos, diagnosticLevel(dia)))
26+
printMessage(messageAndPos(dia.msg, dia.pos, diagnosticLevel(dia)))
2727
if (ctx.settings.Xprompt.value) Reporter.displayPrompt(reader, writer)
2828
true
2929
case dia: ConditionalWarning if !dia.enablingOption.value =>
3030
false
3131
case dia =>
32-
printMessage(messageAndPos(dia.contained, dia.pos, diagnosticLevel(dia)))
32+
printMessage(messageAndPos(dia.msg, dia.pos, diagnosticLevel(dia)))
3333
true
3434
}
3535

36-
if (didPrint && ctx.shouldExplain(dia))
37-
printMessage(explanation(dia.contained))
38-
else if (didPrint && dia.contained.explanation.nonEmpty)
36+
if (didPrint && shouldExplain(dia))
37+
printMessage(explanation(dia.msg))
38+
else if (didPrint && dia.msg.explanation.nonEmpty)
3939
printMessage("\nlonger explanation available when compiling with `-explain`")
4040
}
4141

compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,9 @@ import interfaces.Diagnostic.{ERROR, INFO, WARNING}
1010
import java.util.Optional
1111

1212
object Diagnostic:
13-
val nonSensicalStartTag: String = "<nonsensical>"
14-
val nonSensicalEndTag: String = "</nonsensical>"
1513

16-
implicit class MessageContext(val c: Context) extends AnyVal {
17-
def shouldExplain(dia: Diagnostic): Boolean = {
18-
implicit val ctx = c
19-
dia.contained.explanation match {
20-
case "" => false
21-
case _ => ctx.settings.explain.value
22-
}
23-
}
24-
}
14+
def shouldExplain(dia: Diagnostic)(using ctx: Context): Boolean =
15+
dia.msg.explanation.nonEmpty && ctx.settings.explain.value
2516

2617
// `Diagnostics to be consumed by `Reporter` ---------------------- //
2718
class Error(
@@ -86,44 +77,14 @@ object Diagnostic:
8677
}
8778

8879
class Diagnostic(
89-
val contained: Message,
80+
val msg: Message,
9081
val pos: SourcePosition,
9182
val level: Int
92-
) extends Exception with interfaces.Diagnostic {
93-
import Diagnostic._
94-
private var myMsg: String = null
95-
private var myIsNonSensical: Boolean = false
96-
private var myContained: Message = null
97-
83+
) extends Exception with interfaces.Diagnostic:
9884
override def position: Optional[interfaces.SourcePosition] =
9985
if (pos.exists && pos.source.exists) Optional.of(pos) else Optional.empty()
86+
override def message: String = msg.message
10087

101-
/** The message to report */
102-
def message: String = {
103-
if (myMsg == null) {
104-
myMsg = contained.msg.replaceAll("\u001B\\[[;\\d]*m", "")
105-
if (myMsg.contains(nonSensicalStartTag)) {
106-
myIsNonSensical = true
107-
// myMsg might be composed of several d"..." invocations -> nested
108-
// nonsensical tags possible
109-
myMsg =
110-
myMsg
111-
.replaceAllLiterally(nonSensicalStartTag, "")
112-
.replaceAllLiterally(nonSensicalEndTag, "")
113-
}
114-
}
115-
myMsg
116-
}
117-
118-
/** A message is non-sensical if it contains references to <nonsensical>
119-
* tags. Such tags are inserted by the error diagnostic framework if a
120-
* message contains references to internally generated error types. Normally
121-
* we want to suppress error messages referring to types like this because
122-
* they look weird and are normally follow-up errors to something that was
123-
* diagnosed before.
124-
*/
125-
def isNonSensical: Boolean = { message; myIsNonSensical }
126-
127-
override def toString: String = s"$getClass at $pos: ${message}"
88+
override def toString: String = s"$getClass at $pos: $message"
12889
override def getMessage(): String = message
129-
}
90+
end Diagnostic

compiler/src/dotty/tools/dotc/reporting/HideNonSensicalMessages.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ trait HideNonSensicalMessages extends Reporter {
1313
*/
1414
override def isHidden(dia: Diagnostic)(implicit ctx: Context): Boolean =
1515
super.isHidden(dia) || {
16-
dia.isNonSensical &&
16+
dia.msg.isNonSensical &&
1717
hasErrors && // if there are no errors yet, report even if diagnostic is non-sensical
1818
!ctx.settings.YshowSuppressedErrors.value
1919
}

compiler/src/dotty/tools/dotc/reporting/Message.scala

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import util.SourcePosition
77
import messages._
88

99
object Message {
10+
val nonSensicalStartTag: String = "<nonsensical>"
11+
val nonSensicalEndTag: String = "</nonsensical>"
12+
1013
/** This implicit conversion provides a fallback for error messages that have
1114
* not yet been ported to the new scheme. Comment out this `implicit def` to
1215
* see where old errors still exist
@@ -32,16 +35,18 @@ object Message {
3235
* used to reference documentation online
3336
*/
3437
abstract class Message(val errorId: ErrorMessageID) { self =>
38+
import Message._
3539

3640
/** The `msg` contains the diagnostic message e.g:
3741
*
3842
* > expected: String
3943
* > found: Int
4044
*
4145
* This message will be placed underneath the position given by the enclosing
42-
* `Diagnostic`
46+
* `Diagnostic`. The message is given in raw form, with possible embedded
47+
* <nonsensical> tags.
4348
*/
44-
def msg: String
49+
protected def msg: String
4550

4651
/** The kind of the error message is something like "Syntax" or "Type
4752
* Mismatch"
@@ -54,6 +59,35 @@ abstract class Message(val errorId: ErrorMessageID) { self =>
5459
*/
5560
def explanation: String
5661

62+
private var myMsg: String | Null = null
63+
private var myIsNonSensical: Boolean = false
64+
65+
/** The message with potential embedded <nonsensical> tags */
66+
def rawMessage = message
67+
68+
/** The message to report. <nonsensical> tags are filtered out */
69+
def message: String =
70+
if myMsg == null then
71+
myMsg =
72+
if msg.contains(nonSensicalStartTag) then
73+
myIsNonSensical = true
74+
// myMsg might be composed of several d"..." invocations -> nested
75+
// nonsensical tags possible
76+
msg
77+
.replaceAllLiterally(nonSensicalStartTag, "")
78+
.replaceAllLiterally(nonSensicalEndTag, "")
79+
else msg
80+
myMsg
81+
82+
/** A message is non-sensical if it contains references to <nonsensical>
83+
* tags. Such tags are inserted by the error diagnostic framework if a
84+
* message contains references to internally generated error types. Normally
85+
* we want to suppress error messages referring to types like this because
86+
* they look weird and are normally follow-up errors to something that was
87+
* diagnosed before.
88+
*/
89+
def isNonSensical: Boolean = { message; myIsNonSensical }
90+
5791
/** The implicit `Context` in messages is a large thing that we don't want
5892
* persisted. This method gets around that by duplicating the message,
5993
* forcing its `msg` and `explanation` vals and dropping the implicit context

compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ trait MessageRendering {
151151
val pos1 = pos.nonInlined
152152
val (srcBefore, srcAfter, offset) = sourceLines(pos1, diagnosticLevel)
153153
val marker = columnMarker(pos1, offset, diagnosticLevel)
154-
val err = errorMsg(pos1, msg.msg, offset)
154+
val err = errorMsg(pos1, msg.message, offset)
155155
sb.append((srcBefore ::: marker :: err :: outer(pos, " " * (offset - 1)) ::: srcAfter).mkString(EOL))
156156
}
157-
else sb.append(msg.msg)
157+
else sb.append(msg.message)
158158
sb.toString
159159
}
160160

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,8 +1066,8 @@ trait Applications extends Compatibility {
10661066
*/
10671067
def saysNotFound(state: TyperState, memberName: Name)(using Context): Boolean =
10681068
state.reporter.pendingMessages match
1069-
case msg :: Nil =>
1070-
msg.contained match
1069+
case dia :: Nil =>
1070+
dia.msg match
10711071
case msg: NotFoundMsg => memberName.isEmpty || msg.name == memberName
10721072
case _ => false
10731073
case _ => false

compiler/src/dotty/tools/repl/ReplDriver.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ class ReplDriver(settings: Array[String],
381381

382382
/** Render messages using the `MessageRendering` trait */
383383
private def renderMessage(dia: Diagnostic): Context => String =
384-
messageRenderer.messageAndPos(dia.contained, dia.pos, messageRenderer.diagnosticLevel(dia))(_)
384+
messageRenderer.messageAndPos(dia.msg, dia.pos, messageRenderer.diagnosticLevel(dia))(_)
385385

386386
/** Output errors to `out` */
387387
private def displayErrors(errs: Seq[Diagnostic])(implicit state: State): State = {

compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ trait ErrorMessagesTest extends DottyTest {
3636
if (!runCtx.reporter.hasErrors) new EmptyReport
3737
else {
3838
val rep = runCtx.reporter.asInstanceOf[StoreReporter]
39-
val msgs = rep.removeBufferedMessages(runCtx).map(_.contained).reverse
39+
val msgs = rep.removeBufferedMessages(runCtx).map(_.msg).reverse
4040
new Report(msgs, runCtx)
4141
}
4242
}

compiler/test/dotty/tools/dotc/reporting/TestReporter.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ extends Reporter with UniqueMessagePositions with HideNonSensicalMessages with M
5454

5555
/** Prints the message with the given position indication. */
5656
def printMessageAndPos(dia: Diagnostic, extra: String)(implicit ctx: Context): Unit = {
57-
val msg = messageAndPos(dia.contained, dia.pos, diagnosticLevel(dia))
57+
val msg = messageAndPos(dia.msg, dia.pos, diagnosticLevel(dia))
5858
val extraInfo = inlineInfo(dia.pos)
5959

6060
if (dia.level >= logLevel) {
@@ -69,7 +69,7 @@ extends Reporter with UniqueMessagePositions with HideNonSensicalMessages with M
6969
override def doReport(dia: Diagnostic)(implicit ctx: Context): Unit = {
7070

7171
// Here we add extra information that we should know about the error message
72-
val extra = dia.contained match {
72+
val extra = dia.msg match {
7373
case pm: PatternMatchExhaustivity => s": ${pm.uncovered}"
7474
case _ => ""
7575
}
@@ -127,7 +127,7 @@ object TestReporter {
127127
/** Prints the message with the given position indication in a simplified manner */
128128
override def printMessageAndPos(dia: Diagnostic, extra: String)(implicit ctx: Context): Unit = {
129129
def report() = {
130-
val msg = s"${dia.pos.line + 1}: " + dia.contained.kind + extra
130+
val msg = s"${dia.pos.line + 1}: " + dia.msg.kind + extra
131131
val extraInfo = inlineInfo(dia.pos)
132132

133133
writer.println(msg)

doc-tool/test/dotty/tools/dottydoc/DottyDocTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ trait DottyDocTest extends MessageRendering {
5454
System.err.println("reporter had errors:")
5555
ctx.reporter.removeBufferedMessages.foreach { msg =>
5656
System.err.println {
57-
messageAndPos(msg.contained, msg.pos, diagnosticLevel(msg))
57+
messageAndPos(msg.msg, msg.pos, diagnosticLevel(msg))
5858
}
5959
}
6060
}

language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,12 +709,13 @@ object DottyLanguageServer {
709709
}
710710
}
711711

712-
val message = dia.contained
712+
val message = dia.msg
713713
if (displayMessage(message, dia.pos.source)) {
714714
val code = message.errorId.errorNumber.toString
715715
range(dia.pos).map(r =>
716716
new lsp4j.Diagnostic(
717-
r, dia.message, severity(dia.level), /*source =*/ "", code))
717+
r, dia.message.replaceAll("\u001B\\[[;\\d]*m", ""),
718+
severity(dia.level), /*source =*/ "", code))
718719
} else {
719720
None
720721
}

sbt-bridge/src/xsbt/DelegatingReporter.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ public void printSummary(Context ctx) {
5757
delegate.printSummary();
5858
}
5959

60-
public void doReport(dotty.tools.dotc.reporting.Diagnostic cont, Context ctx) {
60+
public void doReport(dotty.tools.dotc.reporting.Diagnostic dia, Context ctx) {
6161
Severity severity;
62-
switch (cont.level()) {
62+
switch (dia.level()) {
6363
case Diagnostic.ERROR:
6464
severity = Severity.Error;
6565
break;
@@ -70,12 +70,12 @@ public void doReport(dotty.tools.dotc.reporting.Diagnostic cont, Context ctx) {
7070
severity = Severity.Info;
7171
break;
7272
default:
73-
throw new IllegalArgumentException("Bad diagnostic level: " + cont.level());
73+
throw new IllegalArgumentException("Bad diagnostic level: " + dia.level());
7474
}
7575

7676
Position position;
77-
if (cont.pos().exists()) {
78-
SourcePosition pos = cont.pos();
77+
if (dia.pos().exists()) {
78+
SourcePosition pos = dia.pos();
7979
SourceFile src = pos.source();
8080
position = new Position() {
8181
public Optional<java.io.File> sourceFile() {
@@ -123,10 +123,10 @@ public Optional<String> pointerSpace() {
123123
position = noPosition;
124124
}
125125

126-
Message message = cont.contained();
126+
Message message = dia.msg();
127127
StringBuilder rendered = new StringBuilder();
128-
rendered.append(messageAndPos(message, cont.pos(), diagnosticLevel(cont), ctx));
129-
boolean shouldExplain = new dotty.tools.dotc.reporting.Diagnostic.MessageContext(ctx).shouldExplain(cont);
128+
rendered.append(messageAndPos(message, dia.pos(), diagnosticLevel(dia), ctx));
129+
boolean shouldExplain = dotty.tools.dotc.reporting.Diagnostic.shouldExplain(dia, ctx);
130130
if (shouldExplain && !message.explanation().isEmpty()) {
131131
rendered.append(explanation(message, ctx));
132132
}

0 commit comments

Comments
 (0)