Skip to content

Commit

Permalink
Support src filter in -WConf (Closes #18782)
Browse files Browse the repository at this point in the history
  • Loading branch information
povder committed Mar 4, 2024
1 parent c7a0459 commit d65e8f8
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 1 deletion.
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ private sealed trait WarningSettings:
| - Message name: name=PureExpressionInStatementPosition
| The message name is printed with the warning in verbose warning mode.
|
| - Source location: src=regex
| The regex is evaluated against the full source path.
|
|In verbose warning mode the compiler prints matching filters for warnings.
|Verbose mode can be enabled globally using `-Wconf:any:verbose`, or locally
|using the @nowarn annotation (example: `@nowarn("v") def test = try 1`).
Expand All @@ -271,6 +274,7 @@ private sealed trait WarningSettings:
|Examples:
| - change every warning into an error: -Wconf:any:error
| - silence deprecations: -Wconf:cat=deprecation:s
| - silence warnings in src_managed directory: -Wconf:src=src_managed/.*:s
|
|Note: on the command-line you might need to quote configurations containing `*` or `&`
|to prevent the shell from expanding patterns.""".stripMargin,
Expand Down
15 changes: 14 additions & 1 deletion compiler/src/dotty/tools/dotc/reporting/WConf.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ package reporting
import scala.language.unsafeNulls

import dotty.tools.dotc.core.Contexts.*
import dotty.tools.dotc.util.SourcePosition
import dotty.tools.dotc.util.{NoSourcePosition, SourcePosition}
import dotty.tools.dotc.interfaces.SourceFile
import dotty.tools.dotc.reporting.MessageFilter.SourcePattern

import java.util.regex.PatternSyntaxException
import scala.annotation.internal.sharable
Expand All @@ -21,11 +23,19 @@ enum MessageFilter:
val noHighlight = message.msg.message.replaceAll("\\e\\[[\\d;]*[^\\d;]","")
pattern.findFirstIn(noHighlight).nonEmpty
case MessageID(errorId) => message.msg.errorId == errorId
case SourcePattern(pattern) =>
val source = message.position.orElse(NoSourcePosition).source()
val path = source.jfile()
.map(_.toPath.toAbsolutePath.toUri.normalize().getRawPath)
.orElse(source.path())
pattern.findFirstIn(path).nonEmpty

case None => false

case Any, Deprecated, Feature, Unchecked, None
case MessagePattern(pattern: Regex)
case MessageID(errorId: ErrorMessageID)
case SourcePattern(pattern: Regex)

enum Action:
case Error, Warning, Verbose, Info, Silent
Expand Down Expand Up @@ -84,6 +94,9 @@ object WConf:
case "feature" => Right(Feature)
case "unchecked" => Right(Unchecked)
case _ => Left(s"unknown category: $conf")

case "src" => regex(conf).map(SourcePattern.apply)

case _ => Left(s"unknown filter: $filter")
case _ => Left(s"unknown filter: $s")

Expand Down
100 changes: 100 additions & 0 deletions compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import Settings._
import org.junit.Test
import org.junit.Assert._
import core.Decorators.toMessage
import dotty.tools.io.{Path, PlainFile}

import java.net.URI
import java.nio.file.Files
import scala.util.Using

class ScalaSettingsTests:

Expand Down Expand Up @@ -96,5 +101,100 @@ class ScalaSettingsTests:
assertEquals(Action.Silent, sut.action(depr))


private def wconfSrcFilterTest(argsStr: String,
warning: reporting.Diagnostic.Warning): Either[List[String], reporting.Action] =
import reporting.Diagnostic
val settings = new ScalaSettings
val args = ArgsSummary(settings.defaultState, List(argsStr), errors = Nil, warnings = Nil)
val proc = settings.processArguments(args, processAll = true, skipped = Nil)
val wconfStr = settings.Wconf.valueIn(proc.sstate)
val wconf = reporting.WConf.fromSettings(wconfStr)
wconf.map(_.action(warning))

@Test def `WConf src filter silences warnings from a matching path for virtual file`: Unit =
val result = wconfSrcFilterTest(
argsStr = "-Wconf:src=path/.*:s",
warning = reporting.Diagnostic.Warning(
"A warning".toMessage,
util.SourcePosition(
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
span = util.Spans.Span(1L)
)
)
)
assertEquals(result, Right(reporting.Action.Silent))

@Test def `WConf src filter doesn't silence warnings from a non-matching path`: Unit =
val result = wconfSrcFilterTest(
argsStr = "-Wconf:src=another/.*:s",
warning = reporting.Diagnostic.Warning(
"A warning".toMessage,
util.SourcePosition(
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
span = util.Spans.Span(1L)
)
)
)
assertEquals(result, Right(reporting.Action.Warning))

@Test def `WConf src filter silences warnings from a matching path for real file`: Unit =
val result = Using.resource(Files.createTempFile("myfile", ".scala").nn) { file =>
wconfSrcFilterTest(
argsStr = "-Wconf:src=myfile.*?\\.scala:s",
warning = reporting.Diagnostic.Warning(
"A warning".toMessage,
util.SourcePosition(
source = util.SourceFile(new PlainFile(Path(file)), "UTF-8"),
span = util.Spans.Span(1L)
)
)
)
}(Files.deleteIfExists(_))
assertEquals(result, Right(reporting.Action.Silent))

@Test def `WConf src filter doesn't silence warnings from a non-matching path for real file`: Unit =
val result = Using.resource(Files.createTempFile("myfile", ".scala").nn) { file =>
wconfSrcFilterTest(
argsStr = "-Wconf:src=another.*?\\.scala:s",
warning = reporting.Diagnostic.Warning(
"A warning".toMessage,
util.SourcePosition(
source = util.SourceFile(new PlainFile(Path(file)), "UTF-8"),
span = util.Spans.Span(1L)
)
)
)
}(Files.deleteIfExists(_))
assertEquals(result, Right(reporting.Action.Warning))

@Test def `WConf src filter reports an error on an invalid regex`: Unit =
val result = wconfSrcFilterTest(
argsStr = """-Wconf:src=\:s""",
warning = reporting.Diagnostic.Warning(
"A warning".toMessage,
util.SourcePosition(
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
span = util.Spans.Span(1L)
)
),
)
assertTrue(
result.left.exists(errors =>
errors.sizeIs == 1 && errors.headOption.exists(_.startsWith("invalid pattern"))
)
)

@Test def `WConf src filter can be mixed with other filters with rightmost taking precedence`: Unit =
val result = wconfSrcFilterTest(
argsStr = "-Wconf:src=.*:s,cat=deprecation:e",
warning = reporting.Diagnostic.DeprecationWarning(
"A warning".toMessage,
util.SourcePosition(
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
span = util.Spans.Span(1L)
)
)
)
assertEquals(result, Right(reporting.Action.Error))

end ScalaSettingsTests

0 comments on commit d65e8f8

Please sign in to comment.