diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2018-02-04 11:38:02 -0800 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2018-02-04 11:38:02 -0800 |
commit | 2536dc8c071c7c0fc41a0bd806d91ecad300f27c (patch) | |
tree | 67ac9f76d5cdd0fa5fafee1d652877806e2a8505 /core | |
parent | 0e7a30ef554cf5b2725af4a7afc73b9e11287547 (diff) | |
download | mill-2536dc8c071c7c0fc41a0bd806d91ecad300f27c.tar.gz mill-2536dc8c071c7c0fc41a0bd806d91ecad300f27c.tar.bz2 mill-2536dc8c071c7c0fc41a0bd806d91ecad300f27c.zip |
Add support for external modules, useful for things `GenIdea` support
Diffstat (limited to 'core')
-rw-r--r-- | core/src/mill/define/BaseModule.scala | 47 | ||||
-rw-r--r-- | core/src/mill/define/Discover.scala | 6 | ||||
-rw-r--r-- | core/src/mill/define/Module.scala | 39 | ||||
-rw-r--r-- | core/src/mill/eval/Evaluator.scala | 8 | ||||
-rw-r--r-- | core/src/mill/main/ParseArgs.scala | 14 | ||||
-rw-r--r-- | core/src/mill/main/RunScript.scala | 23 | ||||
-rw-r--r-- | core/test/src/mill/eval/ModuleTests.scala | 3 | ||||
-rw-r--r-- | core/test/src/mill/main/MainTests.scala | 6 | ||||
-rw-r--r-- | core/test/src/mill/util/ScriptTestSuite.scala | 2 |
9 files changed, 91 insertions, 57 deletions
diff --git a/core/src/mill/define/BaseModule.scala b/core/src/mill/define/BaseModule.scala new file mode 100644 index 00000000..9cefeeae --- /dev/null +++ b/core/src/mill/define/BaseModule.scala @@ -0,0 +1,47 @@ +package mill.define + +import ammonite.main.Router.Overrides +import ammonite.ops.Path + +object BaseModule{ + case class Implicit(value: BaseModule) +} +class BaseModule(millSourcePath0: Path, external0: Boolean = false) + (implicit millModuleEnclosing0: sourcecode.Enclosing, + millModuleLine0: sourcecode.Line, + millName0: sourcecode.Name) + extends Module()( + mill.define.Ctx.make( + implicitly, + implicitly, + implicitly, + BasePath(millSourcePath0), + Segments(), + Overrides(0), + Ctx.External(external0) + ) + ){ + // A BaseModule should provide an empty Segments list to it's children, since + // it is the root of the module tree, and thus must not include it's own + // sourcecode.Name as part of the list, + override implicit def millModuleSegments: Segments = Segments() + override def millSourcePath = millOuterCtx.millSourcePath + override implicit def millModuleBasePath: BasePath = BasePath(millSourcePath) + implicit def millImplicitBaseModule: BaseModule.Implicit = BaseModule.Implicit(this) +} + + +abstract class ExternalModule(implicit millModuleEnclosing0: sourcecode.Enclosing, + millModuleLine0: sourcecode.Line, + millName0: sourcecode.Name) + extends BaseModule(ammonite.ops.pwd, external0 = true){ + def millDiscover: Discover[_] + implicit def millDiscoverImplicit: Discover[_] = millDiscover + assert( + !" #".exists(millModuleEnclosing0.value.contains(_)), + "External modules must be at a top-level static path, not " + millModuleEnclosing0.value + ) + override implicit def millModuleSegments = { + Segments(millModuleEnclosing0.value.split('.').map(Segment.Label):_*) + } +}
\ No newline at end of file diff --git a/core/src/mill/define/Discover.scala b/core/src/mill/define/Discover.scala index ab2ba900..98e29a76 100644 --- a/core/src/mill/define/Discover.scala +++ b/core/src/mill/define/Discover.scala @@ -53,11 +53,11 @@ object Discover { } yield (m.overrides.length, router.extractMethod(m, curCls).asInstanceOf[c.Tree]) } if overridesRoutes.nonEmpty - val (overrides, routes) = overridesRoutes.unzip - } yield { + val (overrides, routes) = overridesRoutes.unzip val lhs = q"classOf[${discoveredModuleType.typeSymbol.asClass}]" - val rhs = q"scala.Seq[(Int, ammonite.main.Router.EntryPoint[${discoveredModuleType.typeSymbol.asClass}])](..$overridesRoutes)" + val clsType = discoveredModuleType.typeSymbol.asClass + val rhs = q"scala.Seq[(Int, ammonite.main.Router.EntryPoint[$clsType])](..$overridesRoutes)" q"$lhs -> $rhs" } diff --git a/core/src/mill/define/Module.scala b/core/src/mill/define/Module.scala index e765a6b4..66132fa9 100644 --- a/core/src/mill/define/Module.scala +++ b/core/src/mill/define/Module.scala @@ -90,42 +90,3 @@ object Module{ trait TaskModule extends Module { def defaultCommandName(): String } -object BaseModule{ - case class Implicit(value: BaseModule) -} -class BaseModule(millSourcePath0: Path, external0: Boolean = false) - (implicit millModuleEnclosing0: sourcecode.Enclosing, - millModuleLine0: sourcecode.Line, - millName0: sourcecode.Name) - extends Module()( - mill.define.Ctx.make( - implicitly, - implicitly, - implicitly, - BasePath(millSourcePath0), - Segments(), - Overrides(0), - Ctx.External(external0) - ) - ){ - // A BaseModule should provide an empty Segments list to it's children, since - // it is the root of the module tree, and thus must not include it's own - // sourcecode.Name as part of the list, - override implicit def millModuleSegments: Segments = Segments() - override def millSourcePath = millOuterCtx.millSourcePath - override implicit def millModuleBasePath: BasePath = BasePath(millSourcePath) - implicit def millImplicitBaseModule: BaseModule.Implicit = BaseModule.Implicit(this) -} - -class ExternalModule(implicit millModuleEnclosing0: sourcecode.Enclosing, - millModuleLine0: sourcecode.Line, - millName0: sourcecode.Name) - extends BaseModule(ammonite.ops.pwd, external0 = true){ - assert( - !" #".exists(millModuleEnclosing0.value.contains(_)), - "External modules must be at a top-level static path, not " + millModuleEnclosing0.value - ) - override implicit def millModuleSegments = { - Segments(millModuleEnclosing0.value.split('.').map(Segment.Label):_*) - } -}
\ No newline at end of file diff --git a/core/src/mill/eval/Evaluator.scala b/core/src/mill/eval/Evaluator.scala index bb78a020..3d6d253b 100644 --- a/core/src/mill/eval/Evaluator.scala +++ b/core/src/mill/eval/Evaluator.scala @@ -58,7 +58,13 @@ class Evaluator[T](val outPath: Path, } } } - findMatching(c.cls).get.find(_._2.name == c.ctx.segment.pathSegments.head).get._1 + + findMatching(c.cls) match{ + case Some(v) => v.find(_._2.name == c.ctx.segment.pathSegments.head).get._1 + // For now we don't properly support overrides for external modules + // that do not appear in the Evaluator's main Discovered listing + case None => 0 + } case c: mill.define.Worker[_] => 0 } diff --git a/core/src/mill/main/ParseArgs.scala b/core/src/mill/main/ParseArgs.scala index 7170cc60..bafcd907 100644 --- a/core/src/mill/main/ParseArgs.scala +++ b/core/src/mill/main/ParseArgs.scala @@ -2,12 +2,12 @@ package mill.main import mill.util.EitherOps import fastparse.all._ -import mill.define.Segment +import mill.define.{Segment, Segments} object ParseArgs { def apply(scriptArgs: Seq[String]) - : Either[String, (List[List[Segment]], Seq[String])] = { + : Either[String, (List[(Option[Segments], Segments)], Seq[String])] = { val (selectors, args, isMultiSelectors) = extractSelsAndArgs(scriptArgs) for { _ <- validateSelectors(selectors) @@ -119,7 +119,7 @@ object ParseArgs { .parse(input) } - def extractSegments(selectorString: String): Either[String, List[Segment]] = + def extractSegments(selectorString: String): Either[String, (Option[Segments], Segments)] = parseSelector(selectorString) match { case f: Parsed.Failure => Left(s"Parsing exception ${f.msg}") case Parsed.Success(selector, _) => Right(selector) @@ -131,8 +131,12 @@ object ParseArgs { 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 + val simpleQuery = P(segment ~ ("." ~ segment | crossSegment).rep).map { + case (h, rest) => Segments(h :: rest.toList:_*) + } + val query = P( simpleQuery ~ ("/" ~/ simpleQuery).?).map{ + case (q, None) => (None, q) + case (q, Some(q2)) => (Some(q), q2) } query.parse(input) } diff --git a/core/src/mill/main/RunScript.scala b/core/src/mill/main/RunScript.scala index a05c7623..2efe0e97 100644 --- a/core/src/mill/main/RunScript.scala +++ b/core/src/mill/main/RunScript.scala @@ -8,7 +8,7 @@ import ammonite.runtime.SpecialClassLoader import ammonite.util.Util.CodeSource import ammonite.util.{Name, Res, Util} import mill.{PathRef, define} -import mill.define.{Discover, Segment, Task} +import mill.define.{Discover, ExternalModule, Segment, Task} import mill.eval.{Evaluator, Result} import mill.util.{EitherOps, Logger} import mill.util.Strict.Agg @@ -135,15 +135,26 @@ object RunScript{ parsed <- ParseArgs(scriptArgs) (selectors, args) = parsed targets <- { - val selected = selectors.map { sel => - val crossSelectors = sel.map { + val selected = selectors.map { case (scopedSel, sel) => + val (rootModule, discover) = scopedSel match{ + case None => (evaluator.rootModule, evaluator.discover) + case Some(scoping) => + val moduleCls = + evaluator.rootModule.getClass.getClassLoader.loadClass(scoping.render + "$") + + pprint.log(moduleCls.getFields) + pprint.log(moduleCls.getMethods) + val rootModule = moduleCls.getField("MODULE$").get(moduleCls).asInstanceOf[ExternalModule] + (rootModule, rootModule.millDiscover) + } + val crossSelectors = sel.value.map { case Segment.Cross(x) => x.toList.map(_.toString) case _ => Nil } mill.main.Resolve.resolve( - sel, evaluator.rootModule, - evaluator.discover, - args, crossSelectors, Nil + sel.value.toList, rootModule, + discover, + args, crossSelectors.toList, Nil ) } EitherOps.sequence(selected) diff --git a/core/test/src/mill/eval/ModuleTests.scala b/core/test/src/mill/eval/ModuleTests.scala index b452a854..c6061abb 100644 --- a/core/test/src/mill/eval/ModuleTests.scala +++ b/core/test/src/mill/eval/ModuleTests.scala @@ -3,6 +3,7 @@ package mill.eval import ammonite.ops._ import mill.util.{TestEvaluator, TestUtil} import mill.T +import mill.define.Discover import mill.util.TestEvaluator.implicitDisover import utest._ @@ -13,6 +14,7 @@ object ModuleTests extends TestSuite{ object inner extends mill.Module{ def y = T{17} } + def millDiscover = Discover[this.type] } object Build extends TestUtil.BaseModule{ def z = T{ ExternalModule.x() + ExternalModule.inner.y() } @@ -35,6 +37,7 @@ object ModuleTests extends TestSuite{ object Build extends mill.define.ExternalModule { def z = T{ ExternalModule.x() + ExternalModule.inner.y() } + def millDiscover = Discover[this.type] } intercept[java.lang.AssertionError]{ Build } diff --git a/core/test/src/mill/main/MainTests.scala b/core/test/src/mill/main/MainTests.scala index 3d8e4d5c..22f93ae0 100644 --- a/core/test/src/mill/main/MainTests.scala +++ b/core/test/src/mill/main/MainTests.scala @@ -14,8 +14,10 @@ object MainTests extends TestSuite{ val expected = expected0.map(_.map(_(module))) val resolved = for{ selectors <- mill.main.ParseArgs(Seq(selectorString)).map(_._1.head) - val crossSelectors = selectors.map{case Segment.Cross(x) => x.toList.map(_.toString) case _ => Nil} - task <- mill.main.Resolve.resolve(selectors, module, discover, Nil, crossSelectors, Nil) + val crossSelectors = selectors._2.value.map{case Segment.Cross(x) => x.toList.map(_.toString) case _ => Nil} + task <- mill.main.Resolve.resolve( + selectors._2.value.toList, module, discover, Nil, crossSelectors.toList, Nil + ) } yield task assert(resolved == expected) } diff --git a/core/test/src/mill/util/ScriptTestSuite.scala b/core/test/src/mill/util/ScriptTestSuite.scala index 7a963ef9..1aa74de1 100644 --- a/core/test/src/mill/util/ScriptTestSuite.scala +++ b/core/test/src/mill/util/ScriptTestSuite.scala @@ -22,7 +22,7 @@ abstract class ScriptTestSuite extends TestSuite{ def meta(s: String) = { val (List(selector), args) = ParseArgs.apply(Seq(s)).right.get - read(workspacePath / "out" / selector.flatMap(_.pathSegments) / "meta.json") + read(workspacePath / "out" / selector._2.value.flatMap(_.pathSegments) / "meta.json") } |