diff options
Diffstat (limited to 'src')
10 files changed, 296 insertions, 202 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala index 3ded456378..9b8e9fa330 100644 --- a/src/compiler/scala/tools/nsc/CompilerCommand.scala +++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala @@ -107,7 +107,7 @@ class CompilerCommand(arguments: List[String], val settings: Settings) { else { val sb = new StringBuilder allSettings foreach { - case s: MultiChoiceSetting if s.isHelping => sb append s.help + case s: MultiChoiceSetting[_] if s.isHelping => sb append s.help case _ => } sb.toString diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 82ffb35c3f..452081cff1 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1372,7 +1372,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) runCheckers() // output collected statistics - if (settings.Ystatistics) + if (settings.YstatisticsEnabled) statistics.print(phase) advancePhase() diff --git a/src/compiler/scala/tools/nsc/MainBench.scala b/src/compiler/scala/tools/nsc/MainBench.scala index 03190a63f3..f01de0cbe1 100644 --- a/src/compiler/scala/tools/nsc/MainBench.scala +++ b/src/compiler/scala/tools/nsc/MainBench.scala @@ -24,7 +24,7 @@ object MainBench extends Driver with EvalLoop { var start = System.nanoTime() for (i <- 0 until NIter) { if (i == NIter-1) { - theCompiler.settings.Ystatistics.value = true + theCompiler.settings.Ystatistics.default.get foreach theCompiler.settings.Ystatistics.add Statistics.enabled = true } process(args) diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index 8df3969c49..351eb23c4c 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -283,7 +283,7 @@ abstract class Inliners extends SubComponent { } val tfa = new analysis.MTFAGrowable() - tfa.stat = global.settings.Ystatistics.value + tfa.stat = global.settings.YstatisticsEnabled val staleOut = new mutable.ListBuffer[BasicBlock] val splicedBlocks = mutable.Set.empty[BasicBlock] val staleIn = mutable.Set.empty[BasicBlock] diff --git a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala index d0b8fd70ed..6b339b2a6d 100644 --- a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala @@ -7,20 +7,24 @@ package scala package tools.nsc package settings +import scala.language.higherKinds + trait AbsScalaSettings { self: AbsSettings => + type MultiChoiceEnumeration <: Enumeration + type Setting <: AbsSetting - type BooleanSetting <: Setting { type T = Boolean } - 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 } - type PrefixSetting <: Setting { type T = List[String] } + type BooleanSetting <: Setting { type T = Boolean } + type ChoiceSetting <: Setting { type T = String } + type IntSetting <: Setting { type T = Int } + type MultiStringSetting <: Setting { type T = List[String] } + type MultiChoiceSetting[E <: MultiChoiceEnumeration] <: Setting { type T <: E#ValueSet } + type PathSetting <: Setting { type T = String } + type PhasesSetting <: Setting { type T = List[String] } + type StringSetting <: Setting { type T = String } + type PrefixSetting <: Setting { type T = List[String] } type OutputDirs type OutputSetting <: Setting @@ -29,7 +33,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], default: Option[() => Unit])(helper: MultiChoiceSetting => String): MultiChoiceSetting + def MultiChoiceSetting[E <: MultiChoiceEnumeration](name: String, helpArg: String, descr: String, domain: E, default: Option[List[String]]): MultiChoiceSetting[E] 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 f26192f88a..bbe21477cb 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -209,12 +209,11 @@ class MutableSettings(val errorFn: String => Unit) def BooleanSetting(name: String, descr: String) = add(new BooleanSetting(name, descr)) def ChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: String) = 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 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], default: Option[() => Unit] = None)( - helper: MultiChoiceSetting => String = _ => choices.mkString(f"$descr:%n", f"%n ", f"%n") - ) = - add(new MultiChoiceSetting(name, helpArg, descr, choices, default, helper)) + def MultiChoiceSetting[E <: MultiChoiceEnumeration](name: String, helpArg: String, descr: String, domain: E, default: Option[List[String]] = None) = + add(new MultiChoiceSetting[E](name, helpArg, descr, domain, 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)) @@ -367,7 +366,7 @@ class MutableSettings(val errorFn: String => Unit) def withDeprecationMessage(msg: String): this.type = { _deprecationMessage = Some(msg) ; this } } - /** A setting represented by an integer */ + /** A setting represented by an integer. */ class IntSetting private[nsc]( name: String, descr: String, @@ -553,57 +552,193 @@ class MutableSettings(val errorFn: String => Unit) } } - /** A setting that receives any combination of enumerated values, - * including "_" to mean all values and "help" for verbose info. - * In non-colonated mode, stops consuming args at the first - * non-value, instead of at the next option, as for a multi-string. + /** + * Each [[MultiChoiceSetting]] takes a MultiChoiceEnumeration as domain. The enumeration may + * use the Choice class to define values, or simply use the default `Value` constructor: + * + * object SettingDomain extends MultiChoiceEnumeration { val arg1, arg2 = Value } + * + * Or + * + * object SettingDomain extends MultiChoiceEnumeration { + * val arg1 = Choice("arg1", "help") + * val arg2 = Choice("arg2", "help") + * } + * + * Choices with a non-empty `expandsTo` enable other options. Note that expanding choices are + * not present in the multiChoiceSetting.value set, only their expansion. + */ + abstract class MultiChoiceEnumeration extends Enumeration { + case class Choice(name: String, help: String = "", expandsTo: List[Choice] = Nil) extends Val(name) + } + + /** + * A Setting that collects string-valued settings from an enumerated domain. + * - These choices can be turned on or off: "-option:on,-off" + * - If an option is set both on and off, then the option is on + * - The choice "_" enables all choices that have not been explicitly disabled + * + * Arguments can be provided in colonated or non-colonated mode, i.e. "-option a b" or + * "-option:a,b". Note that arguments starting with a "-" can only be provided in colonated mode, + * otherwise they are interpreted as a new option. + * + * In non-colonated mode, the setting stops consuming arguments at the first non-choice, + * i.e. "-option a b c" only consumes "a" and "b" if "c" is not a valid choice. + * + * @param name command-line setting name, eg "-Xlint" + * @param helpArg help description for the kind of arguments it takes, eg "warning" + * @param descr description of the setting + * @param domain enumeration of choices implementing MultiChoice, or the string value is + * taken for the name + * @param default If Some(args), the default options if none are provided. If None, an + * error is printed if there are no arguments. */ - class MultiChoiceSetting private[nsc]( + class MultiChoiceSetting[E <: MultiChoiceEnumeration] private[nsc]( name: String, - arg: String, + helpArg: String, descr: String, - override val choices: List[String], - val default: Option[() => Unit], - helper: MultiChoiceSetting => String - ) extends MultiStringSetting(name, s"_,$arg,-$arg", s"$descr: `_' for all, `$name:help' to list") { + val domain: E, + val default: Option[List[String]] + ) extends Setting(name, s"$descr: `_' for all, `$name:help' to list") with Clearable { - private def badChoice(s: String, n: String) = errorFn(s"'$s' is not a valid choice for '$name'") - private def choosing = choices.nonEmpty - private def isChoice(s: String) = (s == "_") || (choices contains (s stripPrefix "-")) + withHelpSyntax(s"$name:<_,$helpArg,-$helpArg>") - private var sawHelp = false - private var sawAll = false - private val adderAll = () => sawAll = true - private val noargs = () => errorFn(s"'$name' requires an option. See '$name:help'.") + object ChoiceOrVal { + def unapply(a: domain.Value): Option[(String, String, List[domain.Choice])] = a match { + case c: domain.Choice => Some((c.name, c.help, c.expandsTo)) + case v: domain.Value => Some((v.toString, "", Nil)) + } + } + + type T = domain.ValueSet + protected var v: T = domain.ValueSet.empty + + // Explicitly enabled or disabled. Yeas may contain expanding options, nays may not. + private var yeas = domain.ValueSet.empty + private var nays = domain.ValueSet.empty + + // Asked for help + private var sawHelp = false + // Wildcard _ encountered + private var sawAll = false + + private def badChoice(s: String) = errorFn(s"'$s' is not a valid choice for '$name'") + private def isChoice(s: String) = (s == "_") || (choices contains pos(s)) + + private def pos(s: String) = s stripPrefix "-" + private def isPos(s: String) = !(s startsWith "-") + + override val choices: List[String] = domain.values.toList map { + case ChoiceOrVal(name, _, _) => name + } + + def descriptions: List[String] = domain.values.toList map { + case ChoiceOrVal(_, "", x :: xs) => "Enables the options "+ (x :: xs).map(_.name).mkString(", ") + case ChoiceOrVal(_, descr, _) => descr + case _ => "" + } - override protected def tts(args: List[String], halting: Boolean) = { + /** (Re)compute from current yeas, nays, wildcard status. */ + def compute() = { + def simple(v: domain.Value) = v match { + case ChoiceOrVal(_, _, Nil) => true + case _ => false + } + + /** + * Expand an expanding option, if necessary recursively. Expanding options are not included in + * the result (consistent with "_", which is not in `value` either). + * + * Note: by precondition, options in nays are not expanding, they can only be leaves. + */ + def expand(vs: domain.ValueSet): domain.ValueSet = vs flatMap { + case c @ ChoiceOrVal(_, _, Nil) => domain.ValueSet(c) + case ChoiceOrVal(_, _, others) => expand(domain.ValueSet(others: _*)) + } + + // yeas from _ or expansions are weak: an explicit nay will disable them + val weakYeas = if (sawAll) domain.values filter simple else expand(yeas filterNot simple) + value = (yeas filter simple) | (weakYeas &~ nays) + } + + /** Add a named choice to the multichoice value. */ + def add(arg: String) = arg match { + case _ if !isChoice(arg) => + badChoice(arg) + case "_" => + sawAll = true + compute() + case _ if isPos(arg) => + yeas += domain withName arg + compute() + case _ => + val choice = domain withName pos(arg) + choice match { + case ChoiceOrVal(_, _, _ :: _) => errorFn(s"'${pos(arg)}' cannot be negated, it enables other arguments") + case _ => + } + nays += choice + compute() + } + + def tryToSet(args: List[String]) = tryToSetArgs(args, halting = true) + override def tryToSetColon(args: List[String]) = tryToSetArgs(args, halting = false) + override def tryToSetFromPropertyValue(s: String) = tryToSet(s.trim.split(',').toList) // used from ide + + /** Try to set args, handling "help" and default. + * The "halting" parameter means args were "-option a b c -else" so halt + * on "-else" or other non-choice. Otherwise, args were "-option:a,b,c,d", + * so process all and report non-choices as errors. + * @param args args to process + * @param halting stop on non-arg + */ + private def tryToSetArgs(args: List[String], halting: Boolean) = { val added = collection.mutable.ListBuffer.empty[String] + def tryArg(arg: String) = arg match { - case "_" if choosing => addAll() - case "help" if choosing => sawHelp = true - case s if !choosing || isChoice(s) => added += s - case s => badChoice(s, name) + case "help" => sawHelp = true + case s if isChoice(s) => added += s // this case also adds "_" + case s => badChoice(s) } - 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 + case arg :: _ if halting && (!isPos(arg) || !isChoice(arg)) => args + case arg :: rest => tryArg(arg) ; loop(rest) + case Nil => Nil } val rest = loop(args) - if (rest.size == args.size) - (default getOrElse noargs)() // if no arg consumed, trigger default action or error - else - value ++= added.toList // update all new settings at once + + // if no arg consumed, use defaults or error; otherwise, add what they added + if (rest.size == args.size) default match { + case Some(defaults) => defaults foreach add + case None => errorFn(s"'$name' requires an option. See '$name:help'.") + } else { + added foreach add + } + Some(rest) } + def contains(choice: domain.Value): Boolean = value contains choice + def isHelping: Boolean = sawHelp - def help: String = helper(this) - def addAll(): Unit = (default getOrElse adderAll)() - // the semantics is: s is enabled, i.e., either s or (_ but not -s) - override def contains(s: String) = isChoice(s) && (value contains s) || (sawAll && !(value contains s"-$s")) + def help: String = { + val choiceLength = choices.map(_.length).max + 1 + val formatStr = s" %-${choiceLength}s %s" + choices.zipAll(descriptions, "", "").map { + case (arg, descr) => formatStr.format(arg, descr) + } mkString (f"$descr%n", f"%n", "") + } + + def clear(): Unit = { + v = domain.ValueSet.empty + yeas = domain.ValueSet.empty + nays = domain.ValueSet.empty + sawAll = false + sawHelp = false + } + def unparse: List[String] = value.toList map (s => s"$name:$s") + def contains(s: String) = domain.values.find(_.toString == s).exists(value.contains) } /** A setting that accumulates all strings supplied to it, @@ -619,15 +754,15 @@ class MutableSettings(val errorFn: String => Unit) def appendToValue(str: String) = value ++= List(str) // try to set. halting means halt at first non-arg - protected def tts(args: List[String], halting: Boolean) = { + protected def tryToSetArgs(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(loop(args)) } - def tryToSet(args: List[String]) = tts(args, halting = true) - override def tryToSetColon(args: List[String]) = tts(args, halting = false) + def tryToSet(args: List[String]) = tryToSetArgs(args, halting = true) + override def tryToSetColon(args: List[String]) = tryToSetArgs(args, halting = false) override def tryToSetFromPropertyValue(s: String) = tryToSet(s.trim.split(',').toList) // used from ide def clear(): Unit = (v = Nil) diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 8e69598614..91b03869e5 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -45,7 +45,7 @@ trait ScalaSettings extends AbsScalaSettings def infoSettings = List[Setting](version, help, Xhelp, Yhelp, showPlugins, showPhases, genPhaseGraph) /** Any -multichoice:help? Nicer if any option could report that it had help to offer. */ - private def multihelp = allSettings exists { case s: MultiChoiceSetting => s.isHelping case _ => false } + private def multihelp = allSettings exists { case s: MultiChoiceSetting[_] => s.isHelping case _ => false } /** Is an info setting set? */ def isInfo = (infoSettings exists (_.isSetByUser)) || multihelp @@ -69,28 +69,23 @@ trait ScalaSettings extends AbsScalaSettings // 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. + object languageFeatures extends MultiChoiceEnumeration { + val dynamics = Choice("dynamics", "Allow direct or indirect subclasses of scala.Dynamic") + val postfixOps = Choice("postfixOps", "Allow postfix operator notation, such as `1 to 10 toList'") + val reflectiveCalls = Choice("reflectiveCalls", "Allow reflective access to members of structural types") + val implicitConversions = Choice("implicitConversions", "Allow definition of implicit functions called views") + val higherKinds = Choice("higherKinds", "Allow higher-kinded types") + val existentials = Choice("existentials", "Existential types (besides wildcard types) can be written and inferred") + val macros = Choice("experimental.macros", "Allow macro defintion (besides implementation and application)") + } val language = { - val features = List( - "dynamics" -> "Allow direct or indirect subclasses of scala.Dynamic", - "postfixOps" -> "Allow postfix operator notation, such as `1 to 10 toList'", - "reflectiveCalls" -> "Allow reflective access to members of structural types", - "implicitConversions" -> "Allow definition of implicit functions called views", - "higherKinds" -> "Allow higher-kinded types", // "Ask Adriaan, but if you have to ask..." - "existentials" -> "Existential types (besides wildcard types) can be written and inferred", - "experimental.macros" -> "Allow macro defintion (besides implementation and application)" - ) val description = "Enable or disable language features" MultiChoiceSetting( name = "-language", helpArg = "feature", descr = description, - choices = features map (_._1) - ) { s => - val helpline: ((String, String)) => String = { - case (name, text) => f" $name%-25s $text%n" - } - features map helpline mkString (f"$description:%n", "", f"%n") - } + domain = languageFeatures + ) } /* @@ -193,7 +188,6 @@ trait ScalaSettings extends AbsScalaSettings val Ygenjavap = StringSetting ("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "") val Ygenasmp = StringSetting ("-Ygen-asmp", "dir", "Generate a parallel output directory of .asmp files (ie ASM Textifier output).", "") val Ydumpclasses = StringSetting ("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "") - val Ystatistics = BooleanSetting ("-Ystatistics", "Print compiler statistics.") andThen (scala.reflect.internal.util.Statistics.enabled = _) val stopAfter = PhasesSetting ("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat val stopBefore = PhasesSetting ("-Ystop-before", "Stop before") val Yrangepos = BooleanSetting ("-Yrangepos", "Use range positions for syntax trees.") @@ -217,6 +211,20 @@ trait ScalaSettings extends AbsScalaSettings private def removalIn212 = "This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug." + object YstatisticsPhases extends MultiChoiceEnumeration { val parser, typer, patmat, erasure, cleanup = Value } + val Ystatistics = { + val description = "Print compiler statistics for specific phases" + MultiChoiceSetting( + name = "-Ystatistics", + helpArg = "phase", + descr = description, + domain = YstatisticsPhases, + default = Some(List("_")) + ) withPostSetHook { _ => scala.reflect.internal.util.Statistics.enabled = true } + } + + def YstatisticsEnabled = Ystatistics.value.nonEmpty + /** Area-specific debug output. */ val Ydocdebug = BooleanSetting("-Ydoc-debug", "Trace all scaladoc activity.") diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala index 4c37633301..c400e8c29c 100644 --- a/src/compiler/scala/tools/nsc/settings/Warnings.scala +++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala @@ -17,145 +17,94 @@ trait Warnings { // Warning semantics. val fatalWarnings = BooleanSetting("-Xfatal-warnings", "Fail the compilation if there are any warnings.") - // These additional warnings are all so noisy as to be useless in their - // present form, but have the potential to offer useful info. - protected def allWarnings = lintWarnings ++ List( - warnDeadCode, - warnValueDiscard, - warnNumericWiden, - warnUnused, // SI-7712, SI-7707 warnUnused not quite ready for prime-time - warnUnusedImport, // currently considered too noisy for general use - warnValueOverrides // currently turned off as experimental - ) - // These warnings should be pretty quiet unless you're doing - // something inadvisable. - protected def lintWarnings = List( - warnInaccessible, - warnNullaryOverride, - warnNullaryUnit, - warnAdaptedArgs, - warnInferAny, - warnMissingInterpolator, - warnDocDetached, - warnPrivateShadow, - warnTypeParameterShadow, - warnPolyImplicitOverload, - warnOptionImplicit, - warnDelayedInit, - warnByNameRightAssociative, - warnPackageObjectClasses, - warnUnsoundMatch - ) - - // Individual warnings. They can be set with -Ywarn. - private def nonlintflag(name: String, text: String): BooleanSetting = BooleanSetting(name, text) - - val warnDeadCode = nonlintflag("-Ywarn-dead-code", - "Warn when dead code is identified.") - val warnValueDiscard = nonlintflag("-Ywarn-value-discard", - "Warn when non-Unit expression results are unused.") - val warnNumericWiden = nonlintflag("-Ywarn-numeric-widen", - "Warn when numerics are widened.") - val warnUnused = nonlintflag("-Ywarn-unused", - "Warn when local and private vals, vars, defs, and types are are unused") - val warnUnusedImport = nonlintflag("-Ywarn-unused-import", - "Warn when imports are unused") - - // Lint warnings that have no -Y avatar, created with new instead of the autoregistering factory method. - // They evaluate true if set to true or else are unset but -Xlint is true - private def lintflag(name: String, text: String): BooleanSetting = - new BooleanSetting(name, text) { - override def value = if (isSetByUser) super.value else xlint - } - - 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 warnTypeParameterShadow = lintflag("type-parameter-shadow", - "A local type parameter shadows a type already in scope.") - 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") + // Non-lint warnings + + 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.") + // SI-7712, SI-7707 warnUnused not quite ready for prime-time + val warnUnused = BooleanSetting("-Ywarn-unused", "Warn when local and private vals, vars, defs, and types are are unused.") + // currently considered too noisy for general use + val warnUnusedImport = BooleanSetting("-Ywarn-unused-import", "Warn when imports are unused.") // Experimental lint warnings that are turned off, but which could be turned on programmatically. // These warnings are said to blind those who dare enable them. // They are not activated by -Xlint and can't be enabled on the command line. - val warnValueOverrides = { - val flag = lintflag("value-overrides", "Generated value class method overrides an implementation") + val warnValueOverrides = { // currently turned off as experimental. creaded using constructor (new BS), so not available on the command line. + val flag = new BooleanSetting("value-overrides", "Generated value class method overrides an implementation") flag.value = false flag } - // The Xlint warning group. - private val xlint = new BooleanSetting("-Zunused", "True if -Xlint or -Xlint:_") - // On -Xlint or -Xlint:_, set xlint, otherwise set the lint warning unless already set true - val lint = { - val description = "Enable or disable specific warnings" - val choices = (lintWarnings map (_.name)).sorted - MultiChoiceSetting( - name = "-Xlint", - helpArg = "warning", - descr = description, - choices = choices, - default = Some(() => xlint.value = true) - ) { s => - def helpline(n: String) = lintWarnings.find(_.name == n).map(w => f" ${w.name}%-25s ${w.helpDescription}%n") - choices flatMap (helpline(_)) mkString (f"$description:%n", "", f"%n") - } withPostSetHook { x => - val Neg = "-" - def setPolitely(b: BooleanSetting, v: Boolean) = if (!b.isSetByUser || !b) b.value = v - def set(w: String, v: Boolean) = lintWarnings find (_.name == w) foreach (setPolitely(_, v)) - 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 => () - } - propagate(x.value) - } + // Lint warnings + + object LintWarnings extends MultiChoiceEnumeration { + class LintWarning(name: String, help: String, val yAliased: Boolean) extends Choice(name, help) + def LintWarning(name: String, help: String, yAliased: Boolean = false) = new LintWarning(name, help, yAliased) + + val AdaptedArgs = LintWarning("adapted-args", "Warn if an argument list is modified to match the receiver.", true) + val NullaryUnit = LintWarning("nullary-unit", "Warn when nullary methods return Unit.", true) + val Inaccessible = LintWarning("inaccessible", "Warn about inaccessible types in method signatures.", true) + val NullaryOverride = LintWarning("nullary-override", "Warn when non-nullary `def f()' overrides nullary `def f'.", true) + val InferAny = LintWarning("infer-any", "Warn when a type argument is inferred to be `Any`.", true) + val MissingInterpolator = LintWarning("missing-interpolator", "A string literal appears to be missing an interpolator id.") + val DocDetached = LintWarning("doc-detached", "A ScalaDoc comment appears to be detached from its element.") + val PrivateShadow = LintWarning("private-shadow", "A private field (or class parameter) shadows a superclass field.") + val TypeParameterShadow = LintWarning("type-parameter-shadow", "A local type parameter shadows a type already in scope.") + val PolyImplicitOverload = LintWarning("poly-implicit-overload", "Parameterized overloaded implicit methods are not visible as view bounds.") + val OptionImplicit = LintWarning("option-implicit", "Option.apply used implicit view.") + val DelayedInitSelect = LintWarning("delayedinit-select", "Selecting member of DelayedInit") + val ByNameRightAssociative = LintWarning("by-name-right-associative", "By-name parameter of right associative operator.") + val PackageObjectClasses = LintWarning("package-object-classes", "Class or object defined in package object.") + val UnsoundMatch = LintWarning("unsound-match", "Pattern match may not be typesafe.") + + def allLintWarnings = values.toSeq.asInstanceOf[Seq[LintWarning]] } + import LintWarnings._ + + def warnAdaptedArgs = lint contains AdaptedArgs + def warnNullaryUnit = lint contains NullaryUnit + def warnInaccessible = lint contains Inaccessible + def warnNullaryOverride = lint contains NullaryOverride + def warnInferAny = lint contains InferAny + def warnMissingInterpolator = lint contains MissingInterpolator + def warnDocDetached = lint contains DocDetached + def warnPrivateShadow = lint contains PrivateShadow + def warnTypeParameterShadow = lint contains TypeParameterShadow + def warnPolyImplicitOverload = lint contains PolyImplicitOverload + def warnOptionImplicit = lint contains OptionImplicit + def warnDelayedInit = lint contains DelayedInitSelect + def warnByNameRightAssociative = lint contains ByNameRightAssociative + def warnPackageObjectClasses = lint contains PackageObjectClasses + def warnUnsoundMatch = lint contains UnsoundMatch // Lint warnings that are currently -Y, but deprecated in that usage @deprecated("Use warnAdaptedArgs", since="2.11.2") - val YwarnAdaptedArgs = BooleanSetting("-Ywarn-adapted-args", - "Warn if an argument list is modified to match the receiver.") enabling List(warnAdaptedArgs) - //withDeprecationMessage "Enable -Xlint:adapted-args" + def YwarnAdaptedArgs = warnAdaptedArgs @deprecated("Use warnNullaryUnit", since="2.11.2") - val YwarnNullaryUnit = BooleanSetting("-Ywarn-nullary-unit", - "Warn when nullary methods return Unit.") enabling List(warnNullaryUnit) - //withDeprecationMessage "Enable -Xlint:nullary-unit" + def YwarnNullaryUnit = warnNullaryUnit @deprecated("Use warnInaccessible", since="2.11.2") - val YwarnInaccessible = BooleanSetting("-Ywarn-inaccessible", - "Warn about inaccessible types in method signatures.") enabling List(warnInaccessible) - //withDeprecationMessage "Enable -Xlint:inaccessible" + def YwarnInaccessible = warnInaccessible @deprecated("Use warnNullaryOverride", since="2.11.2") - val YwarnNullaryOverride = BooleanSetting("-Ywarn-nullary-override", - "Warn when non-nullary `def f()' overrides nullary `def f'.") enabling List(warnNullaryOverride) - //withDeprecationMessage "Enable -Xlint:nullary-override" + def YwarnNullaryOverride = warnNullaryOverride @deprecated("Use warnInferAny", since="2.11.2") - val YwarnInferAny = BooleanSetting("-Ywarn-infer-any", - "Warn when a type argument is inferred to be `Any`.") enabling List(warnInferAny) - //withDeprecationMessage "Enable -Xlint:infer-any" + def YwarnInferAny = warnInferAny + + // The Xlint warning group. + val lint = MultiChoiceSetting( + name = "-Xlint", + helpArg = "warning", + descr = "Enable or disable specific warnings", + domain = LintWarnings, + default = Some(List("_"))) + + allLintWarnings foreach { + case w if w.yAliased => + BooleanSetting(s"-Ywarn-${w.name}", {w.help}) withPostSetHook { s => + lint.add(if (s) w.name else s"-${w.name}") + } // withDeprecationMessage s"Enable -Xlint:${c._1}" + case _ => + } private lazy val warnSelectNullable = BooleanSetting("-Xcheck-null", "This option is obsolete and does nothing.") diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index fb7651ffd6..421021163e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -552,7 +552,7 @@ trait Infer extends Checkable { } case _ => context.tree.pos } - if (settings.warnInferAny.value && context.reportErrors && canWarnAboutAny) { + if (settings.warnInferAny && context.reportErrors && canWarnAboutAny) { foreachWithIndex(targs) ((targ, idx) => targ.typeSymbol match { case sym @ (AnyClass | AnyValClass) => diff --git a/src/compiler/scala/tools/nsc/util/StatisticsInfo.scala b/src/compiler/scala/tools/nsc/util/StatisticsInfo.scala index 225f6ca68e..be245347a8 100644 --- a/src/compiler/scala/tools/nsc/util/StatisticsInfo.scala +++ b/src/compiler/scala/tools/nsc/util/StatisticsInfo.scala @@ -14,12 +14,10 @@ abstract class StatisticsInfo { import global._ import scala.reflect.internal.TreesStats.nodeByType - val phasesShown = List("parser", "typer", "patmat", "erasure", "cleanup") - val retainedCount = Statistics.newCounter("#retained tree nodes") val retainedByType = Statistics.newByClass("#retained tree nodes by type")(Statistics.newCounter("")) - def print(phase: Phase) = if (phasesShown contains phase.name) { + def print(phase: Phase) = if (settings.Ystatistics contains phase.name) { inform("*** Cumulative statistics at phase " + phase) retainedCount.value = 0 for (c <- retainedByType.keys) |