From 39bfb3f02cc539def76c7df69073c62bb6e5dc96 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sun, 14 Jan 2018 18:13:28 -0800 Subject: Extract out miscellanous mill.define.Module helpers into the millInternal namespace --- core/src/main/scala/mill/define/Cross.scala | 7 +- core/src/main/scala/mill/define/Module.scala | 116 +++++++++++---------- core/src/main/scala/mill/eval/Evaluator.scala | 2 +- .../main/scala/mill/main/ReplApplyHandler.scala | 20 ++-- core/src/main/scala/mill/main/Resolve.scala | 9 +- .../test/scala/mill/eval/JavaCompileJarTests.scala | 4 +- core/src/test/scala/mill/util/TestEvaluator.scala | 2 +- .../src/main/scala/mill/scalalib/GenIdea.scala | 2 +- 8 files changed, 88 insertions(+), 74 deletions(-) diff --git a/core/src/main/scala/mill/define/Cross.scala b/core/src/main/scala/mill/define/Cross.scala index 8bbf9bfd..58f9a158 100644 --- a/core/src/main/scala/mill/define/Cross.scala +++ b/core/src/main/scala/mill/define/Cross.scala @@ -20,7 +20,7 @@ object Cross{ yield q"v.productElement($n).asInstanceOf[${a.info}]" val instance = c.Expr[(Product, mill.define.Ctx) => T]( - q"{ (v, ctx0) => new $tpe(..$argTupleValues){ override def parentCtx = ctx0 } }" + q"{ (v, ctx0) => new $tpe(..$argTupleValues){ override def millOuterCtx = ctx0 } }" ) reify { mill.define.Cross.Factory[T](instance.splice) } @@ -46,7 +46,10 @@ class Cross[T](cases: Any*) (implicit ci: Cross.Factory[T], ctx: mill.define.Ctx) extends mill.define.Module()(ctx) { - override lazy val modules = this.reflectNestedObjects[Module] ++ items.collect{case (k, v: mill.define.Module) => v} + override lazy val millModuleDirectChildren = + this.millInternal.reflectNestedObjects[Module] ++ + items.collect{case (k, v: mill.define.Module) => v} + val items = for(c0 <- cases.toList) yield{ val c = c0 match{ case p: Product => p diff --git a/core/src/main/scala/mill/define/Module.scala b/core/src/main/scala/mill/define/Module.scala index 0236ac5a..33d0e267 100644 --- a/core/src/main/scala/mill/define/Module.scala +++ b/core/src/main/scala/mill/define/Module.scala @@ -14,68 +14,76 @@ import scala.reflect.macros.blackbox * instantiation site so they can capture the enclosing/line information of * the concrete instance. */ -class Module(implicit parentCtx0: mill.define.Ctx) extends mill.moduledefs.Cacher{ +class Module(implicit outerCtx0: mill.define.Ctx) extends mill.moduledefs.Cacher{ outer => - def traverse[T](f: Module => Seq[T]): Seq[T] = { - def rec(m: Module): Seq[T] = f(m) ++ m.modules.flatMap(rec) - rec(this) - } - - lazy val segmentsToModules = traverse{m => Seq(m.millModuleSegments -> m)} - .toMap - - lazy val modules = this.reflectNestedObjects[Module] - lazy val segmentsToTargets = traverse{_.reflect[Target[_]]} - .map(t => (t.ctx.segments, t)) - .toMap + /** + * Miscellaneous machinery around traversing & querying the build hierarchy, + * that should not be needed by normal users of Mill + */ + object millInternal extends Module.Internal(this) - lazy val targets = segmentsToTargets.valuesIterator.toSet - lazy val segmentsToCommands = traverse{ - m => m.reflectNames[Command[_]].map(c => m.parentCtx.segments ++ Seq(Segment.Label(c))) - }.toSet - - def parentCtx = parentCtx0 - // 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 = parentCtx.enclosing - val millModuleLine = parentCtx.lineNum - def basePath: Path = parentCtx.basePath / (parentCtx.segment match{ + lazy val millModuleDirectChildren = millInternal.reflectNestedObjects[Module] + def millOuterCtx = outerCtx0 + def basePath: Path = millOuterCtx.basePath / (millOuterCtx.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 = { - parentCtx.segments0 ++ Seq(parentCtx.segment) - } - def reflect[T: ClassTag] = { - this - .getClass - .getMethods - .filter(!_.getName.contains('$')) - .filter(_.getParameterCount == 0) - .filter(x => (x.getModifiers & Modifier.STATIC) == 0) - .filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _.getReturnType) - .map(_.invoke(this).asInstanceOf[T]) - } - def reflectNames[T: ClassTag] = { - this - .getClass - .getMethods - .filter(x => (x.getModifiers & Modifier.STATIC) == 0) - .filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _.getReturnType) - .map(_.getName) + millOuterCtx.segments0 ++ Seq(millOuterCtx.segment) } - // For some reason, this fails to pick up concrete `object`s nested directly within - // another top-level concrete `object`. This is fine for now, since Mill's Ammonite - // script/REPL runner always wraps user code in a wrapper object/trait - def reflectNestedObjects[T: ClassTag] = { - reflect[T] ++ - this - .getClass - .getClasses - .filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _) - .flatMap(c => c.getFields.find(_.getName == "MODULE$").map(_.get(c).asInstanceOf[T])) +} + +object Module{ + class Internal(outer: Module){ + def traverse[T](f: Module => Seq[T]): Seq[T] = { + 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 segmentsToTargets = traverse{_.millInternal.reflect[Target[_]]} + .map(t => (t.ctx.segments, t)) + .toMap + + lazy val targets = segmentsToTargets.valuesIterator.toSet + + // 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 + lazy val millModuleEnclosing = outer.millOuterCtx.enclosing + lazy val millModuleLine = outer.millOuterCtx.lineNum + + def reflect[T: ClassTag] = { + outer + .getClass + .getMethods + .filter(!_.getName.contains('$')) + .filter(_.getParameterCount == 0) + .filter(x => (x.getModifiers & Modifier.STATIC) == 0) + .filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _.getReturnType) + .map(_.invoke(outer).asInstanceOf[T]) + } + def reflectNames[T: ClassTag] = { + outer + .getClass + .getMethods + .filter(x => (x.getModifiers & Modifier.STATIC) == 0) + .filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _.getReturnType) + .map(_.getName) + } + // For some reason, this fails to pick up concrete `object`s nested directly within + // another top-level concrete `object`. This is fine for now, since Mill's Ammonite + // script/REPL runner always wraps user code in a wrapper object/trait + def reflectNestedObjects[T: ClassTag] = { + reflect[T] ++ + outer + .getClass + .getClasses + .filter(implicitly[ClassTag[T]].runtimeClass isAssignableFrom _) + .flatMap(c => c.getFields.find(_.getName == "MODULE$").map(_.get(c).asInstanceOf[T])) + } } } trait TaskModule extends Module { diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala index fbeb0c62..8f9ff8a2 100644 --- a/core/src/main/scala/mill/eval/Evaluator.scala +++ b/core/src/main/scala/mill/eval/Evaluator.scala @@ -46,7 +46,7 @@ class Evaluator[T](val workspacePath: Path, case t: NamedTask[Any] => val segments = t.ctx.segments val (finalTaskOverrides, enclosing) = t match{ - case t: Target[_] => rootModule.segmentsToTargets(segments).ctx.overrides -> t.ctx.enclosing + case t: Target[_] => rootModule.millInternal.segmentsToTargets(segments).ctx.overrides -> t.ctx.enclosing case c: mill.define.Command[_] => 0 -> c.ctx.enclosing } val additional = diff --git a/core/src/main/scala/mill/main/ReplApplyHandler.scala b/core/src/main/scala/mill/main/ReplApplyHandler.scala index 1dc5410b..97efb6e5 100644 --- a/core/src/main/scala/mill/main/ReplApplyHandler.scala +++ b/core/src/main/scala/mill/main/ReplApplyHandler.scala @@ -70,16 +70,18 @@ class ReplApplyHandler(pprinter0: pprint.PPrinter, val millHandlers: PartialFunction[Any, pprint.Tree] = { case c: Cross[_] => pprint.Tree.Lazy( ctx => - Iterator(c.parentCtx.enclosing , ":", c.parentCtx.lineNum.toString, ctx.applyPrefixColor("\nChildren:").toString) ++ + Iterator(c.millOuterCtx.enclosing , ":", c.millOuterCtx.lineNum.toString, ctx.applyPrefixColor("\nChildren:").toString) ++ c.items.iterator.map(x => "\n (" + x._1.map(pprint.PPrinter.BlackWhite.apply(_)).mkString(", ") + ")" ) ) - case m: mill.Module if evaluator.rootModule.modules.contains(m) => + case m: mill.Module if evaluator.rootModule.millModuleDirectChildren.contains(m) => pprint.Tree.Lazy( ctx => - Iterator(m.millModuleEnclosing, ":", m.millModuleLine.toString) ++ - (if (m.reflect[mill.Module].isEmpty) Nil - else ctx.applyPrefixColor("\nChildren:").toString +: m.reflect[mill.Module].map("\n ." + _.parentCtx.segments.render)) ++ + Iterator(m.millInternal.millModuleEnclosing, ":", m.millInternal.millModuleLine.toString) ++ + (if (m.millInternal.reflect[mill.Module].isEmpty) Nil + else + ctx.applyPrefixColor("\nChildren:").toString +: + m.millInternal.reflect[mill.Module].map("\n ." + _.millOuterCtx.segments.render)) ++ (discover.value.get(m.getClass) match{ case None => Nil case Some(commands) => @@ -89,21 +91,21 @@ class ReplApplyHandler(pprinter0: pprint.PPrinter, ")()" } }) ++ - (if (m.reflect[Target[_]].isEmpty) Nil + (if (m.millInternal.reflect[Target[_]].isEmpty) Nil else { Seq(ctx.applyPrefixColor("\nTargets:").toString) ++ - m.reflect[Target[_]].sortBy(_.label).map(t => + m.millInternal.reflect[Target[_]].sortBy(_.label).map(t => "\n ." + t.label + "()" ) }) ) - case t: mill.define.Target[_] if evaluator.rootModule.targets.contains(t) => + case t: mill.define.Target[_] if evaluator.rootModule.millInternal.targets.contains(t) => val seen = mutable.Set.empty[Task[_]] def rec(t: Task[_]): Seq[Segments] = { if (seen(t)) Nil // do nothing else t match { - case t: Target[_] if evaluator.rootModule.targets.contains(t) => + case t: Target[_] if evaluator.rootModule.millInternal.targets.contains(t) => Seq(t.ctx.segments) case _ => seen.add(t) diff --git a/core/src/main/scala/mill/main/Resolve.scala b/core/src/main/scala/mill/main/Resolve.scala index 6796c821..ed4c4f80 100644 --- a/core/src/main/scala/mill/main/Resolve.scala +++ b/core/src/main/scala/mill/main/Resolve.scala @@ -18,6 +18,7 @@ object Resolve { case Segment.Label(last) :: Nil => val target = obj + .millInternal .reflect[Target[_]] .find(_.label == last) .map(Right(_)) @@ -31,8 +32,8 @@ object Resolve { } val runDefault = for{ - child <- obj.reflectNestedObjects[mill.Module] - if child.parentCtx.segment == Segment.Label(last) + child <- obj.millInternal.reflectNestedObjects[mill.Module] + if child.millOuterCtx.segment == Segment.Label(last) res <- child match{ case taskMod: TaskModule => Some(invokeCommand(child, taskMod.defaultCommandName())) case _ => None @@ -55,8 +56,8 @@ object Resolve { val newRevSelectorsSoFar = head :: revSelectorsSoFar head match{ case Segment.Label(singleLabel) => - obj.reflectNestedObjects[mill.Module].find{ - _.parentCtx.segment == 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) diff --git a/core/src/test/scala/mill/eval/JavaCompileJarTests.scala b/core/src/test/scala/mill/eval/JavaCompileJarTests.scala index e2656913..18948e27 100644 --- a/core/src/test/scala/mill/eval/JavaCompileJarTests.scala +++ b/core/src/test/scala/mill/eval/JavaCompileJarTests.scala @@ -57,7 +57,7 @@ object JavaCompileJarTests extends TestSuite{ Right(Tuple2( evaluated.rawValues(0).asInstanceOf[Result.Success[T]].value, evaluated.evaluated.collect{ - case t: Target[_] if Build.targets.contains(t) => t + case t: Target[_] if Build.millInternal.targets.contains(t) => t case t: mill.define.Command[_] => t }.size )) @@ -72,7 +72,7 @@ object JavaCompileJarTests extends TestSuite{ val evaluated = evaluator.evaluate(targets) .evaluated .flatMap(_.asTarget) - .filter(Build.targets.contains) + .filter(Build.millInternal.targets.contains) .filter(!_.isInstanceOf[Input[_]]) assert(evaluated == expected) } diff --git a/core/src/test/scala/mill/util/TestEvaluator.scala b/core/src/test/scala/mill/util/TestEvaluator.scala index 2f6182d3..47c9d940 100644 --- a/core/src/test/scala/mill/util/TestEvaluator.scala +++ b/core/src/test/scala/mill/util/TestEvaluator.scala @@ -17,7 +17,7 @@ class TestEvaluator(module: mill.Module, Tuple2( evaluated.rawValues.head.asInstanceOf[Result.Success[T]].value, evaluated.evaluated.collect { - case t: Target[_] if module.targets.contains(t) && !t.isInstanceOf[Input[_]] => t + case t: Target[_] if module.millInternal.targets.contains(t) && !t.isInstanceOf[Input[_]] => t case t: mill.define.Command[_] => t }.size )) diff --git a/scalalib/src/main/scala/mill/scalalib/GenIdea.scala b/scalalib/src/main/scala/mill/scalalib/GenIdea.scala index 499e2589..b11c58f3 100644 --- a/scalalib/src/main/scala/mill/scalalib/GenIdea.scala +++ b/scalalib/src/main/scala/mill/scalalib/GenIdea.scala @@ -27,7 +27,7 @@ object GenIdea { def xmlFileLayout[T](evaluator: Evaluator[T], rootModule: mill.Module): Seq[(RelPath, scala.xml.Node)] = { - val modules = rootModule.segmentsToModules.values.collect{case x: scalalib.Module => (x.millModuleSegments, x)}.toSeq + val modules = rootModule.millInternal.segmentsToModules.values.collect{case x: scalalib.Module => (x.millModuleSegments, x)}.toSeq val resolved = for((path, mod) <- modules) yield { val Seq(resolvedCp: Loose.Agg[PathRef], resolvedSrcs: Loose.Agg[PathRef]) = -- cgit v1.2.3