-
Notifications
You must be signed in to change notification settings - Fork 14
Description
Motivation
Broken Windows Theory: clean codebases that keep warnings under control encourage to keep the codebase clean.
-Werror
can often not be enabled, for example due to non-avoidable deprecation warnings when cross-building.
This proposal has two goals: make warnings globally configurable using compiler flags, and allow suppressing warnings locally.
What we have today
@unchecked
in pattern matching- on scrutinee: no exhaustivity check
- in type patterns: no warning about unchecked erased types
@unused
: omit-Ywarn-unused
/-Xlint:unused
warnings for annotated declarations (added in Annotationunused
to suppress warnings scala#7623, discussion at Helper for unused parameters bug#10790)@migration
- with
-Xmigration:<fromScalaVersion>
, show warnings that have a version bigger thanfromScalaVersion
- not for everyone to use, the annotation is
private[scala]
- with
Considerations for new functionality
Global Configuration: allow users to configure what is reported as error, warning, info, or not at all.
- Generalization of
-Werror
, which escalates all warnings -Wconfig
was proposed in deprecatedError + restricted annotation scala#7790 (comment)- only for configuring the propsed
@restricted
warnings
- only for configuring the propsed
- deprecations
- configure by
since
version -- for cross-building, upgrading (adriaan has a WIP, see below) - difficulty:
since
is not only used in standard library, each library has its own version numbers - scaladoc of
deprecated
says "Library authors should prepend the name of their library to the version number"
- configure by
- lint, other flags in
-W
- configure by category
- Compiler warnings
- configure by regex match?
- Compiler errors: are there any that can be downgraded to warnings?
Managing many errors/warnings
-Xmaxerrs
,-Xmaxwarns
- Summarizing
-deprecation
and-feature
to show all warnings, one-line-summary otherwise- Consider reporting deprecation and feature warnings by default bug#8829 suggest showing the warnings by default
- perhaps the new config mechanism will subsume the two flags
- note: the summary is a also a warning, so
-Werror
still breaks Consider reporting deprecation and feature warnings by default bug#8829
- Grouping: deprecations, maybe others
- Show message once on first occurence, add a suffix ("x more occurences", maybe more details)
Local suppression
- support an annotation like
@SuppressWarnings
,@silent
(see below) - other tools (scalafix) should be able to use the same syntax?
Links, Discussions, WIPs
- suppress unchecked warnings globally bug#1781
- asks to make the
@unchecked
annotation to work for an annotated scope, e.g.@unchecked class C { ... }
for all code in a class - or a compiler flag to suppress warnings globally
- asks to make the
- suppress deprecation warnings over a narrow scope bug#7934
- asks for a way to disable warnings in a scope
- https://stackoverflow.com/questions/3506370/is-there-an-equivalent-to-suppresswarnings-in-scala
- Configurable and suppressable warnings #333: Configurable error reporting (2017)
- SI-9350 Command option -Xreporter for custom error reporter scala#4544
-Xreporter
command line
- SI-9350 Command option -Xreporter for custom error reporter scala#4544
- WIP message suppression mechanism scala3#5337 WIP warning suppression for dotty
-Xsuppress-message-ids
,-Xsuppress-warning-kinds
global flags. dotty has error/warning ids and kinds (not sure what kinds are).
- scala/scala@2.13.x...adriaanm:deprconf WIP suppression / escalation for deprecations
-deprecation-suppress
flag. conditions on:since
, definition package, use site package- continued at [SUPERSEDED] Escalate or de-escalate deprecations scala#7728
- https://openjdk.java.net/jeps/277 Enhanced deprecations (in 9)
- parameters for the annotation:
forRemoval
,since
- parameters for the annotation:
- Promote -deprecation to -Xlint:deprecation scala#7714:
Xlint
check to ensure that@deprecated
has explicit arguments - deprecatedError + restricted annotation scala#7790
@restricted
/@compileTimeOnly
as generalization of@deprecated
to mark APIsseverity
parameter. (should we do that? or make them warnings, allow users to change severity?)- Stefan argues that having
@deprecated
with configurable reporting is enough / better than a new annotation (deprecatedError + restricted annotation scala#7790 (comment)).
Existing Tools
Java: @java.lang.SuppressWarnings
- supported:
unchecked
,deprecated
, lint warnings (seejavac -X
to get the list). Eclipse supports may more (https://stackoverflow.com/questions/1205995/what-is-the-list-of-valid-suppresswarnings-warning-names-in-java)
Silencer https://github.com/ghik/silencer
@silent
for scoped suppression@silent("deprecated")
for message pattern, regular expresison- compiler flag to error if nothing is silenced (good idea!)
- compiler flag for global filters (regexes)
- compiler flag for file name filters (regexes, unix-style paths, all warnings in those files are silenced)
Wartremover http://www.wartremover.org/
- Configuration in sbt:
wartremoverErrors ++= Warts.unsafe
,wartremoverWarnings ++= ...
- Local Suppression
@SuppressWarnings(Array("org.wartremover.warts.Var", "org.wartremover.warts.Null"))
on declarationwartremoverExcluded += baseDirectory.value / "src" / "main" / "scala" / "SomeFile.scala"
in sbt
Related Topics
Downstream impact
- IDEs, support local suppression (e.g., for deprecations)
- sbt
Better warning & error messages (considered out of scope / separate proposal)
- Unique IDs for errors and warnings, à la dotty.
- would be useful for scalameta: Classify/label reported messages with unique ID scalameta/scalameta#924
- Error explanations (dotty
-explain
, https://github.com/softwaremill/scala-clippy)- crowdsourcing Missing error messages scala3#1589
- https://contributors.scala-lang.org/t/towards-better-error-messages-in-scalac/1470/2 for previous discussions
Rough Syntax Proposal
Syntax needs to be clarified and probably made less ambiguous, so far i only thought about categories, filters and severities.
Global Configuration
-Wconf <config>
- categories
lint-x
for every-Xlint:<x>
,lint
for all lintsx
for every-W<x>
(dead-code
,value-discard
,unused
)deprecation
language-x
for every-language:<x>
,language
for all feature flags- in the future, when improving error/warnign messages, make new categories
any
: matches any warning, whether or not it's in one of the categories above - filterspos:com.package.Class
where the warning is triggered, displayedmsg:expr
-- need to decide details (full regex? only simple wildcard? substring match?)- only for deprecations:
from:com.package.Class
where the deprecated entity is declared - only for deprecations:
since<2.12
. see https://github.com/scala/scala/pull/7728/files#diff-3da64c3c223da7bbf9970ac26f9fb9b8R108. examples:since<Library 2.3
,since<*2.3
to match any character prefix ("foo bar 2.3"), seems useful in combination withfrom:pkg
- severity:
e(rror)
w(arning)
/w-summary
/w-group
i(nfo)
/i-summary
/i-group
: show, but don't fail on-Werror
(useful?)s(ilent)
- for
warning
andinfo
:summary
: there were n warnings, per category.group
: show every warning with the same mesage once, mention how many instances.
Note: this only configures how warnings are emitted. -Xlint
, -Wunused
, Wdead-code
etc are still required to make the compiler do the additional checks and emit warnings.
First matching rule wins
Relation to existing functionality
- compiler default:
-Wconf deprecation:language:warning-summary,any:warning
- Adding a
-Wconf
adds rules on the left, i.e., the default comes last -deprecation
is the same as-Wconf deprecation:warning
-feature
is-Wconf language:warning
-language:x
is-Wconf language-x:silent
import scala.language.x
is@silent("language-x")
(see below)
Examples
-Wconf any:pos:com.corp.yolo:silent
-Wconf deprecation:from:org.fancy.library:since<*2.2:e,deprecation:i-group
error on some deprecations, info-group others-Wconf 'any:msg:pure expression does nothing in statement position:s'
Local Suppression
@silent
: basically the same as https://github.com/ghik/silencer#annotation-based-suppression
- on declarations
@silent class C
,@silent def f
- on expressions as annotation ascription:
{foo; bar}: @silent
- by default, silence everything
- categories:
@silent("deprecated")
,@silent("deprecated,language-higherKinds")
- regex on message:
@silent(msg="comparing true and false will always")
- compiler error if
@silent
doesn't silence anything