From 4fd5f8cdfdc924bff2f4fbc6b5d7072d530fa531 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sun, 7 Jan 2018 22:38:17 -0800 Subject: Generate the `Segments` list at definition time rather than discovery time, by propagating implicits throughout the tree of nested `mill.Module`s This currently adds some annoying boilerplate to the definition of cross/abstract modules, which can probably be removed using Macros. The `Segments` mapping generated by discovery is still present and used in a few places, though it will be removed --- core/src/main/scala/mill/define/Cross.scala | 57 +++++- core/src/main/scala/mill/define/Module.scala | 59 ++++-- core/src/main/scala/mill/define/Task.scala | 201 +++++---------------- core/src/main/scala/mill/discover/Discovered.scala | 11 +- core/src/main/scala/mill/discover/Mirror.scala | 16 +- core/src/main/scala/mill/eval/Evaluator.scala | 25 ++- .../main/scala/mill/main/ReplApplyHandler.scala | 6 +- core/src/main/scala/mill/main/Resolve.scala | 18 +- core/src/main/scala/mill/main/RunScript.scala | 22 ++- core/src/test/scala/mill/define/GraphTests.scala | 2 +- .../test/scala/mill/define/MacroErrorTests.scala | 8 +- .../scala/mill/discover/ConsistencyTests.scala | 2 +- .../scala/mill/discover/CrossModuleTests.scala | 8 +- .../test/scala/mill/discover/DiscoveredTests.scala | 2 +- .../test/scala/mill/discover/LabelingTests.scala | 6 +- core/src/test/scala/mill/main/MainTests.scala | 4 +- core/src/test/scala/mill/util/TestGraphs.scala | 12 +- core/src/test/scala/mill/util/TestUtil.scala | 28 +-- 18 files changed, 217 insertions(+), 270 deletions(-) (limited to 'core') diff --git a/core/src/main/scala/mill/define/Cross.scala b/core/src/main/scala/mill/define/Cross.scala index 26eef933..4d68ee62 100644 --- a/core/src/main/scala/mill/define/Cross.scala +++ b/core/src/main/scala/mill/define/Cross.scala @@ -26,14 +26,53 @@ object Cross{ def apply[T](t: T*) = new Cross(t.map(i => List(i) -> i).toList) } -class CrossModule[T, V](constructor: T => V, cases: T*) - (implicit e: sourcecode.Enclosing, l: sourcecode.Line) -extends Cross[V](cases.toList.map(x => (List(x), constructor(x)))) +class CrossModule[T, V](constructor: (T, Module.Ctx) => V, cases: T*) + (implicit ctx: Module.Ctx) +extends Cross[V]({ + cases.toList.map(x => + ( + List(x), + constructor( + x, + ctx.copy( + segments0 = Segments(ctx.segments0.value :+ ctx.segment), + segment = Segment.Cross(List(x)) + ) + ) + ) + ) +}) -class CrossModule2[T1, T2, V](constructor: (T1, T2) => V, cases: (T1, T2)*) - (implicit e: sourcecode.Enclosing, l: sourcecode.Line) -extends Cross[V](cases.toList.map(x => (List(x._2, x._1), constructor(x._1, x._2)))) +class CrossModule2[T1, T2, V](constructor: (T1, T2, Module.Ctx) => V, cases: (T1, T2)*) + (implicit ctx: Module.Ctx) +extends Cross[V]( + cases.toList.map(x => + ( + List(x._2, x._1), + constructor( + x._1, x._2, + ctx.copy( + segments0 = Segments(ctx.segments0.value :+ ctx.segment), + segment = Segment.Cross(List(x._2, x._1)) + ) + ) + ) + ) +) -class CrossModule3[T1, T2, T3, V](constructor: (T1, T2, T3) => V, cases: (T1, T2, T3)*) - (implicit e: sourcecode.Enclosing, l: sourcecode.Line) -extends Cross[V](cases.toList.map(x => (List(x._3, x._2, x._1), constructor(x._1, x._2, x._3)))) \ No newline at end of file +class CrossModule3[T1, T2, T3, V](constructor: (T1, T2, T3, Module.Ctx) => V, cases: (T1, T2, T3)*) + (implicit ctx: Module.Ctx) +extends Cross[V]( + cases.toList.map(x => + ( + List(x._3, x._2, x._1), + constructor( + x._1, x._2, x._3, + ctx.copy( + segments0 = Segments(ctx.segments0.value :+ ctx.segment), + segment = Segment.Cross(List(x._3, x._2, x._1)) + ) + ) + ) + ) +) \ No newline at end of file diff --git a/core/src/main/scala/mill/define/Module.scala b/core/src/main/scala/mill/define/Module.scala index b2e90a6e..c5837278 100644 --- a/core/src/main/scala/mill/define/Module.scala +++ b/core/src/main/scala/mill/define/Module.scala @@ -1,42 +1,71 @@ package mill.define +import ammonite.main.Router.Overrides import ammonite.ops.Path +import scala.annotation.implicitNotFound + +sealed trait Segment +object Segment{ + case class Label(value: String) extends Segment + case class Cross(value: Seq[Any]) extends Segment +} + case class BasePath(value: Path) +case class Segments(value: Seq[Segment]) /** * `Module` is a class meant to be extended by `trait`s *only*, in order to * propagate the implicit parameters forward to the final concrete * instantiation site so they can capture the enclosing/line information of * the concrete instance. */ -class Module(implicit ctx: Module.Ctx) extends mill.moduledefs.Cacher{ +class Module(implicit ctx0: Module.Ctx) extends mill.moduledefs.Cacher{ + val ctx = ctx0 // Ensure we do not propagate the implicit parameters as implicits within // the body of any inheriting class/trait/objects, as it would screw up any // one else trying to use sourcecode.{Enclosing,Line} to capture debug info - val millModuleEnclosing = ctx.millModuleEnclosing0 - val millModuleLine = ctx.millModuleLine0 - def basePath: Path = ctx.millModuleBasePath0.value / ctx.millName0.value + val millModuleEnclosing = ctx.enclosing + val millModuleLine = ctx.lineNum + def basePath: Path = ctx.basePath / (ctx.segment match{ + case Segment.Label(s) => List(s) + case Segment.Cross(vs) => vs.map(_.toString) + }) implicit def millModuleBasePath: BasePath = BasePath(basePath) + implicit def millModuleSegments: Segments = { + Segments(ctx.segments0.value :+ ctx.segment) + } } object Module{ - case class Ctx(millModuleEnclosing0: sourcecode.Enclosing, - millModuleLine0: sourcecode.Line, - millName0: sourcecode.Name, - millModuleBasePath0: BasePath) + @implicitNotFound("Modules, Targets and Commands can only be defined within a mill Module") + case class Ctx(enclosing: String, + lineNum: Int, + segment: Segment, + basePath: Path, + segments0: Segments, + overrides: Int){ + def segments = Segments(segments0.value.drop(1)) + } object Ctx{ implicit def make(implicit millModuleEnclosing0: sourcecode.Enclosing, millModuleLine0: sourcecode.Line, millName0: sourcecode.Name, - millModuleBasePath0: BasePath): Ctx = Ctx( - millModuleEnclosing0, - millModuleLine0, - millName0, - millModuleBasePath0 + millModuleBasePath0: BasePath, + segments0: Segments, + overrides0: Overrides): Ctx = Ctx( + millModuleEnclosing0.value, + millModuleLine0.value, + Segment.Label(millName0.value), + millModuleBasePath0.value, + segments0, + overrides0.value ) } } class BaseModule(basePath: Path) (implicit millModuleEnclosing0: sourcecode.Enclosing, millModuleLine0: sourcecode.Line, - millName0: sourcecode.Name) - extends Module()(Module.Ctx.make(implicitly, implicitly, implicitly, BasePath(basePath))) \ No newline at end of file + millName0: sourcecode.Name, + overrides0: Overrides) + extends Module()( + Module.Ctx.make(implicitly, implicitly, implicitly, BasePath(basePath), Segments(Nil), implicitly) + ) \ No newline at end of file diff --git a/core/src/main/scala/mill/define/Task.scala b/core/src/main/scala/mill/define/Task.scala index 34e56907..96fdbb8e 100644 --- a/core/src/main/scala/mill/define/Task.scala +++ b/core/src/main/scala/mill/define/Task.scala @@ -1,6 +1,5 @@ package mill.define -import ammonite.main.Router.Overrides import mill.define.Applicative.Applyable import mill.eval.{PathRef, Result} import mill.util.Ctx @@ -35,14 +34,10 @@ abstract class Task[+T] extends Task.Ops[T] with Applyable[Task, T]{ } trait NamedTask[+T] extends Task[T]{ - def owner: Module - def name: String - def overrides: Int + def ctx: Module.Ctx } trait Target[+T] extends NamedTask[T]{ override def asTarget = Some(this) - def enclosing: String - def lineNum: Int def readWrite: RW[_] } @@ -51,34 +46,19 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul implicit def apply[T](t: T) (implicit r: R[T], w: W[T], - e: sourcecode.Enclosing, - l: sourcecode.Line, - n: sourcecode.Name, - cl: Caller[Module], - o: Overrides): Target[T] = macro targetImpl[T] + ctx: Module.Ctx): Target[T] = macro targetImpl[T] def targetImpl[T: c.WeakTypeTag](c: Context) (t: c.Expr[T]) (r: c.Expr[R[T]], w: c.Expr[W[T]], - e: c.Expr[sourcecode.Enclosing], - l: c.Expr[sourcecode.Line], - n: c.Expr[sourcecode.Name], - cl: c.Expr[Caller[Module]], - o: c.Expr[Overrides]): c.Expr[Target[T]] = { + ctx: c.Expr[Module.Ctx]): c.Expr[Target[T]] = { import c.universe._ val lhs = Applicative.impl0[Task, T, Ctx](c)(reify(Result.Success(t.splice)).tree) mill.moduledefs.Cacher.impl0[TargetImpl[T]](c)( reify( - new TargetImpl[T]( - lhs.splice, - e.splice.value, - l.splice.value, - cl.splice.value, - n.splice.value, - upickle.default.ReadWriter(w.splice.write, r.splice.read), o.splice.value - ) + new TargetImpl[T](lhs.splice, ctx.splice, RW(w.splice.write, r.splice.read)) ) ) } @@ -86,32 +66,20 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul implicit def apply[T](t: Result[T]) (implicit r: R[T], w: W[T], - e: sourcecode.Enclosing, - l: sourcecode.Line, - n: sourcecode.Name, - cl: Caller[Module], - o: Overrides): Target[T] = macro targetResultImpl[T] + ctx: Module.Ctx): Target[T] = macro targetResultImpl[T] def targetResultImpl[T: c.WeakTypeTag](c: Context) (t: c.Expr[Result[T]]) (r: c.Expr[R[T]], w: c.Expr[W[T]], - e: c.Expr[sourcecode.Enclosing], - l: c.Expr[sourcecode.Line], - n: c.Expr[sourcecode.Name], - cl: c.Expr[Caller[Module]], - o: c.Expr[Overrides]): c.Expr[Target[T]] = { + ctx: c.Expr[Module.Ctx]): c.Expr[Target[T]] = { import c.universe._ mill.moduledefs.Cacher.impl0[Target[T]](c)( reify( new TargetImpl[T]( Applicative.impl0[Task, T, Ctx](c)(t.tree).splice, - e.splice.value, - l.splice.value, - cl.splice.value, - n.splice.value, - upickle.default.ReadWriter(w.splice.write, r.splice.read), - o.splice.value + ctx.splice, + RW(w.splice.write, r.splice.read) ) ) ) @@ -120,62 +88,31 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul def apply[T](t: Task[T]) (implicit r: R[T], w: W[T], - e: sourcecode.Enclosing, - l: sourcecode.Line, - n: sourcecode.Name, - cl: Caller[Module], - o: Overrides): Target[T] = macro targetTaskImpl[T] + ctx: Module.Ctx): Target[T] = macro targetTaskImpl[T] def targetTaskImpl[T: c.WeakTypeTag](c: Context) (t: c.Expr[Task[T]]) (r: c.Expr[R[T]], w: c.Expr[W[T]], - e: c.Expr[sourcecode.Enclosing], - l: c.Expr[sourcecode.Line], - n: c.Expr[sourcecode.Name], - cl: c.Expr[Caller[Module]], - o: c.Expr[Overrides]): c.Expr[Target[T]] = { + ctx: c.Expr[Module.Ctx]): c.Expr[Target[T]] = { import c.universe._ mill.moduledefs.Cacher.impl0[Target[T]](c)( reify( - new TargetImpl[T]( - t.splice, - e.splice.value, - l.splice.value, - cl.splice.value, - n.splice.value, - upickle.default.ReadWriter(w.splice.write, r.splice.read), - o.splice.value - ) + new TargetImpl[T](t.splice, ctx.splice, RW(w.splice.write, r.splice.read)) ) ) } - def command[T](t: Result[T]) - (implicit w: W[T], - e: sourcecode.Enclosing, - n: sourcecode.Name, - cl: Caller[Module], - o: Overrides): Command[T] = macro commandImpl[T] - def source(value: Result[ammonite.ops.Path]) (implicit r: R[PathRef], w: W[PathRef], - e: sourcecode.Enclosing, - l: sourcecode.Line, - n: sourcecode.Name, - cl: Caller[Module], - o: Overrides): Input[PathRef] = macro sourceImpl + ctx: Module.Ctx): Input[PathRef] = macro sourceImpl def sourceImpl(c: Context) (value: c.Expr[Result[ammonite.ops.Path]]) (r: c.Expr[R[PathRef]], w: c.Expr[W[PathRef]], - e: c.Expr[sourcecode.Enclosing], - l: c.Expr[sourcecode.Line], - n: c.Expr[sourcecode.Name], - cl: c.Expr[Caller[Module]], - o: c.Expr[Overrides]): c.Expr[Input[PathRef]] = { + ctx: c.Expr[Module.Ctx]): c.Expr[Input[PathRef]] = { import c.universe._ val wrapped: c.Expr[Result[PathRef]] = reify(value.splice match{ case Result.Success(p) => Result.Success(PathRef(p)) @@ -185,12 +122,8 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul reify( new Input[PathRef]( Applicative.impl0[Task, PathRef, Ctx](c)(wrapped.tree).splice, - e.splice.value, - l.splice.value, - cl.splice.value, - n.splice.value, - upickle.default.ReadWriter(w.splice.write, r.splice.read), - o.splice.value + ctx.splice, + RW(w.splice.write, r.splice.read), ) ) ) @@ -199,62 +132,41 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul def input[T](value: Result[T]) (implicit r: R[T], w: W[T], - e: sourcecode.Enclosing, - l: sourcecode.Line, - n: sourcecode.Name, - cl: Caller[Module], - o: Overrides): Input[T] = macro inputImpl[T] + ctx: Module.Ctx): Input[T] = macro inputImpl[T] def inputImpl[T: c.WeakTypeTag](c: Context) (value: c.Expr[T]) (r: c.Expr[R[T]], w: c.Expr[W[T]], - e: c.Expr[sourcecode.Enclosing], - l: c.Expr[sourcecode.Line], - n: c.Expr[sourcecode.Name], - cl: c.Expr[Caller[Module]], - o: c.Expr[Overrides]): c.Expr[Input[T]] = { + ctx: c.Expr[Module.Ctx]): c.Expr[Input[T]] = { import c.universe._ mill.moduledefs.Cacher.impl0[Input[T]](c)( reify( new Input[T]( Applicative.impl[Task, T, Ctx](c)(value).splice, - e.splice.value, - l.splice.value, - cl.splice.value, - n.splice.value, - upickle.default.ReadWriter(w.splice.write, r.splice.read), - o.splice.value + ctx.splice, + RW(w.splice.write, r.splice.read) ) ) ) } def command[T](t: Task[T]) - (implicit c: Caller[Module], - e: sourcecode.Enclosing, - n: sourcecode.Name, - w: W[T], - o: Overrides): Command[T] = new Command(t, e.value, c.value, n.value, w, o.value) + (implicit ctx: Module.Ctx, + w: W[T]): Command[T] = new Command(t, ctx, w) + + def command[T](t: Result[T]) + (implicit w: W[T], + ctx: Module.Ctx): Command[T] = macro commandImpl[T] def commandImpl[T: c.WeakTypeTag](c: Context) (t: c.Expr[T]) (w: c.Expr[W[T]], - e: c.Expr[sourcecode.Enclosing], - n: c.Expr[sourcecode.Name], - cl: c.Expr[Caller[Module]], - o: c.Expr[Overrides]): c.Expr[Command[T]] = { + ctx: c.Expr[Module.Ctx]): c.Expr[Command[T]] = { import c.universe._ reify( - new Command[T]( - Applicative.impl[Task, T, Ctx](c)(t).splice, - e.splice.value, - cl.splice.value, - n.splice.value, - w.splice, - o.splice.value - ) + new Command[T](Applicative.impl[Task, T, Ctx](c)(t).splice, ctx.splice, w.splice) ) } @@ -262,21 +174,13 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul def persistent[T](t: Result[T])(implicit r: R[T], w: W[T], - e: sourcecode.Enclosing, - l: sourcecode.Line, - n: sourcecode.Name, - cl: Caller[Module], - o: Overrides): Target[T] = macro persistentImpl[T] + ctx: Module.Ctx): Target[T] = macro persistentImpl[T] def persistentImpl[T: c.WeakTypeTag](c: Context) (t: c.Expr[T]) (r: c.Expr[R[T]], w: c.Expr[W[T]], - e: c.Expr[sourcecode.Enclosing], - l: c.Expr[sourcecode.Line], - n: c.Expr[sourcecode.Name], - cl: c.Expr[Caller[Module]], - o: c.Expr[Overrides]): c.Expr[Persistent[T]] = { + ctx: c.Expr[Module.Ctx]): c.Expr[Persistent[T]] = { import c.universe._ @@ -284,12 +188,8 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul reify( new Persistent[T]( Applicative.impl[Task, T, Ctx](c)(t).splice, - e.splice.value, - l.splice.value, - cl.splice.value, - n.splice.value, - upickle.default.ReadWriter(w.splice.write, r.splice.read), - o.splice.value + ctx.splice, + RW(w.splice.write, r.splice.read) ) ) ) @@ -319,44 +219,33 @@ object Caller { } class TargetImpl[+T](t: Task[T], - val enclosing: String, - val lineNum: Int, - val owner: Module, - val name: String, - val readWrite: RW[_], - val overrides: Int) extends Target[T] { + ctx0: Module.Ctx, + val readWrite: RW[_]) extends Target[T] { + val ctx = ctx0.copy(segments0 = Segments(ctx0.segments0.value :+ ctx0.segment)) val inputs = Seq(t) def evaluate(args: Ctx) = args[T](0) - override def toString = enclosing + "@" + Integer.toHexString(System.identityHashCode(this)) + override def toString = ctx.enclosing + "@" + Integer.toHexString(System.identityHashCode(this)) } class Command[+T](t: Task[T], - val enclosing: String, - val owner: Module, - val name: String, - val writer: W[_], - val overrides: Int) extends NamedTask[T] { + ctx0: Module.Ctx, + val writer: W[_]) extends NamedTask[T] { + val ctx = ctx0.copy(segments0 = Segments(ctx0.segments0.value :+ ctx0.segment)) val inputs = Seq(t) def evaluate(args: Ctx) = args[T](0) override def asCommand = Some(this) } class Persistent[+T](t: Task[T], - enclosing: String, - lineNum: Int, - owner: Module, - name: String, - readWrite: RW[_], - overrides: Int) - extends TargetImpl[T](t, enclosing, lineNum, owner, name, readWrite, overrides) { + ctx0: Module.Ctx, + readWrite: RW[_]) + extends TargetImpl[T](t, ctx0, readWrite) { + override def flushDest = false override def asPersistent = Some(this) } class Input[T](t: Task[T], - val enclosing: String, - val lineNum: Int, - val owner: Module, - val name: String, - val readWrite: RW[_], - val overrides: Int) extends Target[T]{ + ctx0: Module.Ctx, + val readWrite: RW[_]) extends Target[T]{ + val ctx = ctx0.copy(segments0 = Segments(ctx0.segments0.value :+ ctx0.segment)) val inputs = Seq(t) def evaluate(args: Ctx) = args[T](0) override def sideHash = util.Random.nextInt() diff --git a/core/src/main/scala/mill/discover/Discovered.scala b/core/src/main/scala/mill/discover/Discovered.scala index 44584137..74312f91 100644 --- a/core/src/main/scala/mill/discover/Discovered.scala +++ b/core/src/main/scala/mill/discover/Discovered.scala @@ -1,10 +1,9 @@ package mill.discover -import mill.define.Module -import mill.define.{Cross, Target, Task} +import mill.define._ import ammonite.main.Router import ammonite.main.Router.EntryPoint -import mill.discover.Mirror.{Segment, TargetPoint} +import mill.discover.Mirror.TargetPoint import mill.util.Ctx.Loader import scala.language.experimental.macros @@ -27,7 +26,7 @@ object Discovered { val modulesToPaths = Mirror.traverse(base, mirror){ (mirror, segmentsRev) => val resolvedNode = mirror.node( base, - segmentsRev.reverse.map{case Mirror.Segment.Cross(vs) => vs.toList case _ => Nil}.toList + segmentsRev.reverse.map{case Segment.Cross(vs) => vs.toList case _ => Nil}.toList ) Seq(resolvedNode -> segmentsRev.reverse) }.toMap @@ -35,7 +34,7 @@ object Discovered { val modulesToMirrors = Mirror.traverse[T, T, (Any, Mirror[_, _])](base, mirror){ (mirror, segmentsRev) => val resolvedNode = mirror.node( base, - segmentsRev.reverse.map{case Mirror.Segment.Cross(vs) => vs.toList case _ => Nil}.toList + segmentsRev.reverse.map{case Segment.Cross(vs) => vs.toList case _ => Nil}.toList ) Seq(resolvedNode -> mirror) }.toMap @@ -43,7 +42,7 @@ object Discovered { val targetsToSegments = Mirror.traverse(base, mirror){ (mirror, segmentsRev) => val resolvedNode = mirror.node( base, - segmentsRev.reverse.map{case Mirror.Segment.Cross(vs) => vs.toList case _ => Nil}.toList + segmentsRev.reverse.map{case Segment.Cross(vs) => vs.toList case _ => Nil}.toList ) for(target <- mirror.targets) yield { target.asInstanceOf[TargetPoint[Any, Any]].run(resolvedNode) -> (segmentsRev.reverse :+ Segment.Label(target.label)) diff --git a/core/src/main/scala/mill/discover/Mirror.scala b/core/src/main/scala/mill/discover/Mirror.scala index 63b6900b..3443535e 100644 --- a/core/src/main/scala/mill/discover/Mirror.scala +++ b/core/src/main/scala/mill/discover/Mirror.scala @@ -1,6 +1,6 @@ package mill.discover -import mill.define.{Target, Task} +import mill.define.{Segment, Target, Task} import ammonite.main.Router.EntryPoint import scala.language.experimental.macros @@ -20,21 +20,17 @@ case class Mirror[-T, V](node: (T, List[List[Any]]) => V, crossChildren: Option[(V => List[List[Any]], Mirror[T, _])]) object Mirror{ - def renderSelector(selector: Seq[Mirror.Segment]) = selector.toList match { + def renderSelector(selector: Seq[Segment]) = selector.toList match { case Nil => "" - case Mirror.Segment.Label(head) :: rest => + case Segment.Label(head) :: rest => val stringSegments = rest.map{ - case Mirror.Segment.Label(s) => "." + s - case Mirror.Segment.Cross(vs) => "[" + vs.mkString(",") + "]" + case Segment.Label(s) => "." + s + case Segment.Cross(vs) => "[" + vs.mkString(",") + "]" } head + stringSegments.mkString } - sealed trait Segment - object Segment{ - case class Label(value: String) extends Segment - case class Cross(value: Seq[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]= { diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala index 17108307..ff2d64f2 100644 --- a/core/src/main/scala/mill/eval/Evaluator.scala +++ b/core/src/main/scala/mill/eval/Evaluator.scala @@ -6,7 +6,7 @@ import ammonite.ops._ import ammonite.runtime.SpecialClassLoader import mill.define._ import mill.discover.{Discovered, Mirror} -import mill.discover.Mirror.Segment +import mill.define.Segment import mill.util import mill.util._ @@ -40,16 +40,15 @@ class Evaluator[T](val workspacePath: Path, val transitive = Graph.transitiveTargets(goals) val topoSorted = Graph.topoSorted(transitive) val sortedGroups = Graph.groupAroundImportantTargets(topoSorted){ - case t: NamedTask[Any] if mapping.modulesToPaths.contains(t.owner) => - val segments = mapping.modulesToPaths(t.owner) :+ Segment.Label(t.name) + case t: NamedTask[Any] => + val segments = t.ctx.segments.value val (finalTaskOverrides, enclosing) = t match{ - case t: Target[_] => mapping.segmentsToTargets(segments).overrides -> t.enclosing - case c: mill.define.Command[_] => mapping.segmentsToCommands(segments).overrides -> c.enclosing + case t: Target[_] => mapping.segmentsToTargets(segments).ctx.overrides -> t.ctx.enclosing + case c: mill.define.Command[_] => mapping.segmentsToCommands(segments).overrides -> c.ctx.enclosing } - val delta = finalTaskOverrides - t.overrides val additional = - if (delta == 0) Nil - else Seq(Segment.Label("override" + delta), Segment.Label(enclosing)) + if (finalTaskOverrides == t.ctx.overrides) Nil + else Seq(Segment.Label("overriden"), Segment.Label(enclosing)) Right(Labelled(t, segments ++ additional)) case t if goals.contains(t) => Left(t) @@ -127,9 +126,9 @@ class Evaluator[T](val workspacePath: Path, case _ => 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(",") + "]" + val msgParts = Seq(first.asInstanceOf[Segment.Label].value) ++ rest.map{ + case Segment.Label(s) => "." + s + case Segment.Cross(s) => "[" + s.mkString(",") + "]" } if (labelledTarget.target.flushDest) rm(paths.dest) @@ -258,8 +257,8 @@ object Evaluator{ meta: Path, log: Path) def makeSegmentStrings(segments: Seq[Segment]) = segments.flatMap{ - case Mirror.Segment.Label(s) => Seq(s) - case Mirror.Segment.Cross(values) => values.map(_.toString) + case Segment.Label(s) => Seq(s) + case Segment.Cross(values) => values.map(_.toString) } def resolveDestPaths(workspacePath: Path, segments: Seq[Segment]): Paths = { val segmentStrings = makeSegmentStrings(segments) diff --git a/core/src/main/scala/mill/main/ReplApplyHandler.scala b/core/src/main/scala/mill/main/ReplApplyHandler.scala index 1e88ee53..77926d45 100644 --- a/core/src/main/scala/mill/main/ReplApplyHandler.scala +++ b/core/src/main/scala/mill/main/ReplApplyHandler.scala @@ -3,7 +3,7 @@ package mill.main import mill.define.Applicative.ApplyHandler import mill.define.{Cross, Target, Task} -import mill.discover.Mirror.Segment +import mill.define.Segment import mill.discover.{Discovered, Mirror} import mill.eval.Evaluator import mill.util.OSet @@ -51,7 +51,7 @@ class ReplApplyHandler(pprinter0: pprint.PPrinter, evaluator: Evaluator[_]) exte case m: mill.Module if evaluator.mapping.modulesToMirrors.contains(m) => val mirror = evaluator.mapping.modulesToMirrors(m) pprint.Tree.Lazy( ctx => - Iterator(m.millModuleEnclosing.value, ":", m.millModuleLine.value.toString) ++ + Iterator(m.millModuleEnclosing, ":", m.millModuleLine.toString) ++ (if (mirror.children.isEmpty) Nil else ctx.applyPrefixColor("\nChildren:").toString +: mirror.children.map("\n ." + _._1)) ++ (if (mirror.commands.isEmpty) Nil @@ -79,7 +79,7 @@ class ReplApplyHandler(pprinter0: pprint.PPrinter, evaluator: Evaluator[_]) exte } } pprint.Tree.Lazy(ctx => - Iterator(t.enclosing, ":", t.lineNum.toString, "\n", ctx.applyPrefixColor("Inputs:").toString) ++ + Iterator(t.ctx.enclosing, ":", t.ctx.lineNum.toString, "\n", ctx.applyPrefixColor("Inputs:").toString) ++ t.inputs.iterator.flatMap(rec).map("\n " + Mirror.renderSelector(_)) ) diff --git a/core/src/main/scala/mill/main/Resolve.scala b/core/src/main/scala/mill/main/Resolve.scala index 6196cdc6..b8968091 100644 --- a/core/src/main/scala/mill/main/Resolve.scala +++ b/core/src/main/scala/mill/main/Resolve.scala @@ -1,21 +1,21 @@ package mill.main -import mill.define.Task +import mill.define.{Segment, Task} import mill.define.Task.TaskModule -import mill.discover.{Mirror} +import mill.discover.Mirror import ammonite.main.Router object Resolve { - def resolve[T, V](remainingSelector: List[Mirror.Segment], + def resolve[T, V](remainingSelector: List[Segment], hierarchy: Mirror[T, V], obj: T, rest: Seq[String], remainingCrossSelectors: List[List[String]], - revSelectorsSoFar: List[Mirror.Segment]): Either[String, Task[Any]] = { + revSelectorsSoFar: List[Segment]): Either[String, Task[Any]] = { remainingSelector match{ - case Mirror.Segment.Cross(_) :: Nil => Left("Selector cannot start with a [cross] segment") - case Mirror.Segment.Label(last) :: Nil => + case Segment.Cross(_) :: Nil => Left("Selector cannot start with a [cross] segment") + case Segment.Label(last) :: Nil => def target = hierarchy.targets .find(_.label == last) @@ -44,7 +44,7 @@ object Resolve { command orElse target orElse runDefault.headOption.flatten match{ case None => Left("Cannot resolve task " + Mirror.renderSelector( - (Mirror.Segment.Label(last) :: revSelectorsSoFar).reverse) + (Segment.Label(last) :: revSelectorsSoFar).reverse) ) // Contents of `either` *must* be a `Task`, because we only select // methods returning `Task` in the discovery process @@ -55,7 +55,7 @@ object Resolve { case head :: tail => val newRevSelectorsSoFar = head :: revSelectorsSoFar head match{ - case Mirror.Segment.Label(singleLabel) => + case Segment.Label(singleLabel) => hierarchy.children.collectFirst{ case (label, child) if label == singleLabel => child } match{ @@ -63,7 +63,7 @@ object Resolve { case None => Left("Cannot resolve module " + Mirror.renderSelector(newRevSelectorsSoFar.reverse)) } - case Mirror.Segment.Cross(cross) => + case Segment.Cross(cross) => val Some((crossGen, childMirror)) = hierarchy.crossChildren val crossOptions = crossGen(hierarchy.node(obj, remainingCrossSelectors)) if (crossOptions.contains(cross)){ diff --git a/core/src/main/scala/mill/main/RunScript.scala b/core/src/main/scala/mill/main/RunScript.scala index 7e578fb0..e27d4e1c 100644 --- a/core/src/main/scala/mill/main/RunScript.scala +++ b/core/src/main/scala/mill/main/RunScript.scala @@ -9,7 +9,7 @@ import ammonite.util.Util.CodeSource import ammonite.util.{Name, Res, Util} import mill.{PathRef, define} import mill.define.Task -import mill.discover.Mirror.Segment +import mill.define.Segment import mill.discover.{Discovered, Mirror} import mill.eval.{Evaluator, PathRef, Result} import mill.util.{Logger, OSet, PrintLogger} @@ -122,7 +122,7 @@ object RunScript{ for { sel <- parseArgs(selectorString) crossSelectors = sel.map{ - case Mirror.Segment.Cross(x) => x.toList.map(_.toString) + case Segment.Cross(x) => x.toList.map(_.toString) case _ => Nil } target <- mill.main.Resolve.resolve( @@ -161,11 +161,13 @@ object RunScript{ val json = for(t <- Seq(target)) yield { t match { case t: mill.define.NamedTask[_] => - for (segments <- evaluator.mapping.modulesToPaths.get(t.owner)) yield { - val jsonFile = Evaluator.resolveDestPaths(evaluator.workspacePath, segments :+ Segment.Label(t.name)).meta - val metadata = upickle.json.read(jsonFile.toIO) - metadata(1) - } + val segments = t.ctx.segments.value + val jsonFile = Evaluator.resolveDestPaths( + evaluator.workspacePath, segments + ).meta + val metadata = upickle.json.read(jsonFile.toIO) + Some(metadata(1)) + case _ => None } } @@ -178,10 +180,10 @@ object RunScript{ def parseSelector(input: String) = { import fastparse.all._ val segment = P( CharsWhileIn(('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9')).! ).map( - Mirror.Segment.Label + Segment.Label ) val crossSegment = P( "[" ~ CharsWhile(c => c != ',' && c != ']').!.rep(1, sep=",") ~ "]" ).map( - Mirror.Segment.Cross + Segment.Cross ) val query = P( segment ~ ("." ~ segment | crossSegment).rep ~ End ).map{ case (h, rest) => h :: rest.toList @@ -191,7 +193,7 @@ object RunScript{ - def parseArgs(selectorString: String): Either[String, List[Mirror.Segment]] = { + def parseArgs(selectorString: String): Either[String, List[Segment]] = { import fastparse.all.Parsed if (selectorString.isEmpty) Left("Selector cannot be empty") else parseSelector(selectorString) match { diff --git a/core/src/test/scala/mill/define/GraphTests.scala b/core/src/test/scala/mill/define/GraphTests.scala index a850a0d2..718fd673 100644 --- a/core/src/test/scala/mill/define/GraphTests.scala +++ b/core/src/test/scala/mill/define/GraphTests.scala @@ -157,7 +157,7 @@ object GraphTests extends TestSuite{ Graph.transitiveTargets(OSet.from(goals)) ) val grouped = Graph.groupAroundImportantTargets(topoSorted) { - case t: NamedTask[Any] if mapping.modulesToPaths.contains(t.owner) => t + case t: NamedTask[Any] => t case t if goals.contains(t) => t } grouped.keyCount diff --git a/core/src/test/scala/mill/define/MacroErrorTests.scala b/core/src/test/scala/mill/define/MacroErrorTests.scala index 90d4e65a..a389feaa 100644 --- a/core/src/test/scala/mill/define/MacroErrorTests.scala +++ b/core/src/test/scala/mill/define/MacroErrorTests.scala @@ -30,7 +30,9 @@ object MacroErrorTests extends TestSuite{ } } """) - assert(e.msg.contains("required: mill.define.Module")) + assert(e.msg.contains( + "Modules, Targets and Commands can only be defined within a mill Module") + ) } 'neg - { @@ -72,7 +74,9 @@ object MacroErrorTests extends TestSuite{ def down = T{ TestUtil.test(left, right) } } """) - assert(borkedCachedDiamond1.msg.contains("required: mill.Module")) + assert(borkedCachedDiamond1.msg.contains( + "Modules, Targets and Commands can only be defined within a mill Module") + ) } } } diff --git a/core/src/test/scala/mill/discover/ConsistencyTests.scala b/core/src/test/scala/mill/discover/ConsistencyTests.scala index ae66b199..47eb14ce 100644 --- a/core/src/test/scala/mill/discover/ConsistencyTests.scala +++ b/core/src/test/scala/mill/discover/ConsistencyTests.scala @@ -1,7 +1,7 @@ package mill.discover -import mill.discover.Mirror.Segment.Label +import mill.define.Segment.Label import mill.util.TestGraphs import utest._ diff --git a/core/src/test/scala/mill/discover/CrossModuleTests.scala b/core/src/test/scala/mill/discover/CrossModuleTests.scala index 6ae3d622..7f5cb89c 100644 --- a/core/src/test/scala/mill/discover/CrossModuleTests.scala +++ b/core/src/test/scala/mill/discover/CrossModuleTests.scala @@ -2,8 +2,8 @@ package mill.discover import mill.{Module, T} import mill.define.Cross -import mill.discover.Mirror.Segment -import mill.discover.Mirror.Segment.Label +import mill.define.Segment +import mill.define.Segment.Label import mill.util.TestUtil.test import utest._ import mill.util.TestGraphs._ @@ -15,7 +15,7 @@ object CrossModuleTests extends TestSuite{ 'cross - { object outer extends TestUtil.BaseModule { object crossed extends mill.CrossModule(CrossedModule, "2.10.6", "2.11.8", "2.12.4") - case class CrossedModule(n: String) extends Module{ + case class CrossedModule(n: String, ctx0: Module.Ctx) extends Module()(ctx0){ def scalaVersion = n } } @@ -43,7 +43,7 @@ object CrossModuleTests extends TestSuite{ if !(platform == "native0.3" && scalaVersion == "2.10.6") } yield (platform, scalaVersion) object crossed extends mill.CrossModule2(CrossModule, crossMatrix:_*) - case class CrossModule(platform: String, scalaVersion: String) extends mill.Module{ + case class CrossModule(platform: String, scalaVersion: String, ctx0: Module.Ctx) extends mill.Module()(ctx0){ def suffix = Seq(scalaVersion, platform).filter(_.nonEmpty).map("_"+_).mkString } } diff --git a/core/src/test/scala/mill/discover/DiscoveredTests.scala b/core/src/test/scala/mill/discover/DiscoveredTests.scala index d141352e..83c92adc 100644 --- a/core/src/test/scala/mill/discover/DiscoveredTests.scala +++ b/core/src/test/scala/mill/discover/DiscoveredTests.scala @@ -5,7 +5,7 @@ import java.io.InputStreamReader import ammonite.main.Router.{ArgSig, EntryPoint} import utest._ import mill.{Module, T} -import mill.discover.Mirror.Segment.Label +import mill.define.Segment.Label import mill.util.TestGraphs.{TraitWithModuleObject, nestedModule} import mill.util.TestUtil object DiscoveredTests extends TestSuite{ diff --git a/core/src/test/scala/mill/discover/LabelingTests.scala b/core/src/test/scala/mill/discover/LabelingTests.scala index 595d3ad9..d1ac0536 100644 --- a/core/src/test/scala/mill/discover/LabelingTests.scala +++ b/core/src/test/scala/mill/discover/LabelingTests.scala @@ -1,10 +1,10 @@ package mill.discover -import mill.define.Task +import mill.define.{Segment, Task} import mill.util.TestGraphs import utest._ import Discovered.mapping -import mill.discover.Mirror.Segment.Label +import mill.define.Segment.Label object LabelingTests extends TestSuite{ val tests = Tests{ @@ -16,7 +16,7 @@ object LabelingTests extends TestSuite{ def check(mapping: Discovered.Mapping[_], t: Task[_], relPath: Option[String]) = { - val names: Seq[(Task[_], Seq[Mirror.Segment])] = mapping.targetsToSegments.toSeq + val names: Seq[(Task[_], Seq[Segment])] = mapping.targetsToSegments.toSeq val nameMap = names.toMap val targetLabel = nameMap.get(t).map(_.map{case Label(v) => v}.mkString(".")) diff --git a/core/src/test/scala/mill/main/MainTests.scala b/core/src/test/scala/mill/main/MainTests.scala index 320731fa..013729ff 100644 --- a/core/src/test/scala/mill/main/MainTests.scala +++ b/core/src/test/scala/mill/main/MainTests.scala @@ -1,7 +1,7 @@ package mill.main import mill.Module -import mill.define.Task +import mill.define.{Segment, Task} import mill.discover.{Discovered, Mirror} import mill.util.TestGraphs._ import mill.util.TestUtil.test @@ -14,7 +14,7 @@ object MainTests extends TestSuite{ val resolved = for{ args <- mill.main.RunScript.parseArgs(selectorString) - val crossSelectors = args.map{case Mirror.Segment.Cross(x) => x.toList.map(_.toString) case _ => Nil} + val crossSelectors = args.map{case Segment.Cross(x) => x.toList.map(_.toString) case _ => Nil} task <- mill.main.Resolve.resolve(args, mapping.mirror, mapping.base, Nil, crossSelectors, Nil) } yield task assert(resolved == expected) diff --git a/core/src/test/scala/mill/util/TestGraphs.scala b/core/src/test/scala/mill/util/TestGraphs.scala index 64fc4737..95ed8bf0 100644 --- a/core/src/test/scala/mill/util/TestGraphs.scala +++ b/core/src/test/scala/mill/util/TestGraphs.scala @@ -193,7 +193,7 @@ object TestGraphs{ object singleCross extends TestUtil.BaseModule { object cross extends mill.CrossModule(CrossModule, "210", "211", "212") - case class CrossModule(scalaVersion: String) extends Module{ + case class CrossModule(scalaVersion: String, ctx0: Module.Ctx) extends Module()(ctx0){ def suffix = T{ scalaVersion } } } @@ -204,16 +204,16 @@ object TestGraphs{ if !(platform == "native" && scalaVersion != "212") } yield (scalaVersion, platform) object cross extends mill.CrossModule2(CrossModule, crossMatrix:_*) - case class CrossModule(scalaVersion: String, platform: String) extends Module{ + case class CrossModule(scalaVersion: String, platform: String, ctx0: Module.Ctx) extends Module()(ctx0){ def suffix = T{ scalaVersion + "_" + platform } } } object indirectNestedCrosses extends TestUtil.BaseModule { object cross extends mill.CrossModule(CrossModule, "210", "211", "212") - case class CrossModule(scalaVersion: String) extends mill.Module{ + case class CrossModule(scalaVersion: String, ctx0: Module.Ctx) extends mill.Module()(ctx0){ object cross2 extends mill.CrossModule(CrossModule, "jvm", "js", "native") - case class CrossModule(platform: String) extends mill.Module{ + case class CrossModule(platform: String, ctx0: Module.Ctx) extends mill.Module{ def suffix = T{ scalaVersion + "_" + platform } } } @@ -221,9 +221,9 @@ object TestGraphs{ object nestedCrosses extends TestUtil.BaseModule { object cross extends mill.CrossModule(CrossModule, "210", "211", "212") - case class CrossModule(scalaVersion: String) extends mill.Module{ + case class CrossModule(scalaVersion: String, ctx0: Module.Ctx) extends mill.Module()(ctx0){ object cross2 extends mill.CrossModule(CrossModule, "jvm", "js", "native") - case class CrossModule(platform: String) extends mill.Module{ + case class CrossModule(platform: String, ctx0: Module.Ctx) extends mill.Module()(ctx0){ def suffix = T{ scalaVersion + "_" + platform } } } diff --git a/core/src/test/scala/mill/util/TestUtil.scala b/core/src/test/scala/mill/util/TestUtil.scala index 8f5378cb..88d28f8a 100644 --- a/core/src/test/scala/mill/util/TestUtil.scala +++ b/core/src/test/scala/mill/util/TestUtil.scala @@ -1,34 +1,32 @@ package mill.util import ammonite.main.Router.Overrides -import ammonite.ops.Path -import mill.define.Module -import mill.define.{BasePath, Caller, Target, Task} +import mill.define._ import mill.eval.Result import utest.assert -import utest.framework.TestPath import scala.collection.mutable object TestUtil { class BaseModule(implicit millModuleEnclosing0: sourcecode.Enclosing, millModuleLine0: sourcecode.Line, - millName0: sourcecode.Name) + millName0: sourcecode.Name, + overrides: Overrides) extends Module()( Module.Ctx.make( implicitly, implicitly, implicitly, - BasePath(ammonite.ops.pwd / millModuleEnclosing0.value) + BasePath(ammonite.ops.pwd / millModuleEnclosing0.value), + Segments(Nil), + implicitly ) ) object test{ def anon(inputs: Task[Int]*) = new Test(inputs) def apply(inputs: Task[Int]*) - (implicit enclosing0: sourcecode.Enclosing, - owner0: Caller[mill.Module], - name0: sourcecode.Name)= { + (implicit ctx: Module.Ctx)= { new TestTarget(inputs, pure = inputs.nonEmpty) } } @@ -51,17 +49,9 @@ object TestUtil { */ class TestTarget(inputs: Seq[Task[Int]], val pure: Boolean) - (implicit enclosing0: sourcecode.Enclosing, - lineNum0: sourcecode.Line, - owner0: Caller[mill.Module], - name0: sourcecode.Name, - o: Overrides) + (implicit ctx0: Module.Ctx) extends Test(inputs) with Target[Int]{ - val overrides = o.value - val enclosing = enclosing0.value - val lineNum = lineNum0.value - val owner = owner0.value - val name = name0.value + val ctx = ctx0.copy(segments0 = Segments(ctx0.segments0.value :+ ctx0.segment)) val readWrite = upickle.default.IntRW -- cgit v1.2.3