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

Add origin filter to WConf, DeprecationWarning #21404

Merged
merged 3 commits into from
Aug 26, 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
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/config/CompilerCommand.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ abstract class CompilerCommand extends CliCommand:

final def helpMsg(using settings: ConcreteSettings)(using SettingsState, Context): String =
settings.allSettings.find(isHelping) match
case Some(s) => availableOptionsMsg(_ == s, showArgFileMsg = false)
case Some(s @ settings.language) => availableOptionsMsg(_ == s, showArgFileMsg = false)
case Some(s) => s.description
case _ =>
if (settings.help.value) usageMessage
else if (settings.Vhelp.value) vusageMessage
Expand Down
6 changes: 5 additions & 1 deletion compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ private sealed trait WarningSettings:
"patterns",
default = List(),
descr =
s"""Configure compiler warnings.
raw"""Configure compiler warnings.
|Syntax: -Wconf:<filters>:<action>,<filters>:<action>,...
|multiple <filters> are combined with &, i.e., <filter>&...&<filter>
|
Expand All @@ -254,6 +254,9 @@ private sealed trait WarningSettings:
| - Source location: src=regex
| The regex is evaluated against the full source path.
|
| - Origin of warning: origin=regex
| The regex must match the full name (`package.Class.method`) of the deprecated entity.
|
|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 @@ -273,6 +276,7 @@ private sealed trait WarningSettings:
|Examples:
| - change every warning into an error: -Wconf:any:error
| - silence deprecations: -Wconf:cat=deprecation:s
| - silence a deprecation: -Wconf:origin=java\.lang\.Thread\.getId: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 `&`
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/report.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ object report:
private def issueWarning(warning: Warning)(using Context): Unit =
ctx.reporter.report(warning)

def deprecationWarning(msg: Message, pos: SrcPos)(using Context): Unit =
issueWarning(new DeprecationWarning(msg, pos.sourcePos))
def deprecationWarning(msg: Message, pos: SrcPos, origin: String = "")(using Context): Unit =
issueWarning(new DeprecationWarning(msg, pos.sourcePos, origin))

def migrationWarning(msg: Message, pos: SrcPos)(using Context): Unit =
issueWarning(new MigrationWarning(msg, pos.sourcePos))
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ object Diagnostic:

class DeprecationWarning(
msg: Message,
pos: SourcePosition
pos: SourcePosition,
val origin: String
) extends ConditionalWarning(msg, pos) {
def enablingOption(using Context): Setting[Boolean] = ctx.settings.deprecation
}
Expand Down
39 changes: 22 additions & 17 deletions compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import util.{ SourcePosition, NoSourcePosition }
import util.Chars.{ LF, CR, FF, SU }
import scala.annotation.switch

import scala.collection.mutable
import scala.collection.mutable.StringBuilder

