Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport "Support src filter in -WConf (Closes #17635)" to LTS #21087

Merged
merged 1 commit into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -248,6 +248,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 @@ -267,6 +270,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
117 changes: 117 additions & 0 deletions compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ import CommandLineParser.tokenize
import Settings._

import org.junit.Test
import org.junit.Ignore
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 @@ -83,4 +89,115 @@ class ScalaSettingsTests:
val nowr = new Diagnostic.Warning("This is a problem.".toMessage, util.NoSourcePosition)
assertEquals(Action.Silent, sut.action(nowr))

@Ignore("LTS backport rejected: https://github.com/scala/scala3/pull/18503")
@Test def `i18367 rightmost WConf flags take precedence over flags to the left`: Unit =
import reporting.{Action, Diagnostic}
val sets = new ScalaSettings
val args = List("-Wconf:cat=deprecation:e", "-Wconf:cat=deprecation:s")
val sumy = ArgsSummary(sets.defaultState, args, errors = Nil, warnings = Nil)
val proc = sets.processArguments(sumy, processAll = true, skipped = Nil)
val conf = sets.Wconf.valueIn(proc.sstate)
val msg = "Don't use that!".toMessage
val depr = new Diagnostic.DeprecationWarning(msg, util.NoSourcePosition)
val sut = reporting.WConf.fromSettings(conf).getOrElse(???)
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"))
)
)

@Ignore("LTS backport rejected: https://github.com/scala/scala3/pull/18503")
@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