diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-02-17 17:34:48 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-02-17 17:34:48 -0800 |
commit | 8536c3148d5a6283b580a905ca4231e852525d59 (patch) | |
tree | ce981a3175ee5ef92e3705a3ca728129c079ab3f | |
parent | 6152e9c3153a9c028066abf6b91f6bf105eacdfe (diff) | |
parent | 0538e7fd086c39226b2d005865eee07bb83f5b2e (diff) | |
download | scala-8536c3148d5a6283b580a905ca4231e852525d59.tar.gz scala-8536c3148d5a6283b580a905ca4231e852525d59.tar.bz2 scala-8536c3148d5a6283b580a905ca4231e852525d59.zip |
Merge pull request #3544 from retronym/topic/unused-warnings
Toning down the noise of -Xlint and allow `-optimise -Yinline:false`
10 files changed, 94 insertions, 44 deletions
diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index 0536be92cf..3590254128 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -438,6 +438,17 @@ class MutableSettings(val errorFn: String => Unit) override def tryToSetFromPropertyValue(s : String) { // used from ide value = s.equalsIgnoreCase("true") } + override def tryToSetColon(args: List[String]) = args match { + case Nil => tryToSet(Nil) + case List(x) => + if (x.equalsIgnoreCase("true")) { + value = true + Some(Nil) + } else if (x.equalsIgnoreCase("false")) { + value = false + Some(Nil) + } else errorAndValue("'" + x + "' is not a valid choice for '" + name + "'", None) + } } /** A special setting for accumulating arguments like -Dfoo=bar. */ @@ -668,4 +679,14 @@ class MutableSettings(val errorFn: String => Unit) else name + "[:phases]" ) } + + /** Internal use - syntax enhancements. */ + protected class EnableSettings[T <: BooleanSetting](val s: T) { + def enablingIfNotSetByUser(toEnable: List[BooleanSetting]): s.type = s withPostSetHook (_ => toEnable foreach (sett => if (!sett.isSetByUser) sett.value = s.value)) + def enabling(toEnable: List[BooleanSetting]): s.type = s withPostSetHook (_ => toEnable foreach (_.value = s.value)) + def disabling(toDisable: List[BooleanSetting]): s.type = s withPostSetHook (_ => toDisable foreach (_.value = !s.value)) + def andThen(f: s.T => Unit): s.type = s withPostSetHook (setting => f(setting.value)) + } + import scala.language.implicitConversions + protected implicit def installEnableSettings[T <: BooleanSetting](s: T): EnableSettings[T] = new EnableSettings(s) } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index a385a31165..a643a08614 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -20,7 +20,7 @@ trait ScalaSettings extends AbsScalaSettings self: MutableSettings => /** Set of settings */ - protected lazy val allSettings = mutable.HashSet[Setting]() + protected[scala] lazy val allSettings = mutable.HashSet[Setting]() /** Against my better judgment, giving in to martin here and allowing * CLASSPATH to be used automatically. So for the user-specified part @@ -47,14 +47,6 @@ trait ScalaSettings extends AbsScalaSettings /** Is an info setting set? */ def isInfo = infoSettings exists (_.isSetByUser) - /** Internal use - syntax enhancements. */ - private class EnableSettings[T <: BooleanSetting](val s: T) { - def enabling(toEnable: List[BooleanSetting]): s.type = s withPostSetHook (_ => toEnable foreach (_.value = s.value)) - def disabling(toDisable: List[BooleanSetting]): s.type = s withPostSetHook (_ => toDisable foreach (_.value = !s.value)) - def andThen(f: s.T => Unit): s.type = s withPostSetHook (setting => f(setting.value)) - } - private implicit def installEnableSettings[T <: BooleanSetting](s: T) = new EnableSettings(s) - /** Disable a setting */ def disable(s: Setting) = allSettings -= s @@ -216,10 +208,10 @@ trait ScalaSettings extends AbsScalaSettings /** Groups of Settings. */ - val future = BooleanSetting("-Xfuture", "Turn on future language features.") enabling futureSettings - val optimise = BooleanSetting("-optimise", "Generates faster bytecode by applying optimisations to the program") withAbbreviation "-optimize" enabling optimiseSettings + val future = BooleanSetting("-Xfuture", "Turn on future language features.") enablingIfNotSetByUser futureSettings + val optimise = BooleanSetting("-optimise", "Generates faster bytecode by applying optimisations to the program") withAbbreviation "-optimize" enablingIfNotSetByUser optimiseSettings val nooptimise = BooleanSetting("-Ynooptimise", "Clears all the flags set by -optimise. Useful for testing optimizations in isolation.") withAbbreviation "-Ynooptimize" disabling optimise::optimiseSettings - val Xexperimental = BooleanSetting("-Xexperimental", "Enable experimental extensions.") enabling experimentalSettings + val Xexperimental = BooleanSetting("-Xexperimental", "Enable experimental extensions.") enablingIfNotSetByUser experimentalSettings /** * Settings motivated by GenBCode diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala index 791d44153c..1509ad13b8 100644 --- a/src/compiler/scala/tools/nsc/settings/Warnings.scala +++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala @@ -7,6 +7,8 @@ package scala.tools package nsc package settings +import language.existentials + /** Settings influencing the printing of warnings. */ trait Warnings { @@ -30,21 +32,10 @@ trait Warnings { warnNullaryUnit, warnAdaptedArgs, warnInferAny + // warnUnused SI-7712, SI-7707 warnUnused not quite ready for prime-time + // warnUnusedImport currently considered too noisy for general use ) - // Warning groups. - val lint = ( - BooleanSetting("-Xlint", "Enable recommended additional warnings.") - withPostSetHook (_ => lintWarnings foreach (_.value = true)) - ) - - /*val warnEverything = */ ( - BooleanSetting("-Ywarn-all", "Enable all -Y warnings.") - withPostSetHook { _ => - lint.value = true - allWarnings foreach (_.value = true) - } - ) private lazy val warnSelectNullable = BooleanSetting("-Xcheck-null", "This option is obsolete and does nothing.") // Individual warnings. @@ -56,6 +47,11 @@ trait Warnings { val warnInaccessible = BooleanSetting ("-Ywarn-inaccessible", "Warn about inaccessible types in method signatures.") val warnNullaryOverride = BooleanSetting ("-Ywarn-nullary-override", "Warn when non-nullary overrides nullary, e.g. `def foo()` over `def foo`.") val warnInferAny = BooleanSetting ("-Ywarn-infer-any", "Warn when a type argument is inferred to be `Any`.") + val warnUnused = BooleanSetting ("-Ywarn-unused", "Warn when local and private vals, vars, defs, and types are are unused") + val warnUnusedImport = BooleanSetting ("-Ywarn-unused-import", "Warn when imports are unused") + + // Warning groups. + val lint = BooleanSetting("-Xlint", "Enable recommended additional warnings.") enablingIfNotSetByUser lintWarnings // Backward compatibility. @deprecated("Use fatalWarnings", "2.11.0") def Xwarnfatal = fatalWarnings // used by sbt diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala index 5c02516c47..323fe1c171 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala @@ -102,7 +102,9 @@ trait Analyzer extends AnyRef unit.body = typer.typed(unit.body) if (global.settings.Yrangepos && !global.reporter.hasErrors) global.validatePositions(unit.body) for (workItem <- unit.toCheck) workItem() - if (settings.lint) + if (settings.warnUnusedImport) + warnUnusedImports(unit) + if (settings.warnUnused) typer checkUnused unit } finally { diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index c065fb54b7..974c0842d3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -1210,7 +1210,7 @@ trait Contexts { self: Analyzer => trait ImportContext extends Context { private val impInfo: ImportInfo = { val info = new ImportInfo(tree.asInstanceOf[Import], outerDepth) - if (settings.lint && !isRootImport) // excludes java.lang/scala/Predef imports + if (settings.warnUnusedImport && !isRootImport) // excludes java.lang/scala/Predef imports allImportInfos(unit) ::= info info } @@ -1319,7 +1319,7 @@ trait Contexts { self: Analyzer => if (result == NoSymbol) selectors = selectors.tail } - if (settings.lint && selectors.nonEmpty && result != NoSymbol && pos != NoPosition) + if (settings.warnUnusedImport && selectors.nonEmpty && result != NoSymbol && pos != NoPosition) recordUsage(current, result) // Harden against the fallout from bugs like SI-6745 diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index 71e6454931..dfa1b6db0f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -518,8 +518,6 @@ trait TypeDiagnostics { } def apply(unit: CompilationUnit) = { - warnUnusedImports(unit) - val p = new UnusedPrivates p traverse unit.body val unused = p.unusedTerms diff --git a/test/files/neg/warn-unused-imports.check b/test/files/neg/warn-unused-imports.check index 1b938f4fd7..36c6dd03c3 100644 --- a/test/files/neg/warn-unused-imports.check +++ b/test/files/neg/warn-unused-imports.check @@ -1,11 +1,3 @@ -warn-unused-imports.scala:7: warning: it is not recommended to define classes/objects inside of package objects. -If possible, define class A in package p1 instead. - class A - ^ -warn-unused-imports.scala:13: warning: it is not recommended to define classes/objects inside of package objects. -If possible, define class A in package p2 instead. - class A - ^ warn-unused-imports.scala:57: warning: Unused import import p1.A // warn ^ @@ -36,9 +28,6 @@ warn-unused-imports.scala:98: warning: Unused import warn-unused-imports.scala:118: warning: Unused import import p1.A // warn ^ -warn-unused-imports.scala:99: warning: local trait Warn is never used - trait Warn { // warn about unused local trait for good measure - ^ error: No warnings can be incurred under -Xfatal-warnings. -13 warnings found +10 warnings found one error found diff --git a/test/files/neg/warn-unused-imports.flags b/test/files/neg/warn-unused-imports.flags index 954eaba352..24db705df1 100644 --- a/test/files/neg/warn-unused-imports.flags +++ b/test/files/neg/warn-unused-imports.flags @@ -1 +1 @@ --Xfatal-warnings -Xlint +-Xfatal-warnings -Ywarn-unused-import diff --git a/test/files/neg/warn-unused-privates.flags b/test/files/neg/warn-unused-privates.flags index 7949c2afa2..25474aefb3 100644 --- a/test/files/neg/warn-unused-privates.flags +++ b/test/files/neg/warn-unused-privates.flags @@ -1 +1 @@ --Xlint -Xfatal-warnings +-Ywarn-unused -Xfatal-warnings diff --git a/test/junit/scala/tools/nsc/settings/SettingsTest.scala b/test/junit/scala/tools/nsc/settings/SettingsTest.scala new file mode 100644 index 0000000000..e4b5ecc7c3 --- /dev/null +++ b/test/junit/scala/tools/nsc/settings/SettingsTest.scala @@ -0,0 +1,52 @@ +package scala.tools.nsc +package settings + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import scala.tools.testing.AssertUtil.assertThrows + +@RunWith(classOf[JUnit4]) +class SettingsTest { + @Test def booleanSettingColon() { + def check(args: String*): MutableSettings#BooleanSetting = { + val s = new MutableSettings(msg => throw new IllegalArgumentException(msg)) + val b1 = new s.BooleanSetting("-Ytest-setting", "") + s.allSettings += b1 + val (ok, residual) = s.processArguments(args.toList, processAll = true) + assert(residual.isEmpty) + b1 + } + assertTrue(check("-Ytest-setting").value) + assertTrue(check("-Ytest-setting:true").value) + assertTrue(check("-Ytest-setting:TRUE").value) + assertFalse(check("-Ytest-setting:false").value) + assertFalse(check("-Ytest-setting:FALSE").value) + assertThrows[IllegalArgumentException](check("-Ytest-setting:rubbish")) + } + + @Test def userSettingsHavePredecenceOverOptimize() { + def check(args: String*): MutableSettings#BooleanSetting = { + val s = new MutableSettings(msg => throw new IllegalArgumentException(msg)) + val (ok, residual) = s.processArguments(args.toList, processAll = true) + assert(residual.isEmpty) + s.inline // among -optimize + } + assertTrue(check("-optimise").value) + assertFalse(check("-optimise", "-Yinline:false").value) + assertFalse(check("-Yinline:false", "-optimise").value) + } + + @Test def userSettingsHavePredecenceOverLint() { + def check(args: String*): MutableSettings#BooleanSetting = { + val s = new MutableSettings(msg => throw new IllegalArgumentException(msg)) + val (ok, residual) = s.processArguments(args.toList, processAll = true) + assert(residual.isEmpty) + s.warnAdaptedArgs // among Xlint + } + assertTrue(check("-Xlint").value) + assertFalse(check("-Xlint", "-Ywarn-adapted-args:false").value) + assertFalse(check("-Ywarn-adapted-args:false", "-Xlint").value) + } +} |