Skip to content

Configurable and suppressable warnings #333

@adriaanm

Description

@adriaanm

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 Annotation unused to suppress warnings scala#7623, discussion at Helper for unused parameters bug#10790)
  • @migration
    • with -Xmigration:<fromScalaVersion>, show warnings that have a version bigger than fromScalaVersion
    • not for everyone to use, the annotation is private[scala]

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
  • 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"
  • 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

Local suppression

  • support an annotation like @SuppressWarnings, @silent (see below)
  • other tools (scalafix) should be able to use the same syntax?

Links, Discussions, WIPs

Existing Tools

Java: @java.lang.SuppressWarnings

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 declaration
    • wartremoverExcluded += 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)

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 lints
    • x 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 - filters
    • pos:com.package.Class where the warning is triggered, displayed
    • msg: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 with from: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 and info:
    • 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions