diff options
author | Lukas Rytz <lukas.rytz@typesafe.com> | 2014-07-16 12:25:34 +0200 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@typesafe.com> | 2014-07-16 12:25:34 +0200 |
commit | 04cb634ec4564c6ee3bd34c3cef899537c3787ba (patch) | |
tree | 2acaa0c06544acd35aa286f56dba368996748fad /src/compiler/scala/tools/nsc/settings | |
parent | 0f8b07a8d7deda602a41859a175b0b46bb113d51 (diff) | |
parent | 3b89c168b4926139f7295183fdc1903f6f553798 (diff) | |
download | scala-04cb634ec4564c6ee3bd34c3cef899537c3787ba.tar.gz scala-04cb634ec4564c6ee3bd34c3cef899537c3787ba.tar.bz2 scala-04cb634ec4564c6ee3bd34c3cef899537c3787ba.zip |
Merge pull request #3792 from som-snytt/issue/8525
SI-8525 -Xlint:nowarn-missing-interpolator
Diffstat (limited to 'src/compiler/scala/tools/nsc/settings')
3 files changed, 160 insertions, 41 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..dc49e8b822 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -211,11 +211,8 @@ 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 MultiChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: () => Unit = () => ()) = + add(new MultiChoiceSetting(name, helpArg, descr, 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)) def StringSetting(name: String, arg: String, descr: String, default: String) = add(new StringSetting(name, arg, descr, default)) @@ -444,7 +441,7 @@ class MutableSettings(val errorFn: String => Unit) value = s.equalsIgnoreCase("true") } override def tryToSetColon(args: List[String]) = args match { - case Nil => tryToSet(Nil) + case Nil => tryToSet(Nil) case List(x) => if (x.equalsIgnoreCase("true")) { value = true @@ -452,7 +449,8 @@ class MutableSettings(val errorFn: String => Unit) } else if (x.equalsIgnoreCase("false")) { value = false Some(Nil) - } else errorAndValue("'" + x + "' is not a valid choice for '" + name + "'", None) + } else errorAndValue(s"'$x' is not a valid choice for '$name'", None) + case _ => errorAndValue(s"'$name' accepts only one boolean value", None) } } @@ -553,12 +551,43 @@ 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], + val default: () => Unit + ) extends MultiStringSetting(name, arg, s"$descr${ choices.mkString(": ", ",", ".") }") { + + def badChoice(s: String, n: String) = errorFn(s"'$s' is not a valid choice for '$name'") + def choosing = choices.nonEmpty + def isChoice(s: String) = (s == "_") || (choices contains (s stripPrefix "-")) + def wildcards = choices // filter (!_.isSetByUser) + + override protected def tts(args: List[String], halting: Boolean) = { + val total = collection.mutable.ListBuffer.empty[String] ++ value + def tryArg(arg: String) = arg match { + case "_" if choosing => wildcards foreach (total += _) + case s if !choosing || isChoice(s) => total += s + case s => badChoice(s, name) + } + def stoppingAt(arg: String) = (arg startsWith "-") || (choosing && !isChoice(arg)) + def loop(args: List[String]): List[String] = args match { + case arg :: _ if halting && stoppingAt(arg) => args + case arg :: rest => tryArg(arg) ; loop(rest) + case Nil => Nil + } + val rest = loop(args) + if (rest.size == args.size) default() // if no arg consumed, trigger default action + else value = total.toList // update once + Some(rest) + } + } /** A setting that accumulates all strings supplied to it, * until it encounters one starting with a '-'. @@ -570,24 +599,23 @@ class MutableSettings(val errorFn: String => Unit) extends Setting(name, descr) with Clearable { 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 appendToValue(str: String) = value ++= List(str) - def tryToSet(args: List[String]) = { - val (strings, rest) = args span (x => !x.startsWith("-")) - strings foreach { - case "_" if choices.nonEmpty => choices foreach appendToValue - case s if choices.isEmpty || (choices contains s) => appendToValue(s) - case s => badChoice(s, name) + // try to set. halting means halt at first non-arg + protected def tts(args: List[String], halting: Boolean) = { + def loop(args: List[String]): List[String] = args match { + case arg :: rest => if (halting && (arg startsWith "-")) args else { appendToValue(arg) ; loop(rest) } + case Nil => Nil } - Some(rest) + Some(loop(args)) } - override def tryToSetColon(args: List[String]) = tryToSet(args) + def tryToSet(args: List[String]) = tts(args, halting = true) + override def tryToSetColon(args: List[String]) = tts(args, halting = false) 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 +634,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..3ff2369f86 100644 --- a/src/compiler/scala/tools/nsc/settings/Warnings.scala +++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala @@ -31,27 +31,120 @@ trait Warnings { warnNullaryOverride, warnNullaryUnit, warnAdaptedArgs, - warnInferAny + warnInferAny, // warnUnused SI-7712, SI-7707 warnUnused not quite ready for prime-time // warnUnusedImport currently considered too noisy for general use + // warnValueOverrides + warnMissingInterpolator, + warnDocDetached, + warnPrivateShadow, + warnPolyImplicitOverload, + warnOptionImplicit, + warnDelayedInit, + warnByNameRightAssociative, + warnPackageObjectClasses, + warnUnsoundMatch ) private lazy val warnSelectNullable = BooleanSetting("-Xcheck-null", "This option is obsolete and does nothing.") // Individual warnings. - val warnAdaptedArgs = BooleanSetting ("-Ywarn-adapted-args", "Warn if an argument list is modified to match the receiver.") - val warnDeadCode = BooleanSetting ("-Ywarn-dead-code", "Warn when dead code is identified.") - val warnValueDiscard = BooleanSetting ("-Ywarn-value-discard", "Warn when non-Unit expression results are unused.") - val warnNumericWiden = BooleanSetting ("-Ywarn-numeric-widen", "Warn when numerics are widened.") - val warnNullaryUnit = BooleanSetting ("-Ywarn-nullary-unit", "Warn when nullary methods return Unit.") - 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 + val warnDeadCode = BooleanSetting("-Ywarn-dead-code", + "Warn when dead code is identified.") + val warnValueDiscard = BooleanSetting("-Ywarn-value-discard", + "Warn when non-Unit expression results are unused.") + val warnNumericWiden = BooleanSetting("-Ywarn-numeric-widen", + "Warn when numerics are widened.") + 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") + + // Lint warnings that are not -Y, created with new instead of autoregistering factory method + private def lintflag(name: String, text: String) = new BooleanSetting(name, text) + + val warnAdaptedArgs = lintflag("adapted-args", + "Warn if an argument list is modified to match the receiver.") + val warnNullaryUnit = lintflag("nullary-unit", + "Warn when nullary methods return Unit.") + val warnInaccessible = lintflag("inaccessible", + "Warn about inaccessible types in method signatures.") + val warnNullaryOverride = lintflag("nullary-override", + "Warn when non-nullary `def f()' overrides nullary `def f'.") + val warnInferAny = lintflag("infer-any", + "Warn when a type argument is inferred to be `Any`.") + val warnMissingInterpolator = lintflag("missing-interpolator", + "A string literal appears to be missing an interpolator id.") + val warnDocDetached = lintflag("doc-detached", + "A ScalaDoc comment appears to be detached from its element.") + val warnPrivateShadow = lintflag("private-shadow", + "A private field (or class parameter) shadows a superclass field.") + val warnPolyImplicitOverload = lintflag("poly-implicit-overload", + "Parameterized overloaded implicit methods are not visible as view bounds") + val warnOptionImplicit = lintflag("option-implicit", + "Option.apply used implicit view.") + val warnDelayedInit = lintflag("delayedinit-select", + "Selecting member of DelayedInit") + val warnByNameRightAssociative = lintflag("by-name-right-associative", + "By-name parameter of right associative operator") + val warnPackageObjectClasses = lintflag("package-object-classes", + "Class or object defined in package object") + val warnUnsoundMatch = lintflag("unsound-match", + "Pattern match may not be typesafe") + + // Lint warnings that are not enabled yet + val warnValueOverrides = lintflag("value-overrides", "Generated value class method overrides an implementation") + + // Warning groups. + val lint = { + // Boolean setting for testing if lint is on; not "added" to option processing + val xlint = lintflag("-Xlint", "Enable recommended additional warnings.") + val yprefix = "-Ywarn-" + def lintables = (lintWarnings map (_.name stripPrefix yprefix)).sorted + def isAnon(b: BooleanSetting) = !(b.name startsWith "-") + def setPolitely(b: BooleanSetting, v: Boolean) = if (!b.isSetByUser) b.value = v + def set(w: String, v: Boolean) = lintWarnings find (s => (s.name stripPrefix yprefix) == w) foreach (b => setPolitely(b, v)) + val Neg = "-" + def propagate(ss: List[String]): Unit = ss match { + case w :: rest => if (w startsWith Neg) set(w stripPrefix Neg, false) else set(w, true) ; propagate(rest) + case Nil => () + } + // enable lint and the group, honoring previous -Y settings + def enableAll(): Unit = { + xlint.value = true + for (s <- lintWarnings) setPolitely(s, true) + } + // The command option + MultiChoiceSetting("-Xlint", "warning", "Enable recommended additional warnings", choices = lintables, default = enableAll) withPostSetHook { x => + propagate(x.value) // enabling the selections (on each append to value) + xlint.value = true // only enables lint, not the group + for (b <- lintWarnings if isAnon(b) && !b.isSetByUser) b.value = true // init anonymous settings (but not if disabled) + } + xlint + } + + // Lint warnings that are currently -Y, but deprecated in that usage + // Alas, the -Yarg must have a doppelgaenger that is not deprecated + @deprecated("Use the Xlint flag", since="2.11.2") + val YwarnAdaptedArgs = BooleanSetting("-Ywarn-adapted-args", + "Warn if an argument list is modified to match the receiver.") withDeprecationMessage + "Enable -Xlint:adapted-args" enabling List(warnAdaptedArgs) + @deprecated("Use the Xlint flag", since="2.11.2") + val YwarnNullaryUnit = BooleanSetting("-Ywarn-nullary-unit", + "Warn when nullary methods return Unit.") withDeprecationMessage + "Enable -Xlint:nullary-unit" enabling List(warnNullaryUnit) + @deprecated("Use the Xlint flag", since="2.11.2") + val YwarnInaccessible = BooleanSetting("-Ywarn-inaccessible", + "Warn about inaccessible types in method signatures.") withDeprecationMessage + "Enable -Xlint:inaccessible" enabling List(warnInaccessible) + @deprecated("Use the Xlint flag", since="2.11.2") + val YwarnNullaryOverride = BooleanSetting("-Ywarn-nullary-override", + "Warn when non-nullary `def f()' overrides nullary `def f'.") withDeprecationMessage + "Enable -Xlint:nullary-override" enabling List(warnNullaryOverride) + @deprecated("Use the Xlint flag", since="2.11.2") + val YwarnInferAny = BooleanSetting("-Ywarn-infer-any", + "Warn when a type argument is inferred to be `Any`.") withDeprecationMessage + "Enable -Xlint:infer-any" enabling List(warnInferAny) // Backward compatibility. @deprecated("Use fatalWarnings", "2.11.0") def Xwarnfatal = fatalWarnings // used by sbt |