forked from scala/scala
/
Warnings.scala
250 lines (228 loc) · 15 KB
/
Warnings.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala.tools
package nsc
package settings
import scala.annotation.nowarn
import scala.tools.nsc.Reporting.WarningCategory
/** Settings influencing the printing of warnings.
*/
trait Warnings {
self: MutableSettings =>
val Whelp = BooleanSetting("-W", "Print a synopsis of warning options.")
// Warning semantics.
val fatalWarnings = BooleanSetting("-Werror", "Fail the compilation if there are any warnings.") withAbbreviation "-Xfatal-warnings"
private val WconfDefault = List("cat=deprecation:ws", "cat=feature:ws", "cat=optimizer:ws")
// Note: user-defined settings are added on the right, but the value is reversed before
// it's parsed, so that later defined settings take precedence.
val Wconf = MultiStringSetting(
"-Wconf",
"patterns",
"Configure reporting of compiler warnings; use `help` for details.",
default = WconfDefault,
helpText = Some(
s"""Configure compiler warnings.
|Syntax: -Wconf:<filters>:<action>,<filters>:<action>,...
|multiple <filters> are combined with &, i.e., <filter>&...&<filter>
|
|Note: Run with `-Wconf:any:warning-verbose` to print warnings with their category, site,
|and (for deprecations) origin and since-version.
|
|<filter>
| - Any message: any
|
| - Message categories: cat=deprecation, cat=lint, cat=lint-infer-any
| The full list of warning categories is shown at the end of this help text.
|
| - Message content: msg=regex
| The regex need only match some part of the message, not all of it.
|
| - Site where the warning is triggered: site=my\\.package\\..*
| The regex must match the full name (`package.Class.method`) of the warning position.
|
| - Source file name: src=src_managed/.*
| If `-rootdir` is specified, the regex must match the canonical path relative to the
| root directory. Otherwise, the regex must match the canonical path relative to any
| path segment (`b/.*Test.scala` matches `/a/b/XTest.scala` but not `/ab/Test.scala`).
| Use unix-style paths, separated by `/`.
|
| - Origin of deprecation: origin=external\\.package\\..*
| The regex must match the full name (`package.Class.method`) of the deprecated entity.
|
| - Since of deprecation: since<1.24
| Valid operators: <, =, >, valid versions: N, N.M, N.M.P. Compares against the first
| version of the form N, N.M or N.M.P found in the `since` parameter of the deprecation,
| for example `1.2.3` in `@deprecated("", "some lib 1.2.3-foo")`.
|
|<action>
| - error / e
| - warning / w
| - warning-summary / ws (summary with the number of warnings, like for deprecations)
| - warning-verbose / wv (show warning category and site)
| - info / i (infos are not counted as warnings and don't affect `-Werror`)
| - info-summary / is
| - info-verbose / iv
| - silent / s
|
|The default configuration is:
| -Wconf:${WconfDefault.mkString(",")}
|
|User-defined configurations are added to the left. The leftmost rule matching
|a warning message defines the action.
|
|Examples:
| - change every warning into an error: -Wconf:any:error
| - silence certain deprecations: -Wconf:origin=some\\.lib\\..*&since>2.2:s
|
|Full list of message categories:
|${WarningCategory.all.keys.groupBy(_.split('-').head).toList.sortBy(_._1).map(_._2.toList.sorted.mkString(", ")).mkString(" - ", "\n - ", "")}
|
|To suppress warnings locally, use the `scala.annotation.nowarn` annotation.
|
|Note: on the command-line you might need to quote configurations containing `*` or `&`
|to prevent the shell from expanding patterns.""".stripMargin),
prepend = true)
// Non-lint warnings. -- TODO turn into MultiChoiceEnumeration
val warnMacros = ChoiceSetting(
name = "-Wmacros",
helpArg = "mode",
descr = "Enable lint warnings on macro expansions.",
choices = List("none", "before", "after", "both"),
default = "before",
choicesHelp = List(
"Do not inspect expansions or their original trees when generating unused symbol warnings.",
"Only inspect unexpanded user-written code for unused symbols.",
"Only inspect expanded trees when generating unused symbol warnings.",
"Inspect both user-written code and expanded trees when generating unused symbol warnings."
)
) withAbbreviation "-Ywarn-macros"
val warnDeadCode = BooleanSetting("-Wdead-code", "Warn when dead code is identified.") withAbbreviation "-Ywarn-dead-code"
val warnValueDiscard = BooleanSetting("-Wvalue-discard", "Warn when non-Unit expression results are unused.") withAbbreviation "-Ywarn-value-discard"
val warnNumericWiden = BooleanSetting("-Wnumeric-widen", "Warn when numerics are widened.") withAbbreviation "-Ywarn-numeric-widen"
val warnOctalLiteral = BooleanSetting("-Woctal-literal", "Warn on obsolete octal syntax.") withAbbreviation "-Ywarn-octal-literal"
object UnusedWarnings extends MultiChoiceEnumeration {
val Imports = Choice("imports", "Warn if an import selector is not referenced.")
val PatVars = Choice("patvars", "Warn if a variable bound in a pattern is unused.")
val Privates = Choice("privates", "Warn if a private member is unused.")
val Locals = Choice("locals", "Warn if a local definition is unused.")
val Explicits = Choice("explicits", "Warn if an explicit parameter is unused.")
val Implicits = Choice("implicits", "Warn if an implicit parameter is unused.")
val Synthetics = Choice("synthetics", "Warn if a synthetic implicit parameter (context bound) is unused.")
val Nowarn = Choice("nowarn", "Warn if a @nowarn annotation does not suppress any warnings.")
val Params = Choice("params", "Enable -Wunused:explicits,implicits,synthetics.", expandsTo = List(Explicits, Implicits, Synthetics))
val Linted = Choice("linted", "-Xlint:unused.", expandsTo = List(Imports, Privates, Locals, Implicits, Nowarn))
}
// The -Ywarn-unused warning group.
val warnUnused = MultiChoiceSetting(
name = "-Wunused",
helpArg = "warning",
descr = "Enable or disable specific `unused` warnings",
domain = UnusedWarnings,
default = Some(List("_"))
) withAbbreviation "-Ywarn-unused"
def warnUnusedImport = warnUnused contains UnusedWarnings.Imports
def warnUnusedPatVars = warnUnused contains UnusedWarnings.PatVars
def warnUnusedPrivates = warnUnused contains UnusedWarnings.Privates
def warnUnusedLocals = warnUnused contains UnusedWarnings.Locals
def warnUnusedParams = warnUnusedExplicits || warnUnusedImplicits || warnUnusedSynthetics
def warnUnusedExplicits = warnUnused contains UnusedWarnings.Explicits
def warnUnusedImplicits = warnUnused contains UnusedWarnings.Implicits
def warnUnusedSynthetics = warnUnused contains UnusedWarnings.Synthetics
def warnUnusedNowarn = warnUnused contains UnusedWarnings.Nowarn
val warnExtraImplicit = BooleanSetting("-Wextra-implicit", "Warn when more than one implicit parameter section is defined.") withAbbreviation "-Ywarn-extra-implicit"
@deprecated("Use lintImplicitRecursion", since="2.13.3")
val warnSelfImplicit = BooleanSetting("-Wself-implicit", "An implicit resolves to an enclosing definition.") withAbbreviation "-Ywarn-self-implicit" withDeprecationMessage "Use -Xlint:implicit-recursion"
// Experimental lint warnings that are turned off, but which could be turned on programmatically.
// They are not activated by -Xlint and can't be enabled on the command line because they are not
// created using the standard factory methods.
val warnValueOverrides = new BooleanSetting("value-overrides", "Generated value class method overrides an implementation.", default = false)
// Lint warnings
object LintWarnings extends MultiChoiceEnumeration {
class LintWarning(name: String, help: String) extends Choice(name, help)
def LintWarning(name: String, help: String) = new LintWarning(name, help)
val AdaptedArgs = LintWarning("adapted-args", "An argument list was modified to match the receiver.")
val NullaryUnit = LintWarning("nullary-unit", "`def f: Unit` looks like an accessor; add parens to look side-effecting.")
val Inaccessible = LintWarning("inaccessible", "Warn about inaccessible types in method signatures.")
val InferAny = LintWarning("infer-any", "A type argument was inferred as Any.")
val MissingInterpolator = LintWarning("missing-interpolator", "A string literal appears to be missing an interpolator id.")
val DocDetached = LintWarning("doc-detached", "When running scaladoc, warn if a doc comment is discarded.")
val PrivateShadow = LintWarning("private-shadow", "A private field (or class parameter) shadows a superclass field.")
val TypeParameterShadow = LintWarning("type-parameter-shadow", "A local type parameter shadows a type already in scope.")
val PolyImplicitOverload = LintWarning("poly-implicit-overload", "Parameterized overloaded implicit methods are not visible as view bounds.")
val OptionImplicit = LintWarning("option-implicit", "Option.apply used an implicit view.")
val DelayedInitSelect = LintWarning("delayedinit-select", "Selecting member of DelayedInit.")
val PackageObjectClasses = LintWarning("package-object-classes", "Class or object defined in package object.")
val StarsAlign = LintWarning("stars-align", "In a pattern, a sequence wildcard `_*` should match all of a repeated parameter.")
val StrictUnsealedPatMat = LintWarning("strict-unsealed-patmat", "Pattern match on an unsealed class without a catch-all.")
val Constant = LintWarning("constant", "Evaluation of a constant arithmetic expression resulted in an error.")
val Unused = LintWarning("unused", "Enable -Wunused:imports,privates,locals,implicits,nowarn.")
val NonlocalReturn = LintWarning("nonlocal-return", "A return statement used an exception for flow control.")
val ImplicitNotFound = LintWarning("implicit-not-found", "Check @implicitNotFound and @implicitAmbiguous messages.")
val Serial = LintWarning("serial", "@SerialVersionUID on traits and non-serializable classes.")
val ValPattern = LintWarning("valpattern", "Enable pattern checks in val definitions.")
val EtaZero = LintWarning("eta-zero", "Usage `f` of parameterless `def f()` resulted in eta-expansion, not empty application `f()`.")
val EtaSam = LintWarning("eta-sam", "The Java-defined target interface for eta-expansion was not annotated @FunctionalInterface.")
val Deprecation = LintWarning("deprecation", "Enable -deprecation and also check @deprecated annotations.")
val ByNameImplicit = LintWarning("byname-implicit", "Block adapted by implicit with by-name parameter.")
val RecurseWithDefault = LintWarning("recurse-with-default", "Recursive call used default argument.")
val UnitSpecialization = LintWarning("unit-special", "Warn for specialization of Unit in parameter position.")
val MultiargInfix = LintWarning("multiarg-infix", "Infix operator was defined or used with multiarg operand.")
val ImplicitRecursion = LintWarning("implicit-recursion", "Implicit resolves to an enclosing definition.")
def allLintWarnings = values.toSeq.asInstanceOf[Seq[LintWarning]]
}
import LintWarnings._
def warnAdaptedArgs = lint contains AdaptedArgs
def warnNullaryUnit = lint contains NullaryUnit
def warnInaccessible = lint contains Inaccessible
def warnInferAny = lint contains InferAny
def warnMissingInterpolator = lint contains MissingInterpolator
def warnDocDetached = lint contains DocDetached
def warnPrivateShadow = lint contains PrivateShadow
def warnTypeParameterShadow = lint contains TypeParameterShadow
def warnPolyImplicitOverload = lint contains PolyImplicitOverload
def warnOptionImplicit = lint contains OptionImplicit
def warnDelayedInit = lint contains DelayedInitSelect
def warnPackageObjectClasses = lint contains PackageObjectClasses
def warnStrictUnsealedPatMat = lint contains StrictUnsealedPatMat
def warnStarsAlign = lint contains StarsAlign
def warnConstant = lint contains Constant
def lintUnused = lint contains Unused
def warnNonlocalReturn = lint contains NonlocalReturn
def lintImplicitNotFound = lint contains ImplicitNotFound
def warnSerialization = lint contains Serial
def lintValPatterns = lint contains ValPattern
def warnEtaZero = lint contains EtaZero
def warnEtaSam = lint contains EtaSam
def lintDeprecation = lint contains Deprecation
def warnByNameImplicit = lint contains ByNameImplicit
def warnRecurseWithDefault = lint contains RecurseWithDefault
def unitSpecialization = lint contains UnitSpecialization
def multiargInfix = lint contains MultiargInfix
def lintImplicitRecursion = lint.contains(ImplicitRecursion) || (warnSelfImplicit: @nowarn("cat=deprecation"))
// The Xlint warning group.
val lint = MultiChoiceSetting(
name = "-Xlint",
helpArg = "warning",
descr = "Enable recommended warnings",
domain = LintWarnings,
default = Some(List("_"))
).withPostSetHook { s =>
if (s contains Unused) warnUnused.enable(UnusedWarnings.Linted)
else warnUnused.disable(UnusedWarnings.Linted)
if (s.contains(Deprecation) && deprecation.isDefault) deprecation.value = true
}
// Backward compatibility.
@deprecated("Use fatalWarnings", "2.11.0") def Xwarnfatal = fatalWarnings // used by sbt
private lazy val warnSelectNullable = BooleanSetting("-Xcheck-null", "This option is obsolete and does nothing.")
@deprecated("This option is being removed", "2.11.0") def Xchecknull = warnSelectNullable // used by ide
@deprecated("Use warnDeadCode", "2.11.0") def Ywarndeadcode = warnDeadCode // used by ide
}