diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2018-01-21 16:11:14 -0800 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2018-01-21 17:24:15 -0800 |
commit | 68f158b63c33aa7312ba4b715f6b18527453b761 (patch) | |
tree | 1c23c4bb429742b8c3d68a9c48bc8c54a3fa4a97 /core/src | |
parent | e7acdd81f23b4f0f41e5000e9e173ded9c6c0548 (diff) | |
download | mill-68f158b63c33aa7312ba4b715f6b18527453b761.tar.gz mill-68f158b63c33aa7312ba4b715f6b18527453b761.tar.bz2 mill-68f158b63c33aa7312ba4b715f6b18527453b761.zip |
Implement basic wildcard task running via e.g. `mill _.compile`
Diffstat (limited to 'core/src')
-rw-r--r-- | core/src/mill/define/Module.scala | 5 | ||||
-rw-r--r-- | core/src/mill/define/Task.scala | 3 | ||||
-rw-r--r-- | core/src/mill/main/ParseArgs.scala | 12 | ||||
-rw-r--r-- | core/src/mill/main/Resolve.scala | 64 | ||||
-rw-r--r-- | core/src/mill/main/RunScript.scala | 11 |
5 files changed, 70 insertions, 25 deletions
diff --git a/core/src/mill/define/Module.scala b/core/src/mill/define/Module.scala index e42ce798..c68c2bdd 100644 --- a/core/src/mill/define/Module.scala +++ b/core/src/mill/define/Module.scala @@ -37,8 +37,9 @@ object Module{ def rec(m: Module): Seq[T] = f(m) ++ m.millModuleDirectChildren.flatMap(rec) rec(outer) } - lazy val segmentsToModules = traverse{m => Seq(m.millModuleSegments -> m)} - .toMap + + lazy val modules = traverse(Seq(_)) + lazy val segmentsToModules = modules.map(m => (m.millModuleSegments, m)).toMap lazy val targets = traverse{_.millInternal.reflect[Target[_]]}.toSet diff --git a/core/src/mill/define/Task.scala b/core/src/mill/define/Task.scala index 90908e4e..248f145c 100644 --- a/core/src/mill/define/Task.scala +++ b/core/src/mill/define/Task.scala @@ -43,6 +43,7 @@ abstract class Task[+T] extends Task.Ops[T] with Applyable[Task, T]{ trait NamedTask[+T] extends Task[T]{ def ctx: mill.define.Ctx def label = ctx.segment match{case Segment.Label(v) => v} + override def toString = ctx.segments.render } trait Target[+T] extends NamedTask[T]{ override def asTarget = Some(this) @@ -232,7 +233,7 @@ class TargetImpl[+T](t: Task[T], val ctx = ctx0.copy(segments = ctx0.segments ++ Seq(ctx0.segment)) val inputs = Seq(t) def evaluate(args: mill.util.Ctx) = args[T](0) - override def toString = ctx.enclosing + "@" + Integer.toHexString(System.identityHashCode(this)) + } class Command[+T](t: Task[T], ctx0: mill.define.Ctx, diff --git a/core/src/mill/main/ParseArgs.scala b/core/src/mill/main/ParseArgs.scala index dc848418..7170cc60 100644 --- a/core/src/mill/main/ParseArgs.scala +++ b/core/src/mill/main/ParseArgs.scala @@ -126,13 +126,11 @@ object ParseArgs { } private def parseSelector(input: String) = { - val segment = - P(CharsWhileIn(('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9')).!).map( - Segment.Label - ) - val crossSegment = - P("[" ~ CharsWhile(c => c != ',' && c != ']').!.rep(1, sep = ",") ~ "]") - .map(Segment.Cross) + val identChars = ('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9') ++ "_" + val ident = P( CharsWhileIn(identChars) ).! + val ident2 = P( CharsWhileIn(identChars ++ ".") ).! + val segment = P( ident ).map( Segment.Label) + val crossSegment = P("[" ~ ident2.rep(1, sep = ",") ~ "]").map(Segment.Cross) val query = P(segment ~ ("." ~ segment | crossSegment).rep ~ End).map { case (h, rest) => h :: rest.toList } diff --git a/core/src/mill/main/Resolve.scala b/core/src/mill/main/Resolve.scala index 3d9c0409..d836a1a1 100644 --- a/core/src/mill/main/Resolve.scala +++ b/core/src/mill/main/Resolve.scala @@ -11,7 +11,7 @@ object Resolve { discover: Discover, rest: Seq[String], remainingCrossSelectors: List[List[String]], - revSelectorsSoFar: List[Segment]): Either[String, Task[Any]] = { + revSelectorsSoFar: List[Segment]): Either[String, Seq[Task[Any]]] = { remainingSelector match{ case Segment.Cross(_) :: Nil => Left("Selector cannot start with a [cross] segment") @@ -23,7 +23,7 @@ object Resolve { .find(_.label == last) .map(Right(_)) - def invokeCommand[V](target: mill.Module, name: String) = { + def invokeCommand(target: mill.Module, name: String) = { for{ (cls, entryPoints) <- discover.value.filterKeys(_.isAssignableFrom(target.getClass)) @@ -52,7 +52,7 @@ object Resolve { ) // Contents of `either` *must* be a `Task`, because we only select // methods returning `Task` in the discovery process - case Some(either) => either.right.map{ case x: Task[Any] => x } + case Some(either) => either.right.map{ case x: Task[Any] => Seq(x) } } @@ -60,20 +60,62 @@ object Resolve { val newRevSelectorsSoFar = head :: revSelectorsSoFar head match{ case Segment.Label(singleLabel) => - obj.millInternal.reflectNestedObjects[mill.Module].find{ - _.millOuterCtx.segment == Segment.Label(singleLabel) - } match{ - case Some(child: mill.Module) => resolve(tail, child, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar) - case None => Left("Cannot resolve module " + Segments(newRevSelectorsSoFar.reverse:_*).render) + if (singleLabel == "__"){ + val matching = + obj.millInternal + .modules + .map(resolve(tail, _, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar)) + .collect{case Right(vs) => vs}.flatten + + if (matching.nonEmpty) Right(matching.toSeq) + else Left("Cannot resolve module " + Segments(newRevSelectorsSoFar.reverse:_*).render) + }else if (singleLabel == "_") { + val matching = + obj.millInternal + .reflectNestedObjects[mill.Module] + .map(resolve(tail, _, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar)) + .collect{case Right(vs) => vs}.flatten + + if (matching.nonEmpty)Right(matching) + else Left("Cannot resolve module " + Segments(newRevSelectorsSoFar.reverse:_*).render) + }else{ + + obj.millInternal.reflectNestedObjects[mill.Module].find{ + _.millOuterCtx.segment == Segment.Label(singleLabel) + } match{ + case Some(child: mill.Module) => resolve(tail, child, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar) + case None => Left("Cannot resolve module " + Segments(newRevSelectorsSoFar.reverse:_*).render) + } } case Segment.Cross(cross) => obj match{ case c: Cross[_] => - c.itemMap.get(cross.toList) match{ - case Some(m: mill.Module) => resolve(tail, m, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar) - case None => Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render) + if(cross == Seq("__")){ + val matching = + for ((k, v) <- c.items) + yield resolve(tail, v.asInstanceOf[mill.Module], discover, rest, remainingCrossSelectors, newRevSelectorsSoFar) + + val results = matching.collect{case Right(res) => res}.flatten + + if (results.isEmpty) Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render) + else Right(results) + } else if (cross.contains("_")){ + val matching = for { + (k, v) <- c.items + if k.length == cross.length + if k.zip(cross).forall { case (l, r) => l == r || r == "_" } + } yield resolve(tail, v.asInstanceOf[mill.Module], discover, rest, remainingCrossSelectors, newRevSelectorsSoFar) + + val results = matching.collect{case Right(res) => res}.flatten + if (results.isEmpty) Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render) + else Right(results) + }else{ + c.itemMap.get(cross.toList) match{ + case Some(m: mill.Module) => resolve(tail, m, discover, rest, remainingCrossSelectors, newRevSelectorsSoFar) + case None => Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render) + } } case _ => Left("Cannot resolve cross " + Segments(newRevSelectorsSoFar.reverse:_*).render) } diff --git a/core/src/mill/main/RunScript.scala b/core/src/mill/main/RunScript.scala index aa254048..a69f87be 100644 --- a/core/src/mill/main/RunScript.scala +++ b/core/src/mill/main/RunScript.scala @@ -151,13 +151,16 @@ object RunScript{ } EitherOps.sequence(selected) } - (watched, res) = evaluate(evaluator, targets) + (watched, res) = evaluate( + evaluator, + Agg.from(targets.flatten.distinct) + ) } yield (watched, res) } def evaluate(evaluator: Evaluator[_], - targets: Seq[Task[Any]]): (Seq[PathRef], Either[String, Seq[(Any, Option[upickle.Js.Value])]]) = { - val evaluated = evaluator.evaluate(Agg.from(targets)) + targets: Agg[Task[Any]]): (Seq[PathRef], Either[String, Seq[(Any, Option[upickle.Js.Value])]]) = { + val evaluated = evaluator.evaluate(targets) val watched = evaluated.results .iterator .collect { @@ -194,7 +197,7 @@ object RunScript{ } } - watched -> Right(evaluated.values.zip(json)) + watched -> Right(evaluated.values.zip(json.toSeq)) case n => watched -> Left(s"$n targets failed\n$errorStr") } } |