Skip to content

Commit ccbe7da

Browse files
committed
nowarn cleanups, fixes, tests
- undo ansi escapes before matching the nowarn msg=regex - first tests for nowarn in parser, typer, refchecks warnings - handle summarized conditional warnings in one place
1 parent 2ca3ade commit ccbe7da

File tree

11 files changed

+101
-70
lines changed

11 files changed

+101
-70
lines changed

compiler/src/dotty/tools/dotc/report.scala

+1-9
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,7 @@ object report:
2121
ctx.reporter.report(new Info(msg, pos.sourcePos))
2222

2323
private def issueWarning(warning: Warning)(using Context): Unit =
24-
if (!ctx.settings.silentWarnings.value)
25-
if (ctx.settings.XfatalWarnings.value)
26-
warning match {
27-
case warning: ConditionalWarning if !warning.enablingOption.value =>
28-
ctx.reporter.report(warning) // conditional warnings that are not enabled are not fatal
29-
case _ =>
30-
ctx.reporter.report(warning.toError)
31-
}
32-
else ctx.reporter.report(warning)
24+
ctx.reporter.report(warning)
3325

3426
def deprecationWarning(msg: Message, pos: SrcPos = NoSourcePosition)(using Context): Unit =
3527
issueWarning(new DeprecationWarning(msg, pos.sourcePos))

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

+3-8
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,16 @@ class ConsoleReporter(
2121

2222
/** Prints the message with the given position indication. */
2323
def doReport(dia: Diagnostic)(using Context): Unit = {
24-
val didPrint = dia match {
24+
dia match
2525
case dia: Error =>
2626
printMessage(messageAndPos(dia.msg, dia.pos, diagnosticLevel(dia)))
2727
if (ctx.settings.Xprompt.value) Reporter.displayPrompt(reader, writer)
28-
true
29-
case dia: ConditionalWarning if !dia.enablingOption.value =>
30-
false
3128
case dia =>
3229
printMessage(messageAndPos(dia.msg, dia.pos, diagnosticLevel(dia)))
33-
true
34-
}
3530

36-
if (didPrint && shouldExplain(dia))
31+
if shouldExplain(dia) then
3732
printMessage(explanation(dia.msg))
38-
else if (didPrint && dia.msg.canExplain)
33+
else if dia.msg.canExplain then
3934
printMessage("\nlonger explanation available when compiling with `-explain`")
4035
}
4136

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

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ object Diagnostic:
3737
) extends Diagnostic(msg, pos, WARNING) {
3838
def toError: Error = new Error(msg, pos)
3939
def toInfo: Info = new Info(msg, pos)
40+
def isSummarizedConditional(using Context): Boolean = false
4041
}
4142

4243
class Info(
@@ -49,6 +50,7 @@ object Diagnostic:
4950
pos: SourcePosition
5051
) extends Warning(msg, pos) {
5152
def enablingOption(using Context): Setting[Boolean]
53+
override def isSummarizedConditional(using Context): Boolean = !enablingOption.value
5254
}
5355

