Skip to content

Commit

Permalink
Issue #2929: implement inspect for modules (WIP)
Browse files Browse the repository at this point in the history
Pull request: #3532
  • Loading branch information
Shri333 committed Sep 19, 2024
1 parent 2dc343f commit a4ca793
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 34 deletions.
7 changes: 7 additions & 0 deletions main/define/src/mill/define/Module.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
33 changes: 5 additions & 28 deletions main/resolve/src/mill/resolve/Resolve.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -45,7 +45,6 @@ object Resolve {
val instantiated = ResolveCore
.instantiateModule(rootModule, r.segments.init)
.flatMap(instantiateTarget(r, _))

instantiated.map(Some(_))

case r: Resolved.Command =>
Expand All @@ -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)
Expand Down
63 changes: 57 additions & 6 deletions main/src/mill/main/MainModule.scala
Original file line number Diff line number Diff line change
@@ -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 {

Expand Down Expand Up @@ -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[_]]

Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit a4ca793

Please sign in to comment.