diff --git a/internal/util-collection/src/main/scala/sbt/internal/util/Settings.scala b/internal/util-collection/src/main/scala/sbt/internal/util/Settings.scala index 23e06a372..d6090dc81 100644 --- a/internal/util-collection/src/main/scala/sbt/internal/util/Settings.scala +++ b/internal/util-collection/src/main/scala/sbt/internal/util/Settings.scala @@ -534,6 +534,14 @@ trait Init[Scope] { } } + /** Abstractly defines a value of type `T`. + * + * Specifically it defines a node in a task graph, + * where the `dependencies` represents dependent nodes, + * and `evaluate` represents the calculation based on the existing body of knowledge. + * + * @tparam T the type of the value this defines. + */ sealed trait Initialize[T] { def dependencies: Seq[ScopedKey[_]] def apply[S](g: T => S): Initialize[S] @@ -698,6 +706,10 @@ trait Init[Scope] { private[this] def deps(ls: Seq[Initialize[_]]): Seq[ScopedKey[_]] = ls.flatMap(_.dependencies) + /** An `Initialize[T]` associated with a `ScopedKey[S]`. + * @tparam S the type of the associated `ScopedKey` + * @tparam T the type of the value this `Initialize` defines. + */ sealed trait Keyed[S, T] extends Initialize[T] { def scopedKey: ScopedKey[S] def transform: S => T @@ -724,6 +736,9 @@ trait Init[Scope] { private[this] final class GetValue[S, T](val scopedKey: ScopedKey[S], val transform: S => T) extends Keyed[S, T] + /** A `Keyed` where the type of the value and the associated `ScopedKey` are the same. + * @tparam T the type of both the value this `Initialize` defines and the type of the associated `ScopedKey`. + */ trait KeyedInitialize[T] extends Keyed[T, T] { final val transform = idFun[T] } diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 94589c439..acbefdb16 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -552,7 +552,7 @@ object Defaults extends BuildCommon { val trigMsg = triggeredMessage.value new Watched { val scoped = watchTransitiveSources in base - val key = ScopedKey(scoped.scope, scoped.key) + val key = scoped.scopedKey override def pollInterval = interval override def watchingMessage(s: WatchState) = msg(s) override def triggeredMessage(s: WatchState) = trigMsg(s) diff --git a/main/src/main/scala/sbt/EvaluateTask.scala b/main/src/main/scala/sbt/EvaluateTask.scala index 2400b2163..1d17f5cc3 100644 --- a/main/src/main/scala/sbt/EvaluateTask.scala +++ b/main/src/main/scala/sbt/EvaluateTask.scala @@ -460,6 +460,7 @@ object EvaluateTask { onResult(result, log) { v => if (show) println("Result: " + v); v } + def onResult[T, S](result: Result[T], log: Logger)(f: T => S): S = result match { case Value(v) => f(v) diff --git a/main/src/main/scala/sbt/Extracted.scala b/main/src/main/scala/sbt/Extracted.scala index 5ccf71160..80243ada1 100644 --- a/main/src/main/scala/sbt/Extracted.scala +++ b/main/src/main/scala/sbt/Extracted.scala @@ -15,6 +15,7 @@ import sbt.internal.util.complete.Parser import sbt.internal.util.AttributeKey import sbt.util.Show import std.Transform.DummyTaskMap +import sbt.EvaluateTask.extractedTaskConfig final case class Extracted(structure: BuildStructure, session: SessionSettings, @@ -49,16 +50,16 @@ final case class Extracted(structure: BuildStructure, * If the project axis is not defined for the key, it is resolved to be the current project. * Other axes are resolved to `Zero` if unspecified. * - * This method requests execution of only the given task and does not aggregate execution. See `runAggregated` for that. + * This method requests execution of only the given task and does not aggregate execution. + * See `runAggregated` for that. */ def runTask[T](key: TaskKey[T], state: State): (State, T) = { - import EvaluateTask._ val rkey = resolve(key.scopedKey) val config = extractedTaskConfig(this, structure, state) val value: Option[(State, Result[T])] = - apply(structure, key.scopedKey, state, currentRef, config) + EvaluateTask(structure, key.scopedKey, state, currentRef, config) val (newS, result) = getOrError(rkey.scope, rkey.key, value) - (newS, processResult(result, newS.log)) + (newS, EvaluateTask.processResult(result, newS.log)) } /** @@ -71,25 +72,22 @@ final case class Extracted(structure: BuildStructure, * This method requests execution of only the given task and does not aggregate execution. */ def runInputTask[T](key: InputKey[T], input: String, state: State): (State, T) = { - import EvaluateTask._ - - val scopedKey = Scoped.scopedSetting( - Scope.resolveScope(Load.projectScope(currentRef), currentRef.build, structure.rootProject)( - key.scope), + val scopedKey = ScopedKey( + Scope.resolveScope(Load.projectScope(currentRef), currentRef.build, rootProject)(key.scope), key.key ) - val rkey = resolve(scopedKey.scopedKey) + val rkey = resolve(scopedKey) val inputTask = get(Scoped.scopedSetting(rkey.scope, rkey.key)) val task = Parser.parse(input, inputTask.parser(state)) match { case Right(t) => t case Left(msg) => sys.error(s"Invalid programmatic input:\n$msg") } val config = extractedTaskConfig(this, structure, state) - withStreams(structure, state) { str => - val nv = nodeView(state, str, rkey :: Nil) + EvaluateTask.withStreams(structure, state) { str => + val nv = EvaluateTask.nodeView(state, str, rkey :: Nil) val (newS, result) = EvaluateTask.runTask(task, state, str, structure.index.triggers, config)(nv) - (newS, processResult(result, newS.log)) + (newS, EvaluateTask.processResult(result, newS.log)) } } @@ -112,9 +110,11 @@ final case class Extracted(structure: BuildStructure, private[this] def resolve[T](key: ScopedKey[T]): ScopedKey[T] = Project.mapScope(Scope.resolveScope(GlobalScope, currentRef.build, rootProject))(key.scopedKey) + private def getOrError[T](scope: Scope, key: AttributeKey[_], value: Option[T])( implicit display: Show[ScopedKey[_]]): T = value getOrElse sys.error(display.show(ScopedKey(scope, key)) + " is undefined.") + private def getOrError[T](scope: Scope, key: AttributeKey[T])( implicit display: Show[ScopedKey[_]]): T = structure.data.get(scope, key) getOrElse sys.error(