From a4ca7933cd6b8cc032ecca591143c26bb2857fd1 Mon Sep 17 00:00:00 2001 From: Shri333 Date: Thu, 12 Sep 2024 16:46:56 -0400 Subject: [PATCH] Issue #2929: implement inspect for modules (WIP) Pull request: https://github.com/com-lihaoyi/mill/pull/3532 --- main/define/src/mill/define/Module.scala | 7 +++ main/resolve/src/mill/resolve/Resolve.scala | 33 ++--------- main/src/mill/main/MainModule.scala | 63 +++++++++++++++++++-- 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/main/define/src/mill/define/Module.scala b/main/define/src/mill/define/Module.scala index c90722b5ff2..785620bdbd9 100644 --- a/main/define/src/mill/define/Module.scala +++ b/main/define/src/mill/define/Module.scala @@ -92,3 +92,10 @@ object Module { } } } + +class ModuleTask[+T](val cls: Class[_], val module: Module) + extends NamedTask[T] { + override def t: Task[T] = this + override def ctx0: Ctx = module.millOuterCtx + override def isPrivate: Option[Boolean] = None +} diff --git a/main/resolve/src/mill/resolve/Resolve.scala b/main/resolve/src/mill/resolve/Resolve.scala index 09c0edc6590..c0d5a6a87c1 100644 --- a/main/resolve/src/mill/resolve/Resolve.scala +++ b/main/resolve/src/mill/resolve/Resolve.scala @@ -6,11 +6,11 @@ import mill.define.{ Command, Discover, Module, + ModuleTask, NamedTask, Reflect, Segments, - Target, - TaskModule + Target } import mill.resolve.ResolveCore.{Resolved, makeResultException} import mill.util.EitherOps @@ -45,7 +45,6 @@ object Resolve { val instantiated = ResolveCore .instantiateModule(rootModule, r.segments.init) .flatMap(instantiateTarget(r, _)) - instantiated.map(Some(_)) case r: Resolved.Command => @@ -61,35 +60,13 @@ object Resolve { allowPositionalCommandArgs ) } - instantiated.map(Some(_)) case r: Resolved.Module => - ResolveCore.instantiateModule(rootModule, r.segments).flatMap { - case value: TaskModule => - val directChildrenOrErr = ResolveCore.resolveDirectChildren( - rootModule, - value.getClass, - Some(value.defaultCommandName()), - value.millModuleSegments - ) - - directChildrenOrErr.flatMap(directChildren => - directChildren.head match { - case r: Resolved.Target => instantiateTarget(r, value).map(Some(_)) - case r: Resolved.Command => - instantiateCommand( - rootModule, - r, - value, - args, - nullCommandDefaults, - allowPositionalCommandArgs - ).map(Some(_)) - } - ) - case _ => Right(None) + val instantiated = ResolveCore.instantiateModule(rootModule, r.segments).flatMap { mod => + Right(new ModuleTask(r.cls, mod)) } + instantiated.map(Some(_)) } val sequenced = EitherOps.sequence(taskList).map(_.flatten) diff --git a/main/src/mill/main/MainModule.scala b/main/src/mill/main/MainModule.scala index 54421527574..4d413026315 100644 --- a/main/src/mill/main/MainModule.scala +++ b/main/src/mill/main/MainModule.scala @@ -1,15 +1,17 @@ package mill.main -import java.util.concurrent.LinkedBlockingQueue -import mill.define.{BaseModule0, Command, NamedTask, Segments, Target, Task} import mill.api.{Ctx, Logger, PathRef, Result} +import mill.define._ import mill.eval.{Evaluator, EvaluatorPaths, Terminal} -import mill.resolve.{Resolve, SelectMode} +import mill.moduledefs.Scaladoc import mill.resolve.SelectMode.Separated -import mill.util.Watchable +import mill.resolve.{Resolve, SelectMode} +import mill.util.{Util, Watchable} import pprint.{Renderer, Tree, Truncated} +import java.util.concurrent.LinkedBlockingQueue import scala.collection.mutable +import scala.reflect.NameTransformer.decode object MainModule { @@ -175,12 +177,12 @@ trait MainModule extends BaseModule0 { * Displays metadata about the given task without actually running it. */ def inspect(evaluator: Evaluator, targets: String*): Command[String] = Target.command { - def resolveParents(c: Class[_]): Seq[Class[_]] = { Seq(c) ++ Option(c.getSuperclass).toSeq.flatMap(resolveParents) ++ c.getInterfaces.flatMap( resolveParents ) } + def pprintTask(t: NamedTask[_], evaluator: Evaluator): Tree.Lazy = { val seen = mutable.Set.empty[Task[_]] @@ -266,10 +268,59 @@ trait MainModule extends BaseModule0 { } } + def pprintModule(t: ModuleTask[_]): Tree.Lazy = { + val annotation = t.cls.getAnnotation(classOf[Scaladoc]) + val scaladocOpt = Option.when(annotation != null)( + Util.cleanupScaladoc(annotation.value).map("\n " + _).mkString + ) + val fileName = t.ctx.fileName.split('/').last.split('\\').last + val parents = t.cls.getInterfaces ++ Option(t.cls.getSuperclass).toSeq + val inheritedModules = + parents.distinct.filter(classOf[Module].isAssignableFrom(_)).map(_.getSimpleName) + val moduleDepsOpt = t.cls.getMethods.find(m => decode(m.getName) == "moduleDeps").map( + _.invoke(t.module).asInstanceOf[Seq[Module]] + ).filter(_.nonEmpty) + val defaultTaskOpt = t.module match { + case taskMod: TaskModule => Some(s"${t.module}.${taskMod.defaultCommandName()}") + case _ => None + } + val tasks = t.module.millInternal.targets.map(_.toString) + pprint.Tree.Lazy { ctx => + Iterator( + ctx.applyPrefixColor(t.module.toString).toString, + s"($fileName:${t.ctx.lineNum})" + ) ++ Iterator(scaladocOpt).flatten ++ Iterator( + "\n\n", + ctx.applyPrefixColor("Inherited Modules").toString, + ": ", + inheritedModules.mkString(", ") + ) ++ moduleDepsOpt.fold(Iterator.empty[String])(deps => + Iterator( + "\n\n", + ctx.applyPrefixColor("Module Dependencies").toString, + ": ", + deps.mkString(", ") + ) + ) ++ defaultTaskOpt.fold(Iterator.empty[String])(task => + Iterator("\n\n", ctx.applyPrefixColor("Default Task").toString, ": ", task) + ) ++ (if (tasks.nonEmpty) + Iterator( + "\n\n", + ctx.applyPrefixColor("Tasks").toString, + ": ", + tasks.mkString(", ") + ) + else Iterator.empty[String]) + } + } + MainModule.resolveTasks(evaluator, targets, SelectMode.Multi) { tasks => val output = (for { task <- tasks - tree = pprintTask(task, evaluator) + tree = task match { + case t: ModuleTask[_] => pprintModule(t) + case t => pprintTask(t, evaluator) + } defaults = pprint.PPrinter() renderer = new Renderer( defaults.defaultWidth,