summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2018-09-20 14:15:50 +0800
committerGitHub <noreply@github.com>2018-09-20 14:15:50 +0800
commitd551ee9d751201491a1d64e4da76ab03e3815df6 (patch)
tree60471609f0957401fa1a7002578ad8c1acd6bc75 /main
parentc8fd6bd9e1dc18c24e64147fcd221e0bf91c2d06 (diff)
downloadmill-d551ee9d751201491a1d64e4da76ab03e3815df6.tar.gz
mill-d551ee9d751201491a1d64e4da76ab03e3815df6.tar.bz2
mill-d551ee9d751201491a1d64e4da76ab03e3815df6.zip
Include scaladoc as part of mill inspect (#435)
Diffstat (limited to 'main')
-rw-r--r--main/core/src/mill/define/BaseModule.scala10
-rw-r--r--main/core/src/mill/define/Caller.scala13
-rw-r--r--main/core/src/mill/define/Ctx.scala9
-rw-r--r--main/core/src/mill/define/Task.scala9
-rw-r--r--main/core/src/mill/util/ClassLoader.scala36
-rw-r--r--main/moduledefs/src/mill/moduledefs/AutoOverridePlugin.scala114
-rw-r--r--main/moduledefs/src/mill/moduledefs/Scaladoc.java11
-rw-r--r--main/src/mill/main/MainModule.scala13
-rw-r--r--main/src/mill/main/MainRunner.scala4
-rw-r--r--main/src/mill/main/ReplApplyHandler.scala24
-rw-r--r--main/src/mill/main/Resolve.scala1
-rw-r--r--main/src/mill/main/VisualizeModule.scala1
-rw-r--r--main/src/mill/modules/Util.scala13
-rw-r--r--main/test/src/mill/util/TestUtil.scala3
14 files changed, 224 insertions, 37 deletions
diff --git a/main/core/src/mill/define/BaseModule.scala b/main/core/src/mill/define/BaseModule.scala
index 70826be7..03bdeccc 100644
--- a/main/core/src/mill/define/BaseModule.scala
+++ b/main/core/src/mill/define/BaseModule.scala
@@ -12,7 +12,8 @@ abstract class BaseModule(millSourcePath0: Path,
(implicit millModuleEnclosing0: sourcecode.Enclosing,
millModuleLine0: sourcecode.Line,
millName0: sourcecode.Name,
- millFile0: sourcecode.File)
+ millFile0: sourcecode.File,
+ caller: Caller)
extends Module()(
mill.define.Ctx.make(
implicitly,
@@ -23,7 +24,8 @@ abstract class BaseModule(millSourcePath0: Path,
mill.util.Router.Overrides(0),
Ctx.External(external0),
Ctx.Foreign(foreign0),
- millFile0
+ millFile0,
+ caller
)
){
// A BaseModule should provide an empty Segments list to it's children, since
@@ -40,7 +42,9 @@ abstract class BaseModule(millSourcePath0: Path,
abstract class ExternalModule(implicit millModuleEnclosing0: sourcecode.Enclosing,
millModuleLine0: sourcecode.Line,
millName0: sourcecode.Name)
- extends BaseModule(ammonite.ops.pwd, external0 = true, foreign0 = false){
+ extends BaseModule(ammonite.ops.pwd, external0 = true, foreign0 = false)(
+ implicitly, implicitly, implicitly, implicitly, Caller(())
+ ){
implicit def millDiscoverImplicit: Discover[_] = millDiscover
assert(
diff --git a/main/core/src/mill/define/Caller.scala b/main/core/src/mill/define/Caller.scala
new file mode 100644
index 00000000..6d2d4d1d
--- /dev/null
+++ b/main/core/src/mill/define/Caller.scala
@@ -0,0 +1,13 @@
+package mill.define
+
+import sourcecode.Compat.Context
+import language.experimental.macros
+case class Caller(value: Any)
+object Caller {
+ def apply()(implicit c: Caller) = c.value
+ implicit def generate: Caller = macro impl
+ def impl(c: Context): c.Tree = {
+ import c.universe._
+ q"new _root_.mill.define.Caller(this)"
+ }
+} \ No newline at end of file
diff --git a/main/core/src/mill/define/Ctx.scala b/main/core/src/mill/define/Ctx.scala
index fb15dc19..ba4fae9e 100644
--- a/main/core/src/mill/define/Ctx.scala
+++ b/main/core/src/mill/define/Ctx.scala
@@ -69,7 +69,8 @@ case class Ctx(enclosing: String,
overrides: Int,
external: Boolean,
foreign: Boolean,
- fileName: String){
+ fileName: String,
+ enclosingCls: Class[_]){
}
object Ctx{
@@ -83,7 +84,8 @@ object Ctx{
overrides0: mill.util.Router.Overrides,
external0: External,
foreign0: Foreign,
- fileName: sourcecode.File): Ctx = {
+ fileName: sourcecode.File,
+ enclosing: Caller): Ctx = {
Ctx(
millModuleEnclosing0.value,
millModuleLine0.value,
@@ -93,7 +95,8 @@ object Ctx{
overrides0.value,
external0.value,
foreign0.value,
- fileName.value
+ fileName.value,
+ enclosing.value.getClass
)
}
}
diff --git a/main/core/src/mill/define/Task.scala b/main/core/src/mill/define/Task.scala
index d5f8680e..64e868f8 100644
--- a/main/core/src/mill/define/Task.scala
+++ b/main/core/src/mill/define/Task.scala
@@ -254,15 +254,6 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul
def zip[A, B](a: Task[A], b: Task[B]) = a.zip(b)
}
-case class Caller[A](value: A)
-object Caller {
- def apply[T]()(implicit c: Caller[T]) = c.value
- implicit def generate[T]: Caller[T] = macro impl[T]
- def impl[T: c.WeakTypeTag](c: Context): c.Tree = {
- import c.universe._
- q"new _root_.mill.define.Caller[${weakTypeOf[T]}](this)"
- }
-}
abstract class NamedTaskImpl[+T](ctx0: mill.define.Ctx, t: Task[T]) extends NamedTask[T]{
def evaluate(args: mill.util.Ctx) = args[T](0)
val ctx = ctx0.copy(segments = ctx0.segments ++ Seq(ctx0.segment))
diff --git a/main/core/src/mill/util/ClassLoader.scala b/main/core/src/mill/util/ClassLoader.scala
index 17268fb0..ebe8e50b 100644
--- a/main/core/src/mill/util/ClassLoader.scala
+++ b/main/core/src/mill/util/ClassLoader.scala
@@ -5,15 +5,18 @@ import java.net.{URL, URLClassLoader}
import ammonite.ops._
import io.github.retronym.java9rtexport.Export
-object ClassLoader {
-
- def create(urls: Seq[URL], parent: java.lang.ClassLoader)(
- implicit ctx: Ctx.Home): URLClassLoader = create(urls, parent, _ => None)
+import scala.util.Try
+object ClassLoader {
+ def create(urls: Seq[URL],
+ parent: java.lang.ClassLoader)
+ (implicit ctx: Ctx.Home): URLClassLoader = {
+ create(urls, parent, _ => None)
+ }
def create(urls: Seq[URL],
parent: java.lang.ClassLoader,
- customFindClass: String => Option[Class[_]])(
- implicit ctx: Ctx.Home): URLClassLoader = {
+ customFindClass: String => Option[Class[_]])
+ (implicit ctx: Ctx.Home): URLClassLoader = {
new URLClassLoader(
makeUrls(urls).toArray,
refinePlatformParent(parent)
@@ -25,6 +28,7 @@ object ClassLoader {
}
}
+
/**
* Return `ClassLoader.getPlatformClassLoader` for java 9 and above, if parent class loader is null,
* otherwise return same parent class loader.
@@ -34,15 +38,17 @@ object ClassLoader {
* mill could be compiled only with jdk 9 or above. We don't want to introduce this restriction now.
*/
private def refinePlatformParent(parent: java.lang.ClassLoader): ClassLoader = {
- if (ammonite.util.Util.java9OrAbove) {
- if (parent == null)
- classOf[ClassLoader]
- .getMethod("getPlatformClassLoader")
- .invoke(null)
- .asInstanceOf[ClassLoader]
- else parent
- } else {
- parent
+ if (!ammonite.util.Util.java9OrAbove || parent != null) parent
+ else {
+ // Make sure when `parent == null`, we only delegate java.* classes
+ // to the parent getPlatformClassLoader. This is necessary because
+ // in Java 9+, somehow the getPlatformClassLoader ends up with all
+ // sorts of other non-java stuff on it's classpath, which is not what
+ // we want for an "isolated" classloader!
+ classOf[ClassLoader]
+ .getMethod("getPlatformClassLoader")
+ .invoke(null)
+ .asInstanceOf[ClassLoader]
}
}
diff --git a/main/moduledefs/src/mill/moduledefs/AutoOverridePlugin.scala b/main/moduledefs/src/mill/moduledefs/AutoOverridePlugin.scala
index 5b33abbe..a870e7ec 100644
--- a/main/moduledefs/src/mill/moduledefs/AutoOverridePlugin.scala
+++ b/main/moduledefs/src/mill/moduledefs/AutoOverridePlugin.scala
@@ -1,10 +1,14 @@
package mill.moduledefs
+
+import scala.collection.mutable.ListBuffer
import scala.reflect.internal.Flags
+import scala.tools.nsc.doc.ScaladocSyntaxAnalyzer
import scala.tools.nsc.io.VirtualFile
import scala.tools.nsc.util.BatchSourceFile
import scala.tools.nsc.{Global, Phase}
import scala.tools.nsc.plugins.{Plugin, PluginComponent}
+import scala.tools.nsc.transform.Transform
class AutoOverridePlugin(val global: Global) extends Plugin {
import global._
@@ -12,7 +16,117 @@ class AutoOverridePlugin(val global: Global) extends Plugin {
val name = "auto-override-plugin"
val description = "automatically inserts `override` keywords for you"
+
val components = List[PluginComponent](
+ new PluginComponent with Transform {
+ type GT = AutoOverridePlugin.this.global.type
+ override val global: GT = AutoOverridePlugin.this.global
+ override val phaseName: String = "EmbedScaladocAnnotation"
+ override val runsAfter: List[String] = List("parser")
+ override def newTransformer(unit: global.CompilationUnit): global.Transformer = {
+ new ScaladocTransformer
+ }
+ import global._
+
+
+ class ScaladocTransformer extends global.Transformer {
+
+ val comments = new Comments()
+
+ override def transformUnit(unit: CompilationUnit)= {
+ if (unit.source.file.name.endsWith(".scala") ||
+ unit.source.file.name.endsWith(".sc")){
+ comments.parseComments(unit)
+ super.transformUnit(unit)
+ }
+ }
+
+ override def transform(tree: global.Tree): global.Tree = {
+ super.transform(tree match {
+ case x: global.ClassDef =>
+ comments.getComment(x.pos) match {
+ case Some(comment) =>
+ global.treeCopy.ClassDef(tree, newMods(x.mods, comment), x.name, x.tparams, x.impl)
+ case None => x
+ }
+
+ case x: global.ModuleDef =>
+ comments.getComment(x.pos) match {
+ case Some(comment) =>
+ global.treeCopy.ModuleDef(tree, newMods(x.mods, comment), x.name, x.impl)
+ case None => x
+ }
+
+ case x: global.DefDef =>
+ comments.getComment(x.pos) match {
+ case Some(comment) =>
+ global.treeCopy.DefDef(tree, newMods(x.mods, comment), x.name, x.tparams, x.vparamss, x.tpt, x.rhs)
+ case None => x
+ }
+
+ case x: global.ValDef =>
+ comments.getComment(x.pos) match {
+ case Some(comment) =>
+ global.treeCopy.ValDef(tree, newMods(x.mods, comment), x.name, x.tpt, x.rhs)
+ case None => x
+ }
+
+ case x => x
+ })
+ }
+
+ def newMods(old: global.Modifiers, comment: String) = {
+ old.copy(
+ annotations = createAnnotation(comment) :: old.annotations
+ )
+ }
+
+ private def createAnnotation(comment: String): global.Tree =
+ global.Apply(
+ global.Select(
+ global.New(
+ global.Select(
+ global.Select(
+ global.Ident(
+ global.newTermName("mill")
+ ),
+ global.newTermName("moduledefs")
+ ),
+ global.newTypeName("Scaladoc")
+ )
+ ),
+ global.nme.CONSTRUCTOR
+ ),
+ List(Literal(Constant(comment)))
+ )
+
+ }
+
+ class Comments extends ScaladocSyntaxAnalyzer[global.type](global){
+ val comments = ListBuffer[(Position, String)]()
+
+ def getComment(pos: Position): Option[String] = {
+ val tookComments = comments.takeWhile { case (x, _) => x.end < pos.start }
+ comments --= (tookComments)
+ tookComments.lastOption.map(_._2)
+ }
+
+ def parseComments(unit: CompilationUnit): Unit = {
+ comments.clear()
+
+ new ScaladocUnitParser(unit, Nil) {
+ override def newScanner = new ScaladocUnitScanner(unit, Nil) {
+ override def registerDocComment(str: String, pos: Position) = {
+ comments += ((pos, str))
+ }
+ }
+ }.parse()
+ }
+
+ override val runsAfter: List[String] = Nil
+ override val runsRightAfter: Option[String] = None
+ }
+ },
new PluginComponent {
val global = AutoOverridePlugin.this.global
diff --git a/main/moduledefs/src/mill/moduledefs/Scaladoc.java b/main/moduledefs/src/mill/moduledefs/Scaladoc.java
new file mode 100644
index 00000000..7a7d700b
--- /dev/null
+++ b/main/moduledefs/src/mill/moduledefs/Scaladoc.java
@@ -0,0 +1,11 @@
+package mill.moduledefs;
+
+
+import java.lang.annotation.*;
+
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Scaladoc {
+ String value();
+}
diff --git a/main/src/mill/main/MainModule.scala b/main/src/mill/main/MainModule.scala
index 834d5609..7e326860 100644
--- a/main/src/mill/main/MainModule.scala
+++ b/main/src/mill/main/MainModule.scala
@@ -135,6 +135,7 @@ trait MainModule extends mill.Module{
*/
def inspect(evaluator: Evaluator, targets: String*) = mill.T.command{
MainModule.resolveTasks(evaluator, targets, multiSelect = true){ tasks =>
+ val output = new StringBuilder
for{
task <- tasks
tree = ReplApplyHandler.pprintTask(task, evaluator)
@@ -149,8 +150,10 @@ trait MainModule extends mill.Module{
val truncated = new Truncated(rendered, defaults.defaultWidth, defaults.defaultHeight)
str <- truncated ++ Iterator("\n")
} {
- print(str)
+ output.append(str)
}
+ println(output)
+ output.toString
}
}
@@ -222,10 +225,17 @@ trait MainModule extends mill.Module{
}
}
+
+ /**
+ * Renders the dependencies between the given tasks as a SVG for you to look at
+ */
def visualize(evaluator: Evaluator, targets: String*) = mill.T.command{
visualize0(evaluator, targets, T.ctx(), mill.main.VisualizeModule.worker())
}
+ /**
+ * Renders the dependencies between the given tasks, and all their dependencies, as a SVG
+ */
def visualizePlan(evaluator: Evaluator, targets: String*) = mill.T.command{
plan0(evaluator, targets) match {
case Left(err) => Result.Failure(err)
@@ -258,5 +268,4 @@ trait MainModule extends mill.Module{
}
}
}
-
}
diff --git a/main/src/mill/main/MainRunner.scala b/main/src/mill/main/MainRunner.scala
index 30a23632..58c47998 100644
--- a/main/src/mill/main/MainRunner.scala
+++ b/main/src/mill/main/MainRunner.scala
@@ -144,7 +144,9 @@ class MainRunner(val config: ammonite.main.Cli.Config,
|$imports
|import mill._
|object $wrapName
- |extends mill.define.BaseModule(ammonite.ops.Path($literalPath), foreign0 = $external)
+ |extends mill.define.BaseModule(ammonite.ops.Path($literalPath), foreign0 = $external)(
+ | implicitly, implicitly, implicitly, implicitly, mill.define.Caller(())
+ |)
|with $wrapName{
| // Stub to make sure Ammonite has something to call after it evaluates a script,
| // even if it does nothing...
diff --git a/main/src/mill/main/ReplApplyHandler.scala b/main/src/mill/main/ReplApplyHandler.scala
index c40b82c9..59a6780b 100644
--- a/main/src/mill/main/ReplApplyHandler.scala
+++ b/main/src/mill/main/ReplApplyHandler.scala
@@ -6,6 +6,7 @@ import mill.define.Applicative.ApplyHandler
import mill.define.Segment.Label
import mill.define._
import mill.eval.{Evaluator, Result}
+
import mill.util.Strict.Agg
import scala.collection.mutable
@@ -69,6 +70,11 @@ object ReplApplyHandler{
)
}
+
+ def resolveParents(c: Class[_]): Seq[Class[_]] = {
+ Seq(c) ++ Option(c.getSuperclass).toSeq.flatMap(resolveParents) ++ c.getInterfaces.flatMap(resolveParents)
+ }
+
def pprintTask(t: NamedTask[_], evaluator: Evaluator) = {
val seen = mutable.Set.empty[Task[_]]
def rec(t: Task[_]): Seq[Segments] = {
@@ -81,10 +87,24 @@ object ReplApplyHandler{
t.inputs.flatMap(rec)
}
}
+
+ val annots = for {
+ c <- resolveParents(t.ctx.enclosingCls)
+ m <- c.getMethods
+ if m.getName == t.ctx.segment.pathSegments.head
+ a = m.getAnnotation(classOf[mill.moduledefs.Scaladoc])
+ if a != null
+ }yield a
+
+ val allDocs =
+ for(a <- annots.distinct)
+ yield mill.modules.Util.cleanupScaladoc(a.value).map("\n " + _).mkString
+
pprint.Tree.Lazy(ctx =>
Iterator(
- t.toString, "(", t.ctx.fileName.split('/').last, ":", t.ctx.lineNum.toString, ")",
- "\n", ctx.applyPrefixColor("Inputs:").toString
+ ctx.applyPrefixColor(t.toString).toString, "(", t.ctx.fileName.split('/').last, ":", t.ctx.lineNum.toString, ")",
+ allDocs.mkString("\n"), "\n",
+ "\n", ctx.applyPrefixColor("Inputs").toString, ":"
) ++ t.inputs.iterator.flatMap(rec).map("\n " + _.render)
)
}
diff --git a/main/src/mill/main/Resolve.scala b/main/src/mill/main/Resolve.scala
index d0a08c87..a2c186ed 100644
--- a/main/src/mill/main/Resolve.scala
+++ b/main/src/mill/main/Resolve.scala
@@ -219,6 +219,7 @@ object ResolveTasks extends Resolve[NamedTask[Any]]{
}
}
}
+
object Resolve{
def minimum(i1: Int, i2: Int, i3: Int)= math.min(math.min(i1, i2), i3)
diff --git a/main/src/mill/main/VisualizeModule.scala b/main/src/mill/main/VisualizeModule.scala
index 6945cf2f..ea4d46c6 100644
--- a/main/src/mill/main/VisualizeModule.scala
+++ b/main/src/mill/main/VisualizeModule.scala
@@ -10,7 +10,6 @@ import mill.T
import mill.define.{Discover, ExternalModule}
import mill.eval.{PathRef, Result}
-
object VisualizeModule extends ExternalModule with VisualizeModule {
def repositories = Seq(
Cache.ivy2Local,
diff --git a/main/src/mill/modules/Util.scala b/main/src/mill/modules/Util.scala
index 2d71c13e..38cd056b 100644
--- a/main/src/mill/modules/Util.scala
+++ b/main/src/mill/modules/Util.scala
@@ -7,6 +7,19 @@ import mill.eval.PathRef
import mill.util.{Ctx, IO, Loose}
object Util {
+ def cleanupScaladoc(v: String) = {
+ v.lines.map(
+ _.dropWhile(_.isWhitespace)
+ .stripPrefix("/**")
+ .stripPrefix("*/")
+ .stripPrefix("*")
+ .dropWhile(_.isWhitespace)
+ ).toArray
+ .dropWhile(_.isEmpty)
+ .reverse
+ .dropWhile(_.isEmpty)
+ .reverse
+ }
def download(url: String, dest: RelPath = "download")(implicit ctx: Ctx.Dest) = {
val out = ctx.dest / dest
diff --git a/main/test/src/mill/util/TestUtil.scala b/main/test/src/mill/util/TestUtil.scala
index dede8bcf..b4e3af89 100644
--- a/main/test/src/mill/util/TestUtil.scala
+++ b/main/test/src/mill/util/TestUtil.scala
@@ -31,7 +31,8 @@ object TestUtil {
millModuleLine0: sourcecode.Line,
millName0: sourcecode.Name,
overrides: Overrides)
- extends mill.define.BaseModule(getSrcPathBase() / millModuleEnclosing0.value.split("\\.| |#")){
+ extends mill.define.BaseModule(getSrcPathBase() / millModuleEnclosing0.value.split("\\.| |#"))(
+ implicitly, implicitly, implicitly, implicitly, implicitly){
lazy val millDiscover: Discover[this.type] = Discover[this.type]
}