Adds an Append instance that extracts taskValue

This adds a macro-level hack to support += op for sourceGenerators and resourceGenerators using RHS of Initialize[Task[Seq[File]]].
When the types match up, the macro now calls `.taskValue` automatically.
This commit is contained in:
Eugene Yokota 2017-01-22 22:51:01 -05:00
parent b47f281c6a
commit 51f7d2e24a
7 changed files with 49 additions and 11 deletions

View File

@ -4,6 +4,8 @@ import java.io.File
import Def.Classpath
import scala.annotation.implicitNotFound
import sbt.internal.util.Attributed
import Def.Initialize
import reflect.internal.annotations.compileTimeOnly
object Append {
@implicitNotFound(msg = "No implicit for Append.Value[${A}, ${B}] found,\n so ${B} cannot be appended to ${A}")
@ -24,6 +26,14 @@ object Append {
def appendValues(a: Seq[T], b: Seq[V]): Seq[T] = a ++ (b map { x => (x: T) })
def appendValue(a: Seq[T], b: V): Seq[T] = a :+ (b: T)
}
@compileTimeOnly("This can be used in += only.")
implicit def appendTaskValueSeq[T, V <: T]: Value[Seq[Task[T]], Initialize[Task[V]]] = new Value[Seq[Task[T]], Initialize[Task[V]]] {
def appendValue(a: Seq[Task[T]], b: Initialize[Task[V]]): Seq[Task[T]] = ???
}
@compileTimeOnly("This can be used in += only.")
implicit def appendTaskKeySeq[T, V <: T]: Value[Seq[Task[T]], TaskKey[V]] = new Value[Seq[Task[T]], TaskKey[V]] {
def appendValue(a: Seq[Task[T]], b: TaskKey[V]): Seq[Task[T]] = ???
}
implicit def appendList[T, V <: T]: Sequence[List[T], List[V], V] = new Sequence[List[T], List[V], V] {
def appendValues(a: List[T], b: List[V]): List[T] = a ::: b
def appendValue(a: List[T], b: V): List[T] = a :+ b

View File

@ -161,9 +161,23 @@ object TaskMacro {
/** Implementation of += macro for settings. */
def settingAppend1Impl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(v: c.Expr[U])(a: c.Expr[Append.Value[T, U]]): c.Expr[Setting[T]] =
{
val init = SettingMacro.settingMacroImpl[U](c)(v)
val append = appendMacroImpl(c)(init.tree, a.tree)(Append1InitName)
c.Expr[Setting[T]](append)
import c.universe._
val ttpe = c.weakTypeOf[T]
val typeArgs = ttpe.typeArgs
v.tree.tpe match {
// To allow Initialize[Task[A]] in the position of += RHS, we're going to call "taskValue" automatically.
case tpe if typeArgs.nonEmpty && (tpe weak_<:< c.weakTypeOf[Initialize[_]]) =>
c.macroApplication match {
case Apply(Apply(TypeApply(Select(preT, nmeT), targs), _), _) =>
val tree = Apply(TypeApply(Select(preT, TermName("+=").encodedName), TypeTree(typeArgs.head) :: Nil), Select(v.tree, TermName("taskValue").encodedName) :: Nil)
c.Expr[Setting[T]](tree)
case x => ContextUtil.unexpectedTree(x)
}
case _ =>
val init = SettingMacro.settingMacroImpl[U](c)(v)
val append = appendMacroImpl(c)(init.tree, a.tree)(Append1InitName)
c.Expr[Setting[T]](append)
}
}
/** Implementation of ++= macro for tasks. */
def taskAppendNImpl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(vs: c.Expr[U])(a: c.Expr[Append.Values[T, U]]): c.Expr[Setting[Task[T]]] =
@ -179,7 +193,6 @@ object TaskMacro {
val append = appendMacroImpl(c)(init.tree, a.tree)(AppendNInitName)
c.Expr[Setting[T]](append)
}
/** Implementation of -= macro for tasks. */
def taskRemove1Impl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(v: c.Expr[U])(r: c.Expr[Remove.Value[T, U]]): c.Expr[Setting[Task[T]]] =
{
@ -213,8 +226,8 @@ object TaskMacro {
{
import c.universe._
c.macroApplication match {
case Apply(Apply(TypeApply(Select(preT, nmeT), targs), _), a) =>
Apply(Apply(TypeApply(Select(preT, TermName(newName).encodedName), targs), init :: sourcePosition(c).tree :: Nil), a)
case Apply(Apply(TypeApply(Select(preT, nmeT), targs), _), _) =>
Apply(Apply(TypeApply(Select(preT, TermName(newName).encodedName), targs), init :: sourcePosition(c).tree :: Nil), append :: Nil)
case x => ContextUtil.unexpectedTree(x)
}
}

View File

@ -261,7 +261,7 @@ object Defaults extends BuildCommon {
unmanagedResources := collectFiles(unmanagedResourceDirectories, includeFilter in unmanagedResources, excludeFilter in unmanagedResources).value,
watchSources in ConfigGlobal ++= unmanagedResources.value,
resourceGenerators :== Nil,
resourceGenerators += (Def.task { PluginDiscovery.writeDescriptors(discoveredSbtPlugins.value, resourceManaged.value) }).taskValue,
resourceGenerators += Def.task { PluginDiscovery.writeDescriptors(discoveredSbtPlugins.value, resourceManaged.value) },
managedResources := generate(resourceGenerators).value,
resources := Classpaths.concat(managedResources, unmanagedResources).value
)

View File

@ -0,0 +1,13 @@
lazy val buildInfo = taskKey[Seq[File]]("The task that generates the build info.")
lazy val root = (project in file("."))
.settings(
scalaVersion := "2.11.8",
buildInfo := {
val x = sourceManaged.value / "BuildInfo.scala"
IO.write(x, """object BuildInfo""")
x :: Nil
},
sourceGenerators in Compile += buildInfo,
sourceGenerators in Compile += Def.task { Nil }
)

View File

@ -0,0 +1,2 @@
> compile
$ exists target/scala-2.11/src_managed/BuildInfo.scala

View File

@ -1,8 +1,8 @@
val test123 = project in file(".") enablePlugins TestP settings(
resourceGenerators in Compile += (Def.task {
resourceGenerators in Compile += Def.task {
streams.value.log info "resource generated in settings"
Nil
}).taskValue
}
)
TaskKey[Unit]("check") := {

View File

@ -2,9 +2,9 @@ import sbt._, syntax._, Keys._
object TestP extends AutoPlugin {
override def projectSettings: Seq[Setting[_]] = Seq(
resourceGenerators in Compile += (Def.task {
resourceGenerators in Compile += Def.task {
streams.value.log info "resource generated in plugin"
Nil
}).taskValue
}
)
}