Skip to content

Commit 3028abc

Browse files
authored
Merge pull request #119 from dwijnand/macro-implicit-conv
Implicit convert TaskKey with the macro!
2 parents 3bd8f86 + c47a72b commit 3028abc

File tree

8 files changed

+72
-20
lines changed

8 files changed

+72
-20
lines changed

README.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Add the following in your `build.sbt`:
2828
lazy val root = (project in file(".")).
2929
enablePlugins(BuildInfoPlugin).
3030
settings(
31-
buildInfoKeys := BuildInfoKey.ofN(name, version, scalaVersion, sbtVersion),
31+
buildInfoKeys := Seq[BuildInfoKey](name, version, scalaVersion, sbtVersion),
3232
buildInfoPackage := "hello"
3333
)
3434
```

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
lazy val commonSettings: Seq[Setting[_]] = Seq(
2-
git.baseVersion in ThisBuild := "0.8.0",
2+
git.baseVersion in ThisBuild := "0.9.0",
33
organization in ThisBuild := "com.eed3si9n"
44
)
55

notes/0.9.0.markdown

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
[@dwijnand]: https://github.com/dwijnand
2+
3+
sbt-buildinfo 0.9.0 is published for sbt 1.
4+
5+
### `TaskKey` to `BuildInfoKey` conversion potentially breaking semantic change
6+
7+
*TL;DR* No need for `BuildInfoKey.of(...)` or `BuildInfoKey.ofN(...)` any more. Use
8+
`BuildInfoKey.outOfGraphUnsafe` if your build definition is now circular.
9+
10+
sbt-buildinfo 0.8.0 deprecated the original `TaskKey[A]` to `BuildInfoKey.Entry[A]` implicit and explicit
11+
conversions (`BuildInfoKey.task` and `BuildInfoKey.apply` respectively), that executed the underlying sbt Task
12+
out of sbt's task graph execution, in favour of a newly introduced `BuildInfoKey.of(...)` and
13+
`BuildInfoKey.ofN(...)` API, which correctly wired up the task graph. See [#114][].
14+
15+
As it was implemented (and released) it interacted poorly with sbt-buildinfo's `BuildInfoKey.map` API
16+
([#117][]), due to a mistake in the implementation and test coverage.
17+
18+
In resolving the issue it became clear that instead of introducing a new API, that required sbt-buildinfo users
19+
to change their source code to use, the already used conversions could have been modified to use the new
20+
Task-based semantics.
21+
22+
However, this change breaks any build definition that declares as a build info key any `TaskKey` that depends on
23+
`sourceGenerators` or `resourceGenerators`, because the build definiton would now be circular and fail to load.
24+
To fix this breaking semantic change the user has to either drop the key used, choose another key, or fallback
25+
to the previous semantics by using the not-deprecated `BuildInfoKey.outOfGraphUnsafe` API, also introduced in
26+
sbt-buildinfo 0.8.0.
27+
28+
[#117][]/[#119][] by [@dwijnand][]
29+
30+
[#114]: https://github.com/sbt/sbt-buildinfo/pull/114
31+
[#117]: https://github.com/sbt/sbt-buildinfo/issues/117
32+
[#119]: https://github.com/sbt/sbt-buildinfo/pull/119
33+
34+
### Add direct support for sbt's `Attributed`
35+
36+
A number of keys defined by sbt use sbt's `Attributed` type, specifically the keys that define classpaths.
37+
Prior to this change defining any of these keys as a build info key would generate `Seq[String]` as `Attributed`
38+
would be simply converted to string with `toString`. sbt-buildinfo 0.9.0 introduces direct support for these
39+
keys so they generate `Seq[File]` instead.
40+
41+
[#112][]/[#120][] by [@dwijnand][]
42+
43+
[#112]: https://github.com/sbt/sbt-buildinfo/issues/112
44+
[#120]: https://github.com/sbt/sbt-buildinfo/pull/120

src/main/scala/sbtbuildinfo/package.scala

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,19 @@ package object sbtbuildinfo {
44
type BuildInfoKey = BuildInfoKey.Entry[_]
55
object BuildInfoKey {
66
implicit def setting[A](key: SettingKey[A]): Entry[A] = Setting(key)
7-
@deprecated("Explicitly wrap in BuildInfoKey.of/ofN. Or if out-of-graph execution is required use BuildInfoKey.outOfGraphUnsafe", "0.7.1")
8-
implicit def task[A](key: TaskKey[A]): Entry[A] = Task(key)
7+
implicit def task[A](key: TaskKey[A]): Entry[A] = macro BuildInfoKeyMacros.taskImpl
98
implicit def taskValue[A: Manifest](task: sbt.Task[A]): Entry[A] = TaskValue(task)
109
implicit def constant[A: Manifest](tuple: (String, A)): Entry[A] = Constant(tuple)
1110

1211
def apply[A](key: SettingKey[A]): Entry[A] = Setting(key)
13-
@deprecated("Explicitly wrap in BuildInfoKey.of/ofN. Or if out-of-graph execution is required use BuildInfoKey.outOfGraphUnsafe", "0.7.1")
14-
def apply[A](key: TaskKey[A]): Entry[A] = Task(key)
12+
def apply[A](key: TaskKey[A]): Entry[A] = macro BuildInfoKeyMacros.taskImpl
1513
def apply[A: Manifest](tuple: (String, A)): Entry[A] = Constant(tuple)
1614
def map[A, B: Manifest](from: Entry[A])(fun: ((String, A)) => (String, B)): Entry[B] =
1715
BuildInfoKey.Mapped(from, fun)
1816
def action[A: Manifest](name: String)(fun: => A): Entry[A] = Action(name, () => fun)
1917

20-
def of(x: Any): BuildInfoKey = macro BuildInfoKeyMacros.ofImpl
21-
def ofN(xs: Any*): Seq[BuildInfoKey] = macro BuildInfoKeyMacros.ofNImpl
18+
def of[A](x: BuildInfoKey.Entry[A]): BuildInfoKey.Entry[A] = x
19+
def ofN(xs: BuildInfoKey*): Seq[BuildInfoKey] = xs
2220

2321
def outOfGraphUnsafe[A](key: TaskKey[A]): Entry[A] = Task(key)
2422

@@ -54,6 +52,12 @@ package object sbtbuildinfo {
5452

5553
val BuildInfoKey = q"_root_.sbtbuildinfo.BuildInfoKey"
5654

55+
def taskImpl(key: Tree): Tree = {
56+
val A = key.tpe.typeArgs.head
57+
q"$BuildInfoKey.taskValue[$A]($key.taskValue)($key.key.manifest.typeArguments.head.asInstanceOf[Manifest[$A]])"
58+
}
59+
60+
@deprecated("No longer used", "0.9.0")
5761
def ofImpl(x: Tree): Tree = {
5862
x.tpe match {
5963
case tpe if tpe <:< typeOf[SettingKey[_]] =>
@@ -72,6 +76,7 @@ package object sbtbuildinfo {
7276
}
7377
}
7478

79+
@deprecated("No longer used", "0.9.0")
7580
def ofNImpl(xs: Tree*): Tree = q"_root_.scala.Seq(..${xs map ofImpl})"
7681

7782
}

src/sbt-test/sbt-buildinfo/simple/build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ lazy val root = (project in file(".")).
4040
""" /** The value is "helloworld". */"""::
4141
""" val name: String = "helloworld"""" ::
4242
""" /** The value is 0.1. */"""::
43-
""" val projectVersion: scala.Double = 0.1""" ::
43+
""" val projectVersion = 0.1""" ::
4444
""" /** The value is "2.11.8". */""" ::
4545
""" val scalaVersion: String = "2.11.8"""" ::
4646
""" /** The value is scala.collection.Seq(). */""" ::

src/sbt-test/sbt-buildinfo/task/build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ val projOutOfTaskGraph1 = project settings (
99
val projOutOfTaskGraph2 = project dependsOn projOutOfTaskGraph1 settings (
1010
BuildInfoPlugin.buildInfoDefaultSettings,
1111
addBuildInfoToConfig(Test),
12-
buildInfoKeys in Test += fullClasspath in Compile // intentionally uses the deprecated implicit conversion
12+
buildInfoKeys in Test += BuildInfoKey.outOfGraphUnsafe(fullClasspath in Compile),
1313
)
1414

1515
val projInTaskGraph1 = project settings (

src/sbt-test/sbt-buildinfo/usepackageaspath/build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ lazy val root = (project in file(".")).
3737
""" /** The value is "helloworld". */"""::
3838
""" val name: String = "helloworld"""" ::
3939
""" /** The value is 0.1. */"""::
40-
""" val projectVersion: scala.Double = 0.1""" ::
40+
""" val projectVersion = 0.1""" ::
4141
""" /** The value is "2.10.2". */""" ::
4242
""" val scalaVersion: String = "2.10.2"""" ::
4343
""" /** The value is scala.collection.Seq(). */""" ::

src/test/scala/sbtbuildinfo/BuildInfoKeySpec.scala

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ package sbtbuildinfo
33
import sbt._, Keys._
44
import BuildInfoPlugin.autoImport._
55

6+
/** This is a compile-only test of the BuildInfoKey syntax/macros. */
67
object BuildInfoKeySpec {
7-
// duplicate the out of box implicit so we don't get deprecation warnings in this testing code
8-
implicit def task[A](key: TaskKey[A]): BuildInfoKey.Entry[A] = BuildInfoKey.Task(key)
9-
108
buildInfoKeys := Seq(name, version) // test `:=` works with setting keys
119
buildInfoKeys := Seq(products, fullClasspath) // test `:=` works with task keys
1210
buildInfoKeys := Seq(name, fullClasspath) // test `:=` works with setting and task keys
@@ -15,25 +13,28 @@ object BuildInfoKeySpec {
1513
fullClasspath,
1614
"year" -> 2012,
1715
BuildInfoKey.action("buildTime") { 1234L },
18-
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble }
16+
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble },
17+
BuildInfoKey.map(fullClasspath) { case (ident, cp) => ident -> cp.files },
1918
)
2019

2120
buildInfoKeys += name // test `+=` works with a setting key
22-
buildInfoKeys += fullClasspath // test `+=` works with a task key
21+
//buildInfoKeys += fullClasspath // test `+=` works with a task key
22+
buildInfoKeys += (fullClasspath: BuildInfoKey) // test `+=` works with a task key
2323
buildInfoKeys += "year" -> 2012 // test `+=` works with constants
2424
buildInfoKeys += BuildInfoKey.action("buildTime") { 1234L } // test `+=` works with BuildInfoKey's
2525
buildInfoKeys += BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble }
2626

2727
buildInfoKeys ++= Seq(name, version) // test `++=` works with setting keys
28-
buildInfoKeys ++= Seq(fullClasspath) // test `++=` works with 1 task key
28+
buildInfoKeys ++= Seq[BuildInfoKey](fullClasspath) // test `++=` works with 1 task key
2929
buildInfoKeys ++= Seq[BuildInfoKey](products, fullClasspath) // test `++=` works with n task keys
3030
buildInfoKeys ++= Seq[BuildInfoKey](name, fullClasspath) // test `++=` works with setting and task keys
3131
buildInfoKeys ++= Seq[BuildInfoKey]( // test `++=` works with misc things
3232
name,
3333
fullClasspath,
3434
"year" -> 2012,
3535
BuildInfoKey.action("buildTime") { 1234L },
36-
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble }
36+
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble },
37+
BuildInfoKey.map(fullClasspath) { case (ident, cp) => ident -> cp.files },
3738
)
3839

3940

@@ -45,7 +46,8 @@ object BuildInfoKeySpec {
4546
fullClasspath,
4647
"year" -> 2012,
4748
BuildInfoKey.action("buildTime") { 1234L },
48-
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble }
49+
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble },
50+
BuildInfoKey.map(fullClasspath) { case (ident, cp) => ident -> cp.files },
4951
)
5052

5153
buildInfoKeys += BuildInfoKey.of(name) // test `+=` works with a setting key
@@ -60,6 +62,7 @@ object BuildInfoKeySpec {
6062
fullClasspath,
6163
"year" -> 2012,
6264
BuildInfoKey.action("buildTime") { 1234L },
63-
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble }
65+
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble },
66+
BuildInfoKey.map(fullClasspath) { case (ident, cp) => ident -> cp.files },
6467
)
6568
}

0 commit comments

Comments
 (0)