Skip to content

Commit dd2e03b

Browse files
committed
Support src filter in -WConf (Closes #18782)
1 parent c0eae68 commit dd2e03b

File tree

3 files changed

+86
-1
lines changed

3 files changed

+86
-1
lines changed

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

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

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

+21-1
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,20 @@ 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
1214
import scala.util.matching.Regex
15+
import scala.jdk.OptionConverters._
16+
import scala.collection.mutable
1317

1418
enum MessageFilter:
19+
20+
private val sourcePatternCache = mutable.Map.empty[SourceFile, Boolean]
21+
1522
def matches(message: Diagnostic): Boolean = this match
1623
case Any => true
1724
case Deprecated => message.isInstanceOf[Diagnostic.DeprecationWarning]
@@ -21,11 +28,21 @@ enum MessageFilter:
2128
val noHighlight = message.msg.message.replaceAll("\\e\\[[\\d;]*[^\\d;]","")
2229
pattern.findFirstIn(noHighlight).nonEmpty
2330
case MessageID(errorId) => message.msg.errorId == errorId
31+
case SourcePattern(pattern) =>
32+
val source = message.position.orElse(NoSourcePosition).source()
33+
sourcePatternCache.getOrElseUpdate(source, {
34+
val path = source.jfile()
35+
.map(_.toPath.toAbsolutePath.toUri.normalize().getRawPath)
36+
.orElse(source.path())
37+
pattern.findFirstIn(path).nonEmpty
38+
})
39+
2440
case None => false
2541

2642
case Any, Deprecated, Feature, Unchecked, None
2743
case MessagePattern(pattern: Regex)
2844
case MessageID(errorId: ErrorMessageID)
45+
case SourcePattern(pattern: Regex)
2946

3047
enum Action:
3148
case Error, Warning, Verbose, Info, Silent
@@ -84,6 +101,9 @@ object WConf:
84101
case "feature" => Right(Feature)
85102
case "unchecked" => Right(Unchecked)
86103
case _ => Left(s"unknown category: $conf")
104+
105+
case "src" => regex(conf).map(SourcePattern.apply)
106+
87107
case _ => Left(s"unknown filter: $filter")
88108
case _ => Left(s"unknown filter: $s")
89109

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

+61
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ import Settings._
77
import org.junit.Test
88
import org.junit.Assert._
99
import core.Decorators.toMessage
10+
import dotty.tools.io.{Path, PlainFile}
11+
12+
import java.net.URI
13+
import java.nio.file.Files
14+
import scala.util.Using
1015

1116
class ScalaSettingsTests:
1217

@@ -96,5 +101,61 @@ class ScalaSettingsTests:
96101
assertEquals(Action.Silent, sut.action(depr))
97102

98103

104+
private def wconfSrcFilterTest(argsStr: String, source: util.SourceFile, expectedAction: reporting.Action): Unit =
105+
import reporting.Diagnostic
106+
val settings = new ScalaSettings
107+
val args = ArgsSummary(settings.defaultState, List(argsStr), errors = Nil, warnings = Nil)
108+
val proc = settings.processArguments(args, processAll = true, skipped = Nil)
109+
val wconfStr = settings.Wconf.valueIn(proc.sstate)
110+
val warning = new Diagnostic.Warning(
111+
"A warning".toMessage,
112+
util.SourcePosition(
113+
source = source,
114+
span = util.Spans.Span(1L)
115+
)
116+
)
117+
val wconf = reporting.WConf.fromSettings(wconfStr)
118+
assertEquals(Right(expectedAction), wconf.map(_.action(warning)))
119+
120+
@Test def `WConf src filter silences warnings from a matching path for virtual file`: Unit =
121+
wconfSrcFilterTest(
122+
argsStr = "-Wconf:src=path/.*:s",
123+
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
124+
expectedAction = reporting.Action.Silent
125+
)
126+
127+
@Test def `WConf src filter doesn't silence warnings from a non-matching path`: Unit =
128+
wconfSrcFilterTest(
129+
argsStr = "-Wconf:src=another/.*:s",
130+
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
131+
expectedAction = reporting.Action.Warning
132+
)
133+
134+
@Test def `WConf src filter silences warnings from a matching path for real file`: Unit =
135+
Using.resource(Files.createTempFile("myfile", ".scala").nn) { file =>
136+
wconfSrcFilterTest(
137+
argsStr = "-Wconf:src=myfile.*?\\.scala:s",
138+
source = util.SourceFile(new PlainFile(Path(file)), "UTF-8"),
139+
expectedAction = reporting.Action.Silent
140+
)
141+
}(Files.deleteIfExists(_))
142+
143+
@Test def `WConf src filter doesn't silence warnings from a non-matching path for real file`: Unit =
144+
Using.resource(Files.createTempFile("myfile", ".scala").nn) { file =>
145+
wconfSrcFilterTest(
146+
argsStr = "-Wconf:src=another.*?\\.scala:s",
147+
source = util.SourceFile(new PlainFile(Path(file)), "UTF-8"),
148+
expectedAction = reporting.Action.Warning
149+
)
150+
}(Files.deleteIfExists(_))
151+
152+
@Test def `WConf src filter works when cache is not empty`: Unit =
153+
(0 to 1).foreach { _ =>
154+
wconfSrcFilterTest(
155+
argsStr = "-Wconf:src=path/.*:s",
156+
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
157+
expectedAction = reporting.Action.Silent
158+
)
159+
}
99160

100161
end ScalaSettingsTests

0 commit comments

Comments
 (0)