mirror of https://github.com/sbt/sbt.git
Reduce InputTask to the ideal wrapper around 'State => Parser[Initialize[Task[T]]]'
Ref #407.
This commit is contained in:
parent
1f32688657
commit
076480b50a
|
|
@ -7,112 +7,115 @@ package sbt
|
|||
import Types._
|
||||
|
||||
/** Parses input and produces a task to run. Constructed using the companion object. */
|
||||
sealed trait InputTask[T]
|
||||
{ outer =>
|
||||
private[sbt] type Result
|
||||
private[sbt] def parser: State => Parser[Result]
|
||||
private[sbt] def defined: AttributeKey[Result]
|
||||
private[sbt] def task: Task[T]
|
||||
|
||||
def mapTask[S](f: Task[T] => Task[S]) = new InputTask[S] {
|
||||
type Result = outer.Result
|
||||
def parser = outer.parser
|
||||
def task = f(outer.task)
|
||||
def defined = outer.defined
|
||||
}
|
||||
final class InputTask[T] private(val parser: State => Parser[Task[T]])
|
||||
{
|
||||
def mapTask[S](f: Task[T] => Task[S]): InputTask[S] =
|
||||
new InputTask[S](s => parser(s) map f)
|
||||
}
|
||||
|
||||
object InputTask
|
||||
{
|
||||
@deprecated("Use `create` or the `Def.inputTask` macro.", "0.13.0")
|
||||
def make[T](p: State => Parser[Task[T]]): InputTask[T] = new InputTask[T](p)
|
||||
|
||||
def static[T](p: Parser[Task[T]]): InputTask[T] = free(_ => p)
|
||||
|
||||
@deprecated("Use `create` or the `Def.inputTask` macro.", "0.13.0")
|
||||
def static[I,T](p: Parser[I])(c: I => Task[T]): InputTask[T] = static(p map c)
|
||||
|
||||
@deprecated("Use `create` or the `Def.inputTask` macro.", "0.13.0")
|
||||
def free[T](p: State => Parser[Task[T]]): InputTask[T] = {
|
||||
val key = localKey[Task[T]]
|
||||
new InputTask[T] {
|
||||
type Result = Task[T]
|
||||
def parser = p
|
||||
def defined = key
|
||||
def task = getResult(key)
|
||||
}
|
||||
}
|
||||
def free[T](p: State => Parser[Task[T]]): InputTask[T] = make(p)
|
||||
|
||||
@deprecated("Use `create` or the `Def.inputTask` macro.", "0.13.0")
|
||||
def free[I,T](p: State => Parser[I])(c: I => Task[T]): InputTask[T] = free(s => p(s) map c)
|
||||
|
||||
@deprecated("Use `create` or the `Def.inputTask` macro.", "0.13.0")
|
||||
def separate[I,T](p: State => Parser[I])(action: Initialize[I => Task[T]]): Initialize[InputTask[T]] =
|
||||
separate(Def value p)(action)
|
||||
|
||||
@deprecated("Use `create` or the `Def.inputTask` macro.", "0.13.0")
|
||||
def separate[I,T](p: Initialize[State => Parser[I]])(action: Initialize[I => Task[T]]): Initialize[InputTask[T]] =
|
||||
p.zipWith(action)((parser, act) => free(parser)(act))
|
||||
|
||||
@deprecated("Use `create` or the `Def.inputTask` macro.", "0.13.0")
|
||||
def apply[I,T](p: Initialize[State => Parser[I]])(action: TaskKey[I] => Initialize[Task[T]]): Initialize[InputTask[T]] =
|
||||
/** Constructs an InputTask that accepts no user input. */
|
||||
def createFree[T](action: Initialize[Task[T]]): Initialize[InputTask[T]] =
|
||||
action { tsk => free(emptyParser)( const(tsk) ) }
|
||||
|
||||
/** Constructs an InputTask from:
|
||||
* a) a Parser constructed using other Settings, but not Tasks
|
||||
* b) an action constructed using Settings, Tasks, and the result of parsing */
|
||||
def create[I,T](p: Initialize[State => Parser[I]])(action: Initialize[Task[I => T]]): Initialize[InputTask[T]] =
|
||||
{
|
||||
create(p){ it =>
|
||||
val dummy = TaskKey(localKey[Task[I]])
|
||||
action(dummy) mapConstant subResultForDummy(dummy)
|
||||
}
|
||||
val act = action { (tf: Task[I => T]) => (i: I) => tf.map(f => f(i)) }
|
||||
separate(p)(act)
|
||||
}
|
||||
|
||||
@deprecated("Use `create` or the `Def.inputTask` macro.", "0.13.0")
|
||||
def apply[I,T](p: State => Parser[I])(action: TaskKey[I] => Initialize[Task[T]]): Initialize[InputTask[T]] =
|
||||
apply(Def.value(p))(action)
|
||||
|
||||
// dummy task that will get replaced with the actual mappings from InputTasks to parse results
|
||||
private[sbt] lazy val inputMap: Task[AttributeMap] = mktask { error("Internal sbt error: input map not substituted.") }
|
||||
private[this] def getResult[T](key: AttributeKey[Task[T]]): Task[T] = inputMap flatMap { im =>
|
||||
im get key getOrElse error("Internal sbt error: could not get parser result.")
|
||||
}
|
||||
/** The proper solution is to have a Manifest context bound and accept slight source incompatibility,
|
||||
* The affected InputTask construction methods are all deprecated and so it is better to keep complete
|
||||
* compatibility. Because the AttributeKey is local, it uses object equality and the manifest is not used. */
|
||||
private[this] def localKey[T]: AttributeKey[T] = AttributeKey.local[Unit].asInstanceOf[AttributeKey[T]]
|
||||
|
||||
private[this] def subResultForDummy[I](dummy: TaskKey[I]) =
|
||||
new (ScopedKey ~> Option) { def apply[T](sk: ScopedKey[T]) =
|
||||
if(sk.key eq dummy.key) {
|
||||
// sk.key: AttributeKey[T], dummy.key: AttributeKey[Task[I]]
|
||||
// (sk.key eq dummy.key) ==> T == Task[I] because AttributeKey is invariant
|
||||
Some(getResult(dummy.key).asInstanceOf[T])
|
||||
} else
|
||||
None
|
||||
}
|
||||
|
||||
// This interface allows the Parser to be constructed using other Settings, but not Tasks (which is desired).
|
||||
// The action can be constructed using Settings and Tasks and with the parse result injected into a Task.
|
||||
// This requires Aggregation.applyDynamicTasks to inject an AttributeMap with the parse results.
|
||||
def create[I,T](p: Initialize[State => Parser[I]])(action: Initialize[Task[I]] => Initialize[Task[T]]): Initialize[InputTask[T]] =
|
||||
{
|
||||
val key = localKey[I] // TODO: AttributeKey.local[I]
|
||||
val result: Initialize[Task[I]] = (Def.resolvedScoped zipWith Def.valueStrict(InputTask.inputMap)){(scoped, imTask) =>
|
||||
imTask map { im => im get key getOrElse error("No parsed value for " + Def.displayFull(scoped) + "\n" + im) }
|
||||
}
|
||||
|
||||
(p zipWith action(result)) { (parserF, act) =>
|
||||
new InputTask[T]
|
||||
{
|
||||
type Result = I
|
||||
def parser = parserF
|
||||
def task = act
|
||||
def defined = key
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Constructs an InputTask from:
|
||||
* a) a Parser constructed using other Settings, but not Tasks
|
||||
* b) a dynamically constructed Task that uses Settings, Tasks, and the result of parsing. */
|
||||
def createDyn[I,T](p: Initialize[State => Parser[I]])(action: Initialize[Task[I => Initialize[Task[T]]]]): Initialize[InputTask[T]] =
|
||||
separate(p)(std.FullInstance.flattenFun[I,T](action))
|
||||
|
||||
/** A dummy parser that consumes no input and produces nothing useful (unit).*/
|
||||
def emptyParser: Initialize[State => Parser[Unit]] = parserAsInput(complete.DefaultParsers.success(()))
|
||||
def emptyParser: State => Parser[Unit] = Types.const(complete.DefaultParsers.success(()))
|
||||
|
||||
/** Implementation detail that is public because it is used by a macro.*/
|
||||
def parserAsInput[T](p: Parser[T]): Initialize[State => Parser[T]] = Def.valueStrict(Types.const(p))
|
||||
|
||||
/** Implementation detail that is public because it is used y a macro.*/
|
||||
def initParserAsInput[T](i: Initialize[Parser[T]]): Initialize[State => Parser[T]] = i(Types.const)
|
||||
|
||||
|
||||
|
||||
@deprecated("Use another InputTask constructor or the `Def.inputTask` macro.", "0.13.0")
|
||||
def apply[I,T](p: Initialize[State => Parser[I]])(action: TaskKey[I] => Initialize[Task[T]]): Initialize[InputTask[T]] =
|
||||
{
|
||||
val dummyKey = localKey[Task[I]]
|
||||
val (marker, dummy) = dummyTask[I]
|
||||
val it = action(TaskKey(dummyKey)) mapConstant subResultForDummy(dummyKey, dummy)
|
||||
val act = it { tsk => (value: I) => subForDummy(marker, value, tsk) }
|
||||
separate(p)(act)
|
||||
}
|
||||
|
||||
@deprecated("Use another InputTask constructor or the `Def.inputTask` macro.", "0.13.0")
|
||||
def apply[I,T](p: State => Parser[I])(action: TaskKey[I] => Initialize[Task[T]]): Initialize[InputTask[T]] =
|
||||
apply(Def.value(p))(action)
|
||||
|
||||
/** The proper solution is to have a Manifest context bound and accept slight source incompatibility,
|
||||
* The affected InputTask construction methods are all deprecated and so it is better to keep complete
|
||||
* compatibility. Because the AttributeKey is local, it uses object equality and the manifest is not used. */
|
||||
private[this] def localKey[T]: AttributeKey[T] = AttributeKey.local[Unit].asInstanceOf[AttributeKey[T]]
|
||||
|
||||
private[this] def subResultForDummy[I](dummyKey: AttributeKey[Task[I]], dummyTask: Task[I]) =
|
||||
new (ScopedKey ~> Option) { def apply[T](sk: ScopedKey[T]) =
|
||||
if(sk.key eq dummyKey) {
|
||||
// sk.key: AttributeKey[T], dummy.key: AttributeKey[Task[I]]
|
||||
// (sk.key eq dummy.key) ==> T == Task[I] because AttributeKey is invariant
|
||||
Some(dummyTask.asInstanceOf[T])
|
||||
} else
|
||||
None
|
||||
}
|
||||
|
||||
private[this] def dummyTask[I]: (AttributeKey[Option[I]], Task[I]) =
|
||||
{
|
||||
val key = localKey[Option[I]]
|
||||
val f: () => I = () => error(s"Internal sbt error: InputTask stub was not substituted properly.")
|
||||
val t: Task[I] = Task(Info[I]().set(key, None), Pure(f, false))
|
||||
(key, t)
|
||||
}
|
||||
private[this] def subForDummy[I, T](marker: AttributeKey[Option[I]], value: I, task: Task[T]): Task[T] =
|
||||
{
|
||||
val seen = new java.util.IdentityHashMap[Task[_], Task[_]]
|
||||
lazy val f: Task ~> Task = new (Task ~> Task) { def apply[T](t: Task[T]): Task[T] =
|
||||
{
|
||||
val t0 = seen.get(t)
|
||||
if(t0 == null) {
|
||||
val newAction =
|
||||
if(t.info.get(marker).isDefined)
|
||||
Pure(() => value.asInstanceOf[T], inline = true)
|
||||
else
|
||||
t.work.mapTask(f)
|
||||
val newTask = Task(t.info, newAction)
|
||||
seen.put(t, newTask)
|
||||
newTask
|
||||
} else
|
||||
t0.asInstanceOf[Task[T]]
|
||||
}}
|
||||
f(task)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ object TaskInstance extends MonadInstance
|
|||
import TaskExtra._
|
||||
|
||||
final type M[x] = Task[x]
|
||||
def app[K[L[x]], Z](in: K[Task], f: K[Id] => Z)(implicit a: AList[K]): Task[Z] = new Mapped[Z,K](in, f compose allM, a)
|
||||
def app[K[L[x]], Z](in: K[Task], f: K[Id] => Z)(implicit a: AList[K]): Task[Z] = Task(Info(), new Mapped[Z,K](in, f compose allM, a))
|
||||
def map[S,T](in: Task[S], f: S => T): Task[T] = in map f
|
||||
def flatten[T](in: Task[Task[T]]): Task[T] = in flatMap idFun[Task[T]]
|
||||
def pure[T](t: () => T): Task[T] = toTask(t)
|
||||
|
|
@ -38,6 +38,15 @@ object FullInstance extends Instance.Composed[Initialize, Task](InitializeInstan
|
|||
(a, data) flatMap { case (a,d) => f(a) evaluate d }
|
||||
}
|
||||
}
|
||||
def flattenFun[S,T](in: Initialize[Task[ S => Initialize[Task[T]] ]]): Initialize[S => Task[T]] =
|
||||
{
|
||||
import Scoped._
|
||||
(in,settingsData, Def.capturedTransformations) apply{
|
||||
(a: Task[S => Initialize[Task[T]]], data: Task[SS], f) => (s: S) =>
|
||||
import TaskExtra.multT2Task
|
||||
(a, data) flatMap { case (af,d) => f(af(s)) evaluate d }
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Converts an input `Tree` of type `Initialize[T]`, `Initialize[Task[T]]`, or `Task[T]` into a `Tree` of type `Initialize[Task[T]]`.*/
|
||||
object FullConvert extends Convert
|
||||
|
|
@ -69,6 +78,8 @@ object TaskMacro
|
|||
final val AppendNInitName = "appendN"
|
||||
final val TransformInitName = "transform"
|
||||
final val InputTaskCreateName = "create"
|
||||
final val InputTaskCreateDynName = "createDyn"
|
||||
final val InputTaskCreateFreeName = "createFree"
|
||||
|
||||
def taskMacroImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Initialize[Task[T]]] =
|
||||
Instance.contImpl[T](c, FullInstance, FullConvert, MixedBuilder)(Left(t))
|
||||
|
|
@ -272,9 +283,6 @@ object TaskMacro
|
|||
val ttree = t match { case Left(l) => l.tree; case Right(r) => r.tree }
|
||||
val defs = util.collectDefs(ttree, isAnyWrapper)
|
||||
val checkQual = util.checkReferences(defs, isAnyWrapper)
|
||||
val unitInitTask = c.typeOf[Initialize[Task[Unit]]]
|
||||
val initKeyC = c.typeOf[Initialize[Unit]].typeConstructor
|
||||
val taskKeyC = c.typeOf[Task[Unit]].typeConstructor
|
||||
|
||||
var result: Option[(Tree, Type, ValDef)] = None
|
||||
|
||||
|
|
@ -287,42 +295,47 @@ object TaskMacro
|
|||
else
|
||||
{
|
||||
qual.foreach(checkQual)
|
||||
val itType = appliedType(initKeyC, appliedType(taskKeyC, tpe :: Nil) :: Nil) // Initialize[Task[<tpe>]]
|
||||
val vd = util.freshValDef(itType, qual.symbol) // val $x: Initialize[Task[<tpe>]]
|
||||
val vd = util.freshValDef(tpe, qual.symbol) // val $x: <tpe>
|
||||
result = Some( (qual, tpe, vd) )
|
||||
val tree = util.refVal(vd) // $x
|
||||
tree.setPos(qual.pos) // position needs to be set so that wrapKey passes the position onto the wrapper
|
||||
assert(tree.tpe != null, "Null type: " + tree)
|
||||
val wrapped = InputWrapper.wrapKey(c)( c.Expr[Any](tree) )( c.WeakTypeTag(tpe) )
|
||||
wrapped.tree.setType(tpe)
|
||||
tree.setType(tpe)
|
||||
tree
|
||||
}
|
||||
// Tree for InputTask.create[<tpeA>, <tpeB>](arg1)(arg2)
|
||||
def inputTaskCreate(tpeA: Type, tpeB: Type, arg1: Tree, arg2: Tree) =
|
||||
// Tree for InputTask.<name>[<tpeA>, <tpeB>](arg1)(arg2)
|
||||
def inputTaskCreate(name: String, tpeA: Type, tpeB: Type, arg1: Tree, arg2: Tree) =
|
||||
{
|
||||
val typedApp = TypeApply(Select(it, InputTaskCreateName), TypeTree(tpeA) :: TypeTree(tpeB) :: Nil)
|
||||
val typedApp = TypeApply(Select(it, name), TypeTree(tpeA) :: TypeTree(tpeB) :: Nil)
|
||||
val app = ApplyTree( ApplyTree(typedApp, arg1 :: Nil), arg2 :: Nil)
|
||||
c.Expr[Initialize[InputTask[T]]](app)
|
||||
}
|
||||
def expandTask(dyn: Boolean, tx: Tree): c.Expr[Initialize[Task[T]]] =
|
||||
// Tree for InputTask.createFree[<tpe>](arg1)
|
||||
def inputTaskCreateFree(tpe: Type, arg: Tree) =
|
||||
{
|
||||
val typedApp = TypeApply(Select(it, InputTaskCreateFreeName), TypeTree(tpe) :: Nil)
|
||||
val app = ApplyTree(typedApp, arg :: Nil)
|
||||
c.Expr[Initialize[InputTask[T]]](app)
|
||||
}
|
||||
def expandTask[I: WeakTypeTag](dyn: Boolean, tx: Tree): c.Expr[Initialize[Task[I]]] =
|
||||
if(dyn)
|
||||
taskDynMacroImpl[T](c)( c.Expr[Initialize[Task[T]]](tx) )
|
||||
taskDynMacroImpl[I](c)( c.Expr[Initialize[Task[I]]](tx) )
|
||||
else
|
||||
taskMacroImpl[T](c)( c.Expr[T](tx) )
|
||||
taskMacroImpl[I](c)( c.Expr[I](tx) )
|
||||
def wrapTag[I: WeakTypeTag]: WeakTypeTag[Initialize[Task[I]]] = weakTypeTag
|
||||
|
||||
val tx = util.transformWrappers(ttree, isParserWrapper, (tpe,tree) => subWrapper(tpe,tree))
|
||||
val body = c.resetLocalAttrs( expandTask(t.isRight, tx).tree )
|
||||
result match {
|
||||
case Some((p, tpe, param)) =>
|
||||
val f = Function(param :: Nil, body)
|
||||
inputTaskCreate(tpe, tag.tpe, p, f)
|
||||
val fCore = Function(param :: Nil, tx)
|
||||
val bodyTpe = if(t.isRight) wrapTag(tag).tpe else tag.tpe
|
||||
val fTpe = util.functionType(tpe :: Nil, bodyTpe)
|
||||
val fTag = c.WeakTypeTag[Any](fTpe) // don't know the actual type yet, so use Any
|
||||
val fInit = c.resetLocalAttrs( expandTask(false, fCore)(fTag).tree )
|
||||
inputTaskCreate(if(t.isRight) InputTaskCreateDynName else InputTaskCreateName, tpe, tag.tpe, p, fInit)
|
||||
case None =>
|
||||
// SI-6591 prevents the more direct version using reify:
|
||||
// reify { InputTask[Unit,T].create(TaskMacro.emptyParser)(Types.const(body.splice)) }
|
||||
val initType = c.weakTypeOf[Initialize[Task[T]]]
|
||||
val tt = Ident(util.singleton(Types))
|
||||
val f = ApplyTree(TypeApply(Select(tt, "const"), TypeTree(unitInitTask) :: TypeTree(initType) :: Nil), body :: Nil)
|
||||
val p = reify { InputTask.emptyParser }
|
||||
inputTaskCreate(c.typeOf[Unit], tag.tpe, p.tree, f)
|
||||
val init = c.resetLocalAttrs( expandTask[T](t.isRight, tx).tree )
|
||||
inputTaskCreateFree(tag.tpe, init)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,18 +95,10 @@ final object Aggregation
|
|||
|
||||
def applyDynamicTasks[I](s: State, structure: BuildStructure, inputs: Values[InputTask[I]], show: Boolean)(implicit display: Show[ScopedKey[_]]): Parser[() => State] =
|
||||
{
|
||||
final class Parsed[T](val input: InputTask[_] { type Result = T }, val value: T) {
|
||||
def addTo(im: AttributeMap): AttributeMap = im.put(input.defined, value)
|
||||
}
|
||||
val parsers: Seq[Parser[Parsed[_]]] = for( KeyValue(k,t) <- inputs ) yield
|
||||
t.parser(s).map( v => new Parsed[t.Result](t, v) )
|
||||
|
||||
Command.applyEffect(seq(parsers)) { parseds =>
|
||||
val parsers = for(KeyValue(k,it) <- inputs) yield it.parser(s).map(v => KeyValue(k,v))
|
||||
Command.applyEffect(seq(parsers)) { roots =>
|
||||
import EvaluateTask._
|
||||
val inputMap = (AttributeMap.empty /: parseds) { (im, p) => p.addTo(im) }
|
||||
val dummies = DummyTaskMap(new TaskAndValue(InputTask.inputMap, inputMap) :: Nil)
|
||||
val roots = maps(inputs)(_.task)
|
||||
runTasks(s, structure, roots, dummies, show)
|
||||
runTasks(s, structure, roots, DummyTaskMap(Nil), show)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ object ScriptedTests
|
|||
}
|
||||
def runAll(tests: Seq[() => Option[String]])
|
||||
{
|
||||
val errors = for(test <- tests; err <- test()) yield err
|
||||
val errors = for(test <- tests.par; err <- test()) yield err
|
||||
if(errors.nonEmpty)
|
||||
error(errors.mkString("Failed tests:\n\t", "\n\t", "\n"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,25 +11,39 @@ package sbt
|
|||
// Various natural transformations used, such as PMap, require invariant type constructors for correctness
|
||||
|
||||
/** Defines a task compuation*/
|
||||
sealed trait Action[T]
|
||||
sealed trait Action[T] {
|
||||
// TODO: remove after deprecated InputTask constructors are removed
|
||||
private[sbt] def mapTask(f: Task ~> Task): Action[T]
|
||||
}
|
||||
|
||||
|
||||
/** A direct computation of a value.
|
||||
* If `inline` is true, `f` will be evaluated on the scheduler thread without the overhead of normal scheduling when possible.
|
||||
* This is intended as an optimization for already evaluated values or very short computations. */
|
||||
final case class Pure[T](f: () => T, inline: Boolean) extends Action[T]
|
||||
* This is intended as an optimization for already evaluated values or very short pure computations. */
|
||||
final case class Pure[T](f: () => T, inline: Boolean) extends Action[T] {
|
||||
private[sbt] def mapTask(f: Task ~> Task) = this
|
||||
}
|
||||
|
||||
/** Applies a function to the result of evaluating a heterogeneous list of other tasks.*/
|
||||
final case class Mapped[T, K[L[x]]](in: K[Task], f: K[Result] => T, alist: AList[K]) extends Action[T]
|
||||
final case class Mapped[T, K[L[x]]](in: K[Task], f: K[Result] => T, alist: AList[K]) extends Action[T] {
|
||||
private[sbt] def mapTask(g: Task ~> Task) = Mapped[T,K](alist.transform(in, g), f, alist)
|
||||
}
|
||||
|
||||
/** Computes another task to evaluate based on results from evaluating other tasks.*/
|
||||
final case class FlatMapped[T, K[L[x]]](in: K[Task], f: K[Result] => Task[T], alist: AList[K]) extends Action[T]
|
||||
final case class FlatMapped[T, K[L[x]]](in: K[Task], f: K[Result] => Task[T], alist: AList[K]) extends Action[T] {
|
||||
private[sbt] def mapTask(g: Task ~> Task) = FlatMapped[T,K](alist.transform(in, g), g.fn[T] compose f, alist)
|
||||
}
|
||||
|
||||
/** A computation `in` that requires other tasks `deps` to be evaluated first.*/
|
||||
final case class DependsOn[T](in: Task[T], deps: Seq[Task[_]]) extends Action[T]
|
||||
final case class DependsOn[T](in: Task[T], deps: Seq[Task[_]]) extends Action[T] {
|
||||
private[sbt] def mapTask(g: Task ~> Task) = DependsOn[T](g(in), deps.map(t => g(t)))
|
||||
}
|
||||
|
||||
/** A computation that operates on the results of a homogeneous list of other tasks.
|
||||
* It can either return another task to be evaluated or the final value.*/
|
||||
final case class Join[T, U](in: Seq[Task[U]], f: Seq[Result[U]] => Either[Task[T], T]) extends Action[T]
|
||||
final case class Join[T, U](in: Seq[Task[U]], f: Seq[Result[U]] => Either[Task[T], T]) extends Action[T] {
|
||||
private[sbt] def mapTask(g: Task ~> Task) = Join[T,U](in.map(g.fn[U]), sr => f(sr).left.map(g.fn[T]))
|
||||
}
|
||||
|
||||
/** Combines metadata `info` and a computation `work` to define a task. */
|
||||
final case class Task[T](info: Info[T], work: Action[T])
|
||||
|
|
@ -37,6 +51,7 @@ final case class Task[T](info: Info[T], work: Action[T])
|
|||
override def toString = info.name getOrElse ("Task(" + info + ")")
|
||||
override def hashCode = info.hashCode
|
||||
|
||||
private[sbt] def mapTask(g: Task ~> Task): Task[T] = g(Task(info, work.mapTask(g)))
|
||||
def tag(tags: Tag*): Task[T] = tagw(tags.map(t => (t, 1)) : _*)
|
||||
def tagw(tags: (Tag, Int)*): Task[T] = copy(info = info.set(tagsKey, info.get(tagsKey).getOrElse(Map.empty) ++ tags ))
|
||||
def tags: TagMap = info get tagsKey getOrElse Map.empty
|
||||
|
|
|
|||
|
|
@ -89,11 +89,9 @@ trait TaskExtra
|
|||
final def nop: Task[Unit] = constant( () )
|
||||
final def constant[T](t: T): Task[T] = task(t)
|
||||
|
||||
final implicit def actionToTask[T](a: Action[T]): Task[T] = Task(Info(), a)
|
||||
|
||||
final def task[T](f: => T): Task[T] = toTask(f _)
|
||||
final implicit def toTask[T](f: () => T): Task[T] = new Pure(f, false)
|
||||
final def inlineTask[T](value: T): Task[T] = new Pure(() => value, true)
|
||||
final implicit def toTask[T](f: () => T): Task[T] = Task(Info(), new Pure(f, false))
|
||||
final def inlineTask[T](value: T): Task[T] = Task(Info(), new Pure(() => value, true))
|
||||
|
||||
final implicit def upcastTask[A >: B, B](t: Task[B]): Task[A] = t map { x => x : A }
|
||||
final implicit def toTasks[S](in: Seq[() => S]): Seq[Task[S]] = in.map(toTask)
|
||||
|
|
@ -106,20 +104,20 @@ trait TaskExtra
|
|||
|
||||
final implicit def joinAnyTasks(in: Seq[Task[_]]): JoinTask[Any, Seq] = joinTasks[Any]( existToAny(in) )
|
||||
final implicit def joinTasks[S](in: Seq[Task[S]]): JoinTask[S, Seq] = new JoinTask[S, Seq] {
|
||||
def join: Task[Seq[S]] = new Join(in, (s: Seq[Result[S]]) => Right(TaskExtra.all(s)) )
|
||||
def join: Task[Seq[S]] = Task[Seq[S]](Info(), new Join(in, (s: Seq[Result[S]]) => Right(TaskExtra.all(s)) ))
|
||||
def reduced(f: (S,S) => S): Task[S] = TaskExtra.reduced(in.toIndexedSeq, f)
|
||||
}
|
||||
|
||||
final implicit def multT2Task[A,B](in: (Task[A], Task[B])) = multInputTask[({ type l[L[x]] = (L[A], L[B]) })#l](in)(AList.tuple2[A,B])
|
||||
|
||||
final implicit def multInputTask[K[L[X]]](tasks: K[Task])(implicit a: AList[K]): MultiInTask[K] = new MultiInTask[K] {
|
||||
def flatMapR[T](f: K[Result] => Task[T]): Task[T] = new FlatMapped[T,K](tasks, f, a)
|
||||
def flatMap[T](f: K[Id] => Task[T]): Task[T] = new FlatMapped[T, K](tasks, f compose allM, a)
|
||||
def flatFailure[T](f: Seq[Incomplete] => Task[T]): Task[T] = new FlatMapped[T,K](tasks, f compose anyFailM, a)
|
||||
def flatMapR[T](f: K[Result] => Task[T]): Task[T] = Task(Info(), new FlatMapped[T,K](tasks, f, a))
|
||||
def flatMap[T](f: K[Id] => Task[T]): Task[T] = Task(Info(), new FlatMapped[T, K](tasks, f compose allM, a))
|
||||
def flatFailure[T](f: Seq[Incomplete] => Task[T]): Task[T] = Task(Info(), new FlatMapped[T,K](tasks, f compose anyFailM, a))
|
||||
|
||||
def mapR[T](f: K[Result] => T): Task[T] = new Mapped[T,K](tasks, f, a)
|
||||
def map[T](f: K[Id] => T): Task[T] = new Mapped[T,K](tasks, f compose allM, a)
|
||||
def mapFailure[T](f: Seq[Incomplete] => T): Task[T] = new Mapped[T,K](tasks, f compose anyFailM, a)
|
||||
def mapR[T](f: K[Result] => T): Task[T] = Task(Info(), new Mapped[T,K](tasks, f, a))
|
||||
def map[T](f: K[Id] => T): Task[T] = Task(Info(), new Mapped[T,K](tasks, f compose allM, a))
|
||||
def mapFailure[T](f: Seq[Incomplete] => T): Task[T] = Task(Info(), new Mapped[T,K](tasks, f compose anyFailM, a))
|
||||
}
|
||||
|
||||
final implicit def singleInputTask[S](in: Task[S]): SingleInTask[S] = new SingleInTask[S] {
|
||||
|
|
@ -129,9 +127,9 @@ trait TaskExtra
|
|||
def failure: Task[Incomplete] = mapFailure(idFun)
|
||||
def result: Task[Result[S]] = mapR(idFun)
|
||||
|
||||
def flatMapR[T](f: Result[S] => Task[T]): Task[T] = new FlatMapped[T, K](in, f, ml)
|
||||
def mapR[T](f: Result[S] => T): Task[T] = new Mapped[T, K](in, f, ml)
|
||||
def dependsOn(tasks: Task[_]*): Task[S] = new DependsOn(in, tasks)
|
||||
def flatMapR[T](f: Result[S] => Task[T]): Task[T] = Task(Info(), new FlatMapped[T, K](in, f, ml))
|
||||
def mapR[T](f: Result[S] => T): Task[T] = Task(Info(), new Mapped[T, K](in, f, ml))
|
||||
def dependsOn(tasks: Task[_]*): Task[S] = Task(Info(), new DependsOn(in, tasks))
|
||||
|
||||
def flatMap[T](f: S => Task[T]): Task[T] = flatMapR(f compose successM)
|
||||
def flatFailure[T](f: Incomplete => Task[T]): Task[T] = flatMapR(f compose failM)
|
||||
|
|
@ -230,7 +228,7 @@ object TaskExtra extends TaskExtra
|
|||
}
|
||||
def failuresM[K[L[x]]](implicit a: AList[K]): K[Result] => Seq[Incomplete] = x => failures[Any](a.toList(x))
|
||||
|
||||
def all[D](in: Seq[Result[D]]) =
|
||||
def all[D](in: Seq[Result[D]]): Seq[D] =
|
||||
{
|
||||
val incs = failures(in)
|
||||
if(incs.isEmpty) in.map(Result.tryValue.fn[D]) else throw incompleteDeps(incs)
|
||||
|
|
|
|||
|
|
@ -143,6 +143,13 @@ final class ContextUtil[C <: Context](val ctx: C)
|
|||
/** >: Nothing <: Any */
|
||||
def emptyTypeBounds: TypeBounds = TypeBounds(definitions.NothingClass.toType, definitions.AnyClass.toType)
|
||||
|
||||
def functionType(args: List[Type], result: Type): Type =
|
||||
{
|
||||
val global: Global = ctx.universe.asInstanceOf[Global]
|
||||
val tpe = global.definitions.functionType(args.asInstanceOf[List[global.Type]], result.asInstanceOf[global.Type])
|
||||
tpe.asInstanceOf[Type]
|
||||
}
|
||||
|
||||
/** Create a Tree that references the `val` represented by `vd`. */
|
||||
def refVal(vd: ValDef): Tree =
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue