From 1dc8f54edab2b964e6e71970d56c46e5da5d7bdb Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sat, 18 Nov 2017 02:58:41 -0800 Subject: Extract out shared `Hierarchy.traverse` function for walking `Hierarchy` tree --- core/src/main/scala/mill/Main.scala | 4 +- core/src/main/scala/mill/discover/Discovered.scala | 51 ++++++---------------- core/src/main/scala/mill/discover/Mirror.scala | 43 ++++++++++++++++++ core/src/main/scala/mill/eval/Evaluator.scala | 5 +-- core/src/test/scala/mill/DiscoveredTests.scala | 6 +-- core/src/test/scala/mill/GraphTests.scala | 2 +- .../src/main/scala/mill/scalaplugin/GenIdea.scala | 18 +++----- .../main/scala/mill/scalaplugin/ScalaModule.scala | 2 +- 8 files changed, 73 insertions(+), 58 deletions(-) create mode 100644 core/src/main/scala/mill/discover/Mirror.scala diff --git a/core/src/main/scala/mill/Main.scala b/core/src/main/scala/mill/Main.scala index 857242d6..1f43a3e9 100644 --- a/core/src/main/scala/mill/Main.scala +++ b/core/src/main/scala/mill/Main.scala @@ -30,7 +30,7 @@ object Main { val mapping = Discovered.mapping(obj)(discovered) val workspacePath = pwd / 'out - def resolve[V](selector: List[String], hierarchy: Hierarchy[T, V]): Option[Task[Any]] = { + def resolve[V](selector: List[String], hierarchy: Mirror[T, V]): Option[Task[Any]] = { selector match{ case last :: Nil => @@ -49,7 +49,7 @@ object Main { .flatten } } - resolve(selector.toList, discovered.hierarchy) match{ + resolve(selector.toList, discovered.mirror) match{ case Some(target) => val evaluator = new Evaluator(workspacePath, mapping) val evaluated = evaluator.evaluate(OSet(target)) diff --git a/core/src/main/scala/mill/discover/Discovered.scala b/core/src/main/scala/mill/discover/Discovered.scala index 0108d105..f6b6a6c3 100644 --- a/core/src/main/scala/mill/discover/Discovered.scala +++ b/core/src/main/scala/mill/discover/Discovered.scala @@ -2,49 +2,23 @@ package mill.discover import mill.define.Task.Module import mill.define.{Target, Task} +import mill.discover.Mirror.LabelledTarget import mill.discover.Router.{EntryPoint, Result} import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context -class Discovered[T](val hierarchy: Hierarchy[T, _]){ - def targets(obj: T) = { - def rec[V](segmentsRev: List[String], h: Hierarchy[T, V]): Seq[Labelled[_]]= { - val self = h.targets.map(t => - t.labelled(h.node(obj), (t.label :: segmentsRev).reverse) - ) - self ++ h.children.flatMap{case (label, c) => rec(label :: segmentsRev, c)} - } - rec(Nil, hierarchy) - } - def mains = { - def rec[V](segmentsRev: List[String], h: Hierarchy[T, V]): Seq[(Seq[String], EntryPoint[_])]= { - h.commands.map((segmentsRev.reverse, _)) ++ - h.children.flatMap{case (label, c) => rec(label :: segmentsRev, c)} - } - rec(Nil, hierarchy) - } -} -case class Hierarchy[T, V](node: T => V, - commands: Seq[EntryPoint[V]], - targets: Seq[TargetInfo[V, _]], - children: List[(String, Hierarchy[T, _])]) +class Discovered[T](val mirror: Mirror[T, T]){ -case class Labelled[T](target: Task[T], - format: upickle.default.ReadWriter[T], - segments: Seq[String]) + def targets(obj: T) = Mirror.traverse(mirror) { (h, p) => + h.labelled(obj, p) + } -case class TargetInfo[T, V](label: String, - format: upickle.default.ReadWriter[V], - run: T => Task[V]) { - def labelled(t: T, segments: Seq[String]) = Labelled(run(t), format, segments) -} -object TargetInfo{ - def make[T, V](label: String, func: T => Task[V]) - (implicit f: upickle.default.ReadWriter[V]) = { - TargetInfo(label, f, func) + def mains = Mirror.traverse(mirror) { (h, p) => + h.commands.map(x => (p, x: EntryPoint[_])) } + } object Discovered { @@ -58,7 +32,7 @@ object Discovered { - def mapping[T: Discovered](t: T): Map[Task[_], Labelled[_]] = { + def mapping[T: Discovered](t: T): Map[Task[_], LabelledTarget[_]] = { implicitly[Discovered[T]].targets(t).map(x => x.target -> x).toMap } @@ -82,7 +56,10 @@ object Discovered { !m.name.toString.contains(' ') } yield { val x = Ident(TermName(c.freshName())) - q"mill.discover.TargetInfo.make(${m.name.toString}, ($x: ${m.typeSignature.resultType}) => $x.${m.name.toTermName})" + q"""mill.discover.Mirror.makeTargetPoint( + ${m.name.toString}, + ($x: ${m.typeSignature.resultType}) => $x.${m.name.toTermName} + )""" } @@ -108,7 +85,7 @@ object Discovered { .asInstanceOf[Seq[c.Tree]] .toList - q"""mill.discover.Hierarchy[$tpe, $t]( + q"""mill.discover.Mirror[$tpe, $t]( $hierarchySelector, $commands, $targets, diff --git a/core/src/main/scala/mill/discover/Mirror.scala b/core/src/main/scala/mill/discover/Mirror.scala new file mode 100644 index 00000000..3cfc0962 --- /dev/null +++ b/core/src/main/scala/mill/discover/Mirror.scala @@ -0,0 +1,43 @@ +package mill.discover + +import mill.define.Task +import mill.discover.Router.EntryPoint + +import scala.language.experimental.macros + + +case class Mirror[-T, V](node: T => V, + commands: Seq[EntryPoint[V]], + targets: Seq[Mirror.TargetPoint[V, _]], + children: List[(String, Mirror[T, _])]){ + def labelled(obj: T, p: Seq[String]) = { + targets.map(t => t.labelled(node(obj), p)) + } +} + +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]= { + val self = f(h, segmentsRev) + self ++ h.children.flatMap{case (label, c) => rec(label :: segmentsRev, c)} + } + rec(Nil, hierarchy) + } + + + case class LabelledTarget[T](target: Task[T], + format: upickle.default.ReadWriter[T], + segments: Seq[String]) + + case class TargetPoint[T, V](label: String, + format: upickle.default.ReadWriter[V], + run: T => Task[V]) { + def labelled(t: T, segments: Seq[String]) = LabelledTarget(run(t), format, segments :+ label) + } + + def makeTargetPoint[T, V](label: String, func: T => Task[V]) + (implicit f: upickle.default.ReadWriter[V]) = { + TargetPoint(label, f, func) + } +} diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala index 74cb77d3..22861847 100644 --- a/core/src/main/scala/mill/eval/Evaluator.scala +++ b/core/src/main/scala/mill/eval/Evaluator.scala @@ -2,13 +2,12 @@ package mill.eval import ammonite.ops._ import mill.define.Task -import mill.discover.Labelled +import mill.discover.Mirror.LabelledTarget import mill.util.{Args, MultiBiMap, OSet} - import scala.collection.mutable class Evaluator(workspacePath: Path, - labeling: Map[Task[_], Labelled[_]]){ + labeling: Map[Task[_], LabelledTarget[_]]){ def evaluate(goals: OSet[Task[_]]): Evaluator.Results = { mkdir(workspacePath) diff --git a/core/src/test/scala/mill/DiscoveredTests.scala b/core/src/test/scala/mill/DiscoveredTests.scala index 87d2e340..1a0893df 100644 --- a/core/src/test/scala/mill/DiscoveredTests.scala +++ b/core/src/test/scala/mill/DiscoveredTests.scala @@ -3,7 +3,7 @@ package mill import utest._ import TestUtil.test import mill.define.Task.Module -import mill.discover.{Discovered, Hierarchy} +import mill.discover.{Discovered, Mirror} object DiscoveredTests extends TestSuite{ @@ -29,10 +29,10 @@ object DiscoveredTests extends TestSuite{ val discovered = Discovered[outer.type] - def flatten(h: Hierarchy[outer.type, _]): Seq[Any] = { + def flatten(h: Mirror[outer.type, _]): Seq[Any] = { h.node(outer) :: h.children.flatMap{case (label, c) => flatten(c)} } - val flattenedHierarchy = flatten(discovered.hierarchy) + val flattenedHierarchy = flatten(discovered.mirror) val expectedHierarchy = Seq( outer, diff --git a/core/src/test/scala/mill/GraphTests.scala b/core/src/test/scala/mill/GraphTests.scala index 7d4caaac..d19b747d 100644 --- a/core/src/test/scala/mill/GraphTests.scala +++ b/core/src/test/scala/mill/GraphTests.scala @@ -4,7 +4,7 @@ import utest._ import TestUtil.test import mill.define.Task import mill.define.Task.Module -import mill.discover.{Discovered, Hierarchy} +import mill.discover.{Discovered, Mirror} import mill.eval.Evaluator import mill.util.OSet diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala b/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala index a2f6a8b1..9b120c7e 100644 --- a/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala +++ b/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala @@ -1,7 +1,7 @@ package mill.scalaplugin import ammonite.ops._ -import mill.discover.{Discovered, Hierarchy} +import mill.discover.{Discovered, Mirror} import mill.eval.{Evaluator, PathRef} import mill.util.OSet @@ -19,20 +19,16 @@ object GenIdea { def xmlFileLayout[T: Discovered](obj: T): Seq[(RelPath, scala.xml.Node)] = { val discovered = implicitly[Discovered[T]] - def rec(x: Hierarchy[T]): Seq[(Seq[String], ScalaModule)] = { - val node = x.node(obj) - val self = node match{ - case m: ScalaModule => Seq(x.path -> m) - case _ => Nil - } - - self ++ x.children.flatMap(rec) - } val mapping = Discovered.mapping(obj)(discovered) val workspacePath = pwd / 'out val evaluator = new Evaluator(workspacePath, mapping) - val modules = rec(discovered.hierarchy) + val modules = Mirror.traverse(discovered.mirror){ (h, p) => + h.node(obj) match { + case m: ScalaModule => Seq(p -> m) + case _ => Nil + } + } val resolved = for((path, mod) <- modules) yield { val Seq(resolvedCp: Seq[PathRef], resolvedSrcs: Seq[PathRef]) = evaluator.evaluate(OSet(mod.externalCompileDepClasspath, mod.externalCompileDepSources)) diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala index f5c895bb..a99cf71b 100644 --- a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala +++ b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala @@ -7,7 +7,7 @@ import ammonite.ops._ import coursier.{Cache, Fetch, MavenRepository, Repository, Resolution} import mill.define.Task import mill.define.Task.Module -import mill.discover.{Discovered, Hierarchy} +import mill.discover.{Discovered, Mirror} import mill.eval.{Evaluator, PathRef} import mill.modules.Jvm.{createJar, createAssembly} import mill.util.OSet -- cgit v1.2.3