From 5ae4b9c54ea78bd3de68c1df8ab8129ca0e8b1c3 Mon Sep 17 00:00:00 2001 From: Yadu Krishnan Date: Thu, 3 Apr 2025 22:23:24 +0200 Subject: [PATCH 1/5] Use scalac preset options in directive --- DEV.md | 4 +- .../scala/scala/build/tests/BuildTests.scala | 19 +++++++ .../directives/ScalacOptions.scala | 49 ++++++++++++++++--- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/DEV.md b/DEV.md index 1e11e908a1..e1f2e678fb 100644 --- a/DEV.md +++ b/DEV.md @@ -56,8 +56,8 @@ the unit tests: To can filter unit test suites: ```bash -./mill 'build-module.test' 'scala.build.tests.BuildTestsScalac.*' -./mill 'build-module.test' 'scala.build.tests.BuildTestsScalac.simple' +./mill 'build-module[].test' 'scala.build.tests.BuildTestsScalac.*' +./mill 'build-module[].test' 'scala.build.tests.BuildTestsScalac.simple' ``` #### Run integration tests with the JVM launcher diff --git a/modules/build/src/test/scala/scala/build/tests/BuildTests.scala b/modules/build/src/test/scala/scala/build/tests/BuildTests.scala index c163a1b7bc..10e511bc74 100644 --- a/modules/build/src/test/scala/scala/build/tests/BuildTests.scala +++ b/modules/build/src/test/scala/scala/build/tests/BuildTests.scala @@ -778,6 +778,25 @@ abstract class BuildTests(server: Boolean) extends TestUtil.ScalaCliBuildSuite { } } + test("use scalac preset options") { + val inputs = TestInputs( + os.rel / "foo.scala" -> + """//> using scala 2.13 + |//> using options.preset suggested + | + |def foo = "bar" + |""".stripMargin + ) + + inputs.withBuild(defaultOptions, buildThreads, bloopConfigOpt) { (_, _, maybeBuild) => + val expectedOptions = + Seq("-Xfatal-warnings", "-deprecation", "-unchecked") + val scalacOptions = + maybeBuild.toOption.get.options.scalaOptions.scalacOptions.toSeq.map(_.value.value) + expect(scalacOptions == expectedOptions) + } + } + test("multiple times scalac options with -Xplugin prefix") { val inputs = TestInputs( os.rel / "foo.scala" -> diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala index e3b4add2ff..365d58a106 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala @@ -2,7 +2,7 @@ package scala.build.preprocessing.directives import scala.build.Positioned import scala.build.directives.* -import scala.build.errors.BuildException +import scala.build.errors.{BuildException, DirectiveErrors, InputsException} import scala.build.options.WithBuildRequirements.* import scala.build.options.{ BuildOptions, @@ -22,7 +22,10 @@ import scala.cli.commands.SpecificationLevel "using option _option_ | using options _option1_ _option2_ …", """`//> using option` _option_ | - |`//> using options` _option1_ _option2_ …""".stripMargin + |`//> using options` _option1_ _option2_ … + | + |`//> using options.preset` _suggested_ | _ci_ | _strict_ + |""".stripMargin ) @DirectiveDescription("Add Scala compiler options") @DirectiveLevel(SpecificationLevel.MUST) @@ -32,12 +35,39 @@ final case class ScalacOptions( @DirectiveName("test.option") @DirectiveName("test.options") @DirectiveName("test.scalacOptions") - testOptions: List[Positioned[String]] = Nil + testOptions: List[Positioned[String]] = Nil, + @DirectiveName("option.preset") + @DirectiveName("options.preset") + presetOptions: Option[String] = None ) extends HasBuildOptionsWithRequirements { - def buildOptionsList: List[Either[BuildException, WithBuildRequirements[BuildOptions]]] = List( - ScalacOptions.buildOptions(options).map(_.withEmptyRequirements), - ScalacOptions.buildOptions(testOptions).map(_.withScopeRequirement(Scope.Test)) - ) + def buildOptionsList: List[Either[BuildException, WithBuildRequirements[BuildOptions]]] = { + val explicitScalacOptions = List( + ScalacOptions.buildOptions(options).map(_.withEmptyRequirements), + ScalacOptions.buildOptions(testOptions).map(_.withScopeRequirement(Scope.Test)) + ) + + presetOptions match { + case None => explicitScalacOptions + case Some("suggested") => + val presetOptions = + ScalacOptions.buildOptions(ScalacOptions.presetOptionsSuggested.map(Positioned.none)) + explicitScalacOptions :+ presetOptions.map(_.withEmptyRequirements) + case Some("ci") => + val presetOptions = + ScalacOptions.buildOptions(ScalacOptions.presetOptionsCI.map(Positioned.none)) + explicitScalacOptions :+ presetOptions.map(_.withEmptyRequirements) + case Some("strict") => + val presetOptions = + ScalacOptions.buildOptions(ScalacOptions.presetOptionsStrict.map(Positioned.none)) + explicitScalacOptions :+ presetOptions.map(_.withEmptyRequirements) + case Some(other) => + List(Left( + InputsException( + s"Unknown preset options: $other. Available options are: suggested, ci, strict" + ) + )) + } + } } object ScalacOptions { @@ -50,4 +80,9 @@ object ScalacOptions { ) ) } + + // todo: this should be based on the scala version. This might not be the correct location + def presetOptionsSuggested = List("-Xfatal-warnings", "-deprecation", "-unchecked") + def presetOptionsCI = List("-Xfatal-warnings", "-deprecation", "-unchecked") + def presetOptionsStrict = List("-Xfatal-warnings", "-deprecation", "-unchecked") } From d61c50945b0a1cd5549d00a7815e7ed8e93af61e Mon Sep 17 00:00:00 2001 From: Yadu Krishnan Date: Fri, 4 Apr 2025 17:49:23 +0200 Subject: [PATCH 2/5] enums for preset options --- .../directives/ScalacOptions.scala | 117 ++++++++++++++++-- .../scala/scala/build/options/ScalacOpt.scala | 6 + 2 files changed, 112 insertions(+), 11 deletions(-) diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala index eb545ff6f3..e6c34b0bb0 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala @@ -19,6 +19,7 @@ import scala.cli.commands.SpecificationLevel @DirectiveExamples("//> using options -Xasync -Xfatal-warnings") @DirectiveExamples("//> using test.option -Xasync") @DirectiveExamples("//> using test.options -Xasync -Xfatal-warnings") +@DirectiveExamples("//> using options.preset suggested") @DirectiveUsage( "using option _option_ | using options _option1_ _option2_ …", """`//> using scalacOption` _option_ @@ -58,24 +59,35 @@ final case class ScalacOptions( ScalacOptions.buildOptions(testOptions).map(_.withScopeRequirement(Scope.Test)) ) + // todo: fix: How to get this correctly? + val scalaVersion = "3.3.4" + + //todo: how to get the command line preset option. If it is there in the command line use it, else use from the directive. + presetOptions match { case None => explicitScalacOptions - case Some("suggested") => + case Some(ScalacOpt.PresetOptions.Suggested.preset) => val presetOptions = - ScalacOptions.buildOptions(ScalacOptions.presetOptionsSuggested.map(Positioned.none)) + ScalacOptions.buildOptions( + ScalacOptions.presetOptionsSuggested(scalaVersion).map(Positioned.none) + ) explicitScalacOptions :+ presetOptions.map(_.withEmptyRequirements) - case Some("ci") => + case Some(ScalacOpt.PresetOptions.CI.preset) => val presetOptions = - ScalacOptions.buildOptions(ScalacOptions.presetOptionsCI.map(Positioned.none)) + ScalacOptions.buildOptions( + ScalacOptions.presetOptionsCI(scalaVersion).map(Positioned.none) + ) explicitScalacOptions :+ presetOptions.map(_.withEmptyRequirements) - case Some("strict") => + case Some(ScalacOpt.PresetOptions.Strict.preset) => val presetOptions = - ScalacOptions.buildOptions(ScalacOptions.presetOptionsStrict.map(Positioned.none)) + ScalacOptions.buildOptions( + ScalacOptions.presetOptionsStrict(scalaVersion).map(Positioned.none) + ) explicitScalacOptions :+ presetOptions.map(_.withEmptyRequirements) case Some(other) => List(Left( InputsException( - s"Unknown preset options: $other. Available options are: suggested, ci, strict" + s"Unknown preset options: $other. Available options are: ${ScalacOpt.PresetOptions.values.map(_.preset).mkString(", ")}" ) )) } @@ -93,8 +105,91 @@ object ScalacOptions { ) } - // todo: this should be based on the scala version. This might not be the correct location - def presetOptionsSuggested = List("-Xfatal-warnings", "-deprecation", "-unchecked") - def presetOptionsCI = List("-Xfatal-warnings", "-deprecation", "-unchecked") - def presetOptionsStrict = List("-Xfatal-warnings", "-deprecation", "-unchecked") + // todo: Is this might not be the correct location to handle this? + private def presetOptionsSuggested(scalaVersion: String) = + scalaVersion match { + case v if v.startsWith("2.12") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + case v if v.startsWith("2.13") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + + case v if v.startsWith("3.0") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + } + + private def presetOptionsCI(scalaVersion: String) = + scalaVersion match { + case v if v.startsWith("2.12") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + case v if v.startsWith("2.13") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + + case v if v.startsWith("3.0") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + } + + private def presetOptionsStrict(scalaVersion: String) = + scalaVersion match { + case v if v.startsWith("2.12") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + case v if v.startsWith("2.13") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + + case v if v.startsWith("3.0") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + } } 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 ff7b0dfc5d..7e5afb2446 100644 --- a/modules/options/src/main/scala/scala/build/options/ScalacOpt.scala +++ b/modules/options/src/main/scala/scala/build/options/ScalacOpt.scala @@ -63,4 +63,10 @@ object ScalacOpt { def filterScalacOptionKeys(f: String => Boolean): ShadowingSeq[ScalacOpt] = opts.filterKeys(_.key.exists(f)) } + + enum PresetOptions(val preset: String): + case Suggested extends PresetOptions("suggested") + case CI extends PresetOptions("ci") + case Strict extends PresetOptions("strict") + } From 06f5cd74bfc0d79e7d7ab8085130a327239deee2 Mon Sep 17 00:00:00 2001 From: Yadu Krishnan Date: Thu, 10 Apr 2025 21:44:45 +0200 Subject: [PATCH 3/5] resolve scalac options based on scala version and preset --- .../main/scala/scala/build/CrossSources.scala | 148 +++++++++++++++++- .../build/internal/util/WarningMessages.scala | 3 + .../directives/ScalacOptions.scala | 96 +----------- .../scala/build/options/ScalaOptions.scala | 2 + .../scala/scala/build/options/ScalacOpt.scala | 18 ++- 5 files changed, 170 insertions(+), 97 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/CrossSources.scala b/modules/build/src/main/scala/scala/build/CrossSources.scala index c7e731752a..e37ed7a56f 100644 --- a/modules/build/src/main/scala/scala/build/CrossSources.scala +++ b/modules/build/src/main/scala/scala/build/CrossSources.scala @@ -1,7 +1,6 @@ package scala.build import java.io.File - import scala.build.CollectionOps.* import scala.build.EitherCps.{either, value} import scala.build.Ops.* @@ -17,11 +16,13 @@ import scala.build.input.ElementsUtils.* import scala.build.input.* import scala.build.internal.Constants import scala.build.internal.util.{RegexUtils, WarningMessages} +import scala.build.options.ScalacOpt.PresetOption import scala.build.options.{ BuildOptions, BuildRequirements, MaybeScalaVersion, Scope, + ShadowingSeq, SuppressWarningOptions, WithBuildRequirements } @@ -273,6 +274,64 @@ object CrossSources { ) }).flatten + def resolveScalacOptionsForPreset( + mayBeScalaVersion: Option[MaybeScalaVersion], + presetOption: PresetOption + ): Seq[Positioned[String]] = { + // todo: I don't think this is the right approach + val scalaVersion = mayBeScalaVersion.flatMap(_.versionOpt) match { + case Some(version) => version + case None => Constants.defaultScalaVersion + } + + presetOption match { + case ScalacOpt.PresetOption.Suggested.preset => + presetOptionsSuggested(scalaVersion).map(Positioned.none) + + case ScalacOpt.PresetOption.CI.preset => + presetOptionsCI(scalaVersion).map(Positioned.none) + + case ScalacOpt.PresetOption.Strict.preset => + presetOptionsStrict(scalaVersion).map(Positioned.none) + + } + + } + + def buildOptionWithPreset(opts: BuildOptions) = { + val scalaVersion = opts.scalaOptions.scalaVersion + val scalacOpts = opts.scalaOptions.scalacOptions + val scalacPresetOpt = opts.scalaOptions.scalacPresetOption + if ( + scalacPresetOpt.isDefined && scalacOpts.map( + _.value + ).nonEmpty + ) { + val scalacMsg = WarningMessages.conflictingScalacOptions( + scalacPresetOpt.map( + _.preset + ).get, // safe to do get here since we have check before + scalacOpts.map(_.value) + ) + logger.diagnostic( + scalacMsg, + Severity.Warning, + scalacOpts.map(_.positions).getOrElse(Nil) + ) + opts + } + else if (scalacPresetOpt.isDefined && scalacOpts.isEmpty) + // resolve the preset options and set into BuildOptions + val resolvedOpts = + resolveScalacOptionsForPreset(opts.scalaOptions.scalaVersion, scalacPresetOpt) + opts.copy( + scalaOptions = opts.scalaOptions.copy(scalacOptions = ShadowingSeq.from(resolvedOpts)) + ) + else + opts + + } + val resourceDirectoriesFromDirectives = { val resourceDirsFromCli = allInputs.elements.flatMap { case rd: ResourceDirectory => Some(rd.path); case _ => None } @@ -497,4 +556,91 @@ object CrossSources { Severity.Warning, transitiveAdditionalSource.positions ) + + private def presetOptionsSuggested(scalaVersion: String) = + scalaVersion match { + case v if v.startsWith("2.12") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + case v if v.startsWith("2.13") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + + case v if v.startsWith("3.0") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + } + + private def presetOptionsCI(scalaVersion: String) = + scalaVersion match { + case v if v.startsWith("2.12") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + case v if v.startsWith("2.13") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + + case v if v.startsWith("3.0") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + } + + private def presetOptionsStrict(scalaVersion: String) = + scalaVersion match { + case v if v.startsWith("2.12") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + case v if v.startsWith("2.13") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + + case v if v.startsWith("3.0") => + List( + "-encoding", + "utf8", + "-deprecation", + "-feature", + "-unchecked" + ) + } } diff --git a/modules/build/src/main/scala/scala/build/internal/util/WarningMessages.scala b/modules/build/src/main/scala/scala/build/internal/util/WarningMessages.scala index 9f74e9c212..7694bef0e4 100644 --- a/modules/build/src/main/scala/scala/build/internal/util/WarningMessages.scala +++ b/modules/build/src/main/scala/scala/build/internal/util/WarningMessages.scala @@ -139,4 +139,7 @@ object WarningMessages { else s"""Using 'latest' for toolkit is deprecated, use 'default' to get more stable behaviour: | $updatedValue""".stripMargin + + def conflictingScalacOptions(preset: String, scalacOptions: Seq[String]) = + s"The scalacPreset $preset is used, but explicit scalac options ${scalacOptions.mkString(",")} are provided. Preset option is ignored." } diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala index 88baaf012a..0d18604f46 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala @@ -72,19 +72,19 @@ final case class ScalacOptions( presetOptions match { case None => explicitScalacOptions - case Some(ScalacOpt.PresetOptions.Suggested.preset) => + case Some(ScalacOpt.PresetOption.Suggested.preset) => val presetOptions = ScalacOptions.buildOptions( ScalacOptions.presetOptionsSuggested(scalaVersion).map(Positioned.none) ) explicitScalacOptions :+ presetOptions.map(_.withEmptyRequirements) - case Some(ScalacOpt.PresetOptions.CI.preset) => + case Some(ScalacOpt.PresetOption.CI.preset) => val presetOptions = ScalacOptions.buildOptions( ScalacOptions.presetOptionsCI(scalaVersion).map(Positioned.none) ) explicitScalacOptions :+ presetOptions.map(_.withEmptyRequirements) - case Some(ScalacOpt.PresetOptions.Strict.preset) => + case Some(ScalacOpt.PresetOption.Strict.preset) => val presetOptions = ScalacOptions.buildOptions( ScalacOptions.presetOptionsStrict(scalaVersion).map(Positioned.none) @@ -93,7 +93,7 @@ final case class ScalacOptions( case Some(other) => List(Left( InputsException( - s"Unknown preset options: $other. Available options are: ${ScalacOpt.PresetOptions.values.map(_.preset).mkString(", ")}" + s"Unknown preset options: $other. Available options are: ${ScalacOpt.PresetOption.values.map(_.preset).mkString(", ")}" ) )) } @@ -110,92 +110,4 @@ object ScalacOptions { ) ) } - - // todo: Is this might not be the correct location to handle this? - private def presetOptionsSuggested(scalaVersion: String) = - scalaVersion match { - case v if v.startsWith("2.12") => - List( - "-encoding", - "utf8", - "-deprecation", - "-feature", - "-unchecked" - ) - case v if v.startsWith("2.13") => - List( - "-encoding", - "utf8", - "-deprecation", - "-feature", - "-unchecked" - ) - - case v if v.startsWith("3.0") => - List( - "-encoding", - "utf8", - "-deprecation", - "-feature", - "-unchecked" - ) - } - - private def presetOptionsCI(scalaVersion: String) = - scalaVersion match { - case v if v.startsWith("2.12") => - List( - "-encoding", - "utf8", - "-deprecation", - "-feature", - "-unchecked" - ) - case v if v.startsWith("2.13") => - List( - "-encoding", - "utf8", - "-deprecation", - "-feature", - "-unchecked" - ) - - case v if v.startsWith("3.0") => - List( - "-encoding", - "utf8", - "-deprecation", - "-feature", - "-unchecked" - ) - } - - private def presetOptionsStrict(scalaVersion: String) = - scalaVersion match { - case v if v.startsWith("2.12") => - List( - "-encoding", - "utf8", - "-deprecation", - "-feature", - "-unchecked" - ) - case v if v.startsWith("2.13") => - List( - "-encoding", - "utf8", - "-deprecation", - "-feature", - "-unchecked" - ) - - case v if v.startsWith("3.0") => - List( - "-encoding", - "utf8", - "-deprecation", - "-feature", - "-unchecked" - ) - } } diff --git a/modules/options/src/main/scala/scala/build/options/ScalaOptions.scala b/modules/options/src/main/scala/scala/build/options/ScalaOptions.scala index a236e36ae5..a640226f7c 100644 --- a/modules/options/src/main/scala/scala/build/options/ScalaOptions.scala +++ b/modules/options/src/main/scala/scala/build/options/ScalaOptions.scala @@ -4,6 +4,7 @@ import dependency.AnyDependency import scala.build.Positioned import scala.build.internal.Constants +import scala.build.options.ScalacOpt.PresetOption final case class ScalaOptions( scalaVersion: Option[MaybeScalaVersion] = None, @@ -12,6 +13,7 @@ final case class ScalaOptions( addScalaCompiler: Option[Boolean] = None, semanticDbOptions: SemanticDbOptions = SemanticDbOptions(), scalacOptions: ShadowingSeq[Positioned[ScalacOpt]] = ShadowingSeq.empty, + scalacPresetOption: Option[PresetOption] = None, extraScalaVersions: Set[String] = Set.empty, compilerPlugins: Seq[Positioned[AnyDependency]] = Nil, platform: Option[Positioned[Platform]] = None, 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 7e5afb2446..2bc9d1e4c8 100644 --- a/modules/options/src/main/scala/scala/build/options/ScalacOpt.scala +++ b/modules/options/src/main/scala/scala/build/options/ScalacOpt.scala @@ -64,9 +64,19 @@ object ScalacOpt { opts.filterKeys(_.key.exists(f)) } - enum PresetOptions(val preset: String): - case Suggested extends PresetOptions("suggested") - case CI extends PresetOptions("ci") - case Strict extends PresetOptions("strict") + /* enum PresetOption(val preset: String): + case Suggested extends PresetOption("suggested") + case CI extends PresetOption("ci") + case Strict extends PresetOption("strict")*/ + sealed abstract class PresetOption(val preset: String) extends Product with Serializable + object PresetOption { + case object Suggested extends PresetOption("suggested") + case object CI extends PresetOption("ci") + case object Strict extends PresetOption("strict") + + implicit val hashedType: HashedType[PresetOption] = { + opt => opt.preset + } + } } From ec393ed7a7fb7c78d162dec4da6011adc319bbc8 Mon Sep 17 00:00:00 2001 From: Yadu Krishnan Date: Thu, 10 Apr 2025 22:13:39 +0200 Subject: [PATCH 4/5] fixed compilation errors --- .../main/scala/scala/build/CrossSources.scala | 41 +++++++++---------- .../directives/ScalacOptions.scala | 38 +---------------- .../scala/build/options/HashedType.scala | 4 ++ .../scala/scala/build/options/ScalacOpt.scala | 9 ---- 4 files changed, 25 insertions(+), 67 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/CrossSources.scala b/modules/build/src/main/scala/scala/build/CrossSources.scala index e37ed7a56f..f768244a1b 100644 --- a/modules/build/src/main/scala/scala/build/CrossSources.scala +++ b/modules/build/src/main/scala/scala/build/CrossSources.scala @@ -21,6 +21,7 @@ import scala.build.options.{ BuildOptions, BuildRequirements, MaybeScalaVersion, + ScalacOpt, Scope, ShadowingSeq, SuppressWarningOptions, @@ -277,7 +278,7 @@ object CrossSources { def resolveScalacOptionsForPreset( mayBeScalaVersion: Option[MaybeScalaVersion], presetOption: PresetOption - ): Seq[Positioned[String]] = { + ): Seq[Positioned[ScalacOpt]] = { // todo: I don't think this is the right approach val scalaVersion = mayBeScalaVersion.flatMap(_.versionOpt) match { case Some(version) => version @@ -285,13 +286,13 @@ object CrossSources { } presetOption match { - case ScalacOpt.PresetOption.Suggested.preset => + case PresetOption.Suggested => presetOptionsSuggested(scalaVersion).map(Positioned.none) - case ScalacOpt.PresetOption.CI.preset => + case PresetOption.CI => presetOptionsCI(scalaVersion).map(Positioned.none) - case ScalacOpt.PresetOption.Strict.preset => + case PresetOption.Strict => presetOptionsStrict(scalaVersion).map(Positioned.none) } @@ -302,28 +303,24 @@ object CrossSources { val scalaVersion = opts.scalaOptions.scalaVersion val scalacOpts = opts.scalaOptions.scalacOptions val scalacPresetOpt = opts.scalaOptions.scalacPresetOption - if ( - scalacPresetOpt.isDefined && scalacOpts.map( - _.value - ).nonEmpty - ) { + if (scalacPresetOpt.isDefined && scalacOpts.keys.nonEmpty) { val scalacMsg = WarningMessages.conflictingScalacOptions( scalacPresetOpt.map( _.preset ).get, // safe to do get here since we have check before - scalacOpts.map(_.value) + scalacOpts.keys.map(_.value.value) ) logger.diagnostic( scalacMsg, Severity.Warning, - scalacOpts.map(_.positions).getOrElse(Nil) + Nil // todo: fix this ) opts } - else if (scalacPresetOpt.isDefined && scalacOpts.isEmpty) + else if (scalacPresetOpt.isDefined && scalacOpts.keys.isEmpty) // resolve the preset options and set into BuildOptions val resolvedOpts = - resolveScalacOptionsForPreset(opts.scalaOptions.scalaVersion, scalacPresetOpt) + resolveScalacOptionsForPreset(opts.scalaOptions.scalaVersion, scalacPresetOpt.get) opts.copy( scalaOptions = opts.scalaOptions.copy(scalacOptions = ShadowingSeq.from(resolvedOpts)) ) @@ -566,7 +563,7 @@ object CrossSources { "-deprecation", "-feature", "-unchecked" - ) + ).map(ScalacOpt.apply) case v if v.startsWith("2.13") => List( "-encoding", @@ -574,7 +571,7 @@ object CrossSources { "-deprecation", "-feature", "-unchecked" - ) + ).map(ScalacOpt.apply) case v if v.startsWith("3.0") => List( @@ -583,7 +580,7 @@ object CrossSources { "-deprecation", "-feature", "-unchecked" - ) + ).map(ScalacOpt.apply) } private def presetOptionsCI(scalaVersion: String) = @@ -595,7 +592,7 @@ object CrossSources { "-deprecation", "-feature", "-unchecked" - ) + ).map(ScalacOpt.apply) case v if v.startsWith("2.13") => List( "-encoding", @@ -603,7 +600,7 @@ object CrossSources { "-deprecation", "-feature", "-unchecked" - ) + ).map(ScalacOpt.apply) case v if v.startsWith("3.0") => List( @@ -612,7 +609,7 @@ object CrossSources { "-deprecation", "-feature", "-unchecked" - ) + ).map(ScalacOpt.apply) } private def presetOptionsStrict(scalaVersion: String) = @@ -624,7 +621,7 @@ object CrossSources { "-deprecation", "-feature", "-unchecked" - ) + ).map(ScalacOpt.apply) case v if v.startsWith("2.13") => List( "-encoding", @@ -632,7 +629,7 @@ object CrossSources { "-deprecation", "-feature", "-unchecked" - ) + ).map(ScalacOpt.apply) case v if v.startsWith("3.0") => List( @@ -641,6 +638,6 @@ object CrossSources { "-deprecation", "-feature", "-unchecked" - ) + ).map(ScalacOpt.apply) } } diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala index 0d18604f46..cbb5f4375e 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/ScalacOptions.scala @@ -59,45 +59,11 @@ final case class ScalacOptions( @DirectiveName("options.preset") presetOptions: Option[String] = None ) extends HasBuildOptionsWithRequirements { - def buildOptionsList: List[Either[BuildException, WithBuildRequirements[BuildOptions]]] = { - val explicitScalacOptions = List( + def buildOptionsList: List[Either[BuildException, WithBuildRequirements[BuildOptions]]] = + List( ScalacOptions.buildOptions(options).map(_.withEmptyRequirements), ScalacOptions.buildOptions(testOptions).map(_.withScopeRequirement(Scope.Test)) ) - - // todo: fix: How to get this correctly? - val scalaVersion = "3.3.4" - - //todo: how to get the command line preset option. If it is there in the command line use it, else use from the directive. - - presetOptions match { - case None => explicitScalacOptions - case Some(ScalacOpt.PresetOption.Suggested.preset) => - val presetOptions = - ScalacOptions.buildOptions( - ScalacOptions.presetOptionsSuggested(scalaVersion).map(Positioned.none) - ) - explicitScalacOptions :+ presetOptions.map(_.withEmptyRequirements) - case Some(ScalacOpt.PresetOption.CI.preset) => - val presetOptions = - ScalacOptions.buildOptions( - ScalacOptions.presetOptionsCI(scalaVersion).map(Positioned.none) - ) - explicitScalacOptions :+ presetOptions.map(_.withEmptyRequirements) - case Some(ScalacOpt.PresetOption.Strict.preset) => - val presetOptions = - ScalacOptions.buildOptions( - ScalacOptions.presetOptionsStrict(scalaVersion).map(Positioned.none) - ) - explicitScalacOptions :+ presetOptions.map(_.withEmptyRequirements) - case Some(other) => - List(Left( - InputsException( - s"Unknown preset options: $other. Available options are: ${ScalacOpt.PresetOption.values.map(_.preset).mkString(", ")}" - ) - )) - } - } } object ScalacOptions { diff --git a/modules/options/src/main/scala/scala/build/options/HashedType.scala b/modules/options/src/main/scala/scala/build/options/HashedType.scala index 8a12804643..42abbb8ef3 100644 --- a/modules/options/src/main/scala/scala/build/options/HashedType.scala +++ b/modules/options/src/main/scala/scala/build/options/HashedType.scala @@ -47,6 +47,10 @@ object HashedType { pf => pf.repr } + implicit val presetOption: HashedType[ScalacOpt.PresetOption] = { + opt => opt.preset + } + implicit val unit: HashedType[Unit] = { _ => "" } 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 2bc9d1e4c8..d5383e8497 100644 --- a/modules/options/src/main/scala/scala/build/options/ScalacOpt.scala +++ b/modules/options/src/main/scala/scala/build/options/ScalacOpt.scala @@ -64,19 +64,10 @@ object ScalacOpt { opts.filterKeys(_.key.exists(f)) } - /* enum PresetOption(val preset: String): - case Suggested extends PresetOption("suggested") - case CI extends PresetOption("ci") - case Strict extends PresetOption("strict")*/ - sealed abstract class PresetOption(val preset: String) extends Product with Serializable object PresetOption { case object Suggested extends PresetOption("suggested") case object CI extends PresetOption("ci") case object Strict extends PresetOption("strict") - - implicit val hashedType: HashedType[PresetOption] = { - opt => opt.preset - } } } From c8fea6eedc7e314bfbb2915a25f4f57f0818a274 Mon Sep 17 00:00:00 2001 From: Yadu Krishnan Date: Fri, 11 Apr 2025 10:04:44 +0200 Subject: [PATCH 5/5] updated buildOPtions with preset --- .../main/scala/scala/build/CrossSources.scala | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/CrossSources.scala b/modules/build/src/main/scala/scala/build/CrossSources.scala index f768244a1b..80135fe947 100644 --- a/modules/build/src/main/scala/scala/build/CrossSources.scala +++ b/modules/build/src/main/scala/scala/build/CrossSources.scala @@ -263,18 +263,6 @@ object CrossSources { else fromDirectives } - val buildOptions: Seq[WithBuildRequirements[BuildOptions]] = (for { - preprocessedSource <- preprocessedSources - opts <- preprocessedSource.options.toSeq - if opts != BuildOptions() || preprocessedSource.optionsWithTargetRequirements.nonEmpty - } yield { - val baseReqs0 = baseReqs(preprocessedSource.scopePath) - preprocessedSource.optionsWithTargetRequirements :+ WithBuildRequirements( - preprocessedSource.requirements.fold(baseReqs0)(_ orElse baseReqs0), - opts - ) - }).flatten - def resolveScalacOptionsForPreset( mayBeScalaVersion: Option[MaybeScalaVersion], presetOption: PresetOption @@ -299,7 +287,7 @@ object CrossSources { } - def buildOptionWithPreset(opts: BuildOptions) = { + def buildOptionWithPreset(opts: BuildOptions): BuildOptions = { val scalaVersion = opts.scalaOptions.scalaVersion val scalacOpts = opts.scalaOptions.scalacOptions val scalacPresetOpt = opts.scalaOptions.scalacPresetOption @@ -329,6 +317,19 @@ object CrossSources { } + val buildOptions: Seq[WithBuildRequirements[BuildOptions]] = (for { + preprocessedSource <- preprocessedSources + opts <- preprocessedSource.options.toSeq + optsWithPreset = buildOptionWithPreset(opts) + if optsWithPreset != BuildOptions() || preprocessedSource.optionsWithTargetRequirements.nonEmpty + } yield { + val baseReqs0 = baseReqs(preprocessedSource.scopePath) + preprocessedSource.optionsWithTargetRequirements :+ WithBuildRequirements( + preprocessedSource.requirements.fold(baseReqs0)(_ orElse baseReqs0), + optsWithPreset + ) + }).flatten + val resourceDirectoriesFromDirectives = { val resourceDirsFromCli = allInputs.elements.flatMap { case rd: ResourceDirectory => Some(rd.path); case _ => None }