summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2018-01-21 16:11:14 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2018-01-21 17:24:15 -0800
commit68f158b63c33aa7312ba4b715f6b18527453b761 (patch)
tree1c23c4bb429742b8c3d68a9c48bc8c54a3fa4a97 /core/src
parente7acdd81f23b4f0f41e5000e9e173ded9c6c0548 (diff)
downloadmill-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.scala5
-rw-r--r--core/src/mill/define/Task.scala3
-rw-r--r--core/src/mill/main/ParseArgs.scala12
-rw-r--r--core/src/mill/main/Resolve.scala64
-rw-r--r--core/src/mill/main/RunScript.scala11
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")
}
}