From 2e120ed86f6b486521f7d5fde0ef1e843ce23348 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Tue, 31 Jul 2012 11:52:10 -0400 Subject: [PATCH] split out InputTask --- main/settings/InputTask.scala | 64 ++++++++++++++++++++++++++++++ main/settings/Structure.scala | 74 ----------------------------------- 2 files changed, 64 insertions(+), 74 deletions(-) create mode 100644 main/settings/InputTask.scala diff --git a/main/settings/InputTask.scala b/main/settings/InputTask.scala new file mode 100644 index 000000000..ecc89244c --- /dev/null +++ b/main/settings/InputTask.scala @@ -0,0 +1,64 @@ +package sbt + + import complete.Parser + import Def.{Initialize, ScopedKey} + import std.TaskExtra.{task => mktask, _} + import Task._ + import Types._ + +/** Parses input and produces a task to run. Constructed using the companion object. */ +sealed trait InputTask[T] { + def mapTask[S](f: Task[T] => Task[S]): InputTask[S] +} +private final class InputStatic[T](val parser: State => Parser[Task[T]]) extends InputTask[T] { + def mapTask[S](f: Task[T] => Task[S]) = new InputStatic(s => parser(s) map f) +} +private sealed trait InputDynamic[T] extends InputTask[T] +{ outer => + type Result + def parser: State => Parser[Result] + def defined: ScopedKey[_] + def task: Task[T] + def mapTask[S](f: Task[T] => Task[S]) = new InputDynamic[S] { + type Result = outer.Result + def parser = outer.parser + def task = f(outer.task) + def defined = outer.defined + } +} +object InputTask +{ + def static[T](p: Parser[Task[T]]): InputTask[T] = free(_ => p) + def static[I,T](p: Parser[I])(c: I => Task[T]): InputTask[T] = static(p map c) + + def free[T](p: State => Parser[Task[T]]): InputTask[T] = new InputStatic[T](p) + def free[I,T](p: State => Parser[I])(c: I => Task[T]): InputTask[T] = free(s => p(s) map c) + + def separate[I,T](p: State => Parser[I])(action: Initialize[I => Task[T]]): Initialize[InputTask[T]] = + separate(Def value p)(action) + 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)) + + private[sbt] lazy val inputMap: Task[Map[AnyRef,Any]] = mktask { error("Internal sbt error: input map not substituted.") } + + // 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 is the ugly part, requiring hooks in Load.finalTransforms and Aggregation.applyDynamicTasks + // to handle the dummy task for the parse result. + // However, this results in a minimal interface to the full capabilities of an InputTask for users + def apply[I,T](p: Initialize[State => Parser[I]])(action: TaskKey[I] => Initialize[Task[T]]): Initialize[InputTask[T]] = + { + val key: TaskKey[I] = Def.parseResult.asInstanceOf[TaskKey[I]] + (p zip Def.resolvedScoped zipWith action(key)) { case ((parserF, scoped), act) => + new InputDynamic[T] + { + type Result = I + def parser = parserF + def task = act + def defined = scoped + } + } + } + def apply[I,T](p: State => Parser[I])(action: TaskKey[I] => Initialize[Task[T]]): Initialize[InputTask[T]] = + apply(Def.value(p))(action) +} diff --git a/main/settings/Structure.scala b/main/settings/Structure.scala index 2b3bce010..6ff75c035 100644 --- a/main/settings/Structure.scala +++ b/main/settings/Structure.scala @@ -8,7 +8,6 @@ package sbt import java.io.File import java.net.URI - import complete.Parser import ConcurrentRestrictions.Tag import Def.{Initialize, KeyedInitialize, ScopedKey, Setting, setting} import Path._ @@ -16,63 +15,6 @@ package sbt import Task._ import Types._ -/** Parses input and produces a task to run. Constructed using the companion object. */ -sealed trait InputTask[T] { - def mapTask[S](f: Task[T] => Task[S]): InputTask[S] -} -private final class InputStatic[T](val parser: State => Parser[Task[T]]) extends InputTask[T] { - def mapTask[S](f: Task[T] => Task[S]) = new InputStatic(s => parser(s) map f) -} -private sealed trait InputDynamic[T] extends InputTask[T] -{ outer => - type Result - def parser: State => Parser[Result] - def defined: ScopedKey[_] - def task: Task[T] - def mapTask[S](f: Task[T] => Task[S]) = new InputDynamic[S] { - type Result = outer.Result - def parser = outer.parser - def task = f(outer.task) - def defined = outer.defined - } -} -object InputTask -{ - def static[T](p: Parser[Task[T]]): InputTask[T] = free(_ => p) - def static[I,T](p: Parser[I])(c: I => Task[T]): InputTask[T] = static(p map c) - - def free[T](p: State => Parser[Task[T]]): InputTask[T] = new InputStatic[T](p) - def free[I,T](p: State => Parser[I])(c: I => Task[T]): InputTask[T] = free(s => p(s) map c) - - def separate[I,T](p: State => Parser[I])(action: Initialize[I => Task[T]]): Initialize[InputTask[T]] = - separate(Def value p)(action) - 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)) - - private[sbt] lazy val inputMap: Task[Map[AnyRef,Any]] = mktask { error("Internal sbt error: input map not substituted.") } - - // 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 is the ugly part, requiring hooks in Load.finalTransforms and Aggregation.applyDynamicTasks - // to handle the dummy task for the parse result. - // However, this results in a minimal interface to the full capabilities of an InputTask for users - def apply[I,T](p: Initialize[State => Parser[I]])(action: TaskKey[I] => Initialize[Task[T]]): Initialize[InputTask[T]] = - { - val key: TaskKey[I] = Def.parseResult.asInstanceOf[TaskKey[I]] - (p zip Def.resolvedScoped zipWith action(key)) { case ((parserF, scoped), act) => - new InputDynamic[T] - { - type Result = I - def parser = parserF - def task = act - def defined = scoped - } - } - } - def apply[I,T](p: State => Parser[I])(action: TaskKey[I] => Initialize[Task[T]]): Initialize[InputTask[T]] = - apply(Def.value(p))(action) -} - sealed trait Scoped { def scope: Scope; val key: AttributeKey[_] } /** A common type for SettingKey and TaskKey so that both can be used as inputs to tasks.*/ @@ -396,22 +338,6 @@ object Scoped protected def convert[M[_],R](z: Fun[M,R]) = z.tupled }*/ - // this doesn't actually work for mixed KLists because the compiler crashes trying to infer the bound when constructing the KList -/* implicit def richTaskableKeys[KL <: KList[ScopedTaskable]](in: KList): RichTaskableKeys[KL] = new RichTaskableKeys[KL](in) - final class RichTaskableKeys[KL <: KList[ScopedTaskable]](keys: KL) - { - type App[T] = Initialize[Task[T]] - private[this] def inputs: keys.Transform[App] = keys.transform( new (ScopedTaskable ~> App) { def apply[T](in: ScopedTaskable[T]): App[T] = in.toTask }) - - def identity: App[In] = map(idFun) - def flatMap[T](f: keys.Transform[Id] => Task[T]): App[T] = flatMapR(f compose allM) - def flatMapR[T](f: keys.Transform[Result] => Task[T]): App[T] = red.combine(Combine.flatMapR, f) - def map[T](f: In => T): App[T] = mapR(f compose allM) - def mapR[T](f: Results[In] => T): App[T] = red.combine[Id,T](Combine.mapR, f) - def flatFailure[T](f: Seq[Incomplete] => Task[T]): App[T] = flatMapR(f compose anyFailM) - def mapFailure[T](f: Seq[Incomplete] => T): App[T] = mapR(f compose anyFailM) - }*/ - implicit def t2ToApp2[A,B](t2: (Initialize[A], Initialize[B]) ): Apply2[A,B] = new Apply2(t2) implicit def t3ToApp3[A,B,C](t3: (Initialize[A], Initialize[B], Initialize[C]) ): Apply3[A,B,C] = new Apply3(t3) implicit def t4ToApp4[A,B,C,D](t4: (Initialize[A], Initialize[B], Initialize[C], Initialize[D]) ): Apply4[A,B,C,D] = new Apply4(t4)