5456
class FeatureWarning(

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

+32-35
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,7 @@ object Reporter {
2121
/** Convert a SimpleReporter into a real Reporter */
2222
def fromSimpleReporter(simple: interfaces.SimpleReporter): Reporter =
2323
new Reporter with UniqueMessagePositions with HideNonSensicalMessages {
24-
override def doReport(dia: Diagnostic)(using Context): Unit = dia match {
25-
case dia: ConditionalWarning if !dia.enablingOption.value =>
26-
case _ =>
27-
simple.report(dia)
28-
}
24+
override def doReport(dia: Diagnostic)(using Context): Unit = simple.report(dia)
2925
}
3026

3127
/** A reporter that ignores reports, and doesn't record errors */
@@ -143,47 +139,48 @@ abstract class Reporter extends interfaces.ReporterResult {
143139
def issueIfNotSuppressed(dia: Diagnostic)(using Context): Unit =
144140
def go() =
145141
import Action._
146-
val toReport = dia match {
147-
case w: Warning => WConf.parsed.action(dia) match {
148-
case Silent => None
149-
case Info => Some(w.toInfo)
150-
case Warning => Some(w)
151-
case Error => Some(w.toError)
152-
}
142+
143+
val toReport = dia match
144+
case w: Warning =>
145+
if ctx.settings.silentWarnings.value then None
146+
else if ctx.settings.XfatalWarnings.value && !w.isSummarizedConditional then Some(w.toError)
147+
else WConf.parsed.action(dia) match
148+
case Silent => None
149+
case Info => Some(w.toInfo)
150+
case Warning => Some(w)
151+
case Error => Some(w.toError)
153152
case _ => Some(dia)
153+
154+
toReport foreach {
155+
case cw: ConditionalWarning if cw.isSummarizedConditional =>
156+
val key = cw.enablingOption.name
157+
unreportedWarnings =
158+
unreportedWarnings.updated(key, unreportedWarnings.getOrElse(key, 0) + 1)
159+
case d if !isHidden(d) =>
160+
withMode(Mode.Printing)(doReport(d))
161+
d match {
162+
case _: Warning => _warningCount += 1
163+
case e: Error =>
164+
errors = e :: errors
165+
_errorCount += 1
166+
case _: Info => // nothing to do here
167+
// match error if d is something else
168+
}
169+
case _ => // hidden
154170
}
155-
for (d <- toReport) {
156-
withMode(Mode.Printing)(doReport(d))
157-
d match
158-
case cw: ConditionalWarning if !cw.enablingOption.value =>
159-
val key = cw.enablingOption.name
160-
unreportedWarnings =
161-
unreportedWarnings.updated(key, unreportedWarnings.getOrElse(key, 0) + 1)
162-
case _: Warning => _warningCount += 1
163-
case e: Error =>
164-
errors = e :: errors
165-
_errorCount += 1
166-
case _: Info => // nothing to do here
167-
// match error if d is something else
168-
}
171+
end go
169172

170-
dia match {
173+
dia match
171174
case w: Warning if ctx.run != null =>
172175
val sup = ctx.run.suppressions
173176
if sup.suppressionsComplete(w.pos.source) then
174177
if !sup.isSuppressed(w) then go()
175178
else
176179
sup.addSuspendedMessage(w)
177180
case _ => go()
178-
}
181+
end issueIfNotSuppressed
179182

180-
def report(dia: Diagnostic)(using Context): Unit =
181-
val isSummarized = dia match
182-
case cw: ConditionalWarning => !cw.enablingOption.value
183-
case _ => false
184-
// avoid isHidden test for summarized warnings so that message is not forced
185-
if isSummarized || !isHidden(dia) then
186-
issueIfNotSuppressed(dia)
183+
def report(dia: Diagnostic)(using Context): Unit = issueIfNotSuppressed(dia)
187184

188185
def incomplete(dia: Diagnostic)(using Context): Unit =
189186
incompleteHandler(dia, ctx)

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ enum MessageFilter:
1515
case Any => true
1616
case Deprecated => message.isInstanceOf[Diagnostic.DeprecationWarning]
1717
case Feature => message.isInstanceOf[Diagnostic.FeatureWarning]
18-
case MessagePattern(pattern) => pattern.findFirstIn(message.msg.rawMessage).nonEmpty
18+
case MessagePattern(pattern) =>
19+
val noHighlight = message.msg.rawMessage.replaceAll("\\e\\[[\\d;]*[^\\d;]","")
20+
pattern.findFirstIn(noHighlight).nonEmpty
21+
case None => false
1922
}
20-
case Any, Deprecated, Feature
23+
case Any, Deprecated, Feature, None
2124
case MessagePattern(pattern: Regex)
2225

2326
enum Action:

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

+8-8
Original file line numberDiff line numberDiff line change
@@ -2106,7 +2106,7 @@ class Typer extends Namer
21062106
for (annot <- mdef.mods.annotations)
21072107
val annot1 = typedAnnotation(annot)(using annotCtx)
21082108
checkAnnotApplicable(annot1, sym)
2109-
if (Annotations.annotClass(annot1) == defn.NowarnAnnot)
2109+
if Annotations.annotClass(annot1) == defn.NowarnAnnot then
21102110
registerNowarn(annot1, mdef)
21112111
}
21122112

@@ -2118,21 +2118,21 @@ class Typer extends Namer
21182118
def argPos = annot.argument(0).getOrElse(tree).sourcePos
21192119
val filters =
21202120
if annot.arguments.isEmpty then List(MessageFilter.Any)
2121-
else annot.argumentConstantString(0) match {
2122-
case None => annot.argument(0) match {
2123-
case Some(t: Select) if t.name.toString == "$lessinit$greater$default$1" => List(MessageFilter.Any)
2121+
else annot.argumentConstantString(0) match
2122+
case None => annot.argument(0) match
2123+
case Some(t: Select) if t.name.is(DefaultGetterName) => List(MessageFilter.Any)
21242124
case _ =>
21252125
report.warning(s"filter needs to be a compile-time constant string", argPos)
21262126
Nil
2127-
}
21282127
case Some(s) =>
21292128
if s.isEmpty then Nil
21302129
else
21312130
val (ms, fs) = s.split('&').map(WConf.parseFilter).toList.partitionMap(identity)
2132-
if (ms.nonEmpty)
2131+
if ms.nonEmpty then
21332132
report.warning(s"Invalid message filter\n${ms.mkString("\n")}", argPos)
2134-
fs
2135-
}
2133+
List(MessageFilter.None)
2134+
else
2135+
fs
21362136
val range = mdef.sourcePos
21372137
ctx.run.suppressions.addSuppression(Suppression(tree.sourcePos, filters, range.start, range.end))
21382138

compiler/test/dotty/tools/dotc/CompilationTests.scala

+1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class CompilationTests {
128128
compileFilesInDir("tests/neg-no-kind-polymorphism", defaultOptions and "-Yno-kind-polymorphism"),
129129
compileFilesInDir("tests/neg-custom-args/deprecation", defaultOptions.and("-Xfatal-warnings", "-deprecation")),
130130
compileFilesInDir("tests/neg-custom-args/fatal-warnings", defaultOptions.and("-Xfatal-warnings")),
131+
compileFilesInDir("tests/neg-custom-args/nowarn", defaultOptions.and("-deprecation", "-Werror")),
131132
compileFilesInDir("tests/neg-custom-args/erased", defaultOptions.and("-language:experimental.erasedDefinitions")),
132133
compileFilesInDir("tests/neg-custom-args/allow-double-bindings", allowDoubleBindings),
133134
compileFilesInDir("tests/neg-custom-args/allow-deep-subtypes", allowDeepSubtypes),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-- [E000] Syntax Error: tests/neg-custom-args/nowarn/nowarn-parser-typer.scala:8:10 ------------------------------------
2+
8 |def t1a = try 1 // error, parser warning
3+
| ^^^^^
4+
| A try without catch or finally is equivalent to putting
5+
| its body in a block; no exceptions are handled.
6+
7+
longer explanation available when compiling with `-explain`
8+
-- [E129] Potential Issue Error: tests/neg-custom-args/nowarn/nowarn-parser-typer.scala:16:11 --------------------------
9+
16 |def t3 = { 1; 2 } // error, the invalid nowarn doesn't silence this warning
10+
| ^
11+
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
12+
13+
longer explanation available when compiling with `-explain`
14+
-- Error: tests/neg-custom-args/nowarn/nowarn-parser-typer.scala:15:8 --------------------------------------------------
15+
15 |@nowarn("wat?") // error, invalid filter
16+
| ^^^^^^
17+
| Invalid message filter
18+
| unknown filter: wat?
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import annotation.nowarn
2+
3+
// parser warnigns are buffered until the end of typer (where `@nowarn` annotations are handled).
4+
5+
// separate test file, because with `-Werror` this test only runs to the end of type checking.
6+
// later warnings (eg deprecations in refchecks) are not issued.
7+
8+
def t1a = try 1 // error, parser warning
9+
@nowarn("msg=try without catch") def t1b = try 1
10+
11+
@deprecated def f = 0
12+
13+
def t2 = f // not reported because refchecks doesn't run
14+
15+
@nowarn("wat?") // error, invalid filter
16+
def t3 = { 1; 2 } // error, the invalid nowarn doesn't silence this warning
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-- Error: tests/neg-custom-args/nowarn/nowarn-refchecks.scala:5:9 ------------------------------------------------------
2+
5 |def t1 = f // error
3+
| ^
4+
| method f is deprecated
5+
-- Error: tests/neg-custom-args/nowarn/nowarn-refchecks.scala:9:29 -----------------------------------------------------
6+
9 |@nowarn("msg=fish") def t4 = f // error
7+
| ^
8+
| method f is deprecated
9+
-- Error: tests/neg-custom-args/nowarn/nowarn-refchecks.scala:15:9 -----------------------------------------------------
10+
15 |def t9 = f: @nowarn("msg=fish") // error
11+
| ^
12+
| method f is deprecated

tests/neg/nowarn.scala renamed to tests/neg-custom-args/nowarn/nowarn-refchecks.scala

+3-8
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,16 @@ import annotation.nowarn
22

33
@deprecated def f = 1
44

5-
def t1 = f // warn
5+
def t1 = f // error
66

77
@nowarn("cat=deprecation") def t2 = f
88
@nowarn("msg=deprecated") def t3 = f
9-
@nowarn("msg=fish") def t4 = f // warn
9+
@nowarn("msg=fish") def t4 = f // error
1010
@nowarn("") def t5 = f
1111
@nowarn def t6 = f
1212

1313
def t7 = f: @nowarn("cat=deprecation")
1414
def t8 = f: @nowarn("msg=deprecated")
15-
def t9 = f: @nowarn("msg=fish") // warn
15+
def t9 = f: @nowarn("msg=fish") // error
1616
def t10 = f: @nowarn("")
1717
def t11 = f: @nowarn
18-
19-
def t12 = List(List(1): _*) // warn -source:future-migration
20-
@nowarn("msg=vararg splices") def t13 = List(List(1): _*)
21-
22-
class K { override def blup = 1 } // error

0 commit comments

Comments
 (0)