trait MessageRendering {
import Highlight.*
Expand Down Expand Up @@ -209,22 +209,27 @@ trait MessageRendering {
sb.toString
}

private def appendFilterHelp(dia: Diagnostic, sb: mutable.StringBuilder): Unit =
import dia.*
private def appendFilterHelp(dia: Diagnostic, sb: StringBuilder): Unit =
import dia.msg
val hasId = msg.errorId.errorNumber >= 0
val category = dia match {
case _: UncheckedWarning => "unchecked"
case _: DeprecationWarning => "deprecation"
case _: FeatureWarning => "feature"
case _ => ""
}
if (hasId || category.nonEmpty)
sb.append(EOL).append("Matching filters for @nowarn or -Wconf:")
if (hasId)
sb.append(EOL).append(" - id=E").append(msg.errorId.errorNumber)
sb.append(EOL).append(" - name=").append(msg.errorId.productPrefix.stripSuffix("ID"))
if (category.nonEmpty)
sb.append(EOL).append(" - cat=").append(category)
val (category, origin) = dia match
case _: UncheckedWarning => ("unchecked", "")
case w: DeprecationWarning => ("deprecation", w.origin)
case _: FeatureWarning => ("feature", "")
case _ => ("", "")
var entitled = false
def addHelp(what: String)(value: String): Unit =
if !entitled then
sb.append(EOL).append("Matching filters for @nowarn or -Wconf:")
entitled = true
sb.append(EOL).append(" - ").append(what).append(value)
if hasId then
addHelp("id=E")(msg.errorId.errorNumber.toString)
addHelp("name=")(msg.errorId.productPrefix.stripSuffix("ID"))
if category.nonEmpty then
addHelp("cat=")(category)
if origin.nonEmpty then
addHelp("origin=")(origin)

/** The whole message rendered from `msg` */
def messageAndPos(dia: Diagnostic)(using Context): String = {
Expand All @@ -236,7 +241,7 @@ trait MessageRendering {
else 0
given Level = Level(level)
given Offset = Offset(maxLineNumber.toString.length + 2)
val sb = mutable.StringBuilder()
val sb = StringBuilder()
val posString = posStr(pos, msg, diagnosticLevel(dia))
if (posString.nonEmpty) sb.append(posString).append(EOL)
if (pos.exists) {
Expand Down
9 changes: 7 additions & 2 deletions compiler/src/dotty/tools/dotc/reporting/WConf.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,27 @@ enum MessageFilter:
case Deprecated => message.isInstanceOf[Diagnostic.DeprecationWarning]
case Feature => message.isInstanceOf[Diagnostic.FeatureWarning]
case Unchecked => message.isInstanceOf[Diagnostic.UncheckedWarning]
case MessageID(errorId) => message.msg.errorId == errorId
case MessagePattern(pattern) =>
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 Origin(pattern) =>
message match
case message: Diagnostic.DeprecationWarning => pattern.findFirstIn(message.origin).nonEmpty
case _ => false
case None => false

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

enum Action:
case Error, Warning, Verbose, Info, Silent
Expand Down Expand Up @@ -96,6 +100,7 @@ object WConf:
case _ => Left(s"unknown category: $conf")

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

case _ => Left(s"unknown filter: $filter")
case _ => Left(s"unknown filter: $s")
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class CrossVersionChecks extends MiniPhase:
do
val msg = annot.argumentConstantString(0).map(msg => s": $msg").getOrElse("")
val since = annot.argumentConstantString(1).map(version => s" (since: $version)").getOrElse("")
report.deprecationWarning(em"inheritance from $psym is deprecated$since$msg", parent.srcPos)
report.deprecationWarning(em"inheritance from $psym is deprecated$since$msg", parent.srcPos, origin=psym.showFullName)
}

override def transformValDef(tree: ValDef)(using Context): ValDef =
Expand Down Expand Up @@ -171,7 +171,7 @@ object CrossVersionChecks:
def maybeWarn(annotee: Symbol, annot: Annotation) = if !skipWarning(sym) then
val message = annot.argumentConstantString(0).filter(!_.isEmpty).map(": " + _).getOrElse("")
val since = annot.argumentConstantString(1).filter(!_.isEmpty).map(" since " + _).getOrElse("")
report.deprecationWarning(em"${annotee.showLocated} is deprecated${since}${message}", pos)
report.deprecationWarning(em"${annotee.showLocated} is deprecated${since}${message}", pos, origin=annotee.showFullName)
sym.getAnnotation(defn.DeprecatedAnnot) match
case Some(annot) => maybeWarn(sym, annot)
case _ =>
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,9 @@ object RefChecks {
def overrideDeprecation(what: String, member: Symbol, other: Symbol, fix: String): Unit =
report.deprecationWarning(
em"overriding $what${infoStringWithLocation(other)} is deprecated;\n ${infoString(member)} should be $fix.",
if member.owner == clazz then member.srcPos else clazz.srcPos)
if member.owner == clazz then member.srcPos else clazz.srcPos,
origin = other.showFullName
)

def autoOverride(sym: Symbol) =
sym.is(Synthetic) && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class ScalaSettingsTests:
val conf = sets.Wconf.valueIn(proc.sstate)
val sut = reporting.WConf.fromSettings(conf).getOrElse(???)
val msg = "There was a problem!".toMessage
val depr = new Diagnostic.DeprecationWarning(msg, util.NoSourcePosition)
val depr = new Diagnostic.DeprecationWarning(msg, util.NoSourcePosition, origin="")
assertEquals(Action.Silent, sut.action(depr))
val feat = new Diagnostic.FeatureWarning(msg, util.NoSourcePosition)
assertEquals(Action.Error, sut.action(feat))
Expand Down Expand Up @@ -197,7 +197,7 @@ class ScalaSettingsTests:
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 depr = new Diagnostic.DeprecationWarning(msg, util.NoSourcePosition, origin="")
val sut = reporting.WConf.fromSettings(conf).getOrElse(???)
assertEquals(Action.Silent, sut.action(depr))

Expand Down Expand Up @@ -293,7 +293,8 @@ class ScalaSettingsTests:
util.SourcePosition(
source = util.SourceFile.virtual(new URI("file:///some/path/file.scala"), ""),
span = util.Spans.Span(1L)
)
),
origin="",
)
)
assertEquals(result, Right(reporting.Action.Error))
Expand Down
14 changes: 14 additions & 0 deletions tests/warn/deprecated-origin-verbose.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- Deprecation Warning: tests/warn/deprecated-origin-verbose.scala:12:18 -----------------------------------------------
12 | class D extends C // warn
| ^
| class C in package p is deprecated since 1.0: Old style
Matching filters for @nowarn or -Wconf:
- cat=deprecation
- origin=p.C
-- Deprecation Warning: tests/warn/deprecated-origin-verbose.scala:13:20 -----------------------------------------------
13 | class Oil extends Crude // warn
| ^^^^^
| class Crude in package p is deprecated since 1.0: Bad style
Matching filters for @nowarn or -Wconf:
- cat=deprecation
- origin=p.Crude
15 changes: 15 additions & 0 deletions tests/warn/deprecated-origin-verbose.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//> using options -deprecation -Wconf:any:verbose

package p:
@deprecated("Old style", since="1.0")
class C
@deprecated("Bad style", since="1.0")
class Crude

package q:
import annotation.*
import p.*
class D extends C // warn
class Oil extends Crude // warn
@nowarn("""origin=p\.Crude""")
class Language extends Crude // nowarn obvs
15 changes: 15 additions & 0 deletions tests/warn/deprecated-origin.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//> using options -deprecation -Wconf:origin=p\.C$:s

package p:
@deprecated("Old style", since="1.0")
class C
@deprecated("Bad style", since="1.0")
class Crude

package q:
import annotation.*
import p.*
class D extends C // nowarn - C$ pattern avoids matching Crude
class Oil extends Crude // warn
@nowarn("""origin=p\.Crude""")
class Language extends Crude // nowarn obvs
Loading