Skip to content

Commit 46d7c09

Browse files
committed
Introduce BuildInfoKey.of/ofN macros
These exist to avoid having to explain the concept of the .taskValue method and sbt.Task to users.
1 parent 81b66e7 commit 46d7c09

File tree

4 files changed

+97
-1
lines changed

4 files changed

+97
-1
lines changed

build.sbt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ lazy val root = (project in file(".")).
1212
// sbtVersion in Global := "0.13.0"
1313
// scalaVersion in Global := "2.10.2"
1414
scalacOptions := Seq("-unchecked", "-deprecation", "-feature", "-language:implicitConversions"),
15+
scalacOptions += "-language:experimental.macros",
16+
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided,
1517
description := "sbt plugin to generate build info",
1618
licenses := Seq("MIT License" -> url("https://github.com/sbt/sbt-buildinfo/blob/master/LICENSE")),
1719
scriptedLaunchOpts ++= Seq("-Xmx1024M", "-Dplugin.version=" + version.value),

src/main/scala/sbtbuildinfo/package.scala

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ package object sbtbuildinfo {
1515
BuildInfoKey.Mapped(from, fun)
1616
def action[A: Manifest](name: String)(fun: => A): Entry[A] = Action(name, () => fun)
1717

18+
def of(x: Any): BuildInfoKey = macro BuildInfoKeyMacros.ofImpl
19+
def ofN(xs: Any*): Seq[BuildInfoKey] = macro BuildInfoKeyMacros.ofNImpl
20+
1821
private[sbtbuildinfo] final case class Setting[A](scoped: SettingKey[A]) extends Entry[A] {
1922
def manifest = scoped.key.manifest
2023
}
@@ -39,4 +42,33 @@ package object sbtbuildinfo {
3942
private[sbtbuildinfo] def manifest: Manifest[A]
4043
}
4144
}
45+
46+
import scala.reflect.macros.blackbox
47+
48+
final class BuildInfoKeyMacros(val c: blackbox.Context) {
49+
import c.universe._
50+
51+
val BuildInfoKey = q"_root_.sbtbuildinfo.BuildInfoKey"
52+
53+
def ofImpl(x: Tree): Tree = {
54+
x.tpe match {
55+
case tpe if tpe <:< typeOf[SettingKey[_]] =>
56+
val A = tpe.typeArgs.head
57+
q"$BuildInfoKey.setting[$A]($x)"
58+
59+
case tpe if tpe <:< typeOf[TaskKey[_]] =>
60+
val A = tpe.typeArgs.head
61+
q"$BuildInfoKey.taskValue[$A]($x.taskValue)($x.key.manifest.typeArguments.head.asInstanceOf[Manifest[$A]])"
62+
63+
case tpe if tpe <:< typeOf[(_, _)] =>
64+
val A = tpe.typeArgs.tail.head
65+
q"$BuildInfoKey.constant[$A]($x)"
66+
67+
case tpe if tpe <:< typeOf[BuildInfoKey] => x
68+
}
69+
}
70+
71+
def ofNImpl(xs: Tree*): Tree = q"_root_.scala.Seq(..${xs map ofImpl})"
72+
73+
}
4274
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ val projInTaskGraph1 = project settings (
1919
val projInTaskGraph2 = project dependsOn projInTaskGraph1 settings (
2020
BuildInfoPlugin.buildInfoDefaultSettings,
2121
addBuildInfoToConfig(Test),
22-
buildInfoKeys in Test += (fullClasspath in Compile).taskValue
22+
buildInfoKeys in Test += BuildInfoKey.of(fullClasspath in Compile)
2323
)
2424

2525
TaskKey[Unit]("checkOutOfTaskGraph") := {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package sbtbuildinfo
2+
3+
import sbt._, Keys._
4+
import BuildInfoPlugin.autoImport._
5+
6+
object BuildInfoKeySpec {
7+
buildInfoKeys := Seq(name, version) // test `:=` works with setting keys
8+
buildInfoKeys := Seq(products, fullClasspath) // test `:=` works with task keys
9+
buildInfoKeys := Seq(name, fullClasspath) // test `:=` works with setting and task keys
10+
buildInfoKeys := Seq( // test `:=` works with misc things
11+
name,
12+
fullClasspath,
13+
"year" -> 2012,
14+
BuildInfoKey.action("buildTime") { 1234L },
15+
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble }
16+
)
17+
18+
buildInfoKeys += name // test `+=` works with a setting key
19+
buildInfoKeys += fullClasspath // test `+=` works with a task key
20+
buildInfoKeys += "year" -> 2012 // test `+=` works with constants
21+
buildInfoKeys += BuildInfoKey.action("buildTime") { 1234L } // test `+=` works with BuildInfoKey's
22+
buildInfoKeys += BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble }
23+
24+
buildInfoKeys ++= Seq(name, version) // test `++=` works with setting keys
25+
buildInfoKeys ++= Seq(fullClasspath) // test `++=` works with 1 task key
26+
buildInfoKeys ++= Seq[BuildInfoKey](products, fullClasspath) // test `++=` works with n task keys
27+
buildInfoKeys ++= Seq[BuildInfoKey](name, fullClasspath) // test `++=` works with setting and task keys
28+
buildInfoKeys ++= Seq[BuildInfoKey]( // test `++=` works with misc things
29+
name,
30+
fullClasspath,
31+
"year" -> 2012,
32+
BuildInfoKey.action("buildTime") { 1234L },
33+
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble }
34+
)
35+
36+
37+
buildInfoKeys := BuildInfoKey.ofN(name, version) // test `:=` works with setting keys
38+
buildInfoKeys := BuildInfoKey.ofN(products, fullClasspath) // test `:=` works with task keys
39+
buildInfoKeys := BuildInfoKey.ofN(name, fullClasspath) // test `:=` works with setting and task keys
40+
buildInfoKeys := BuildInfoKey.ofN( // test `:=` works with misc things
41+
name,
42+
fullClasspath,
43+
"year" -> 2012,
44+
BuildInfoKey.action("buildTime") { 1234L },
45+
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble }
46+
)
47+
48+
buildInfoKeys += BuildInfoKey.of(name) // test `+=` works with a setting key
49+
buildInfoKeys += BuildInfoKey.of(fullClasspath) // test `+=` works with a task key
50+
51+
buildInfoKeys ++= BuildInfoKey.ofN(name, version) // test `++=` works with setting keys
52+
buildInfoKeys ++= BuildInfoKey.ofN(fullClasspath) // test `++=` works with 1 task key
53+
buildInfoKeys ++= BuildInfoKey.ofN(products, fullClasspath) // test `++=` works with n task keys
54+
buildInfoKeys ++= BuildInfoKey.ofN(name, fullClasspath) // test `++=` works with setting and task keys
55+
buildInfoKeys ++= BuildInfoKey.ofN( // test `++=` works with misc things
56+
name,
57+
fullClasspath,
58+
"year" -> 2012,
59+
BuildInfoKey.action("buildTime") { 1234L },
60+
BuildInfoKey.map(version) { case (_, v) => "projectVersion" -> v.toDouble }
61+
)
62+
}

0 commit comments

Comments
 (0)