From f60d035059d3306007cfd13a0442608a01a363c2 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 23 Dec 2020 16:35:02 +0000 Subject: [PATCH] fix #10810: pass aliases to setting constructor --- .../tools/dotc/config/ScalaSettings.scala | 62 +++++++++---------- .../dotty/tools/dotc/config/Settings.scala | 41 +++++------- .../dotc/config/ScalaSettingsTests.scala | 13 ++++ 3 files changed, 61 insertions(+), 55 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index be9e851c7418..70633ec78dd3 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -12,25 +12,25 @@ trait CommonScalaSettings { self: Settings.SettingGroup => protected def defaultClasspath: String = sys.env.getOrElse("CLASSPATH", ".") /** Path related settings */ - val bootclasspath: Setting[String] = PathSetting("-bootclasspath", "Override location of bootstrap class files.", Defaults.scalaBootClassPath) withAbbreviation "--boot-class-path" - val extdirs: Setting[String] = PathSetting("-extdirs", "Override location of installed extensions.", Defaults.scalaExtDirs) withAbbreviation "--extension-directories" - val javabootclasspath: Setting[String] = PathSetting("-javabootclasspath", "Override java boot classpath.", Defaults.javaBootClassPath) withAbbreviation "--java-boot-class-path" - val javaextdirs: Setting[String] = PathSetting("-javaextdirs", "Override java extdirs classpath.", Defaults.javaExtDirs) withAbbreviation "--java-extension-directories" - val sourcepath: Setting[String] = PathSetting("-sourcepath", "Specify location(s) of source files.", Defaults.scalaSourcePath) withAbbreviation "--source-path" + val bootclasspath: Setting[String] = PathSetting("-bootclasspath", "Override location of bootstrap class files.", Defaults.scalaBootClassPath, aliases = List("--boot-class-path")) + val extdirs: Setting[String] = PathSetting("-extdirs", "Override location of installed extensions.", Defaults.scalaExtDirs, aliases = List("--extension-directories")) + val javabootclasspath: Setting[String] = PathSetting("-javabootclasspath", "Override java boot classpath.", Defaults.javaBootClassPath, aliases = List("--java-boot-class-path")) + val javaextdirs: Setting[String] = PathSetting("-javaextdirs", "Override java extdirs classpath.", Defaults.javaExtDirs, aliases = List("--java-extension-directories")) + val sourcepath: Setting[String] = PathSetting("-sourcepath", "Specify location(s) of source files.", Defaults.scalaSourcePath, aliases = List("--source-path")) val sourceroot: Setting[String] = PathSetting("-sourceroot", "Specify workspace root directory.", ".") - val classpath: Setting[String] = PathSetting("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp" withAbbreviation "--class-path" + val classpath: Setting[String] = PathSetting("-classpath", "Specify where to find user class files.", defaultClasspath, aliases = List("-cp", "--class-path")) val outputDir: Setting[AbstractFile] = OutputSetting("-d", "directory|jar", "Destination for generated classfiles.", new PlainDirectory(Directory("."))) - val color: Setting[String] = ChoiceSetting("-color", "mode", "Colored output", List("always", "never"/*, "auto"*/), "always"/* "auto"*/) withAbbreviation "--color" - val verbose: Setting[Boolean] = BooleanSetting("-verbose", "Output messages about what the compiler is doing.") withAbbreviation "--verbose" - val version: Setting[Boolean] = BooleanSetting("-version", "Print product version and exit.") withAbbreviation "--version" - val pageWidth: Setting[Int] = IntSetting("-pagewidth", "Set page width", 80) withAbbreviation "--page-width" - val silentWarnings: Setting[Boolean] = BooleanSetting("-nowarn", "Silence all warnings.") withAbbreviation "--no-warnings" + val color: Setting[String] = ChoiceSetting("-color", "mode", "Colored output", List("always", "never"/*, "auto"*/), "always"/* "auto"*/, aliases = List("--color")) + val verbose: Setting[Boolean] = BooleanSetting("-verbose", "Output messages about what the compiler is doing.", aliases = List("--verbose")) + val version: Setting[Boolean] = BooleanSetting("-version", "Print product version and exit.", aliases = List("--version")) + val pageWidth: Setting[Int] = IntSetting("-pagewidth", "Set page width", 80, aliases = List("--page-width")) + val silentWarnings: Setting[Boolean] = BooleanSetting("-nowarn", "Silence all warnings.", aliases = List("--no-warnings")) /** Other settings */ - val encoding: Setting[String] = StringSetting("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding) withAbbreviation "--encoding" - val usejavacp: Setting[Boolean] = BooleanSetting("-usejavacp", "Utilize the java.class.path in classpath resolution.") withAbbreviation "--use-java-class-path" + val encoding: Setting[String] = StringSetting("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding, aliases = List("--encoding")) + val usejavacp: Setting[Boolean] = BooleanSetting("-usejavacp", "Utilize the java.class.path in classpath resolution.", aliases = List("--use-java-class-path")) /** Plugin-related setting */ val plugin: Setting[List[String]] = MultiStringSetting ("-Xplugin", "paths", "Load a plugin from each classpath.") @@ -88,19 +88,19 @@ class ScalaSettings extends Settings.SettingGroup with CommonScalaSettings { /** Path related settings */ val semanticdbTarget: Setting[String] = PathSetting("-semanticdb-target", "Specify an alternative output directory for SemanticDB files.", "") - val deprecation: Setting[Boolean] = BooleanSetting("-deprecation", "Emit warning and location for usages of deprecated APIs.") withAbbreviation "--deprecation" - val explainTypes: Setting[Boolean] = BooleanSetting("-explain-types", "Explain type errors in more detail.") withAbbreviation "--explain-types" - val explain: Setting[Boolean] = BooleanSetting("-explain", "Explain errors in more detail.") withAbbreviation "--explain" - val feature: Setting[Boolean] = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.") withAbbreviation "--feature" - val help: Setting[Boolean] = BooleanSetting("-help", "Print a synopsis of standard options.") withAbbreviation "--help" - val release: Setting[String] = ChoiceSetting("-release", "release", "Compile code with classes specific to the given version of the Java platform available on the classpath and emit bytecode for this version.", supportedReleaseVersions, "").withAbbreviation("--release") - val source: Setting[String] = ChoiceSetting("-source", "source version", "source version", List("3.0", "3.1", "3.0-migration", "3.1-migration"), "3.0").withAbbreviation("--source") - val scalajs: Setting[Boolean] = BooleanSetting("-scalajs", "Compile in Scala.js mode (requires scalajs-library.jar on the classpath).") withAbbreviation "--scalajs" - val unchecked: Setting[Boolean] = BooleanSetting("-unchecked", "Enable additional warnings where generated code depends on assumptions.") withAbbreviation "--unchecked" - val uniqid: Setting[Boolean] = BooleanSetting("-uniqid", "Uniquely tag all identifiers in debugging output.") withAbbreviation "--unique-id" - val language: Setting[List[String]] = MultiStringSetting("-language", "feature", "Enable one or more language features.") withAbbreviation "--language" - val rewrite: Setting[Option[Rewrites]] = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with a `...-migration` source version, rewrites sources to migrate to new version.") withAbbreviation "--rewrite" - val fromTasty: Setting[Boolean] = BooleanSetting("-from-tasty", "Compile classes from tasty files. The arguments are .tasty or .jar files.") withAbbreviation "--from-tasty" + val deprecation: Setting[Boolean] = BooleanSetting("-deprecation", "Emit warning and location for usages of deprecated APIs.", aliases = List("--deprecation")) + val explainTypes: Setting[Boolean] = BooleanSetting("-explain-types", "Explain type errors in more detail.", aliases = List("--explain-types")) + val explain: Setting[Boolean] = BooleanSetting("-explain", "Explain errors in more detail.", aliases = List("--explain")) + val feature: Setting[Boolean] = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.", aliases = List("--feature")) + val help: Setting[Boolean] = BooleanSetting("-help", "Print a synopsis of standard options.", aliases = List("--help")) + val release: Setting[String] = ChoiceSetting("-release", "release", "Compile code with classes specific to the given version of the Java platform available on the classpath and emit bytecode for this version.", supportedReleaseVersions, "", aliases = List("--release")) + val source: Setting[String] = ChoiceSetting("-source", "source version", "source version", List("3.0", "3.1", "3.0-migration", "3.1-migration"), "3.0", aliases = List("--source")) + val scalajs: Setting[Boolean] = BooleanSetting("-scalajs", "Compile in Scala.js mode (requires scalajs-library.jar on the classpath).", aliases = List("--scalajs")) + val unchecked: Setting[Boolean] = BooleanSetting("-unchecked", "Enable additional warnings where generated code depends on assumptions.", aliases = List("--unchecked")) + val uniqid: Setting[Boolean] = BooleanSetting("-uniqid", "Uniquely tag all identifiers in debugging output.", aliases = List("--unique-id")) + val language: Setting[List[String]] = MultiStringSetting("-language", "feature", "Enable one or more language features.", aliases = List("--language")) + val rewrite: Setting[Option[Rewrites]] = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with a `...-migration` source version, rewrites sources to migrate to new version.", aliases = List("--rewrite")) + val fromTasty: Setting[Boolean] = BooleanSetting("-from-tasty", "Compile classes from tasty files. The arguments are .tasty or .jar files.", aliases = List("--from-tasty")) val newSyntax: Setting[Boolean] = BooleanSetting("-new-syntax", "Require `then` and `do` in control expressions.") val oldSyntax: Setting[Boolean] = BooleanSetting("-old-syntax", "Require `(...)` around conditions.") @@ -109,8 +109,8 @@ class ScalaSettings extends Settings.SettingGroup with CommonScalaSettings { val YindentColons: Setting[Boolean] = BooleanSetting("-Yindent-colons", "Allow colons at ends-of-lines to start indentation blocks.") /** Decompiler settings */ - val printTasty: Setting[Boolean] = BooleanSetting("-print-tasty", "Prints the raw tasty.") withAbbreviation "--print-tasty" - val printLines: Setting[Boolean] = BooleanSetting("-print-lines", "Show source code line numbers.") withAbbreviation "--print-lines" + val printTasty: Setting[Boolean] = BooleanSetting("-print-tasty", "Prints the raw tasty.", aliases = List("--print-tasty")) + val printLines: Setting[Boolean] = BooleanSetting("-print-lines", "Show source code line numbers.", aliases = List("--print-lines")) /** Scala.js-related settings */ val scalajsGenStaticForwardersForNonTopLevelObjects: Setting[Boolean] = BooleanSetting("-scalajs-genStaticForwardersForNonTopLevelObjects", "Generate static forwarders even for non-top-level objects (Scala.js only)") @@ -135,8 +135,8 @@ class ScalaSettings extends Settings.SettingGroup with CommonScalaSettings { val XverifySignatures: Setting[Boolean] = BooleanSetting("-Xverify-signatures", "Verify generic signatures in generated bytecode.") val XignoreScala2Macros: Setting[Boolean] = BooleanSetting("-Xignore-scala2-macros", "Ignore errors when compiling code that calls Scala2 macros, these will fail at runtime.") val XimportSuggestionTimeout: Setting[Int] = IntSetting("-Ximport-suggestion-timeout", "Timeout (in ms) for searching for import suggestions when errors are reported.", 8000) - val Xsemanticdb: Setting[Boolean] = BooleanSetting("-Xsemanticdb", "Store information in SemanticDB.").withAbbreviation("-Ysemanticdb") - val Xtarget: Setting[String] = ChoiceSetting("-Xtarget", "target", "Emit bytecode for the specified version of the Java platform. This might produce bytecode that will break at runtime. When on JDK 9+, consider -release as a safer alternative.", supportedTargetVersions, "") withAbbreviation "--Xtarget" + val Xsemanticdb: Setting[Boolean] = BooleanSetting("-Xsemanticdb", "Store information in SemanticDB.", aliases = List("-Ysemanticdb")) + val Xtarget: Setting[String] = ChoiceSetting("-Xtarget", "target", "Emit bytecode for the specified version of the Java platform. This might produce bytecode that will break at runtime. When on JDK 9+, consider -release as a safer alternative.", supportedTargetVersions, "", aliases = List("--Xtarget")) val XmixinForceForwarders = ChoiceSetting( name = "-Xmixin-force-forwarders", @@ -175,7 +175,7 @@ class ScalaSettings extends Settings.SettingGroup with CommonScalaSettings { val YnoPredef: Setting[Boolean] = BooleanSetting("-Yno-predef", "Compile without importing Predef.") val Yskip: Setting[List[String]] = PhasesSetting("-Yskip", "Skip") val Ydumpclasses: Setting[String] = StringSetting("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "") - val YstopAfter: Setting[List[String]] = PhasesSetting("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat + val YstopAfter: Setting[List[String]] = PhasesSetting("-Ystop-after", "Stop after", aliases = List("-stop")) // backward compat val YstopBefore: Setting[List[String]] = PhasesSetting("-Ystop-before", "Stop before") // stop before erasure as long as we have not debugged it fully val YshowSuppressedErrors: Setting[Boolean] = BooleanSetting("-Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally suppressed.") val YdetailedStats: Setting[Boolean] = BooleanSetting("-Ydetailed-stats", "Show detailed internal compiler stats (needs Stats.enabled to be set to true).") diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index fb6fd75e9b4d..c5eee24ba6ae 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -67,12 +67,6 @@ object Settings { private var changed: Boolean = false - def withAbbreviation(abbrv: String): Setting[T] = - copy(aliases = aliases :+ abbrv)(idx) - - def dependsOn[U](setting: Setting[U], value: U): Setting[T] = - copy(depends = depends :+ (setting, value))(idx) - def valueIn(state: SettingsState): T = state.value(idx).asInstanceOf[T] @@ -170,9 +164,11 @@ object Settings { missingArg } + def matches(argName: String) = (name :: aliases).exists(_ == argName) + if (prefix != "" && arg.startsWith(prefix)) doSet(arg drop prefix.length) - else if (prefix == "" && name == arg.takeWhile(_ != ':')) + else if (prefix == "" && matches(arg.takeWhile(_ != ':'))) doSet(arg.dropWhile(_ != ':').drop(1)) else state @@ -257,35 +253,32 @@ object Settings { setting } - def BooleanSetting(name: String, descr: String, initialValue: Boolean = false): Setting[Boolean] = - publish(Setting(name, descr, initialValue)) + def BooleanSetting(name: String, descr: String, initialValue: Boolean = false, aliases: List[String] = Nil): Setting[Boolean] = + publish(Setting(name, descr, initialValue, aliases = aliases)) def StringSetting(name: String, helpArg: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] = publish(Setting(name, descr, default, helpArg, aliases = aliases)) - def ChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: String): Setting[String] = - publish(Setting(name, descr, default, helpArg, Some(choices))) + def ChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil): Setting[String] = + publish(Setting(name, descr, default, helpArg, Some(choices), aliases = aliases)) - def IntSetting(name: String, descr: String, default: Int): Setting[Int] = - publish(Setting(name, descr, default)) + def IntSetting(name: String, descr: String, default: Int, aliases: List[String] = Nil): Setting[Int] = + publish(Setting(name, descr, default, aliases = aliases)) def IntChoiceSetting(name: String, descr: String, choices: Seq[Int], default: Int): Setting[Int] = publish(Setting(name, descr, default, choices = Some(choices))) - def MultiStringSetting(name: String, helpArg: String, descr: String): Setting[List[String]] = - publish(Setting(name, descr, Nil, helpArg)) + def MultiStringSetting(name: String, helpArg: String, descr: String, aliases: List[String] = Nil): Setting[List[String]] = + publish(Setting(name, descr, Nil, helpArg, aliases = aliases)) def OutputSetting(name: String, helpArg: String, descr: String, default: AbstractFile): Setting[AbstractFile] = publish(Setting(name, descr, default, helpArg)) - def PathSetting(name: String, descr: String, default: String): Setting[String] = - publish(Setting(name, descr, default)) - - def PathSetting(name: String, helpArg: String, descr: String, default: String): Setting[String] = - publish(Setting(name, descr, default, helpArg)) + def PathSetting(name: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] = + publish(Setting(name, descr, default, aliases = aliases)) - def PhasesSetting(name: String, descr: String, default: String = ""): Setting[List[String]] = - publish(Setting(name, descr, if (default.isEmpty) Nil else List(default))) + def PhasesSetting(name: String, descr: String, default: String = "", aliases: List[String] = Nil): Setting[List[String]] = + publish(Setting(name, descr, if (default.isEmpty) Nil else List(default), aliases = aliases)) def PrefixSetting(name: String, pre: String, descr: String): Setting[List[String]] = publish(Setting(name, descr, Nil, prefix = pre)) @@ -293,7 +286,7 @@ object Settings { def VersionSetting(name: String, descr: String, default: ScalaVersion = NoScalaVersion): Setting[ScalaVersion] = publish(Setting(name, descr, default)) - def OptionSetting[T: ClassTag](name: String, descr: String): Setting[Option[T]] = - publish(Setting(name, descr, None, propertyClass = Some(implicitly[ClassTag[T]].runtimeClass))) + def OptionSetting[T: ClassTag](name: String, descr: String, aliases: List[String] = Nil): Setting[Option[T]] = + publish(Setting(name, descr, None, propertyClass = Some(implicitly[ClassTag[T]].runtimeClass), aliases = aliases)) } } diff --git a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala index 60c4bfa57fc1..a18f96dfd35b 100644 --- a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala +++ b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala @@ -9,6 +9,19 @@ import org.junit.Assert._ class ScalaSettingsTests: + @Test def `A setting with aliases is accepted`: Unit = + class MySettings extends SettingGroup: + val classpath: Setting[String] = PathSetting("-classpath", "Specify where to find user class files.", ".", aliases = List("--class-path", "-cp")) + val settings = MySettings() + val args = tokenize("-cp path/to/classes1:other/path/to/classes2") + val summary = ArgsSummary(settings.defaultState, args, errors = Nil, warnings = Nil) + val res = settings.processArguments(summary, processAll = true, skipped = Nil) + val classpath = settings.classpath.valueIn(res.sstate) + assertEquals(2, args.length) + assertTrue(s"found warnings: ${res.warnings}", res.warnings.isEmpty) + assertTrue(s"found errors: ${res.errors}", res.errors.isEmpty) + assertTrue("wrong classpath", classpath == "path/to/classes1:other/path/to/classes2") + @Test def `A multistring setting is multivalued`: Unit = class SUT extends SettingGroup: val language: Setting[List[String]] = MultiStringSetting("-language", "feature", "Enable one or more language features.")