diff --git a/build.sbt b/build.sbt index 241d0c385..920e63c9c 100644 --- a/build.sbt +++ b/build.sbt @@ -805,6 +805,9 @@ lazy val mainSettingsProj = (project in file("main-settings")) // added a method to a sealed trait exclude[InheritedNewAbstractMethodProblem]("sbt.Scoped.canEqual"), exclude[InheritedNewAbstractMethodProblem]("sbt.ScopedTaskable.canEqual"), + // widened ScopedTaskable parameter to (new) supertype Taskable + exclude[IncompatibleSignatureProblem]("sbt.Scoped#RichTaskable*.this"), + exclude[IncompatibleSignatureProblem]("sbt.TupleSyntax.t*ToTable*"), ), ) .configure( diff --git a/main-settings/src/main/scala/sbt/Structure.scala b/main-settings/src/main/scala/sbt/Structure.scala index f29ca0fa5..e21b57baa 100644 --- a/main-settings/src/main/scala/sbt/Structure.scala +++ b/main-settings/src/main/scala/sbt/Structure.scala @@ -30,11 +30,14 @@ sealed trait Scoped extends Equals { override def hashCode() = (scope, key).## } -/** A common type for SettingKey and TaskKey so that both can be used as inputs to tasks.*/ -sealed trait ScopedTaskable[T] extends Scoped { +/** A SettingKey, TaskKey or `Initialize[Task]` that can be converted into an `Initialize[Task]`. */ +sealed trait Taskable[T] { def toTask: Initialize[Task[T]] } +/** A common type for SettingKey and TaskKey so that both can be used as inputs to tasks.*/ +sealed trait ScopedTaskable[T] extends Scoped with Taskable[T] + /** * Identifies a setting. It consists of three parts: the scope, the name, and the type of a value associated with this key. * The scope is represented by a value of type Scope. @@ -457,7 +460,7 @@ object Scoped { Initialize.joinAny[Task](keys).apply(deps => nop.dependsOn(deps: _*)) } - sealed abstract class RichTaskables[K[L[x]]](final val keys: K[ScopedTaskable])( + sealed abstract class RichTaskables[K[L[x]]](final val keys: K[Taskable])( implicit a: AList[K] ) { @@ -466,7 +469,7 @@ object Scoped { protected def convert[M[_], Ret](f: Fun[M, Ret]): K[M] => Ret - private[this] val inputs: K[App] = a.transform(keys, λ[ScopedTaskable ~> App](_.toTask)) + private[this] val inputs: K[App] = a.transform(keys, λ[Taskable ~> App](_.toTask)) private[this] def onTasks[T](f: K[Task] => Task[T]): App[T] = Def.app[λ[L[x] => K[(L ∙ Task)#l]], Task[T]](inputs)(f)(AList.asplit[K, Task](a)) @@ -481,7 +484,7 @@ object Scoped { // format: off - type ST[X] = ScopedTaskable[X] + type ST[X] = Taskable[X] final class RichTaskable2[A, B](t2: (ST[A], ST[B])) extends RichTaskables[AList.T2K[A, B]#l](t2)(AList.tuple2[A, B]) { type Fun[M[_], Ret] = (M[A], M[B]) => Ret def identityMap = map(mkTuple2) @@ -605,16 +608,17 @@ trait TupleSyntax { // format: off // this is the least painful arrangement I came up with - implicit def t2ToTable2[A, B](t2: (ScopedTaskable[A], ScopedTaskable[B])): RichTaskable2[A, B] = new RichTaskable2(t2) - implicit def t3ToTable3[A, B, C](t3: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C])): RichTaskable3[A, B, C] = new RichTaskable3(t3) - implicit def t4ToTable4[A, B, C, D](t4: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D])): RichTaskable4[A, B, C, D] = new RichTaskable4(t4) - implicit def t5ToTable5[A, B, C, D, E](t5: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E])): RichTaskable5[A, B, C, D, E] = new RichTaskable5(t5) - implicit def t6ToTable6[A, B, C, D, E, F](t6: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F])): RichTaskable6[A, B, C, D, E, F] = new RichTaskable6(t6) - implicit def t7ToTable7[A, B, C, D, E, F, G](t7: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F], ScopedTaskable[G])): RichTaskable7[A, B, C, D, E, F, G] = new RichTaskable7(t7) - implicit def t8ToTable8[A, B, C, D, E, F, G, H](t8: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F], ScopedTaskable[G], ScopedTaskable[H])): RichTaskable8[A, B, C, D, E, F, G, H] = new RichTaskable8(t8) - implicit def t9ToTable9[A, B, C, D, E, F, G, H, I](t9: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F], ScopedTaskable[G], ScopedTaskable[H], ScopedTaskable[I])): RichTaskable9[A, B, C, D, E, F, G, H, I] = new RichTaskable9(t9) - implicit def t10ToTable10[A, B, C, D, E, F, G, H, I, J](t10: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F], ScopedTaskable[G], ScopedTaskable[H], ScopedTaskable[I], ScopedTaskable[J])): RichTaskable10[A, B, C, D, E, F, G, H, I, J] = new RichTaskable10(t10) - implicit def t11ToTable11[A, B, C, D, E, F, G, H, I, J, K](t11: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F], ScopedTaskable[G], ScopedTaskable[H], ScopedTaskable[I], ScopedTaskable[J], ScopedTaskable[K])): RichTaskable11[A, B, C, D, E, F, G, H, I, J, K] = new RichTaskable11(t11) + type ST[T] = Taskable[T] + implicit def t2ToTable2[A, B](t2: (ST[A], ST[B])): RichTaskable2[A, B] = new RichTaskable2(t2) + implicit def t3ToTable3[A, B, C](t3: (ST[A], ST[B], ST[C])): RichTaskable3[A, B, C] = new RichTaskable3(t3) + implicit def t4ToTable4[A, B, C, D](t4: (ST[A], ST[B], ST[C], ST[D])): RichTaskable4[A, B, C, D] = new RichTaskable4(t4) + implicit def t5ToTable5[A, B, C, D, E](t5: (ST[A], ST[B], ST[C], ST[D], ST[E])): RichTaskable5[A, B, C, D, E] = new RichTaskable5(t5) + implicit def t6ToTable6[A, B, C, D, E, F](t6: (ST[A], ST[B], ST[C], ST[D], ST[E], ST[F])): RichTaskable6[A, B, C, D, E, F] = new RichTaskable6(t6) + implicit def t7ToTable7[A, B, C, D, E, F, G](t7: (ST[A], ST[B], ST[C], ST[D], ST[E], ST[F], ST[G])): RichTaskable7[A, B, C, D, E, F, G] = new RichTaskable7(t7) + implicit def t8ToTable8[A, B, C, D, E, F, G, H](t8: (ST[A], ST[B], ST[C], ST[D], ST[E], ST[F], ST[G], ST[H])): RichTaskable8[A, B, C, D, E, F, G, H] = new RichTaskable8(t8) + implicit def t9ToTable9[A, B, C, D, E, F, G, H, I](t9: (ST[A], ST[B], ST[C], ST[D], ST[E], ST[F], ST[G], ST[H], ST[I])): RichTaskable9[A, B, C, D, E, F, G, H, I] = new RichTaskable9(t9) + implicit def t10ToTable10[A, B, C, D, E, F, G, H, I, J](t10: (ST[A], ST[B], ST[C], ST[D], ST[E], ST[F], ST[G], ST[H], ST[I], ST[J])): RichTaskable10[A, B, C, D, E, F, G, H, I, J] = new RichTaskable10(t10) + implicit def t11ToTable11[A, B, C, D, E, F, G, H, I, J, K](t11: (ST[A], ST[B], ST[C], ST[D], ST[E], ST[F], ST[G], ST[H], ST[I], ST[J], ST[K])): RichTaskable11[A, B, C, D, E, F, G, H, I, J, K] = new RichTaskable11(t11) 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) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 891d26f78..1e409d017 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -1327,10 +1327,12 @@ object Defaults extends BuildCommon { case _ => None } } + def resourceMappings = relativeMappings(unmanagedResources, unmanagedResourceDirectories) + def relativeMappings( - files: ScopedTaskable[Seq[File]], - dirs: ScopedTaskable[Seq[File]] + files: Taskable[Seq[File]], + dirs: Taskable[Seq[File]] ): Initialize[Task[Seq[(File, String)]]] = Def.task { val rdirs = dirs.toTask.value.toSet @@ -1340,14 +1342,27 @@ object Defaults extends BuildCommon { case _ => None } } + def collectFiles( - dirs: ScopedTaskable[Seq[File]], - filter: ScopedTaskable[FileFilter], - excludes: ScopedTaskable[FileFilter] + dirs: Taskable[Seq[File]], + filter: Taskable[FileFilter], + excludes: Taskable[FileFilter] ): Initialize[Task[Seq[File]]] = Def.task { dirs.toTask.value.descendantsExcept(filter.toTask.value, excludes.toTask.value).get } + + def relativeMappings( // forward to widened variant + files: ScopedTaskable[Seq[File]], + dirs: ScopedTaskable[Seq[File]] + ): Initialize[Task[Seq[(File, String)]]] = relativeMappings(files: Taskable[Seq[File]], dirs) + + def collectFiles( // forward to widened variant + dirs: ScopedTaskable[Seq[File]], + filter: ScopedTaskable[FileFilter], + excludes: ScopedTaskable[FileFilter] + ): Initialize[Task[Seq[File]]] = collectFiles(dirs: Taskable[Seq[File]], filter, excludes) + def artifactPathSetting(art: SettingKey[Artifact]): Initialize[File] = Def.setting { val f = artifactName.value @@ -2021,20 +2036,30 @@ object Defaults extends BuildCommon { } } } + object Classpaths { import Defaults._ import Keys._ - def concatDistinct[T]( + def concatDistinct[T](a: Taskable[Seq[T]], b: Taskable[Seq[T]]): Initialize[Task[Seq[T]]] = + Def.task((a.toTask.value ++ b.toTask.value).distinct) + + def concat[T](a: Taskable[Seq[T]], b: Taskable[Seq[T]]): Initialize[Task[Seq[T]]] = + Def.task(a.toTask.value ++ b.toTask.value) + + def concatSettings[T](a: Initialize[Seq[T]], b: Initialize[Seq[T]]): Initialize[Seq[T]] = + Def.setting { a.value ++ b.value } + + def concatDistinct[T]( // forward to widened variant a: ScopedTaskable[Seq[T]], b: ScopedTaskable[Seq[T]] - ): Initialize[Task[Seq[T]]] = Def.task { - (a.toTask.value ++ b.toTask.value).distinct - } + ): Initialize[Task[Seq[T]]] = concatDistinct(a: Taskable[Seq[T]], b) + def concat[T](a: ScopedTaskable[Seq[T]], b: ScopedTaskable[Seq[T]]): Initialize[Task[Seq[T]]] = - Def.task { a.toTask.value ++ b.toTask.value } + concat(a: Taskable[Seq[T]], b) // forward to widened variant + def concatSettings[T](a: SettingKey[Seq[T]], b: SettingKey[Seq[T]]): Initialize[Seq[T]] = - Def.setting { a.value ++ b.value } + concatSettings(a: Initialize[Seq[T]], b) // forward to widened variant lazy val configSettings: Seq[Setting[_]] = classpaths ++ Seq( products := makeProducts.value, diff --git a/main/src/test/scala/ClasspathsTest.scala b/main/src/test/scala/ClasspathsTest.scala new file mode 100644 index 000000000..c0f9fee65 --- /dev/null +++ b/main/src/test/scala/ClasspathsTest.scala @@ -0,0 +1,33 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt.test + +import sbt._ +import sbt.Classpaths._ +import sbt.Def.Initialize + +class ClasspathsTest[T]( + settKey: SettingKey[Seq[T]], + taskKey: TaskKey[Seq[T]], + initVal: Initialize[Seq[T]], +) { + + def testConcat() = { + concat(settKey, settKey) + concat(settKey, taskKey) + concat(taskKey, settKey) + concat(taskKey, taskKey) + } + + def testConcatSettings() = { + concatSettings(settKey, settKey) + concatSettings(settKey, initVal) + concatSettings(initVal, settKey) + concatSettings(initVal, initVal) + } +}