mirror of https://github.com/sbt/sbt.git
commit
975e3db43e
|
|
@ -14,6 +14,10 @@ object Classes {
|
||||||
def map[S, T](f: S => T, v: M[S]): M[T]
|
def map[S, T](f: S => T, v: M[S]): M[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait Selective[M[_]] extends Applicative[M] {
|
||||||
|
def select[A, B](fab: M[Either[A, B]])(fn: M[A => B]): M[B]
|
||||||
|
}
|
||||||
|
|
||||||
trait Monad[M[_]] extends Applicative[M] {
|
trait Monad[M[_]] extends Applicative[M] {
|
||||||
def flatten[T](m: M[M[T]]): M[T]
|
def flatten[T](m: M[M[T]]): M[T]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -221,6 +221,7 @@ object Def extends Init[Scope] with TaskMacroExtra with InitializeImplicits {
|
||||||
inputTaskDynMacroImpl,
|
inputTaskDynMacroImpl,
|
||||||
inputTaskMacroImpl,
|
inputTaskMacroImpl,
|
||||||
taskDynMacroImpl,
|
taskDynMacroImpl,
|
||||||
|
taskIfMacroImpl,
|
||||||
taskMacroImpl
|
taskMacroImpl
|
||||||
}
|
}
|
||||||
import std._
|
import std._
|
||||||
|
|
@ -234,6 +235,42 @@ object Def extends Init[Scope] with TaskMacroExtra with InitializeImplicits {
|
||||||
def inputTask[T](t: T): Def.Initialize[InputTask[T]] = macro inputTaskMacroImpl[T]
|
def inputTask[T](t: T): Def.Initialize[InputTask[T]] = macro inputTaskMacroImpl[T]
|
||||||
def inputTaskDyn[T](t: Def.Initialize[Task[T]]): Def.Initialize[InputTask[T]] =
|
def inputTaskDyn[T](t: Def.Initialize[Task[T]]): Def.Initialize[InputTask[T]] =
|
||||||
macro inputTaskDynMacroImpl[T]
|
macro inputTaskDynMacroImpl[T]
|
||||||
|
def taskIf[T](a: T): Def.Initialize[Task[T]] = macro taskIfMacroImpl[T]
|
||||||
|
|
||||||
|
private[sbt] def selectITask[A, B](
|
||||||
|
fab: Initialize[Task[Either[A, B]]],
|
||||||
|
fin: Initialize[Task[A => B]]
|
||||||
|
): Initialize[Task[B]] =
|
||||||
|
fab.zipWith(fin)((ab, in) => TaskExtra.select(ab, in))
|
||||||
|
|
||||||
|
import Scoped.syntax._
|
||||||
|
|
||||||
|
// derived from select
|
||||||
|
private[sbt] def branchS[A, B, C](
|
||||||
|
x: Def.Initialize[Task[Either[A, B]]]
|
||||||
|
)(l: Def.Initialize[Task[A => C]])(r: Def.Initialize[Task[B => C]]): Def.Initialize[Task[C]] = {
|
||||||
|
val lhs = {
|
||||||
|
val innerLhs: Def.Initialize[Task[Either[A, Either[B, C]]]] =
|
||||||
|
x.map((fab: Either[A, B]) => fab.right.map(Left(_)))
|
||||||
|
val innerRhs: Def.Initialize[Task[A => Either[B, C]]] =
|
||||||
|
l.map((fn: A => C) => fn.andThen(Right(_)))
|
||||||
|
selectITask(innerLhs, innerRhs)
|
||||||
|
}
|
||||||
|
selectITask(lhs, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// derived from select
|
||||||
|
def ifS[A](
|
||||||
|
x: Def.Initialize[Task[Boolean]]
|
||||||
|
)(t: Def.Initialize[Task[A]])(e: Def.Initialize[Task[A]]): Def.Initialize[Task[A]] = {
|
||||||
|
val condition: Def.Initialize[Task[Either[Unit, Unit]]] =
|
||||||
|
x.map((p: Boolean) => if (p) Left(()) else Right(()))
|
||||||
|
val left: Def.Initialize[Task[Unit => A]] =
|
||||||
|
t.map((a: A) => { _ => a })
|
||||||
|
val right: Def.Initialize[Task[Unit => A]] =
|
||||||
|
e.map((a: A) => { _ => a })
|
||||||
|
branchS(condition)(left)(right)
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns `PromiseWrap[A]`, which is a wrapper around `scala.concurrent.Promise`.
|
/** Returns `PromiseWrap[A]`, which is a wrapper around `scala.concurrent.Promise`.
|
||||||
* When a task is typed promise (e.g. `Def.Initialize[Task[PromiseWrap[A]]]`),an implicit
|
* When a task is typed promise (e.g. `Def.Initialize[Task[PromiseWrap[A]]]`),an implicit
|
||||||
|
|
|
||||||
|
|
@ -315,6 +315,20 @@ object Scoped {
|
||||||
final def ??[T >: S](or: => T): Initialize[T] = Def.optional(scopedKey)(_ getOrElse or)
|
final def ??[T >: S](or: => T): Initialize[T] = Def.optional(scopedKey)(_ getOrElse or)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Duplicated with ProjectExtra.
|
||||||
|
private[sbt] object syntax {
|
||||||
|
implicit def richInitializeTask[T](init: Initialize[Task[T]]): Scoped.RichInitializeTask[T] =
|
||||||
|
new Scoped.RichInitializeTask(init)
|
||||||
|
|
||||||
|
implicit def richInitializeInputTask[T](
|
||||||
|
init: Initialize[InputTask[T]]
|
||||||
|
): Scoped.RichInitializeInputTask[T] =
|
||||||
|
new Scoped.RichInitializeInputTask(init)
|
||||||
|
|
||||||
|
implicit def richInitialize[T](i: Initialize[T]): Scoped.RichInitialize[T] =
|
||||||
|
new Scoped.RichInitialize[T](i)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps an [[sbt.Def.Initialize]] instance to provide `map` and `flatMap` semantics.
|
* Wraps an [[sbt.Def.Initialize]] instance to provide `map` and `flatMap` semantics.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -211,15 +211,16 @@ object TaskLinterDSLFeedback {
|
||||||
""".stripMargin
|
""".stripMargin
|
||||||
|
|
||||||
def useOfValueInsideIfExpression(task: String): String =
|
def useOfValueInsideIfExpression(task: String): String =
|
||||||
s"""${startBold}The evaluation of `$task` happens always inside a regular task.$reset
|
s"""${startBold}value lookup of `$task` inside an `if` expression$reset
|
||||||
|
|
|
|
||||||
|$ProblemHeader: `$task` is inside the if expression of a regular task.
|
|$ProblemHeader: `$task.value` is inside an `if` expression of a regular task.
|
||||||
| Regular tasks always evaluate task inside the bodies of if expressions.
|
| Regular tasks always evaluate task dependencies (`.value`) regardless of `if` expressions.
|
||||||
|$SolutionHeader:
|
|$SolutionHeader:
|
||||||
| 1. If you only want to evaluate it when the if predicate is true or false, use a dynamic task.
|
| 1. Use a conditional task `Def.taskIf(...)` to evaluate it when the `if` predicate is true or false.
|
||||||
| 2. Make the static evaluation explicit by evaluating `$task` outside the if expression.
|
| 2. Or turn the task body into a single `if` expression; the task is then auto-converted to a conditional task.
|
||||||
| 3. If you still want to force the static evaluation, you may annotate the task evaluation with `@sbtUnchecked`, e.g. `($task.value: @sbtUnchecked)`.
|
| 3. Or make the static evaluation explicit by declaring `$task.value` outside the `if` expression.
|
||||||
| 4. Add `import sbt.dsl.LinterLevel.Ignore` to your build file to disable all task linting.
|
| 4. If you still want to force the static lookup, you may annotate the task lookup with `@sbtUnchecked`, e.g. `($task.value: @sbtUnchecked)`.
|
||||||
|
| 5. Add `import sbt.dsl.LinterLevel.Ignore` to your build file to disable all task linting.
|
||||||
""".stripMargin
|
""".stripMargin
|
||||||
|
|
||||||
def missingValueForKey(key: String): String =
|
def missingValueForKey(key: String): String =
|
||||||
|
|
|
||||||
|
|
@ -104,11 +104,26 @@ object TaskMacro {
|
||||||
|
|
||||||
def taskMacroImpl[T: c.WeakTypeTag](
|
def taskMacroImpl[T: c.WeakTypeTag](
|
||||||
c: blackbox.Context
|
c: blackbox.Context
|
||||||
)(t: c.Expr[T]): c.Expr[Initialize[Task[T]]] =
|
)(t: c.Expr[T]): c.Expr[Initialize[Task[T]]] = {
|
||||||
Instance.contImpl[T, Id](c, FullInstance, FullConvert, MixedBuilder, TaskLinterDSL)(
|
import c.universe._
|
||||||
Left(t),
|
t.tree match {
|
||||||
Instance.idTransform[c.type]
|
// the tree matches `if` and only `if`
|
||||||
)
|
case If(cond, thenp, elsep) =>
|
||||||
|
c.Expr[Initialize[Task[T]]](mkIfS(c)(cond, thenp, elsep))
|
||||||
|
case _ =>
|
||||||
|
Instance.contImpl[T, Id](c, FullInstance, FullConvert, MixedBuilder, TaskLinterDSL)(
|
||||||
|
Left(t),
|
||||||
|
Instance.idTransform[c.type]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def mkIfS(
|
||||||
|
c: blackbox.Context
|
||||||
|
)(cond: c.Tree, thenp: c.Tree, elsep: c.Tree): c.Tree = {
|
||||||
|
import c.universe._
|
||||||
|
q"""Def.ifS(Def.task($cond))(Def.task($thenp))(Def.task($elsep))"""
|
||||||
|
}
|
||||||
|
|
||||||
def taskDynMacroImpl[T: c.WeakTypeTag](
|
def taskDynMacroImpl[T: c.WeakTypeTag](
|
||||||
c: blackbox.Context
|
c: blackbox.Context
|
||||||
|
|
@ -118,6 +133,19 @@ object TaskMacro {
|
||||||
Instance.idTransform[c.type]
|
Instance.idTransform[c.type]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def taskIfMacroImpl[A: c.WeakTypeTag](
|
||||||
|
c: blackbox.Context
|
||||||
|
)(a: c.Expr[A]): c.Expr[Initialize[Task[A]]] = {
|
||||||
|
import c.universe._
|
||||||
|
a.tree match {
|
||||||
|
case Block(stat, If(cond, thenp, elsep)) =>
|
||||||
|
c.Expr[Initialize[Task[A]]](mkIfS(c)(Block(stat, cond), thenp, elsep))
|
||||||
|
case If(cond, thenp, elsep) =>
|
||||||
|
c.Expr[Initialize[Task[A]]](mkIfS(c)(cond, thenp, elsep))
|
||||||
|
case x => ContextUtil.unexpectedTree(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Implementation of := macro for settings. */
|
/** Implementation of := macro for settings. */
|
||||||
def settingAssignMacroImpl[T: c.WeakTypeTag](
|
def settingAssignMacroImpl[T: c.WeakTypeTag](
|
||||||
c: blackbox.Context
|
c: blackbox.Context
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ class TaskConfigSpec extends fixture.FunSuite with fixture.TestDataFixture {
|
||||||
|var condition = true
|
|var condition = true
|
||||||
|
|
|
|
||||||
|val barNeg = Def.task[String] {
|
|val barNeg = Def.task[String] {
|
||||||
|
| val s = 1
|
||||||
| if (condition) fooNeg.value
|
| if (condition) fooNeg.value
|
||||||
| else ""
|
| else ""
|
||||||
|}
|
|}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,20 @@
|
||||||
package sbt.std
|
package sbt.std
|
||||||
|
|
||||||
class TaskPosSpec {
|
class TaskPosSpec {
|
||||||
|
// Starting sbt 1.4.0, Def.task can have task value lookups inside
|
||||||
|
// if branches since tasks with single if-expressions are automatically
|
||||||
|
// converted into a conditional task.
|
||||||
|
locally {
|
||||||
|
import sbt._, Def._
|
||||||
|
val foo = taskKey[String]("")
|
||||||
|
val bar = taskKey[String]("")
|
||||||
|
val condition = true
|
||||||
|
Def.task[String] {
|
||||||
|
if (condition) foo.value
|
||||||
|
else bar.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dynamic tasks can have task invocations inside if branches
|
// Dynamic tasks can have task invocations inside if branches
|
||||||
locally {
|
locally {
|
||||||
import sbt._, Def._
|
import sbt._, Def._
|
||||||
|
|
@ -147,8 +161,12 @@ class TaskPosSpec {
|
||||||
|
|
||||||
locally {
|
locally {
|
||||||
import sbt._, Def._
|
import sbt._, Def._
|
||||||
def withKey(foo: => SettingKey[String]) = {
|
def withKey(foo: => SettingKey[String]): Def.Initialize[Task[Unit]] = {
|
||||||
Def.task { if (true) foo.value }
|
Def.task {
|
||||||
|
if (true) {
|
||||||
|
foo.value; ()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val foo = settingKey[String]("")
|
val foo = settingKey[String]("")
|
||||||
withKey(foo)
|
withKey(foo)
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ class TaskNegSpec extends fixture.FunSuite with fixture.TestDataFixture {
|
||||||
|var condition = true
|
|var condition = true
|
||||||
|
|
|
|
||||||
|val bazNeg = Def.task[String] {
|
|val bazNeg = Def.task[String] {
|
||||||
|
| val s = 1
|
||||||
| if (condition) fooNeg.value
|
| if (condition) fooNeg.value
|
||||||
| else barNeg.value
|
| else barNeg.value
|
||||||
|}
|
|}
|
||||||
|
|
@ -66,6 +67,7 @@ class TaskNegSpec extends fixture.FunSuite with fixture.TestDataFixture {
|
||||||
|def bi(s: String) = s + " "
|
|def bi(s: String) = s + " "
|
||||||
|
|
|
|
||||||
|val bazNeg = Def.task[String] {
|
|val bazNeg = Def.task[String] {
|
||||||
|
| val s = 1
|
||||||
| if (condition) "" + fooNeg.value
|
| if (condition) "" + fooNeg.value
|
||||||
| else bi(barNeg.value)
|
| else bi(barNeg.value)
|
||||||
|}
|
|}
|
||||||
|
|
@ -87,6 +89,7 @@ class TaskNegSpec extends fixture.FunSuite with fixture.TestDataFixture {
|
||||||
|val bazNeg = Def.taskDyn[String] {
|
|val bazNeg = Def.taskDyn[String] {
|
||||||
| if (condition) {
|
| if (condition) {
|
||||||
| Def.task {
|
| Def.task {
|
||||||
|
| val s = 1
|
||||||
| if (condition) {
|
| if (condition) {
|
||||||
| fooNeg.value
|
| fooNeg.value
|
||||||
| } else ""
|
| } else ""
|
||||||
|
|
@ -114,6 +117,7 @@ class TaskNegSpec extends fixture.FunSuite with fixture.TestDataFixture {
|
||||||
|val bazNeg = Def.taskDyn[String] {
|
|val bazNeg = Def.taskDyn[String] {
|
||||||
| if (condition) {
|
| if (condition) {
|
||||||
| Def.task {
|
| Def.task {
|
||||||
|
| val s = 1
|
||||||
| if (condition) {
|
| if (condition) {
|
||||||
| val first = if (!condition && condition) {
|
| val first = if (!condition && condition) {
|
||||||
| fooNeg.value
|
| fooNeg.value
|
||||||
|
|
@ -144,6 +148,7 @@ class TaskNegSpec extends fixture.FunSuite with fixture.TestDataFixture {
|
||||||
|val bazNeg = Def.taskDyn[String] {
|
|val bazNeg = Def.taskDyn[String] {
|
||||||
| if (condition) {
|
| if (condition) {
|
||||||
| Def.task {
|
| Def.task {
|
||||||
|
| val s = 1
|
||||||
| if (condition) ""
|
| if (condition) ""
|
||||||
| else barNeg.value
|
| else barNeg.value
|
||||||
| }
|
| }
|
||||||
|
|
|
||||||
|
|
@ -2138,16 +2138,9 @@ object Defaults extends BuildCommon {
|
||||||
)
|
)
|
||||||
|
|
||||||
def dependencyResolutionTask: Def.Initialize[Task[DependencyResolution]] =
|
def dependencyResolutionTask: Def.Initialize[Task[DependencyResolution]] =
|
||||||
Def.taskDyn {
|
Def.taskIf {
|
||||||
if (useCoursier.value) {
|
if (useCoursier.value) CoursierDependencyResolution(csrConfiguration.value)
|
||||||
Def.task { CoursierDependencyResolution(csrConfiguration.value) }
|
else IvyDependencyResolution(ivyConfiguration.value, CustomHttp.okhttpClient.value)
|
||||||
} else
|
|
||||||
Def.task {
|
|
||||||
IvyDependencyResolution(
|
|
||||||
ivyConfiguration.value,
|
|
||||||
CustomHttp.okhttpClient.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2972,12 +2965,15 @@ object Classpaths {
|
||||||
publishTask(config)
|
publishTask(config)
|
||||||
|
|
||||||
def publishTask(config: TaskKey[PublishConfiguration]): Initialize[Task[Unit]] =
|
def publishTask(config: TaskKey[PublishConfiguration]): Initialize[Task[Unit]] =
|
||||||
Def.taskDyn {
|
Def.taskIf {
|
||||||
val s = streams.value
|
if ((publish / skip).value) {
|
||||||
val skp = (skip in publish).value
|
val s = streams.value
|
||||||
val ref = thisProjectRef.value
|
val ref = thisProjectRef.value
|
||||||
if (skp) Def.task { s.log.debug(s"Skipping publish* for ${ref.project}") } else
|
s.log.debug(s"Skipping publish* for ${ref.project}")
|
||||||
Def.task { IvyActions.publish(ivyModule.value, config.value, s.log) }
|
} else {
|
||||||
|
val s = streams.value
|
||||||
|
IvyActions.publish(ivyModule.value, config.value, s.log)
|
||||||
|
}
|
||||||
} tag (Tags.Publish, Tags.Network)
|
} tag (Tags.Publish, Tags.Network)
|
||||||
|
|
||||||
val moduleIdJsonKeyFormat: sjsonnew.JsonKeyFormat[ModuleID] =
|
val moduleIdJsonKeyFormat: sjsonnew.JsonKeyFormat[ModuleID] =
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
val condition = taskKey[Boolean]("")
|
||||||
|
val number = settingKey[Int]("")
|
||||||
|
val trueAction = taskKey[Unit]("")
|
||||||
|
val falseAction = taskKey[Unit]("")
|
||||||
|
val negAction = taskKey[Unit]("")
|
||||||
|
val zeroAction = taskKey[Unit]("")
|
||||||
|
val posAction = taskKey[Unit]("")
|
||||||
|
val foo = taskKey[Unit]("")
|
||||||
|
val bar = taskKey[Unit]("")
|
||||||
|
val output = settingKey[File]("")
|
||||||
|
|
||||||
|
lazy val root = (project in file("."))
|
||||||
|
.settings(
|
||||||
|
name := "ifs",
|
||||||
|
output := baseDirectory.value / "output.txt",
|
||||||
|
condition := true,
|
||||||
|
number := -1,
|
||||||
|
|
||||||
|
// automatic conversion to Def.ifS
|
||||||
|
bar := {
|
||||||
|
if (number.value < 0) negAction.value
|
||||||
|
else if (number.value == 0) zeroAction.value
|
||||||
|
else posAction.value
|
||||||
|
},
|
||||||
|
|
||||||
|
// explicit call to Def.taskIf
|
||||||
|
foo := (Def.taskIf {
|
||||||
|
if (condition.value) trueAction.value
|
||||||
|
else falseAction.value
|
||||||
|
}).value,
|
||||||
|
|
||||||
|
trueAction := { IO.write(output.value, s"true\n", append = true) },
|
||||||
|
falseAction := { IO.write(output.value, s"false\n", append = true) },
|
||||||
|
negAction := { IO.write(output.value, s"neg\n", append = true) },
|
||||||
|
zeroAction := { IO.write(output.value, s"zero\n", append = true) },
|
||||||
|
posAction := { IO.write(output.value, s"pos\n", append = true) },
|
||||||
|
|
||||||
|
TaskKey[Unit]("checkTrue") := checkLines("true"),
|
||||||
|
TaskKey[Unit]("checkFalse") := checkLines("false"),
|
||||||
|
TaskKey[Unit]("checkNeg") := checkLines("neg"),
|
||||||
|
TaskKey[Unit]("checkZero") := checkLines("zero"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def checkLines(content: String) = Def.task {
|
||||||
|
val lines = IO.read(output.value).linesIterator.toList
|
||||||
|
assert(lines == List("true"), s"$content was expected but found: $lines")
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
> foo
|
||||||
|
> checkTrue
|
||||||
|
|
||||||
|
$ delete output.txt
|
||||||
|
> bar
|
||||||
|
> checkNeg
|
||||||
|
|
||||||
|
$ delete output.txt
|
||||||
|
> set condition := false
|
||||||
|
> foo
|
||||||
|
> checkFalse
|
||||||
|
|
||||||
|
$ delete output.txt
|
||||||
|
> set number := 0
|
||||||
|
> bar
|
||||||
|
> checkZero
|
||||||
|
|
@ -57,6 +57,31 @@ final case class Join[T, U](in: Seq[Task[U]], f: Seq[Result[U]] => Either[Task[T
|
||||||
Join[T, U](in.map(g.fn[U]), sr => f(sr).left.map(g.fn[T]))
|
Join[T, U](in.map(g.fn[U]), sr => f(sr).left.map(g.fn[T]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A computation that conditionally falls back to a second transformation.
|
||||||
|
* This can be used to encode `if` conditions.
|
||||||
|
*/
|
||||||
|
final case class Selected[A, B](fab: Task[Either[A, B]], fin: Task[A => B]) extends Action[B] {
|
||||||
|
private def ml = AList.single[Either[A, B]]
|
||||||
|
type K[L[x]] = L[Either[A, B]]
|
||||||
|
|
||||||
|
private[sbt] def mapTask(g: Task ~> Task) =
|
||||||
|
Selected[A, B](g(fab), g(fin))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode this computation as a flatMap.
|
||||||
|
*/
|
||||||
|
private[sbt] def asFlatMapped: FlatMapped[B, K] = {
|
||||||
|
val f: Either[A, B] => Task[B] = {
|
||||||
|
case Right(b) => std.TaskExtra.task(b)
|
||||||
|
case Left(a) => std.TaskExtra.singleInputTask(fin).map(_(a))
|
||||||
|
}
|
||||||
|
FlatMapped[B, K](fab, {
|
||||||
|
f compose std.TaskExtra.successM
|
||||||
|
}, ml)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Combines metadata `info` and a computation `work` to define a task. */
|
/** Combines metadata `info` and a computation `work` to define a task. */
|
||||||
final case class Task[T](info: Info[T], work: Action[T]) {
|
final case class Task[T](info: Info[T], work: Action[T]) {
|
||||||
override def toString = info.name getOrElse ("Task(" + info + ")")
|
override def toString = info.name getOrElse ("Task(" + info + ")")
|
||||||
|
|
|
||||||
|
|
@ -146,10 +146,7 @@ trait TaskExtra {
|
||||||
def failure: Task[Incomplete] = mapFailure(idFun)
|
def failure: Task[Incomplete] = mapFailure(idFun)
|
||||||
def result: Task[Result[S]] = mapR(idFun)
|
def result: Task[Result[S]] = mapR(idFun)
|
||||||
|
|
||||||
// The "taskDefinitionKey" is used, at least, by the ".previous" functionality.
|
private def newInfo[A]: Info[A] = TaskExtra.newInfo(in.info)
|
||||||
// But apparently it *cannot* survive a task map/flatMap/etc. See actions/depends-on.
|
|
||||||
private def newInfo[A]: Info[A] =
|
|
||||||
Info[A](AttributeMap(in.info.attributes.entries.filter(_.key.label != "taskDefinitionKey")))
|
|
||||||
|
|
||||||
def flatMapR[T](f: Result[S] => Task[T]): Task[T] =
|
def flatMapR[T](f: Result[S] => Task[T]): Task[T] =
|
||||||
Task(newInfo, new FlatMapped[T, K](in, f, ml))
|
Task(newInfo, new FlatMapped[T, K](in, f, ml))
|
||||||
|
|
@ -285,5 +282,13 @@ object TaskExtra extends TaskExtra {
|
||||||
|
|
||||||
def incompleteDeps(incs: Seq[Incomplete]): Incomplete = Incomplete(None, causes = incs)
|
def incompleteDeps(incs: Seq[Incomplete]): Incomplete = Incomplete(None, causes = incs)
|
||||||
|
|
||||||
|
def select[A, B](fab: Task[Either[A, B]], f: Task[A => B]): Task[B] =
|
||||||
|
Task(newInfo(fab.info), new Selected[A, B](fab, f))
|
||||||
|
|
||||||
|
// The "taskDefinitionKey" is used, at least, by the ".previous" functionality.
|
||||||
|
// But apparently it *cannot* survive a task map/flatMap/etc. See actions/depends-on.
|
||||||
|
private[sbt] def newInfo[A](info: Info[_]): Info[A] =
|
||||||
|
Info[A](AttributeMap(info.attributes.entries.filter(_.key.label != "taskDefinitionKey")))
|
||||||
|
|
||||||
private[sbt] def existToAny(in: Seq[Task[_]]): Seq[Task[Any]] = in.asInstanceOf[Seq[Task[Any]]]
|
private[sbt] def existToAny(in: Seq[Task[_]]): Seq[Task[Any]] = in.asInstanceOf[Seq[Task[Any]]]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ object Transform {
|
||||||
case Pure(eval, _) => uniform(Nil)(_ => Right(eval()))
|
case Pure(eval, _) => uniform(Nil)(_ => Right(eval()))
|
||||||
case m: Mapped[t, k] => toNode[t, k](m.in)(right ∙ m.f)(m.alist)
|
case m: Mapped[t, k] => toNode[t, k](m.in)(right ∙ m.f)(m.alist)
|
||||||
case m: FlatMapped[t, k] => toNode[t, k](m.in)(left ∙ m.f)(m.alist)
|
case m: FlatMapped[t, k] => toNode[t, k](m.in)(left ∙ m.f)(m.alist)
|
||||||
|
case s: Selected[_, t] => val m = s.asFlatMapped; toNode(m.in)(left ∙ m.f)(m.alist)
|
||||||
case DependsOn(in, deps) => uniform(existToAny(deps))(const(Left(in)) compose all)
|
case DependsOn(in, deps) => uniform(existToAny(deps))(const(Left(in)) compose all)
|
||||||
case Join(in, f) => uniform(in)(f)
|
case Join(in, f) => uniform(in)(f)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue