diff options
author | Paul Phillips <paulp@improving.org> | 2011-03-30 00:55:20 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-03-30 00:55:20 +0000 |
commit | 5691a3900dd81cfaaa25e618828d854bed277039 (patch) | |
tree | 014c34fd8d33ecd3a368841c3c5380e76aa5987b | |
parent | f21113d28ae0fa4bae1f405933991c323f5f5553 (diff) | |
download | scala-5691a3900dd81cfaaa25e618828d854bed277039.tar.gz scala-5691a3900dd81cfaaa25e618828d854bed277039.tar.bz2 scala-5691a3900dd81cfaaa25e618828d854bed277039.zip |
Wanting to deprecate -make, first I had to writ...
Wanting to deprecate -make, first I had to write a way to deprecate
-make. So there's that, now you can do
val s = SomeSetting(...) withDeprecationMessage "don't use this"
And it will do the usual deprecation things. And, deprecated -make. And
couldn't resist fixing a bug in -make, it would crash if you gave it its
own default option (i.e. -make:all.) Let's deprecate more!
I also did further cleaning up of our help outputs. Do I smell a
pulitzer in the making? No review.
11 files changed, 104 insertions, 61 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala index cbf2d9b27a..c9791b929c 100644 --- a/src/compiler/scala/tools/nsc/CompilerCommand.scala +++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala @@ -26,13 +26,6 @@ class CompilerCommand(arguments: List[String], val settings: Settings) { /** The name of the command */ def cmdName = "scalac" - private def helpSyntaxColumnWidth: Int = - (settings.visibleSettings map (_.helpSyntax.length)) max - - private def format(s: String): String = - if (s.length >= helpSyntaxColumnWidth) s - else s + (" " * (helpSyntaxColumnWidth - s.length)) - private def explainAdvanced = "\n" + """ |-- Notes on option parsing -- |Boolean settings are always false unless set. @@ -44,7 +37,7 @@ class CompilerCommand(arguments: List[String], val settings: Settings) { | example: -Xprint:expl,24-26 prints phases explicitouter, closelim, dce, jvm. | example: -Xprint:-4 prints only the phases up to typer. | - """.stripMargin.trim + "\n\n" + """.stripMargin.trim + "\n" def shortUsage = "Usage: %s <options> <source files>" format cmdName def createUsagePreface(shouldExplain: Boolean) = @@ -52,20 +45,36 @@ class CompilerCommand(arguments: List[String], val settings: Settings) { /** Creates a help message for a subset of options based on cond */ def createUsageMsg(cond: Setting => Boolean): String = { - def helpStr(s: Setting) = format(s.helpSyntax) + " " + s.helpDescription - // Separating out any debugging options from others for easier reading - val (debug, rest) = (settings.visibleSettings filter cond).toList sortBy (_.name) partition (_.isForDebug) - - (rest map helpStr).mkString("", "\n ", "\n") + ( - if (debug.isEmpty) "" - else (debug map helpStr).mkString("\nAdditional debug settings:\n ", "\n ", "\n") - ) + val baseList = (settings.visibleSettings filter cond).toList sortBy (_.name) + val width = baseList map (_.helpSyntax.length) max + def format(s: String) = ("%-" + width + "s") format s + def helpStr(s: Setting) = { + val str = format(s.helpSyntax) + " " + s.helpDescription + val suffix = s.deprecationMessage match { + case Some(msg) => "\n" + format("") + " deprecated: " + msg + case _ => "" + } + str + suffix + } + val debugs = baseList filter (_.isForDebug) + val deprecateds = baseList filter (_.isDeprecated) + val theRest = baseList filterNot (debugs.toSet ++ deprecateds) + + def sstring(msg: String, xs: List[Setting]) = + if (xs.isEmpty) None else Some(msg :: xs.map(helpStr) mkString "\n ") + + List( + sstring("", theRest), + sstring("\nAdditional debug settings:", debugs), + sstring("\nDeprecated settings:", deprecateds) + ).flatten mkString "\n" } + def createUsageMsg(label: String, shouldExplain: Boolean, cond: Setting => Boolean): String = { val prefix = List( Some(shortUsage), Some(explainAdvanced) filter (_ => shouldExplain), - Some(label + " options include:\n ") + Some(label + " options include:") ).flatten mkString "\n" prefix + createUsageMsg(cond) diff --git a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala index 7923412304..27596dc899 100644 --- a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala +++ b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala @@ -53,10 +53,10 @@ extends CompilerCommand(args, settings) { Usage: @cmd@ <options> [<script|class|object|jar> <arguments>] or @cmd@ -help -All options to @compileCmd@ are also allowed. See @compileCmd@ -help. - """) +All options to @compileCmd@ (see @compileCmd@ -help) are also allowed. +""") - override def usageMsg = shortUsageMsg + "\n" + interpolate(""" + override def usageMsg = shortUsageMsg + interpolate(""" The first given argument other than options to @cmd@ designates what to run. Runnable targets are: diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 7b23582e74..40d8bd5c82 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -792,6 +792,12 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable _unitbufSize += 1 // counting as they're added so size is cheap compiledFiles += unit.source.file.path } + private def checkDeprecatedSettings(unit: CompilationUnit) { + // issue warnings for any usage of deprecated settings + settings.userSetSettings filter (_.isDeprecated) foreach { s => + unit.deprecationWarning(NoPosition, s.name + " is deprecated: " + s.deprecationMessage.get) + } + } /* An iterator returning all the units being compiled in this run */ /* !!! Note: changing this to unitbuf.toList.iterator breaks a bunch @@ -868,17 +874,51 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable } } + def reportCompileErrors() { + if (reporter.hasErrors) { + for ((sym, file) <- symSource.iterator) { + sym.reset(new loaders.SourcefileLoader(file)) + if (sym.isTerm) + sym.moduleClass reset loaders.moduleClassLoader + } + } + else { + def warn(count: Int, what: String, option: Settings#BooleanSetting) = ( + if (option.isDefault && count > 0) + warning("there were %d %s warnings; re-run with %s for details".format(count, what, option.name)) + ) + warn(deprecationWarnings, "deprecation", settings.deprecation) + warn(uncheckedWarnings, "unchecked", settings.unchecked) + // todo: migrationWarnings + } + } + /** Compile list of source files */ def compileSources(_sources: List[SourceFile]) { - val depSources = dependencyAnalysis.calculateFiles(_sources.distinct) // bug #1268, scalac confused by duplicated filenames + val depSources = dependencyAnalysis calculateFiles _sources.distinct val sources = coreClassesFirst(depSources) - if (reporter.hasErrors) // there is a problem already, e.g. a plugin was passed a bad option + // there is a problem already, e.g. a plugin was passed a bad option + if (reporter.hasErrors) return - val startTime = currentTime - reporter.reset() - for (source <- sources) addUnit(new CompilationUnit(source)) + // nothing to compile, but we should still report use of deprecated options + if (sources.isEmpty) { + checkDeprecatedSettings(new CompilationUnit(new BatchSourceFile("<no file>", ""))) + reportCompileErrors() + return + } + val startTime = currentTime + reporter.reset(); + { + val first :: rest = sources + val unit = new CompilationUnit(first) + addUnit(unit) + checkDeprecatedSettings(unit) + + for (source <- rest) + addUnit(new CompilationUnit(source)) + } globalPhase = firstPhase if (opt.profileAll) { @@ -947,23 +987,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable if (opt.noShow) showMembers() - if (reporter.hasErrors) { - for ((sym, file) <- symSource.iterator) { - sym.reset(new loaders.SourcefileLoader(file)) - if (sym.isTerm) - sym.moduleClass reset loaders.moduleClassLoader - } - } - else { - def warn(count: Int, what: String, option: Settings#BooleanSetting) = ( - if (option.isDefault && count > 0) - warning("there were %d %s warnings; re-run with %s for details".format(count, what, option.name)) - ) - warn(deprecationWarnings, "deprecation", settings.deprecation) - warn(uncheckedWarnings, "unchecked", settings.unchecked) - // todo: migrationWarnings - } - + reportCompileErrors() symSource.keys foreach (x => resetPackageClass(x.owner)) informTime("total", startTime) diff --git a/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala b/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala index ef974da965..ad45651e23 100644 --- a/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala +++ b/src/compiler/scala/tools/nsc/OfflineCompilerCommand.scala @@ -36,7 +36,7 @@ class OfflineCompilerCommand(arguments: List[String], settings: FscSettings) ext override def cmdName = "fsc" override def usageMsg = ( createUsageMsg("where possible fsc", false, x => x.isStandard && settings.isFscSpecific(x.name)) + - "\nStandard scalac options also available:\n " + + "\n\nStandard scalac options also available:" + createUsageMsg(x => x.isStandard && !settings.isFscSpecific(x.name)) ) } diff --git a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala index c7d1cc58a2..b2a93873b0 100644 --- a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala +++ b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala @@ -11,7 +11,7 @@ trait DependencyAnalysis extends SubComponent with Files { val phaseName = "dependencyAnalysis" - def off = settings.make.isDefault + def off = settings.make.isDefault || settings.make.value == "all" def shouldCheckClasspath = settings.make.value != "transitivenocp" def newPhase(prev: Phase) = new AnalysisPhase(prev) @@ -35,9 +35,9 @@ trait DependencyAnalysis extends SubComponent with Files { } lazy val maxDepth = settings.make.value match { - case "changed" => 0 - case "transitive" | "transitivenocp" => Int.MaxValue + case "changed" => 0 case "immediate" => 1 + case _ => Int.MaxValue } // todo: order insensible checking and, also checking timestamp? diff --git a/src/compiler/scala/tools/nsc/plugins/Plugins.scala b/src/compiler/scala/tools/nsc/plugins/Plugins.scala index 6205633a7c..64e38fee9a 100644 --- a/src/compiler/scala/tools/nsc/plugins/Plugins.scala +++ b/src/compiler/scala/tools/nsc/plugins/Plugins.scala @@ -115,6 +115,6 @@ trait Plugins { /** Summary of the options for all loaded plugins */ def pluginOptionsHelp: String = (for (plug <- roughPluginsList ; help <- plug.optionsHelp) yield { - "Options for plugin %s:\n%s\n".format(plug.name, help) + "\nOptions for plugin '%s':\n%s\n".format(plug.name, help) }) mkString } diff --git a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala index 6f130b9e74..be2f8a370a 100644 --- a/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/AbsScalaSettings.scala @@ -9,17 +9,19 @@ package settings trait AbsScalaSettings { self: AbsSettings => - type BooleanSetting <: AbsSetting { type T = Boolean } - type ChoiceSetting <: AbsSetting { type T = String } - type IntSetting <: AbsSetting { type T = Int } - type MultiStringSetting <: AbsSetting { type T = List[String] } - type PathSetting <: AbsSetting { type T = String } - type PhasesSetting <: AbsSetting { type T = List[String] } - type StringSetting <: AbsSetting { type T = String } - type PrefixSetting <: AbsSetting { type T = List[String] } + 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 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 <: AbsSetting + type OutputSetting <: Setting def BooleanSetting(name: String, descr: String): BooleanSetting def ChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: String): ChoiceSetting diff --git a/src/compiler/scala/tools/nsc/settings/AbsSettings.scala b/src/compiler/scala/tools/nsc/settings/AbsSettings.scala index f70e6dc7d3..82e311028b 100644 --- a/src/compiler/scala/tools/nsc/settings/AbsSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/AbsSettings.scala @@ -75,8 +75,10 @@ trait AbsSettings { */ def withAbbreviation(name: String): this.type def withHelpSyntax(help: String): this.type + def withDeprecationMessage(msg: String): this.type def helpSyntax: String = name + def deprecationMessage: Option[String] = None def abbreviations: List[String] = Nil def dependencies: List[(Setting, String)] = Nil def respondsTo(label: String) = (name == label) || (abbreviations contains label) @@ -122,10 +124,11 @@ trait AbsSettings { /** These categorizations are so the help output shows -X and -P among * the standard options and -Y among the advanced options. */ - def isAdvanced = name match { case "-Y" => true ; case "-X" => false ; case _ => name startsWith "-X" } - def isPrivate = name match { case "-Y" => false ; case _ => name startsWith "-Y" } - def isStandard = !isAdvanced && !isPrivate - def isForDebug = isPrivate && (name contains ("-debug")) // by convention, i.e. -Ytyper-debug + def isAdvanced = name match { case "-Y" => true ; case "-X" => false ; case _ => name startsWith "-X" } + def isPrivate = name match { case "-Y" => false ; case _ => name startsWith "-Y" } + def isStandard = !isAdvanced && !isPrivate + def isForDebug = name endsWith "-debug" // by convention, i.e. -Ytyper-debug + def isDeprecated = deprecationMessage.isDefined def compare(that: Setting): Int = name compare that.name diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index 12b9ef7154..a4a0cd3867 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -345,6 +345,10 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal private var dependency: Option[(Setting, String)] = None override def dependencies = dependency.toList def dependsOn(s: Setting, value: String): this.type = { dependency = Some((s, value)); this } + + private var _deprecationMessage: Option[String] = None + override def deprecationMessage = _deprecationMessage + def withDeprecationMessage(msg: String): this.type = { _deprecationMessage = Some(msg) ; this } } /** A setting represented by an integer */ diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 0ba0e59fea..c1067cbde9 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -140,7 +140,7 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings { val Ybuilderdebug = ChoiceSetting ("-Ybuilder-debug", "manager", "Compile using the specified build manager.", List("none", "refined", "simple"), "none") val Ybuildmanagerdebug = BooleanSetting ("-Ybuild-manager-debug", "Generate debug information for the Refined Build Manager compiler.") - val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignements.") + val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignments.") val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.") val Yrepldebug = BooleanSetting ("-Yrepl-debug", "Trace all repl activity.") . withPostSetHook(set => interpreter.isReplDebug = true) diff --git a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala index 3975ae4998..cc960e55dd 100644 --- a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala @@ -35,6 +35,7 @@ trait StandardScalaSettings { val g = ChoiceSetting ("-g", "level", "Set level of generated debugging info.", List("none", "source", "line", "vars", "notailcalls"), "vars") val help = BooleanSetting ("-help", "Print a synopsis of standard options") val make = ChoiceSetting ("-make", "policy", "Recompilation detection policy", List("all", "changed", "immediate", "transitive", "transitivenocp"), "all") + . withDeprecationMessage ("this option is unmaintained. Use sbt or an IDE for selective recompilation.") val nowarn = BooleanSetting ("-nowarn", "Generate no warnings") val optimise: BooleanSetting // depends on post hook which mutates other settings val print = BooleanSetting ("-print", "Print program with Scala-specific features removed.") |