From 2d7241efab9ad4589b1a7db8353607a417ab1567 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Tue, 26 Dec 2017 00:42:45 -0800 Subject: - Shift `MappingCtx` into a magic `LoaderCtx` `Loader` to avoid circular dependencies between `Ctx` -> `Discovered` -> `Task` - `mill idea` works now using `GenIdea` as a standalone `T.command` making use of the new contextually-available `Mapping` - Limit implicit `ReplApplyHandler` to `--repl` only, to avoid it kicking in if `build.sc` scripts are screwed up and adding further confusion --- build.sc | 2 +- core/src/main/scala/mill/Main.scala | 3 ++- core/src/main/scala/mill/discover/Discovered.scala | 5 +++++ core/src/main/scala/mill/eval/Evaluator.scala | 7 +++---- core/src/main/scala/mill/main/MainWrapper.scala | 12 +----------- core/src/main/scala/mill/main/ReplApplyHandler.scala | 15 +++++++++++++-- core/src/main/scala/mill/main/RunScript.scala | 2 +- core/src/main/scala/mill/util/Ctx.scala | 11 +++-------- scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala | 14 +++++++++----- 9 files changed, 38 insertions(+), 33 deletions(-) diff --git a/build.sc b/build.sc index 23c438b2..705e50d3 100755 --- a/build.sc +++ b/build.sc @@ -165,4 +165,4 @@ def releaseAssembly = T{ assemblyBase(assemblyClasspath().flatten, "") } -def idea = T{ mill.scalaplugin.GenIdea() } \ No newline at end of file +def idea() = T.command{ mill.scalaplugin.GenIdea() } \ No newline at end of file diff --git a/core/src/main/scala/mill/Main.scala b/core/src/main/scala/mill/Main.scala index 4b4af35c..c6d05577 100644 --- a/core/src/main/scala/mill/Main.scala +++ b/core/src/main/scala/mill/Main.scala @@ -47,9 +47,10 @@ object Main { System.exit(1) case Right((cliConfig, leftoverArgs)) => val config = - if(!repl) cliConfig + if(!repl) cliConfig.copy(defaultPredef = false) else cliConfig.copy( defaultPredef = false, + predefCode = "implicit val replApplyHandler = mill.main.ReplApplyHandler(mapping)", predefFile = Some(pwd/"build.sc"), welcomeBanner = None ) diff --git a/core/src/main/scala/mill/discover/Discovered.scala b/core/src/main/scala/mill/discover/Discovered.scala index 1f27c771..a8d91f1d 100644 --- a/core/src/main/scala/mill/discover/Discovered.scala +++ b/core/src/main/scala/mill/discover/Discovered.scala @@ -5,6 +5,7 @@ import mill.define.{Cross, Target, Task} import mill.discover.Mirror.LabelledTarget import ammonite.main.Router import ammonite.main.Router.{EntryPoint, Result} +import mill.util.Ctx.Loader import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context @@ -26,6 +27,10 @@ class Discovered[T](val mirror: Mirror[T, T]){ } object Discovered { + object Mapping extends Loader[Mapping[_]] { + // Magically injected by the `Evaluator`, rather than being constructed here + def make() = ??? + } case class Mapping[T](value: Map[Target[Any], LabelledTarget[_]], mirror: Mirror[T, T], base: T) diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala index 5ca89793..96ee1b6e 100644 --- a/core/src/main/scala/mill/eval/Evaluator.scala +++ b/core/src/main/scala/mill/eval/Evaluator.scala @@ -13,14 +13,14 @@ import mill.util._ import scala.collection.mutable -class Evaluator[T](workspacePath: Path, +class Evaluator[T](val workspacePath: Path, val mapping: Discovered.Mapping[T], log: Logger, val classLoaderSig: Seq[(Path, Long)] = Evaluator.classLoaderSig){ val labeling = mapping.value val workerCache = mutable.Map.empty[Ctx.Loader[_], Any] - + workerCache(Discovered.Mapping) = mapping def evaluate(goals: OSet[Task[_]]): Evaluator.Results = { mkdir(workspacePath) @@ -162,8 +162,7 @@ class Evaluator[T](workspacePath: Path, def load[T](x: Ctx.Loader[T]): T = { workerCache.getOrElseUpdate(x, x.make()).asInstanceOf[T] } - }, - mapping + } ) val out = System.out diff --git a/core/src/main/scala/mill/main/MainWrapper.scala b/core/src/main/scala/mill/main/MainWrapper.scala index 403740aa..da8fc55a 100644 --- a/core/src/main/scala/mill/main/MainWrapper.scala +++ b/core/src/main/scala/mill/main/MainWrapper.scala @@ -5,15 +5,5 @@ package mill.main */ trait MainWrapper[T]{ val discovered: mill.discover.Discovered[T] - val interpApi: ammonite.interp.InterpAPI - val mapping = discovered.mapping(this.asInstanceOf[T]) - - implicit val replApplyHandler: mill.main.ReplApplyHandler = - new mill.main.ReplApplyHandler( - new mill.eval.Evaluator( - ammonite.ops.pwd / 'out, - mapping, - new mill.util.PrintLogger(true) - ) - ) + lazy val mapping = discovered.mapping(this.asInstanceOf[T]) } diff --git a/core/src/main/scala/mill/main/ReplApplyHandler.scala b/core/src/main/scala/mill/main/ReplApplyHandler.scala index f91d0ff2..d0c8365a 100644 --- a/core/src/main/scala/mill/main/ReplApplyHandler.scala +++ b/core/src/main/scala/mill/main/ReplApplyHandler.scala @@ -3,9 +3,20 @@ package mill.main import mill.define.Applicative.ApplyHandler import mill.define.Task +import mill.discover.Discovered import mill.eval.Evaluator -import mill.util.{OSet} - +import mill.util.OSet +object ReplApplyHandler{ + def apply[T](mapping: Discovered.Mapping[T]) = { + new ReplApplyHandler( + new mill.eval.Evaluator( + ammonite.ops.pwd / 'out, + mapping, + new mill.util.PrintLogger(true) + ) + ) + } +} class ReplApplyHandler(evaluator: Evaluator[_]) extends ApplyHandler[Task] { // Evaluate classLoaderSig only once in the REPL to avoid busting caches // as the user enters more REPL commands and changes the classpath diff --git a/core/src/main/scala/mill/main/RunScript.scala b/core/src/main/scala/mill/main/RunScript.scala index decc18a0..e201beaf 100644 --- a/core/src/main/scala/mill/main/RunScript.scala +++ b/core/src/main/scala/mill/main/RunScript.scala @@ -38,7 +38,7 @@ object RunScript{ case _ => interp.watch(path) for(mapping <- evaluateMapping(wd, path, interp)) - yield (mapping, new Evaluator(pwd / 'out, mapping, log)) + yield (mapping, new Evaluator(pwd / 'out, mapping, log)) } } yield { val evaluationWatches = mutable.Buffer.empty[(Path, Long)] diff --git a/core/src/main/scala/mill/util/Ctx.scala b/core/src/main/scala/mill/util/Ctx.scala index ad9b32db..9604021a 100644 --- a/core/src/main/scala/mill/util/Ctx.scala +++ b/core/src/main/scala/mill/util/Ctx.scala @@ -2,7 +2,7 @@ package mill.util import ammonite.ops.Path import mill.define.Applicative.ImplicitStub -import mill.util.Ctx.{ArgCtx, DestCtx, LoaderCtx, LogCtx, MappingCtx} +import mill.util.Ctx.{ArgCtx, DestCtx, LoaderCtx, LogCtx} import scala.annotation.compileTimeOnly import scala.language.implicitConversions @@ -31,20 +31,15 @@ object Ctx{ trait Loader[T]{ def make(): T } - trait MappingCtx{ - def mapping: mill.discover.Discovered.Mapping[_] - } } class Ctx(val args: IndexedSeq[_], val dest: Path, val log: Logger, - workerCtx0: Ctx.LoaderCtx, - val mapping: mill.discover.Discovered.Mapping[_]) + workerCtx0: Ctx.LoaderCtx) extends DestCtx with LogCtx with ArgCtx - with LoaderCtx - with MappingCtx{ + with LoaderCtx{ def load[T](x: Ctx.Loader[T]): T = workerCtx0.load(x) def length = args.length diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala b/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala index 86e33d8d..c7ea448a 100644 --- a/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala +++ b/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala @@ -5,11 +5,13 @@ import mill.define.Target import mill.discover.Mirror.{LabelledTarget, Segment} import mill.discover.{Discovered, Mirror} import mill.eval.{Evaluator, PathRef} +import mill.util.Ctx.LoaderCtx import mill.util.{OSet, PrintLogger} object GenIdea { - def apply[T](mapping: Discovered.Mapping[T]): Unit = { + def apply()(implicit ctx: LoaderCtx): Unit = { + val mapping = ctx.load(mill.discover.Discovered.Mapping) val pp = new scala.xml.PrettyPrinter(999, 4) rm! pwd/".idea" rm! pwd/".idea_modules" @@ -18,13 +20,12 @@ object GenIdea { val evaluator = new Evaluator(workspacePath, mapping, new PrintLogger(true)) - for((relPath, xml) <- xmlFileLayout(mapping, evaluator)){ + for((relPath, xml) <- xmlFileLayout(evaluator)){ write.over(pwd/relPath, pp.format(xml)) } } - def xmlFileLayout[T](evaluator: Evaluator): Seq[(RelPath, scala.xml.Node)] = { - + def xmlFileLayout[T](evaluator: Evaluator[T]): Seq[(RelPath, scala.xml.Node)] = { val modules = Mirror .traverse(evaluator.mapping.base, evaluator.mapping.mirror){ (h, p) => @@ -77,7 +78,10 @@ object GenIdea { val Seq(sourcePath: PathRef) = evaluator.evaluate(OSet(mod.sources)).values - val (destPath, jsonPath) = evaluator.resolveDestPaths(mapping.value(mod.compile)) + val (destPath, jsonPath) = Evaluator.resolveDestPaths( + evaluator.workspacePath, + evaluator.mapping.value(mod.compile) + ) val elem = moduleXmlTemplate( sourcePath.path, -- cgit v1.2.3