From cae9eebd387e523fcb3a4598dc31545f75306fd3 Mon Sep 17 00:00:00 2001 From: Piotr Chabelski Date: Thu, 24 Oct 2024 11:26:11 +0200 Subject: [PATCH 1/2] Ensure consecutive -Wconf:* flags are not ignored --- .../scala/cli/integration/SipScalaTests.scala | 33 +++++++++++++++++++ .../scala/scala/build/options/ScalacOpt.scala | 3 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/modules/integration/src/test/scala/scala/cli/integration/SipScalaTests.scala b/modules/integration/src/test/scala/scala/cli/integration/SipScalaTests.scala index 86e8a6ca2d..e0c342863b 100644 --- a/modules/integration/src/test/scala/scala/cli/integration/SipScalaTests.scala +++ b/modules/integration/src/test/scala/scala/cli/integration/SipScalaTests.scala @@ -515,6 +515,39 @@ class SipScalaTests extends ScalaCliSuite with SbtTestHelper with MillTestHelper } } + test("consecutive -Wconf:* flags are not ignored") { + val sv = "3.5.2" + val sourceFileName = "example.scala" + val warningConfOptions = Seq("-Wconf:cat=deprecation:e", "-Wconf:any:s") + TestInputs(os.rel / sourceFileName -> + s"""//> using scala $sv + |//> using options ${warningConfOptions.mkString(" ")} + |object WConfExample extends App { + | @deprecated("This method will be removed", "1.0.0") + | def oldMethod(): Unit = println("This is an old method.") + | oldMethod() + |} + |""".stripMargin).fromRoot { root => + val localCache = root / "local-cache" + val localBin = root / "local-bin" + os.proc( + TestUtil.cs, + "install", + "--cache", + localCache, + "--install-dir", + localBin, + s"scalac:$sv" + ).call(cwd = root) + val cliRes = os.proc(TestUtil.cli, "compile", sourceFileName, "--server=false") + .call(cwd = root, check = false, stderr = os.Pipe) + val scalacRes = os.proc(localBin / "scalac", warningConfOptions, sourceFileName) + .call(cwd = root, check = false, stderr = os.Pipe) + expect(scalacRes.exitCode == cliRes.exitCode) + expect(scalacRes.err.trim() == cliRes.err.trim()) + } + } + for { sv <- Seq(Constants.scala212, Constants.scala213, Constants.scala3NextRc) code = diff --git a/modules/options/src/main/scala/scala/build/options/ScalacOpt.scala b/modules/options/src/main/scala/scala/build/options/ScalacOpt.scala index 6fbcb86a84..a03d53f474 100644 --- a/modules/options/src/main/scala/scala/build/options/ScalacOpt.scala +++ b/modules/options/src/main/scala/scala/build/options/ScalacOpt.scala @@ -18,7 +18,8 @@ object ScalacOpt { private val repeatingKeys = Set( "-Xplugin", "-P", // plugin options - "-language" + "-language", + "-Wconf" ) implicit val hashedType: HashedType[ScalacOpt] = { From 9454f6e5b4db042475b39b8687e55f79681a9402 Mon Sep 17 00:00:00 2001 From: Piotr Chabelski Date: Thu, 24 Oct 2024 15:04:45 +0200 Subject: [PATCH 2/2] Ensure compiler options passed via the command line and using directives follow the same order --- .../cli/commands/shared/ScalacOptions.scala | 6 ++--- .../scala/cli/integration/SipScalaTests.scala | 23 +++++++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/modules/cli/src/main/scala/scala/cli/commands/shared/ScalacOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/shared/ScalacOptions.scala index 62e772f500..ce73e08edc 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/shared/ScalacOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/shared/ScalacOptions.scala @@ -101,16 +101,16 @@ object ScalacOptions { case h :: t if scalacOptionsPrefixes.exists(h.startsWith) && !ScalacDeprecatedOptions.contains(h) => - Right(Some((Some(h :: acc.getOrElse(Nil)), t))) + Right(Some((Some(acc.getOrElse(Nil) :+ h), t))) case h :: t if scalacNoArgAliasedOptions.contains(h) => - Right(Some((Some(h :: acc.getOrElse(Nil)), t))) + Right(Some((Some(acc.getOrElse(Nil) :+ h), t))) case h :: t if scalacAliasedOptions.contains(h) => // check if the next scalac arg is a different option or a param to the current option val maybeOptionArg = t.headOption.filter(!_.startsWith("-")) // if it's a param, it'll be treated as such and considered already parsed val newTail = maybeOptionArg.map(_ => t.drop(1)).getOrElse(t) val newHead = List(h) ++ maybeOptionArg - Right(Some((Some(newHead ++ acc.getOrElse(Nil)), newTail))) + Right(Some((Some(acc.getOrElse(Nil) ++ newHead), newTail))) case _ => underlying.step(args, index, acc, formatter) } def get(acc: Option[List[String]], formatter: Formatter[Name]): Either[Error, List[String]] = diff --git a/modules/integration/src/test/scala/scala/cli/integration/SipScalaTests.scala b/modules/integration/src/test/scala/scala/cli/integration/SipScalaTests.scala index e0c342863b..e0e637f610 100644 --- a/modules/integration/src/test/scala/scala/cli/integration/SipScalaTests.scala +++ b/modules/integration/src/test/scala/scala/cli/integration/SipScalaTests.scala @@ -515,13 +515,19 @@ class SipScalaTests extends ScalaCliSuite with SbtTestHelper with MillTestHelper } } - test("consecutive -Wconf:* flags are not ignored") { + for { + useDirective <- Seq(true, false) + if !Properties.isWin + optionsSource = if (useDirective) "using directive" else "command line" + } test(s"consecutive -Wconf:* flags are not ignored (passed via $optionsSource)") { val sv = "3.5.2" val sourceFileName = "example.scala" val warningConfOptions = Seq("-Wconf:cat=deprecation:e", "-Wconf:any:s") + val maybeDirectiveString = + if (useDirective) s"//> using options ${warningConfOptions.mkString(" ")}" else "" TestInputs(os.rel / sourceFileName -> s"""//> using scala $sv - |//> using options ${warningConfOptions.mkString(" ")} + |$maybeDirectiveString |object WConfExample extends App { | @deprecated("This method will be removed", "1.0.0") | def oldMethod(): Unit = println("This is an old method.") @@ -539,12 +545,19 @@ class SipScalaTests extends ScalaCliSuite with SbtTestHelper with MillTestHelper localBin, s"scalac:$sv" ).call(cwd = root) - val cliRes = os.proc(TestUtil.cli, "compile", sourceFileName, "--server=false") - .call(cwd = root, check = false, stderr = os.Pipe) + val cliRes = + os.proc( + TestUtil.cli, + "compile", + sourceFileName, + "--server=false", + if (useDirective) Nil else warningConfOptions + ) + .call(cwd = root, check = false, stderr = os.Pipe) val scalacRes = os.proc(localBin / "scalac", warningConfOptions, sourceFileName) .call(cwd = root, check = false, stderr = os.Pipe) expect(scalacRes.exitCode == cliRes.exitCode) - expect(scalacRes.err.trim() == cliRes.err.trim()) + expect(cliRes.err.trim() == scalacRes.err.trim()) } }