From 0538e7fd086c39226b2d005865eee07bb83f5b2e Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 17 Feb 2014 18:54:46 +0100 Subject: Group settings should honor user-set individual options In the last commit, we added the ability to explicitly disable boolean settings form the command line. This commit changes group settings (like -optimize), to leave them alone if set explicitly. Examples: `scalac -Xlint -Ywarn-unused:false -optimize -Yinline:false` The mechanism for such settings has also been refactored to `MutableSettings`, to let use reuse this for `-Xlint`. --- .../scala/tools/nsc/settings/MutableSettings.scala | 10 +++++++++ .../scala/tools/nsc/settings/ScalaSettings.scala | 14 +++---------- .../scala/tools/nsc/settings/Warnings.scala | 18 +++++----------- .../scala/tools/nsc/settings/SettingsTest.scala | 24 ++++++++++++++++++++++ 4 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index a8421c8b15..3590254128 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -679,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 57aa8243b6..a643a08614 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -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 5214f6485f..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 { @@ -34,19 +36,6 @@ trait Warnings { // 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. @@ -61,6 +50,9 @@ trait Warnings { 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 @deprecated("This option is being removed", "2.11.0") def Xchecknull = warnSelectNullable // used by ide diff --git a/test/junit/scala/tools/nsc/settings/SettingsTest.scala b/test/junit/scala/tools/nsc/settings/SettingsTest.scala index 4b0e58ff79..e4b5ecc7c3 100644 --- a/test/junit/scala/tools/nsc/settings/SettingsTest.scala +++ b/test/junit/scala/tools/nsc/settings/SettingsTest.scala @@ -25,4 +25,28 @@ class SettingsTest { 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) + } } -- cgit v1.2.3