From 654d35d1badc1bbcd91ff11aea8472f3b8a0a4b6 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Tue, 26 Mar 2024 14:37:41 +0100 Subject: [PATCH] Fix triggeredBy and runBefore --- .../sbt/internal/EvaluateConfigurations.scala | 31 +++++++------------ .../src/main/scala/sbt/std/Instances.scala | 17 +++++----- .../src/sbt-test/actions/task-map/build.sbt | 6 ++-- sbt-app/src/sbt-test/actions/task-map/pending | 7 ----- sbt-app/src/sbt-test/actions/task-map/test | 7 +++++ .../main/scala/sbt/internal/util/INode.scala | 15 ++++----- .../src/main/scala/sbt/util/Applicative.scala | 2 ++ 7 files changed, 40 insertions(+), 45 deletions(-) delete mode 100644 sbt-app/src/sbt-test/actions/task-map/pending create mode 100644 sbt-app/src/sbt-test/actions/task-map/test diff --git a/buildfile/src/main/scala/sbt/internal/EvaluateConfigurations.scala b/buildfile/src/main/scala/sbt/internal/EvaluateConfigurations.scala index b74e4b831..d18e3ec64 100644 --- a/buildfile/src/main/scala/sbt/internal/EvaluateConfigurations.scala +++ b/buildfile/src/main/scala/sbt/internal/EvaluateConfigurations.scala @@ -398,27 +398,18 @@ object Index { def triggers(ss: Settings[Scope]): Triggers = { val runBefore = new TriggerMap val triggeredBy = new TriggerMap - ss.data.values foreach ( - _.entries foreach { - case AttributeEntry(_, value: Task[?]) => - val as = value.info.attributes - update(runBefore, value, as.get(Def.runBefore.asInstanceOf)) - update(triggeredBy, value, as.get(Def.triggeredBy.asInstanceOf)) - case _ => () - } - ) - val onComplete = (GlobalScope / Def.onComplete) get ss getOrElse (() => ()) + for + a <- ss.data.values + case AttributeEntry(_, base: Task[?]) <- a.entries + do + def update(map: TriggerMap, key: AttributeKey[Seq[Task[?]]]): Unit = + base.info.attributes.get(key).getOrElse(Seq.empty).foreach { task => + map(task) = base +: map.getOrElse(task, Nil) + } + update(runBefore, Def.runBefore) + update(triggeredBy, Def.triggeredBy) + val onComplete = (GlobalScope / Def.onComplete).get(ss).getOrElse(() => ()) new Triggers(runBefore, triggeredBy, map => { onComplete(); map }) } - private[this] def update( - map: TriggerMap, - base: Task[?], - tasksOpt: Option[Seq[Task[?]]] - ): Unit = - for { - tasks <- tasksOpt - task <- tasks - } - map(task) = base +: map.getOrElse(task, Nil) } diff --git a/main-settings/src/main/scala/sbt/std/Instances.scala b/main-settings/src/main/scala/sbt/std/Instances.scala index 223372d65..8d3d0c964 100644 --- a/main-settings/src/main/scala/sbt/std/Instances.scala +++ b/main-settings/src/main/scala/sbt/std/Instances.scala @@ -25,13 +25,6 @@ object InitializeInstance: Def.flatMap[A1, A2](fa)(f) end InitializeInstance -private[std] object ComposeInstance: - import InitializeInstance.initializeMonad - val InitInstance = summon[Applicative[Initialize]] - val F1F2: Applicative[[a] =>> Initialize[Task[a]]] = - summon[Applicative[[a] =>> Initialize[Task[a]]]] -end ComposeInstance - object ParserInstance: type F1[x] = State => Parser[x] // import sbt.internal.util.Classes.Applicative @@ -59,11 +52,17 @@ object FullInstance: KeyRanks.DTask ) - given Monad[Initialize] = InitializeInstance.initializeMonad - val F1F2: Applicative[[a] =>> Initialize[Task[a]]] = ComposeInstance.F1F2 + val F1F2: Applicative[[a] =>> Initialize[Task[a]]] = Applicative.given_Applicative_F1(using + InitializeInstance.initializeMonad, + Task.taskMonad + ) given initializeTaskMonad: Monad[[a] =>> Initialize[Task[a]]] with type F[x] = Initialize[Task[x]] override def pure[A1](x: () => A1): Initialize[Task[A1]] = F1F2.pure(x) + + override def map[A1, A2](fa: Initialize[Task[A1]])(f: A1 => A2): Initialize[Task[A2]] = + F1F2.map(fa)(f) + override def ap[A1, A2](ff: Initialize[Task[A1 => A2]])( fa: Initialize[Task[A1]] ): Initialize[Task[A2]] = diff --git a/sbt-app/src/sbt-test/actions/task-map/build.sbt b/sbt-app/src/sbt-test/actions/task-map/build.sbt index b642bcf02..72b1d8047 100644 --- a/sbt-app/src/sbt-test/actions/task-map/build.sbt +++ b/sbt-app/src/sbt-test/actions/task-map/build.sbt @@ -4,6 +4,8 @@ val taskB = taskKey[File]("") val taskE = taskKey[File]("") val taskF = taskKey[File]("") +scalaVersion := "3.3.1" +name := "task-map" taskA := touch(target.value / "a") taskB := touch(target.value / "b") @@ -14,13 +16,13 @@ taskF := touch(target.value / "f") // means "a" will be triggered by "b" // said differently, invoking "b" will run "b" and then run "a" -taskA := (taskA triggeredBy taskB).value +taskA := taskA.triggeredBy(taskB).value // e <<= e runBefore f // means "e" will be run before running "f" // said differently, invoking "f" will run "e" and then run "f" -taskE := (taskE runBefore taskF).value +taskE := taskE.runBefore(taskF).value // test utils def touch(f: File): File = { IO.touch(f); f } diff --git a/sbt-app/src/sbt-test/actions/task-map/pending b/sbt-app/src/sbt-test/actions/task-map/pending deleted file mode 100644 index 3a88d40a7..000000000 --- a/sbt-app/src/sbt-test/actions/task-map/pending +++ /dev/null @@ -1,7 +0,0 @@ -> taskB -$ exists target/b -$ exists target/a - -> taskF -$ exists target/e -$ exists target/f diff --git a/sbt-app/src/sbt-test/actions/task-map/test b/sbt-app/src/sbt-test/actions/task-map/test new file mode 100644 index 000000000..f22910038 --- /dev/null +++ b/sbt-app/src/sbt-test/actions/task-map/test @@ -0,0 +1,7 @@ +> taskB +$ exists target/out/jvm/scala-3.3.1/task-map/b +$ exists target/out/jvm/scala-3.3.1/task-map/a + +> taskF +$ exists target/out/jvm/scala-3.3.1/task-map/e +$ exists target/out/jvm/scala-3.3.1/task-map/f diff --git a/util-collection/src/main/scala/sbt/internal/util/INode.scala b/util-collection/src/main/scala/sbt/internal/util/INode.scala index a81a223f6..6e647f4ab 100644 --- a/util-collection/src/main/scala/sbt/internal/util/INode.scala +++ b/util-collection/src/main/scala/sbt/internal/util/INode.scala @@ -40,7 +40,7 @@ abstract class EvaluateSettings[ScopeType]: case k: Keyed[s, A] => single(getStatic(k.scopedKey), k.transform) case u: Uniform[s, A] => UniformNode(u.inputs.map(transform[s]), u.f) case a: Apply[k, A] => - MixedNode[k, A](TupleMapExtension.transform(a.inputs) { transform }, a.f) + MixedNode[k, A](TupleMapExtension.transform(a.inputs)(transform), a.f) case b: Bind[s, A] => BindNode[s, A](transform(b.in), x => transform(b.f(x))) case v: Value[A] => constant(v.value) case v: ValidationCapture[a] => strictConstant(v.key: A) @@ -89,8 +89,7 @@ abstract class EvaluateSettings[ScopeType]: private[this] def submit(work: => Unit): Unit = startWork() - // new Runnable { def run = if (!cancel.get()) run0(work) } - executor.execute(() => if !cancel.get() then run0(work) else ()) + executor.execute(() => if !cancel.get() then run0(work)) private[this] def run0(work: => Unit): Unit = try { @@ -102,7 +101,6 @@ abstract class EvaluateSettings[ScopeType]: private[this] def workComplete(): Unit = if running.decrementAndGet() == 0 then complete.put(None) - else () private[this] sealed abstract class INode[A1]: private[this] var state: EvaluationState = New @@ -116,9 +114,12 @@ abstract class EvaluateSettings[ScopeType]: keyString private[this] def keyString = - (static.toSeq.flatMap { case (key, value) => - if (value eq this) init.showFullKey.show(key) :: Nil else List.empty[String] - }).headOption getOrElse "non-static" + static.toSeq + .flatMap { case (key, value) => + if (value eq this) init.showFullKey.show(key) :: Nil else Nil + } + .headOption + .getOrElse("non-static") final def get: A1 = synchronized { assert(value != null, toString + " not evaluated") diff --git a/util-collection/src/main/scala/sbt/util/Applicative.scala b/util-collection/src/main/scala/sbt/util/Applicative.scala index 088ee3559..16d558d46 100644 --- a/util-collection/src/main/scala/sbt/util/Applicative.scala +++ b/util-collection/src/main/scala/sbt/util/Applicative.scala @@ -23,6 +23,8 @@ object Applicative: val F1 = summon[Applicative[F1]] val F2 = summon[Applicative[F2]] override def pure[A1](x: () => A1): F1[F2[A1]] = F1.pure(() => F2.pure(x)) + override def map[A1, A2](fa: F1[F2[A1]])(f: A1 => A2): F1[F2[A2]] = + F1.map(fa)(f2 => F2.map(f2)(f)) override def ap[A1, A2](f1f2f: F1[F2[A1 => A2]])(f1f2a: F1[F2[A1]]): F1[F2[A2]] = F1.ap(F1.map(f1f2f) { (f2f: F2[A1 => A2]) => (f2a: F2[A1]) => F2.ap(f2f)(f2a) })(f1f2a)