summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2014-05-22 09:02:18 -0700
committerSom Snytt <som.snytt@gmail.com>2014-07-08 21:28:35 -0700
commit2103dbc5230ddf2a369389f179f4ef70eae344f2 (patch)
tree28c5cd4446ea34018daf746760d896c39388f58c
parentd1fa9ac2dc8a9432925e3c7fb4d63e62bdc98a29 (diff)
downloadscala-2103dbc5230ddf2a369389f179f4ef70eae344f2.tar.gz
scala-2103dbc5230ddf2a369389f179f4ef70eae344f2.tar.bz2
scala-2103dbc5230ddf2a369389f179f4ef70eae344f2.zip
SI-8610 -Xlint is multichoice option
Make -Xlint a "multichoice" option for purposes of option parsing. This allows turning on "lint with these warnings" instead of only "turn off these warnings but enable other lint warnings". ``` $ scalac -Xlint:warn-adapted-args linty.scala # lint plus a warning $ scalac -Xlint warn-adapted-args linty.scala # same $ scalac -Xlint linty.scala # same as now $ scalac -Xlint -- linty.scala # ok, not necessary $ scalac -Xlint _ -- linty.scala # another funky underscore ``` This would also enable Xlint options that are not standalone options, although that is not implemented in this commit. For example, `-Xlint:no-missing-interpolator` could be used to disable that warning. (There is no `-Xoption:flavor=off` syntax.) (`no-` switches would not be enabled by `_`.)
-rw-r--r--src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/MutableSettings.scala48
-rw-r--r--src/compiler/scala/tools/nsc/settings/Warnings.scala22
-rw-r--r--test/files/neg/t8610-arg.check9
-rw-r--r--test/files/neg/t8610-arg.flags1
-rw-r--r--test/files/neg/t8610-arg.scala7
-rw-r--r--test/files/neg/t8610.check15
-rw-r--r--test/files/neg/t8610.flags1
-rw-r--r--test/files/neg/t8610.scala7
-rw-r--r--test/files/run/t8610.check10
-rw-r--r--test/files/run/t8610.flags1
-rw-r--r--test/files/run/t8610.scala13
12 files changed, 116 insertions, 20 deletions
diff --git a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala
index 38a7525862..ef9695a594 100644
--- a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala
@@ -29,7 +29,7 @@ trait AbsScalaSettings {
def ChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: String): ChoiceSetting
def IntSetting(name: String, descr: String, default: Int, range: Option[(Int, Int)], parser: String => Option[Int]): IntSetting
def MultiStringSetting(name: String, helpArg: String, descr: String): MultiStringSetting
- def MultiChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String]): MultiChoiceSetting
+ def MultiChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: () => Unit): MultiChoiceSetting
def OutputSetting(outputDirs: OutputDirs, default: String): OutputSetting
def PathSetting(name: String, descr: String, default: String): PathSetting
def PhasesSetting(name: String, descr: String, default: String): PhasesSetting
diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
index 54e444decf..5b5c80c514 100644
--- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
@@ -211,10 +211,10 @@ class MutableSettings(val errorFn: String => Unit)
add(new ChoiceSetting(name, helpArg, descr, choices, default))
def IntSetting(name: String, descr: String, default: Int, range: Option[(Int, Int)], parser: String => Option[Int]) = add(new IntSetting(name, descr, default, range, parser))
def MultiStringSetting(name: String, arg: String, descr: String) = add(new MultiStringSetting(name, arg, descr))
- def MultiChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String]): MultiChoiceSetting = {
+ def MultiChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: () => Unit = () => ()): MultiChoiceSetting = {
val fullChoix = choices.mkString(": ", ",", ".")
val fullDescr = s"$descr$fullChoix"
- add(new MultiChoiceSetting(name, helpArg, fullDescr, choices))
+ add(new MultiChoiceSetting(name, helpArg, fullDescr, choices, default))
}
def OutputSetting(outputDirs: OutputDirs, default: String) = add(new OutputSetting(outputDirs, default))
def PhasesSetting(name: String, descr: String, default: String = "") = add(new PhasesSetting(name, descr, default))
@@ -553,12 +553,18 @@ class MutableSettings(val errorFn: String => Unit)
}
}
+ /** A setting that receives any combination of enumerated values,
+ * including "_" to mean all values.
+ * In non-colonated mode, stops consuming args at the first
+ * non-value, instead of at the next option, as for a multi-string.
+ */
class MultiChoiceSetting private[nsc](
name: String,
arg: String,
descr: String,
- override val choices: List[String])
- extends MultiStringSetting(name, arg, descr)
+ override val choices: List[String],
+ override val default: () => Unit
+ ) extends MultiStringSetting(name, arg, descr)
/** A setting that accumulates all strings supplied to it,
* until it encounters one starting with a '-'.
@@ -570,24 +576,34 @@ class MutableSettings(val errorFn: String => Unit)
extends Setting(name, descr) with Clearable {
type T = List[String]
protected var v: T = Nil
+ val default: () => Unit = () => () // no natural default
def appendToValue(str: String) { value ++= List(str) }
def badChoice(s: String, n: String) = errorFn(s"'$s' is not a valid choice for '$name'")
- def tryToSet(args: List[String]) = {
- val (strings, rest) = args span (x => !x.startsWith("-"))
- strings foreach {
- case "_" if choices.nonEmpty => choices foreach appendToValue
+ private def tts(args: List[String], verify: Boolean) = {
+ def tryArg(arg: String) = arg match {
+ case "_" if choices.nonEmpty => choices foreach appendToValue
case s if choices.isEmpty || (choices contains s) => appendToValue(s)
- case s => badChoice(s, name)
+ case s => badChoice(s, name)
}
+ def loop(args: List[String]): List[String] = args match {
+ case Nil => Nil
+ case arg :: _
+ if (arg startsWith "-") || (!verify && choices.nonEmpty && !(choices contains arg))
+ => args
+ case arg :: rest => tryArg(arg) ; loop(rest)
+ }
+ val rest = loop(args)
+ if (rest.size == args.size) default() // if no arg consumed, trigger default action
Some(rest)
}
- override def tryToSetColon(args: List[String]) = tryToSet(args)
+ def tryToSet(args: List[String]) = tts(args, verify = false)
+ override def tryToSetColon(args: List[String]) = tts(args, verify = true)
override def tryToSetFromPropertyValue(s: String) = tryToSet(s.trim.split(',').toList) // used from ide
- def clear(): Unit = (v = Nil)
- def unparse: List[String] = value map (name + ":" + _)
- def contains(s: String) = value contains s
+ def clear(): Unit = (v = Nil)
+ def unparse: List[String] = value map (name + ":" + _)
+ def contains(s: String) = value contains s
withHelpSyntax(name + ":<" + arg + ">")
}
@@ -606,10 +622,8 @@ class MutableSettings(val errorFn: String => Unit)
protected var v: T = default
def indexOfChoice: Int = choices indexOf value
- private def usageErrorMessage = {
- "Usage: %s:<%s>\n where <%s> choices are %s (default: %s)\n".format(
- name, helpArg, helpArg, choices mkString ", ", default)
- }
+ private def usageErrorMessage = f"Usage: $name:<$helpArg>%n where <$helpArg> choices are ${choices mkString ", "} (default: $default)%n"
+
def tryToSet(args: List[String]) = errorAndValue(usageErrorMessage, None)
override def tryToSetColon(args: List[String]) = args match {
diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala
index 1509ad13b8..ae2696accf 100644
--- a/src/compiler/scala/tools/nsc/settings/Warnings.scala
+++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala
@@ -50,8 +50,26 @@ 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
+ // Warning groups.
+ val lint = {
+ // Boolean setting for testing if lint is on; not "added" to option processing
+ val xlint = new BooleanSetting("-Xlint", "Enable recommended additional warnings.")
+ val lintables = (lintWarnings map (_.name drop 2)).sorted
+ def propagate(ss: List[String]): Unit = ss match {
+ case w :: rest => lintWarnings find (_.name == s"-Y$w") foreach (_.value = true) ; propagate(rest)
+ case Nil => ()
+ }
+ def enableAll(): Unit = { // enable lint and the group
+ xlint.value = true
+ for (s <- lintWarnings if !s.isSetByUser) s.value = true
+ }
+ // The command option
+ MultiChoiceSetting("-Xlint", "warning", "Enable recommended additional warnings", lintables, enableAll) withPostSetHook { x =>
+ propagate(x.value) // enabling the selections (on each append to value)
+ xlint.value = true // only enables lint, not the group
+ }
+ xlint
+ }
// Backward compatibility.
@deprecated("Use fatalWarnings", "2.11.0") def Xwarnfatal = fatalWarnings // used by sbt
diff --git a/test/files/neg/t8610-arg.check b/test/files/neg/t8610-arg.check
new file mode 100644
index 0000000000..f2879b0d45
--- /dev/null
+++ b/test/files/neg/t8610-arg.check
@@ -0,0 +1,9 @@
+t8610-arg.scala:3: warning: `$name` looks like an interpolated identifier! Did you forget the interpolator?
+ def x = "Hi, $name" // missing interp
+ ^
+t8610-arg.scala:6: warning: side-effecting nullary methods are discouraged: suggest defining as `def u()` instead
+ def u: Unit = () // unitarian universalist
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+two warnings found
+one error found
diff --git a/test/files/neg/t8610-arg.flags b/test/files/neg/t8610-arg.flags
new file mode 100644
index 0000000000..f8867a7b4e
--- /dev/null
+++ b/test/files/neg/t8610-arg.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -Xlint warn-nullary-unit
diff --git a/test/files/neg/t8610-arg.scala b/test/files/neg/t8610-arg.scala
new file mode 100644
index 0000000000..494a3354da
--- /dev/null
+++ b/test/files/neg/t8610-arg.scala
@@ -0,0 +1,7 @@
+
+case class X(name: String) {
+ def x = "Hi, $name" // missing interp
+ def f(p: (Int, Int)): Int = p._1 * p._2
+ def g = f(3, 4) // adapted
+ def u: Unit = () // unitarian universalist
+}
diff --git a/test/files/neg/t8610.check b/test/files/neg/t8610.check
new file mode 100644
index 0000000000..7a18e55127
--- /dev/null
+++ b/test/files/neg/t8610.check
@@ -0,0 +1,15 @@
+t8610.scala:3: warning: `$name` looks like an interpolated identifier! Did you forget the interpolator?
+ def x = "Hi, $name" // missing interp
+ ^
+t8610.scala:5: warning: Adapting argument list by creating a 2-tuple: this may not be what you want.
+ signature: X.f(p: (Int, Int)): Int
+ given arguments: 3, 4
+ after adaptation: X.f((3, 4): (Int, Int))
+ def g = f(3, 4) // adapted
+ ^
+t8610.scala:6: warning: side-effecting nullary methods are discouraged: suggest defining as `def u()` instead
+ def u: Unit = () // unitarian universalist
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+three warnings found
+one error found
diff --git a/test/files/neg/t8610.flags b/test/files/neg/t8610.flags
new file mode 100644
index 0000000000..954eaba352
--- /dev/null
+++ b/test/files/neg/t8610.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -Xlint
diff --git a/test/files/neg/t8610.scala b/test/files/neg/t8610.scala
new file mode 100644
index 0000000000..494a3354da
--- /dev/null
+++ b/test/files/neg/t8610.scala
@@ -0,0 +1,7 @@
+
+case class X(name: String) {
+ def x = "Hi, $name" // missing interp
+ def f(p: (Int, Int)): Int = p._1 * p._2
+ def g = f(3, 4) // adapted
+ def u: Unit = () // unitarian universalist
+}
diff --git a/test/files/run/t8610.check b/test/files/run/t8610.check
new file mode 100644
index 0000000000..077382fb1c
--- /dev/null
+++ b/test/files/run/t8610.check
@@ -0,0 +1,10 @@
+t8610.scala:4: warning: `$name` looks like an interpolated identifier! Did you forget the interpolator?
+ def x = "Hi, $name" // missing interp
+ ^
+t8610.scala:6: warning: Adapting argument list by creating a 2-tuple: this may not be what you want.
+ signature: X.f(p: (Int, Int)): Int
+ given arguments: 3, 4
+ after adaptation: X.f((3, 4): (Int, Int))
+ def g = f(3, 4) // adapted
+ ^
+Hi, $name
diff --git a/test/files/run/t8610.flags b/test/files/run/t8610.flags
new file mode 100644
index 0000000000..edcb5f4d0c
--- /dev/null
+++ b/test/files/run/t8610.flags
@@ -0,0 +1 @@
+-Xlint:warn-adapted-args
diff --git a/test/files/run/t8610.scala b/test/files/run/t8610.scala
new file mode 100644
index 0000000000..dd9e8e861e
--- /dev/null
+++ b/test/files/run/t8610.scala
@@ -0,0 +1,13 @@
+
+// flags don't warn on u
+case class X(name: String) {
+ def x = "Hi, $name" // missing interp
+ def f(p: (Int, Int)): Int = p._1 * p._2
+ def g = f(3, 4) // adapted
+ def u: Unit = () // unitarian universalist
+}
+
+object Test extends App {
+ // poignant demonstration
+ Console println X("Bob").x
+}