summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-11-22 20:41:35 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-11-22 20:41:35 -0800
commit3a87314737bea39b5d194ad2a9e7a88085011755 (patch)
tree26efb3ae3326df423376c675913a3a5bed359103 /core
parentc73413a6ce30ba78f6dd34081bdd3d9bb8f2099d (diff)
downloadmill-3a87314737bea39b5d194ad2a9e7a88085011755.tar.gz
mill-3a87314737bea39b5d194ad2a9e7a88085011755.tar.bz2
mill-3a87314737bea39b5d194ad2a9e7a88085011755.zip
Targets living in cross modules can now be properly discovered, run and cached.
Try out the following commands on our Mill `build.sc` file to exercise this functionality - `scalaplugin/target/mill run Core.cross[jarA].jar` - `scalaplugin/target/mill run Core.cross[jarB].jar` - `scalaplugin/target/mill run Core.cross[jarC].jar`
Diffstat (limited to 'core')
-rw-r--r--core/src/main/scala/mill/discover/Discovered.scala19
-rw-r--r--core/src/main/scala/mill/discover/Mirror.scala34
-rw-r--r--core/src/main/scala/mill/eval/Evaluator.scala16
-rw-r--r--core/src/test/scala/mill/discover/ConsistencyTests.scala8
-rw-r--r--core/src/test/scala/mill/discover/CrossModuleTests.scala55
-rw-r--r--core/src/test/scala/mill/discover/DiscoveredTests.scala9
-rw-r--r--core/src/test/scala/mill/discover/LabelingTests.scala6
7 files changed, 109 insertions, 38 deletions
diff --git a/core/src/main/scala/mill/discover/Discovered.scala b/core/src/main/scala/mill/discover/Discovered.scala
index 21669fbb..4b4fab50 100644
--- a/core/src/main/scala/mill/discover/Discovered.scala
+++ b/core/src/main/scala/mill/discover/Discovered.scala
@@ -12,17 +12,15 @@ import scala.reflect.macros.blackbox.Context
* Allows you to implicitly summon up a build [[Mirror]] for arbitrary types
*/
class Discovered[T](val mirror: Mirror[T, T]){
-
- def targets(obj: T, crosses: List[List[Any]]) = Mirror.traverse(mirror) { (h, p) =>
- h.labelled(obj, p, crosses)
+ def targets(obj: T) = Mirror.traverse(obj, mirror) { (h, p) =>
+ h.labelled(obj, p)
}
-
}
object Discovered {
def consistencyCheck[T](base: T, d: Discovered[T]) = {
val inconsistent = for{
- (t1, t2) <- d.targets(base, Nil).zip(d.targets(base, Nil))
+ (t1, t2) <- d.targets(base).zip(d.targets(base))
if t1.target ne t2.target
} yield t1.segments
inconsistent
@@ -30,7 +28,7 @@ object Discovered {
def mapping[T: Discovered](t: T): Map[Target[_], LabelledTarget[_]] = {
- implicitly[Discovered[T]].targets(t, Nil).map(x => x.target -> x).toMap
+ implicitly[Discovered[T]].targets(t).map(x => x.target -> x).toMap
}
implicit def apply[T]: Discovered[T] = macro applyImpl[T]
@@ -79,13 +77,14 @@ object Discovered {
q"($name, ${rec(Some(name) :: segments, m.typeSignature)})"
}
+ val crossName = q"${TermName(c.freshName())}"
val hierarchySelector = {
val base = q"${TermName(c.freshName())}"
- val ident = segments.reverse.foldLeft[Tree](base) {
- case (prefix, Some(name)) => q"$prefix.${TermName(name)}"
- case (prefix, None) => q"$prefix.apply(crosses.head)"
+ val ident = segments.zipWithIndex.reverse.foldLeft[Tree](base) {
+ case (prefix, (Some(name), i)) => q"$prefix.${TermName(name)}"
+ case (prefix, (None, i)) => q"$prefix.apply($crossName($i))"
}
- q"($base: $tpe, crosses: List[List[Any]]) => $ident"
+ q"($base: $tpe, $crossName: List[List[Any]]) => $ident"
}
val commands =
diff --git a/core/src/main/scala/mill/discover/Mirror.scala b/core/src/main/scala/mill/discover/Mirror.scala
index bea2d8e3..962c156b 100644
--- a/core/src/main/scala/mill/discover/Mirror.scala
+++ b/core/src/main/scala/mill/discover/Mirror.scala
@@ -18,19 +18,31 @@ case class Mirror[-T, V](node: (T, List[List[Any]]) => V,
targets: Seq[Mirror.TargetPoint[V, _]],
children: List[(String, Mirror[T, _])],
crossChildren: Option[(V => List[List[Any]], Mirror[T, _])]){
- def labelled(obj: T,
- p: Seq[String],
- crosses: List[List[Any]]) = {
- targets.map(t => t.labelled(node(obj, crosses), p))
+ def labelled(obj: T, p: Seq[Mirror.Segment]) = {
+ val crossValues = p.map{case Mirror.Segment.Cross(vs) => vs case _ => Nil}.toList
+ targets.map(t => t.labelled(node(obj, crossValues), p.reverse))
}
}
object Mirror{
- def traverse[T, V, R](hierarchy: Mirror[T, V])
- (f: (Mirror[T, _], => Seq[String]) => Seq[R]): Seq[R] = {
- def rec[C](segmentsRev: List[String], h: Mirror[T, C]): Seq[R]= {
+ sealed trait Segment
+ object Segment{
+ case class Label(value: String) extends Segment
+ case class Cross(value: List[Any]) extends Segment
+ }
+ def traverse[T, V, R](t: T, hierarchy: Mirror[T, V])
+ (f: (Mirror[T, _], => Seq[Segment]) => Seq[R]): Seq[R] = {
+ def rec[C](segmentsRev: List[Segment], h: Mirror[T, C]): Seq[R]= {
+ val crossValues = segmentsRev.map{case Segment.Cross(vs) => vs case _ => Nil}
val self = f(h, segmentsRev)
- self ++ h.children.flatMap{case (label, c) => rec(label :: segmentsRev, c)}
+ self ++
+ h.children.flatMap{case (label, c) => rec(Segment.Label(label) :: segmentsRev, c)} ++
+ h.crossChildren.toSeq.flatMap{
+ case (crossGen, c) =>
+ crossGen(h.node(t, crossValues)).flatMap(cross =>
+ rec(Segment.Cross(cross) :: segmentsRev, c)
+ )
+ }
}
rec(Nil, hierarchy)
}
@@ -40,7 +52,7 @@ object Mirror{
*/
case class LabelledTarget[V](target: Target[V],
format: upickle.default.ReadWriter[V],
- segments: Seq[String])
+ segments: Seq[Segment])
/**
* Represents metadata about a particular target, before the target is
@@ -49,7 +61,9 @@ object Mirror{
case class TargetPoint[T, V](label: String,
format: upickle.default.ReadWriter[V],
run: T => Target[V]) {
- def labelled(t: T, segments: Seq[String]) = LabelledTarget(run(t), format, segments :+ label)
+ def labelled(t: T, segments: Seq[Segment]) = {
+ LabelledTarget(run(t), format, segments :+ Segment.Label(label))
+ }
}
def makeTargetPoint[T, V](label: String, func: T => Target[V])
diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala
index a36129a5..f91a1e8c 100644
--- a/core/src/main/scala/mill/eval/Evaluator.scala
+++ b/core/src/main/scala/mill/eval/Evaluator.scala
@@ -2,6 +2,7 @@ package mill.eval
import ammonite.ops._
import mill.define.{Graph, Target, Task}
+import mill.discover.Mirror
import mill.discover.Mirror.LabelledTarget
import mill.util
import mill.util.{Args, MultiBiMap, OSet}
@@ -45,7 +46,11 @@ class Evaluator(workspacePath: Path,
}
def resolveDestPaths(t: LabelledTarget[_]): (Path, Path) = {
- val targetDestPath = workspacePath / t.segments
+ val segmentStrings = t.segments.flatMap{
+ case Mirror.Segment.Label(s) => Seq(s)
+ case Mirror.Segment.Cross(values) => values.map(_.toString)
+ }
+ val targetDestPath = workspacePath / segmentStrings
val metadataPath = targetDestPath / up / (targetDestPath.last + ".mill.json")
(targetDestPath, metadataPath)
}
@@ -79,7 +84,14 @@ class Evaluator(workspacePath: Path,
case _ =>
- log("Running " + labelledTarget.segments.mkString("."))
+ pprint.log(labelledTarget.segments)
+ val Seq(first, rest @_*) = labelledTarget.segments
+ val msgParts = Seq(first.asInstanceOf[Mirror.Segment.Label].value) ++ rest.map{
+ case Mirror.Segment.Label(s) => "." + s
+ case Mirror.Segment.Cross(s) => "[" + s.mkString(",") + "]"
+ }
+
+ log("Running " + msgParts.mkString)
if (labelledTarget.target.flushDest) rm(destPath)
val (newResults, newEvaluated) = evaluateGroup(group, results, Some(destPath))
diff --git a/core/src/test/scala/mill/discover/ConsistencyTests.scala b/core/src/test/scala/mill/discover/ConsistencyTests.scala
index 67e22595..0591d5fc 100644
--- a/core/src/test/scala/mill/discover/ConsistencyTests.scala
+++ b/core/src/test/scala/mill/discover/ConsistencyTests.scala
@@ -1,6 +1,7 @@
package mill.discover
+import mill.discover.Mirror.Segment.Label
import mill.util.TestGraphs
import utest._
@@ -15,7 +16,12 @@ object ConsistencyTests extends TestSuite{
//
// Maybe later we can convert them into compile errors somehow
- val expected = List(List("down"), List("right"), List("left"), List("up"))
+ val expected = List(
+ List(Label("down")),
+ List(Label("right")),
+ List(Label("left")),
+ List(Label("up"))
+ )
'diamond - {
val inconsistent = Discovered.consistencyCheck(
diff --git a/core/src/test/scala/mill/discover/CrossModuleTests.scala b/core/src/test/scala/mill/discover/CrossModuleTests.scala
index c4e075da..8d8a86f6 100644
--- a/core/src/test/scala/mill/discover/CrossModuleTests.scala
+++ b/core/src/test/scala/mill/discover/CrossModuleTests.scala
@@ -2,6 +2,8 @@ package mill.discover
import mill.{Module, T}
import mill.define.Cross
+import mill.discover.Mirror.{LabelledTarget, Segment}
+import mill.discover.Mirror.Segment.Label
import utest._
object CrossModuleTests extends TestSuite{
@@ -17,7 +19,9 @@ object CrossModuleTests extends TestSuite{
}
}
- val Some((gen, innerMirror)) = Discovered[outer.type]
+ val discovered = Discovered[outer.type]
+
+ val Some((gen, innerMirror)) = discovered
.mirror
.children
.head._2
@@ -68,14 +72,49 @@ object CrossModuleTests extends TestSuite{
assert(suffix == expected)
}
}
- 'crossCommands - {
- object outer {
- val cross = for (c <- mill.define.Cross("a", "b", "c")) yield new mill.Module {
- def printIt() = T.command {
- println("PRINTING IT: " + c)
- }
- }
+ 'crossTargetDiscovery - {
+ object outer{
+ val crossed =
+ for(n <- Cross("2.10.6", "2.11.8", "2.12.4"))
+ yield new Module{ def scalaVersion = T{ n } }
}
+ val discovered = Discovered[outer.type]
+
+ val segments = discovered.targets(outer).map(_.segments)
+ val expectedSegments = List(
+ List(Label("crossed"), Segment.Cross(List("2.10.6")), Label("scalaVersion")),
+ List(Label("crossed"), Segment.Cross(List("2.11.8")), Label("scalaVersion")),
+ List(Label("crossed"), Segment.Cross(List("2.12.4")), Label("scalaVersion"))
+ )
+ assert(segments == expectedSegments)
+ val targets = discovered.targets(outer).map(_.target)
+ val expected = List(
+ outer.crossed(List("2.10.6")).scalaVersion,
+ outer.crossed(List("2.11.8")).scalaVersion,
+ outer.crossed(List("2.12.4")).scalaVersion
+ )
+ assert(targets == expected)
+
+ }
+ 'doubleCrossTargetDiscovery - {
+ object outer{
+ val crossed =
+ for{
+ n <- Cross("2.11.8", "2.12.4")
+ platform <- Cross("sjs0.6", "native0.3")
+ } yield new Module{ def suffix = T{ n + "_" + platform } }
+ }
+ val discovered = Discovered[outer.type]
+ val targets = discovered.targets(outer).map(_.target)
+
+ val expected = List(
+ outer.crossed(List("sjs0.6", "2.11.8")).suffix,
+ outer.crossed(List("native0.3", "2.11.8")).suffix,
+ outer.crossed(List("sjs0.6", "2.12.4")).suffix,
+ outer.crossed(List("native0.3", "2.12.4")).suffix
+ )
+ assert(targets == expected)
+
}
}
}
diff --git a/core/src/test/scala/mill/discover/DiscoveredTests.scala b/core/src/test/scala/mill/discover/DiscoveredTests.scala
index b09ff2de..7fa030eb 100644
--- a/core/src/test/scala/mill/discover/DiscoveredTests.scala
+++ b/core/src/test/scala/mill/discover/DiscoveredTests.scala
@@ -6,6 +6,7 @@ import mill.discover.Router.{ArgSig, EntryPoint}
import utest._
import mill.{Module, T}
import mill.util.TestUtil.test
+import mill.discover.Mirror.Segment.Label
object DiscoveredTests extends TestSuite{
val tests = Tests{
@@ -44,12 +45,12 @@ object DiscoveredTests extends TestSuite{
)
assert(flattenedHierarchy == expectedHierarchy)
- val mapped = discovered.targets(outer, Nil).map(x => x.segments -> x.target)
+ val mapped = discovered.targets(outer).map(x => x.segments -> x.target)
val expected = Seq(
- (List("classInstance", "single"), outer.classInstance.single),
- (List("nested", "single"), outer.nested.single),
- (List("single"), outer.single)
+ (List(Label("classInstance"), Label("single")), outer.classInstance.single),
+ (List(Label("nested"), Label("single")), outer.nested.single),
+ (List(Label("single")), outer.single)
)
assert(mapped.toSet == expected.toSet)
}
diff --git a/core/src/test/scala/mill/discover/LabelingTests.scala b/core/src/test/scala/mill/discover/LabelingTests.scala
index a37c090c..94d91cda 100644
--- a/core/src/test/scala/mill/discover/LabelingTests.scala
+++ b/core/src/test/scala/mill/discover/LabelingTests.scala
@@ -3,7 +3,7 @@ package mill.discover
import mill.define.Task
import mill.util.TestGraphs
import utest._
-
+import mill.discover.Mirror.Segment.Label
object LabelingTests extends TestSuite{
val tests = Tests{
@@ -15,10 +15,10 @@ object LabelingTests extends TestSuite{
def check[T: Discovered](base: T, t: Task[_], relPath: Option[String]) = {
- val names: Seq[(Task[_], Seq[String])] = Discovered.mapping(base).mapValues(_.segments).toSeq
+ val names: Seq[(Task[_], Seq[Mirror.Segment])] = Discovered.mapping(base).mapValues(_.segments).toSeq
val nameMap = names.toMap
- val targetLabel = nameMap.get(t).map(_.mkString("."))
+ val targetLabel = nameMap.get(t).map(_.map{case Label(v) => v}.mkString("."))
assert(targetLabel == relPath)
}
'singleton - check(singleton, singleton.single, Some("single"))