summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2014-02-28 05:25:08 -0800
committerSom Snytt <som.snytt@gmail.com>2014-02-28 09:04:42 -0800
commita40af3e42fdfff62901dbc807ed3d899272d2b37 (patch)
tree528339320e7b7c5c9fc43883ecc9713e93a2ee19
parentec4479aa7d0279daa701481fb7d77c1f43617190 (diff)
downloadscala-a40af3e42fdfff62901dbc807ed3d899272d2b37.tar.gz
scala-a40af3e42fdfff62901dbc807ed3d899272d2b37.tar.bz2
scala-a40af3e42fdfff62901dbc807ed3d899272d2b37.zip
SI-5905 Sanity check -language options
The option names are hardcoded, but checked by a test. There are no hooks to verify options after the compiler is constructed. Introduced a `MultiChoiceSetting` required for the setting creation framework.
-rw-r--r--src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/MutableSettings.scala22
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala10
-rw-r--r--test/files/run/t5905-features.flags1
-rw-r--r--test/files/run/t5905-features.scala28
-rw-r--r--test/files/run/t5905b-features.check1
-rw-r--r--test/files/run/t5905b-features.scala15
7 files changed, 74 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala
index 8b897b83b2..38a7525862 100644
--- a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala
@@ -16,6 +16,7 @@ trait AbsScalaSettings {
type ChoiceSetting <: Setting { type T = String }
type IntSetting <: Setting { type T = Int }
type MultiStringSetting <: Setting { type T = List[String] }
+ type MultiChoiceSetting <: Setting { type T = List[String] }
type PathSetting <: Setting { type T = String }
type PhasesSetting <: Setting { type T = List[String] }
type StringSetting <: Setting { type T = String }
@@ -28,6 +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 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 3590254128..c22dc564b2 100644
--- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
@@ -211,6 +211,11 @@ 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 = {
+ val fullChoix = choices.mkString(": ", ",", ".")
+ val fullDescr = s"$descr$fullChoix"
+ add(new MultiChoiceSetting(name, helpArg, fullDescr, choices))
+ }
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))
def StringSetting(name: String, arg: String, descr: String, default: String) = add(new StringSetting(name, arg, descr, default))
@@ -548,8 +553,16 @@ class MutableSettings(val errorFn: String => Unit)
}
}
+ class MultiChoiceSetting private[nsc](
+ name: String,
+ arg: String,
+ descr: String,
+ override val choices: List[String])
+ extends MultiStringSetting(name, arg, descr)
+
/** A setting that accumulates all strings supplied to it,
- * until it encounters one starting with a '-'. */
+ * until it encounters one starting with a '-'.
+ */
class MultiStringSetting private[nsc](
name: String,
val arg: String,
@@ -558,11 +571,14 @@ class MutableSettings(val errorFn: String => Unit)
type T = List[String]
protected var v: T = Nil
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 appendToValue
-
+ strings foreach {
+ case s if choices.isEmpty || (choices contains s) => appendToValue(s)
+ case s => badChoice(s, name)
+ }
Some(rest)
}
override def tryToSetColon(args: List[String]) = tryToSet(args)
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index a643a08614..20ccc30ff6 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -62,8 +62,14 @@ trait ScalaSettings extends AbsScalaSettings
/*val argfiles = */ BooleanSetting ("@<file>", "A text file containing compiler arguments (options and source files)")
val classpath = PathSetting ("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp"
val d = OutputSetting (outputDirs, ".")
- val nospecialization = BooleanSetting ("-no-specialization", "Ignore @specialize annotations.")
- val language = MultiStringSetting("-language", "feature", "Enable one or more language features.")
+ val nospecialization = BooleanSetting ("-no-specialization", "Ignore @specialize annotations.")
+
+ // Would be nice to build this dynamically from scala.languageFeature.
+ // The two requirements: delay error checking until you have symbols, and let compiler command build option-specific help.
+ val language = {
+ val features = List("dynamics", "postfixOps", "reflectiveCalls", "implicitConversions", "higherKinds", "existentials", "experimental.macros")
+ MultiChoiceSetting("-language", "feature", "Enable one or more language features", features)
+ }
/*
* The previous "-source" option is intended to be used mainly
diff --git a/test/files/run/t5905-features.flags b/test/files/run/t5905-features.flags
new file mode 100644
index 0000000000..ad51758c39
--- /dev/null
+++ b/test/files/run/t5905-features.flags
@@ -0,0 +1 @@
+-nowarn
diff --git a/test/files/run/t5905-features.scala b/test/files/run/t5905-features.scala
new file mode 100644
index 0000000000..fbffddf114
--- /dev/null
+++ b/test/files/run/t5905-features.scala
@@ -0,0 +1,28 @@
+
+import tools.partest.DirectTest
+
+// verify that all languageFeature names are accepted by -language
+object Test extends DirectTest {
+ override def code = "class Code { def f = (1 to 10) size }" // exercise a feature
+
+ override def extraSettings = s"-usejavacp -d ${testOutput.path}"
+
+ override def show() = {
+ val global = newCompiler("-language:postfixOps", "-Ystop-after:typer")
+ compileString(global)(code)
+ import global._
+ exitingTyper {
+ def isFeature(s: Symbol) = s.annotations.exists((a: AnnotationInfo) => a.tpe <:< typeOf[scala.annotation.meta.languageFeature])
+ val langf = definitions.languageFeatureModule.typeSignature
+ val feats = langf.declarations filter (s => isFeature(s)) map (_.name.decoded)
+ val xmen = langf.member(TermName("experimental")).typeSignature.declarations filter (s => isFeature(s)) map (s => s"experimental.${s.name.decoded}")
+ val all = (feats ++ xmen) mkString ","
+
+ assert(feats.nonEmpty, "Test must find feature flags.")
+
+ //dynamics,postfixOps,reflectiveCalls,implicitConversions,higherKinds,existentials,experimental.macros
+ compile(s"-language:$all")
+ }
+ }
+}
+
diff --git a/test/files/run/t5905b-features.check b/test/files/run/t5905b-features.check
new file mode 100644
index 0000000000..08c76d74aa
--- /dev/null
+++ b/test/files/run/t5905b-features.check
@@ -0,0 +1 @@
+'noob' is not a valid choice for '-language'
diff --git a/test/files/run/t5905b-features.scala b/test/files/run/t5905b-features.scala
new file mode 100644
index 0000000000..627df8334b
--- /dev/null
+++ b/test/files/run/t5905b-features.scala
@@ -0,0 +1,15 @@
+
+import tools.partest.DirectTest
+
+// verify that only languageFeature names are accepted by -language
+object Test extends DirectTest {
+ override def code = "class Code"
+
+ override def extraSettings = s"-usejavacp -d ${testOutput.path}"
+
+ override def show() = {
+ //compile("-language", "--") // no error
+ compile(s"-language:noob")
+ }
+}
+