Skip to content

Commit 6397a0d

Browse files
committed
Support src filter in -WConf (Closes #17635) (#18783)
Fixes #18782 [Cherry-picked 86e2fe5][modified]
1 parent 26c09db commit 6397a0d

File tree

3 files changed

+135
-1
lines changed

3 files changed

+135
-1
lines changed

Diff for: compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

+4
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ private sealed trait WarningSettings:
248248
| - Message name: name=PureExpressionInStatementPosition
249249
| The message name is printed with the warning in verbose warning mode.
250250
|
251+
| - Source location: src=regex
252+
| The regex is evaluated against the full source path.
253+
|
251254
|In verbose warning mode the compiler prints matching filters for warnings.
252255
|Verbose mode can be enabled globally using `-Wconf:any:verbose`, or locally
253256
|using the @nowarn annotation (example: `@nowarn("v") def test = try 1`).
@@ -267,6 +270,7 @@ private sealed trait WarningSettings:
267270
|Examples:
268271
| - change every warning into an error: -Wconf:any:error
269272
| - silence deprecations: -Wconf:cat=deprecation:s
273+
| - silence warnings in src_managed directory: -Wconf:src=src_managed/.*:s
270274
|
271275
|Note: on the command-line you might need to quote configurations containing `*` or `&`
272276
|to prevent the shell from expanding patterns.""".stripMargin,

Diff for: compiler/src/dotty/tools/dotc/reporting/WConf.scala

+14-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ package reporting
55
import scala.language.unsafeNulls
66

77
import dotty.tools.dotc.core.Contexts.*
8-
import dotty.tools.dotc.util.SourcePosition
8+
import dotty.tools.dotc.util.{NoSourcePosition, SourcePosition}
9+
import dotty.tools.dotc.interfaces.SourceFile
10+
import dotty.tools.dotc.reporting.MessageFilter.SourcePattern
911

1012
import java.util.regex.PatternSyntaxException
1113
import scala.annotation.internal.sharable
@@ -21,11 +23,19 @@ enum MessageFilter:
2123
val noHighlight = message.msg.message.replaceAll("\\e\\[[\\d;]*[^\\d;]","")
2224
pattern.findFirstIn(noHighlight).nonEmpty
2325
case MessageID(errorId) => message.msg.errorId == errorId
26+
case SourcePattern(pattern) =>
27+
val source = message.position.orElse(NoSourcePosition).source()
28+
val path = source.jfile()
29+
.map(_.toPath.toAbsolutePath.toUri.normalize().getRawPath)
30+
.orElse(source.path())
31+
pattern.findFirstIn(path).nonEmpty
32+
2433
case None => false
2534

2635
case Any, Deprecated, Feature, Unchecked, None
2736
case MessagePattern(pattern: Regex)
2837
case MessageID(errorId: ErrorMessageID)
38+
case SourcePattern(pattern: Regex)
2939

3040
enum Action:
3141
case Error, Warning, Verbose, Info, Silent
@@ -84,6 +94,9 @@ object WConf:
8494
case "feature" => Right(Feature)
8595
case "unchecked" => Right(Unchecked)
8696
case _ => Left(s"unknown category: $conf")
97+
98+
case "src" => regex(conf).map(SourcePattern.apply)
99+
87100
case _ => Left(s"unknown filter: $filter")
88101
case _ => Left(s"unknown filter: $s")
89102

Diff for: compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala

+117
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@ import CommandLineParser.tokenize
55
import Settings._
66

77
import org.junit.Test
8+
import org.junit.Ignore
89
import org.junit.Assert._
910
import core.Decorators.toMessage
11+
import dotty.tools.io.{Path, PlainFile}
12+
13+
import java.net.URI
14+
import java.nio.file.Files
15+
import scala.util.Using
1016

1117
class ScalaSettingsTests:
1218

@@ -83,4 +89,115 @@ class ScalaSettingsTests:
8389
val nowr = new Diagnostic.Warning("This is a problem.".toMessage, util.NoSourcePosition)
8490
assertEquals(Action.Silent, sut.action(nowr))
8591

92+
@Ignore("LTS backport rejected: https://github.com/scala/scala3/pull/18503")
93+
@Test def `i18367 rightmost WConf flags take precedence over flags to the left`: Unit =
94+
import reporting.{Action, Diagnostic}
95+
val sets = new ScalaSettings
96+
val args = List("-Wconf:cat=deprecation:e", "-Wconf:cat=deprecation:s")
97+
val sumy = ArgsSummary(sets.defaultState, args, errors = Nil, warnings = Nil)
98+
val proc = sets.processArguments(sumy, processAll = true, skipped = Nil)
99+
val conf = sets.Wconf.valueIn(proc.sstate)
100+
val msg = "Don't use that!".toMessage
101+
val depr = new Diagnostic.DeprecationWarning(msg, util.NoSourcePosition)
102+
val sut = reporting.WConf.fromSettings(conf).getOrElse(???)
103+
assertEquals(Action.Silent, sut.action(depr))
104+
105+
106+
private def wconfSrcFilterTest(argsStr: String,
107+
warning: reporting.Diagnostic.Warning): Either[List[String], reporting.Action] =
108+
import reporting.Diagnostic
109+
val settings = new ScalaSettings
110+
val args = ArgsSummary(settings.defaultState, List(argsStr), errors = Nil, warnings = Nil)
111+
val proc = settings.processArguments(args, processAll = true, skipped = Nil)
112+
val wconfStr = settings.Wconf.valueIn(proc.sstate)
113+
val wconf = reporting.WConf.fromSettings(wconfStr)
114+
wconf.map(_.action(warning))
115+
116+
@Test def `WConf src filter silences warnings from a matching path for virtual file`: Unit =
117+
val result = wconfSrcFilterTest(
118+
argsStr = "-Wconf:src=path/.*:s",
119+
warning = reporting.Diagnostic.Warning(
120+
"A warning".toMessage,
121+
util.SourcePosition(
122+
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
123+
span = util.Spans.Span(1L)
124+
)
125+
)
126+
)
127+
assertEquals(result, Right(reporting.Action.Silent))
128+
129+
@Test def `WConf src filter doesn't silence warnings from a non-matching path`: Unit =
130+
val result = wconfSrcFilterTest(
131+
argsStr = "-Wconf:src=another/.*:s",
132+
warning = reporting.Diagnostic.Warning(
133+
"A warning".toMessage,
134+
util.SourcePosition(
135+
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
136+
span = util.Spans.Span(1L)
137+
)
138+
)
139+
)
140+
assertEquals(result, Right(reporting.Action.Warning))
141+
142+
@Test def `WConf src filter silences warnings from a matching path for real file`: Unit =
143+
val result = Using.resource(Files.createTempFile("myfile", ".scala").nn) { file =>
144+
wconfSrcFilterTest(
145+
argsStr = "-Wconf:src=myfile.*?\\.scala:s",
146+
warning = reporting.Diagnostic.Warning(
147+
"A warning".toMessage,
148+
util.SourcePosition(
149+
source = util.SourceFile(new PlainFile(Path(file)), "UTF-8"),
150+
span = util.Spans.Span(1L)
151+
)
152+
)
153+
)
154+
}(Files.deleteIfExists(_))
155+
assertEquals(result, Right(reporting.Action.Silent))
156+
157+
@Test def `WConf src filter doesn't silence warnings from a non-matching path for real file`: Unit =
158+
val result = Using.resource(Files.createTempFile("myfile", ".scala").nn) { file =>
159+
wconfSrcFilterTest(
160+
argsStr = "-Wconf:src=another.*?\\.scala:s",
161+
warning = reporting.Diagnostic.Warning(
162+
"A warning".toMessage,
163+
util.SourcePosition(
164+
source = util.SourceFile(new PlainFile(Path(file)), "UTF-8"),
165+
span = util.Spans.Span(1L)
166+
)
167+
)
168+
)
169+
}(Files.deleteIfExists(_))
170+
assertEquals(result, Right(reporting.Action.Warning))
171+
172+
@Test def `WConf src filter reports an error on an invalid regex`: Unit =
173+
val result = wconfSrcFilterTest(
174+
argsStr = """-Wconf:src=\:s""",
175+
warning = reporting.Diagnostic.Warning(
176+
"A warning".toMessage,
177+
util.SourcePosition(
178+
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
179+
span = util.Spans.Span(1L)
180+
)
181+
),
182+
)
183+
assertTrue(
184+
result.left.exists(errors =>
185+
errors.sizeIs == 1 && errors.headOption.exists(_.startsWith("invalid pattern"))
186+
)
187+
)
188+
189+
@Ignore("LTS backport rejected: https://github.com/scala/scala3/pull/18503")
190+
@Test def `WConf src filter can be mixed with other filters with rightmost taking precedence`: Unit =
191+
val result = wconfSrcFilterTest(
192+
argsStr = "-Wconf:src=.*:s,cat=deprecation:e",
193+
warning = reporting.Diagnostic.DeprecationWarning(
194+
"A warning".toMessage,
195+
util.SourcePosition(
196+
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
197+
span = util.Spans.Span(1L)
198+
)
199+
)
200+
)
201+
assertEquals(result, Right(reporting.Action.Error))
202+
86203
end ScalaSettingsTests

0 commit comments

Comments
 (0)