diff options
20 files changed, 185 insertions, 178 deletions
diff --git a/core/src/main/scala/mill/Main.scala b/core/src/main/scala/mill/Main.scala index 6a9d1945..86ee8649 100644 --- a/core/src/main/scala/mill/Main.scala +++ b/core/src/main/scala/mill/Main.scala @@ -39,13 +39,12 @@ object Main { } - def discoverMirror[T: Discovered](obj: T): Either[String, Discovered[T]] = { - val discovered = implicitly[Discovered[T]] - val consistencyErrors = Discovered.consistencyCheck(obj, discovered) + def consistencyCheck[T](mapping: Discovered.Mapping[T]): Either[String, Unit] = { + val consistencyErrors = Discovered.consistencyCheck(mapping) if (consistencyErrors.nonEmpty) { Left(s"Failed Discovered.consistencyCheck: ${consistencyErrors.map(Mirror.renderSelector)}") } else { - Right(discovered) + Right(()) } } @@ -77,10 +76,10 @@ object Main { } } - def apply[T: Discovered](args: Seq[String], - obj: T, - watch: Path => Unit, - coloredOutput: Boolean): Int = { + def apply[T](args: Seq[String], + mapping: Discovered.Mapping[T], + watch: Path => Unit, + coloredOutput: Boolean): Int = { val log = new PrintLogger(coloredOutput) @@ -88,13 +87,13 @@ object Main { val res = for { sel <- parseArgs(selectorString) - disc <- discoverMirror(obj) + _ <- consistencyCheck(mapping) crossSelectors = sel.map{ case Mirror.Segment.Cross(x) => x.toList.map(_.toString) case _ => Nil } - target <- mill.main.Resolve.resolve(sel, disc.mirror, obj, rest, crossSelectors, Nil) - evaluator = new Evaluator(pwd / 'out, Discovered.mapping(obj)(disc), log, sel) + target <- mill.main.Resolve.resolve(sel, mapping.mirror, mapping.base, rest, crossSelectors, Nil) + evaluator = new Evaluator(pwd / 'out, mapping.value, log, sel) _ <- evaluate(evaluator, target, watch).toLeft(()) } yield () @@ -119,20 +118,17 @@ object Main { s"""import $$file.^.build |import mill._ | - |val discovered = implicitly[mill.discover.Discovered[build.type]] + |val mapping = mill.discover.Discovered.mapping(build) | - |@main def run(args: String*) = mill.Main(args, build, interp.watch, true)(discovered) + |mill.Main.consistencyCheck(mapping).left.foreach(msg => throw new Exception(msg)) | - |@main def idea() = mill.scalaplugin.GenIdea(build)(discovered) + |@main def run(args: String*) = mill.Main(args, mapping, interp.watch, true) | - |val mirror = mill.Main.discoverMirror(build) match{ - | case Left(err) => throw new Exception("Failed discovery consistency check: " + err) - | case Right(mirror) => mirror - |} + |@main def idea() = mill.scalaplugin.GenIdea(mapping) | |val evaluator = new mill.eval.Evaluator( | ammonite.ops.pwd / 'out, - | mill.discover.Discovered.mapping(build)(mirror), + | mapping.value, | new mill.util.PrintLogger(true) |) | diff --git a/core/src/main/scala/mill/discover/Discovered.scala b/core/src/main/scala/mill/discover/Discovered.scala index 753ac141..0034a877 100644 --- a/core/src/main/scala/mill/discover/Discovered.scala +++ b/core/src/main/scala/mill/discover/Discovered.scala @@ -15,24 +15,37 @@ class Discovered[T](val mirror: Mirror[T, T]){ def targets(obj: T) = Mirror.traverse(obj, mirror) { (h, p) => h.labelled(obj, p) } + def mapping(t: T) = { + Discovered.Mapping( + targets(t).map(x => x.target -> x).toMap[Target[Any], LabelledTarget[_]], + mirror, + t + ) + } } object Discovered { - def consistencyCheck[T](base: T, d: Discovered[T]) = { + case class Mapping[T](value: Map[Target[Any], LabelledTarget[_]], + mirror: Mirror[T, T], + base: T) + + def consistencyCheck[T](mapping: Discovered.Mapping[T]) = { + val d = new Discovered(mapping.mirror) val inconsistent = for{ - (t1, t2) <- d.targets(base).zip(d.targets(base)) + (t1, t2) <- d.targets(mapping.base).zip(d.targets(mapping.base)) if t1.target ne t2.target } yield t1.segments inconsistent } - def mapping[T: Discovered](t: T): Map[Target[_], LabelledTarget[_]] = { - implicitly[Discovered[T]].targets(t).map(x => x.target -> x).toMap - } - - implicit def apply[T]: Discovered[T] = macro applyImpl[T] + def make[T]: Discovered[T] = macro applyImpl[T] + def mapping[T](t: T): Discovered.Mapping[T] = macro mappingImpl[T] def tupleLeft[T, V](items: List[(T, V)]) = items.map(_._1) + def mappingImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[Discovered.Mapping[T]] = { + import c.universe._ + c.Expr[Discovered.Mapping[T]](q"${applyImpl[T](c)}.mapping($t)") + } def applyImpl[T: c.WeakTypeTag](c: Context): c.Expr[Discovered[T]] = { import c.universe._ diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala index fab5dbe9..ea680ada 100644 --- a/core/src/main/scala/mill/eval/Evaluator.scala +++ b/core/src/main/scala/mill/eval/Evaluator.scala @@ -5,7 +5,7 @@ import java.net.URLClassLoader import ammonite.ops._ import ammonite.runtime.SpecialClassLoader import mill.define.{Graph, Target, Task, Worker} -import mill.discover.Mirror +import mill.discover.{Discovered, Mirror} import mill.discover.Mirror.LabelledTarget import mill.discover.Mirror.Segment.{Cross, Label} import mill.util @@ -19,6 +19,7 @@ class Evaluator(workspacePath: Path, sel: List[Mirror.Segment] = List(), classLoaderSig: Seq[(Path, Long)] = Evaluator.classLoaderSig){ val workerCache = mutable.Map.empty[Ctx.Loader[_], Any] + def evaluate(goals: OSet[Task[_]]): Evaluator.Results = { mkdir(workspacePath) diff --git a/core/src/main/scala/mill/main/ReplApplyHandler.scala b/core/src/main/scala/mill/main/ReplApplyHandler.scala index b2b688df..bb55c03f 100644 --- a/core/src/main/scala/mill/main/ReplApplyHandler.scala +++ b/core/src/main/scala/mill/main/ReplApplyHandler.scala @@ -1,12 +1,10 @@ package mill.main -import ammonite.ops.pwd -import mill.Main.discoverMirror + import mill.define.Applicative.ApplyHandler import mill.define.Task -import mill.discover.Discovered import mill.eval.Evaluator -import mill.util.{OSet, PrintLogger} +import mill.util.{OSet} class ReplApplyHandler(evaluator: Evaluator) extends ApplyHandler[Task] { // Evaluate classLoaderSig only once in the REPL to avoid busting caches diff --git a/core/src/test/scala/mill/define/CacherTests.scala b/core/src/test/scala/mill/define/CacherTests.scala index 4b8e31ab..4e647f82 100644 --- a/core/src/test/scala/mill/define/CacherTests.scala +++ b/core/src/test/scala/mill/define/CacherTests.scala @@ -25,29 +25,33 @@ object CacherTests extends TestSuite{ val tests = Tests{ - def eval[T: Discovered, V](base: T, v: Task[V])(implicit tp: TestPath) = { + def eval[V](mapping: Discovered.Mapping[_], v: Task[V])(implicit tp: TestPath) = { val workspace = ammonite.ops.pwd / 'target / 'workspace / tp.value - val evaluator = new Evaluator(workspace, Discovered.mapping(base), DummyLogger) + val evaluator = new Evaluator(workspace, mapping.value, DummyLogger) evaluator.evaluate(OSet(v)).values(0) } 'simpleDefIsCached - assert( Base.value eq Base.value, - eval(Base, Base.value) == 1 + eval(Discovered.mapping(Base), Base.value) == 1 ) + val middleMapping = Discovered.mapping(Middle) + 'overridingDefIsAlsoCached - assert( - eval(Middle, Middle.value) == 3, + eval(middleMapping, Middle.value) == 3, Middle.value eq Middle.value ) 'overridenDefRemainsAvailable - assert( - eval(Middle, Middle.overriden) == 1 + eval(middleMapping, Middle.overriden) == 1 ) + val terminalMapping = Discovered.mapping(Terminal) + 'multipleOverridesWork- assert( - eval(Terminal, Terminal.value) == 7, - eval(Terminal, Terminal.overriden) == 1 + eval(terminalMapping, Terminal.value) == 7, + eval(terminalMapping, Terminal.overriden) == 1 ) // Doesn't fail, presumably compileError doesn't go far enough in the // compilation pipeline to hit the override checks diff --git a/core/src/test/scala/mill/define/GraphTests.scala b/core/src/test/scala/mill/define/GraphTests.scala index 52f144f0..9442f9ab 100644 --- a/core/src/test/scala/mill/define/GraphTests.scala +++ b/core/src/test/scala/mill/define/GraphTests.scala @@ -2,6 +2,7 @@ package mill.define import mill.discover.Discovered +import Discovered.mapping import mill.eval.Evaluator import mill.util.{OSet, TestGraphs, TestUtil} import utest._ @@ -150,13 +151,13 @@ object GraphTests extends TestSuite{ ) } 'multiTerminalGroupCounts - { - def countGroups[T: Discovered](t: T, goals: Task[_]*) = { - val labeling = Discovered.mapping(t) + def countGroups(mapping: Discovered.Mapping[_], goals: Task[_]*) = { + val topoSorted = Graph.topoSorted( Graph.transitiveTargets(OSet.from(goals)) ) val grouped = Graph.groupAroundImportantTargets(topoSorted) { - case t: Target[_] if labeling.contains(t) || goals.contains(t) => t + case t: Target[_] if mapping.value.contains(t) || goals.contains(t) => t case t if goals.contains(t) => t } grouped.keyCount @@ -164,7 +165,7 @@ object GraphTests extends TestSuite{ 'separateGroups - { import separateGroups._ - val groupCount = countGroups(separateGroups, right, left) + val groupCount = countGroups(mapping(separateGroups), right, left) assert(groupCount == 3) } @@ -173,7 +174,7 @@ object GraphTests extends TestSuite{ // `right` depends on `left`, both of them depend on the un-cached `task` // which would force them both to re-compute every time `task` changes import triangleTask._ - val groupCount = countGroups(triangleTask, right, left) + val groupCount = countGroups(mapping(triangleTask), right, left) assert(groupCount == 2) } @@ -181,7 +182,7 @@ object GraphTests extends TestSuite{ 'multiTerminalGroup - { // Make sure the following graph ends up as two groups import multiTerminalGroup._ - val groupCount = countGroups(multiTerminalGroup, right, left) + val groupCount = countGroups(mapping(multiTerminalGroup), right, left) assert(groupCount == 2) } @@ -190,7 +191,7 @@ object GraphTests extends TestSuite{ // Make sure the following graph ends up as a three groups: one for // each cached target, and one for the downstream task we are running import multiTerminalBoundary._ - val groupCount = countGroups(multiTerminalBoundary, task2) + val groupCount = countGroups(mapping(multiTerminalBoundary), task2) assert(groupCount == 3) } } diff --git a/core/src/test/scala/mill/discover/ConsistencyTests.scala b/core/src/test/scala/mill/discover/ConsistencyTests.scala index 0591d5fc..ae66b199 100644 --- a/core/src/test/scala/mill/discover/ConsistencyTests.scala +++ b/core/src/test/scala/mill/discover/ConsistencyTests.scala @@ -25,16 +25,14 @@ object ConsistencyTests extends TestSuite{ 'diamond - { val inconsistent = Discovered.consistencyCheck( - diamond, - Discovered[diamond.type] + Discovered.mapping(diamond) ) assert(inconsistent == Nil) } 'anonDiamond - { val inconsistent = Discovered.consistencyCheck( - anonDiamond, - Discovered[anonDiamond.type] + Discovered.mapping(anonDiamond) ) assert(inconsistent == Nil) @@ -42,15 +40,13 @@ object ConsistencyTests extends TestSuite{ 'borkedCachedDiamond2 - { val inconsistent = Discovered.consistencyCheck( - borkedCachedDiamond2, - Discovered[borkedCachedDiamond2.type] + Discovered.mapping(borkedCachedDiamond2) ) assert(inconsistent == expected) } 'borkedCachedDiamond3 - { val inconsistent = Discovered.consistencyCheck( - borkedCachedDiamond3, - Discovered[borkedCachedDiamond3.type] + Discovered.mapping(borkedCachedDiamond3) ) assert(inconsistent == expected) } diff --git a/core/src/test/scala/mill/discover/CrossModuleTests.scala b/core/src/test/scala/mill/discover/CrossModuleTests.scala index a3a66daf..135d76e3 100644 --- a/core/src/test/scala/mill/discover/CrossModuleTests.scala +++ b/core/src/test/scala/mill/discover/CrossModuleTests.scala @@ -20,7 +20,7 @@ object CrossModuleTests extends TestSuite{ } } - val discovered = Discovered[outer.type] + val discovered = Discovered.make[outer.type] val Some((gen, innerMirror)) = discovered .mirror @@ -47,7 +47,7 @@ object CrossModuleTests extends TestSuite{ } } - val Some((gen, innerMirror)) = Discovered[outer.type] + val Some((gen, innerMirror)) = Discovered.make[outer.type] .mirror .children .head._2 @@ -63,7 +63,7 @@ object CrossModuleTests extends TestSuite{ List("2.11.8", "sjs0.6"), List("2.12.4", "sjs0.6"), List("2.11.8", "native0.3"), - List("2.12.4", "native0.3"), + List("2.12.4", "native0.3") ) assert(keys == expectedKeys) @@ -75,7 +75,7 @@ object CrossModuleTests extends TestSuite{ } 'crossTargetDiscovery - { - val discovered = Discovered[singleCross.type].targets(singleCross) + val discovered = Discovered.make[singleCross.type].targets(singleCross) val segments = discovered.map(_.segments) val expectedSegments = List( @@ -94,7 +94,7 @@ object CrossModuleTests extends TestSuite{ } 'doubleCrossTargetDiscovery - { - val discovered = Discovered[doubleCross.type] + val discovered = Discovered.make[doubleCross.type] val targets = discovered.targets(doubleCross).map(_.target) val expected = List( @@ -111,7 +111,7 @@ object CrossModuleTests extends TestSuite{ } 'nestedCrosses - { - val discovered = Discovered[nestedCrosses.type].targets(nestedCrosses) + val discovered = Discovered.make[nestedCrosses.type].targets(nestedCrosses) assert(discovered.length == 9) } } diff --git a/core/src/test/scala/mill/discover/DiscoveredTests.scala b/core/src/test/scala/mill/discover/DiscoveredTests.scala index 1d0f7a78..33196ff9 100644 --- a/core/src/test/scala/mill/discover/DiscoveredTests.scala +++ b/core/src/test/scala/mill/discover/DiscoveredTests.scala @@ -12,7 +12,7 @@ object DiscoveredTests extends TestSuite{ val tests = Tests{ 'targets - { - val discovered = Discovered[nestedModule.type] + val discovered = Discovered.make[nestedModule.type] def flatten(h: Mirror[nestedModule.type, _]): Seq[Any] = { h.node(nestedModule, Nil) :: h.children.flatMap{case (label, c) => flatten(c)} @@ -22,7 +22,7 @@ object DiscoveredTests extends TestSuite{ val expectedHierarchy = Seq( nestedModule, nestedModule.classInstance, - nestedModule.nested, + nestedModule.nested ) assert(flattenedHierarchy == expectedHierarchy) @@ -37,7 +37,7 @@ object DiscoveredTests extends TestSuite{ } 'traitWithModule - { - val discovered = Discovered[TraitWithModuleObject.type] + val discovered = Discovered.make[TraitWithModuleObject.type] val mapped = discovered.targets(TraitWithModuleObject).map(x => x.segments -> x.target) val expected = Seq( ( @@ -64,7 +64,7 @@ object DiscoveredTests extends TestSuite{ } - val discovered = Discovered[outer.type] + val discovered = Discovered.make[outer.type] val outerCommands = discovered.mirror.commands assertMatch(outerCommands){case Seq( @@ -93,7 +93,7 @@ object DiscoveredTests extends TestSuite{ def single = mill.T{ new InputStreamReader(System.in) } } - val error = compileError("Discovered[outer.type]") + val error = compileError("Discovered.make[outer.type]") assert( error.msg.contains("uPickle does not know how to read"), error.pos.contains("def single = mill.T{ new InputStreamReader(System.in) }") @@ -105,7 +105,7 @@ object DiscoveredTests extends TestSuite{ def single(in: InputStreamReader) = mill.T.command{ println(123) } } - val error = compileError("Discovered[outer.type]") + val error = compileError("Discovered.make[outer.type]") assert( error.msg.contains("could not find implicit value"), diff --git a/core/src/test/scala/mill/discover/LabelingTests.scala b/core/src/test/scala/mill/discover/LabelingTests.scala index 94d91cda..fa417373 100644 --- a/core/src/test/scala/mill/discover/LabelingTests.scala +++ b/core/src/test/scala/mill/discover/LabelingTests.scala @@ -3,6 +3,7 @@ package mill.discover import mill.define.Task import mill.util.TestGraphs import utest._ +import Discovered.mapping import mill.discover.Mirror.Segment.Label object LabelingTests extends TestSuite{ @@ -12,39 +13,39 @@ object LabelingTests extends TestSuite{ 'labeling - { - def check[T: Discovered](base: T, t: Task[_], relPath: Option[String]) = { + def check(mapping: Discovered.Mapping[_], t: Task[_], relPath: Option[String]) = { - val names: Seq[(Task[_], Seq[Mirror.Segment])] = Discovered.mapping(base).mapValues(_.segments).toSeq + val names: Seq[(Task[_], Seq[Mirror.Segment])] = mapping.value.mapValues(_.segments).toSeq val nameMap = names.toMap val targetLabel = nameMap.get(t).map(_.map{case Label(v) => v}.mkString(".")) assert(targetLabel == relPath) } - 'singleton - check(singleton, singleton.single, Some("single")) + 'singleton - check(mapping(singleton), singleton.single, Some("single")) 'pair - { - check(pair, pair.up, Some("up")) - check(pair, pair.down, Some("down")) + check(mapping(pair), pair.up, Some("up")) + check(mapping(pair), pair.down, Some("down")) } 'anonTriple - { - check(anonTriple, anonTriple.up, Some("up")) - check(anonTriple, anonTriple.down.inputs(0), None) - check(anonTriple, anonTriple.down, Some("down")) + check(mapping(anonTriple), anonTriple.up, Some("up")) + check(mapping(anonTriple), anonTriple.down.inputs(0), None) + check(mapping(anonTriple), anonTriple.down, Some("down")) } 'diamond - { - check(diamond, diamond.up, Some("up")) - check(diamond, diamond.left, Some("left")) - check(diamond, diamond.right, Some("right")) - check(diamond, diamond.down, Some("down")) + check(mapping(diamond), diamond.up, Some("up")) + check(mapping(diamond), diamond.left, Some("left")) + check(mapping(diamond), diamond.right, Some("right")) + check(mapping(diamond), diamond.down, Some("down")) } 'anonDiamond - { - check(anonDiamond, anonDiamond.up, Some("up")) - check(anonDiamond, anonDiamond.down.inputs(0), None) - check(anonDiamond, anonDiamond.down.inputs(1), None) - check(anonDiamond, anonDiamond.down, Some("down")) + check(mapping(anonDiamond), anonDiamond.up, Some("up")) + check(mapping(anonDiamond), anonDiamond.down.inputs(0), None) + check(mapping(anonDiamond), anonDiamond.down.inputs(1), None) + check(mapping(anonDiamond), anonDiamond.down, Some("down")) } } diff --git a/core/src/test/scala/mill/eval/EvaluationTests.scala b/core/src/test/scala/mill/eval/EvaluationTests.scala index 3b136ba0..31a330d1 100644 --- a/core/src/test/scala/mill/eval/EvaluationTests.scala +++ b/core/src/test/scala/mill/eval/EvaluationTests.scala @@ -5,16 +5,17 @@ import mill.util.TestUtil.{Test, test} import mill.define.{Graph, Target, Task} import mill.{Module, T} import mill.discover.Discovered +import mill.discover.Discovered.mapping import mill.util.{DummyLogger, OSet, TestGraphs, TestUtil} import utest._ import utest.framework.TestPath object EvaluationTests extends TestSuite{ - class Checker[T: Discovered](base: T)(implicit tp: TestPath) { + class Checker(mapping: Discovered.Mapping[_])(implicit tp: TestPath) { val workspace = ammonite.ops.pwd / 'target / 'workspace / tp.value ammonite.ops.rm(ammonite.ops.Path(workspace, ammonite.ops.pwd)) // Make sure data is persisted even if we re-create the evaluator each time - def evaluator = new Evaluator(workspace, Discovered.mapping(base), DummyLogger) + def evaluator = new Evaluator(workspace, mapping.value, DummyLogger) def apply(target: Task[_], expValue: Any, expEvaled: OSet[Task[_]], @@ -57,7 +58,7 @@ object EvaluationTests extends TestSuite{ 'singleton - { import singleton._ - val check = new Checker(singleton) + val check = new Checker(mapping(singleton)) // First time the target is evaluated check(single, expValue = 0, expEvaled = OSet(single)) @@ -67,7 +68,7 @@ object EvaluationTests extends TestSuite{ } 'pair - { import pair._ - val check = new Checker(pair) + val check = new Checker(mapping(pair)) check(down, expValue = 0, expEvaled = OSet(up, down)) down.counter += 1 @@ -78,7 +79,7 @@ object EvaluationTests extends TestSuite{ } 'anonTriple - { import anonTriple._ - val check = new Checker(anonTriple) + val check = new Checker(mapping(anonTriple)) val middle = down.inputs(0) check(down, expValue = 0, expEvaled = OSet(up, middle, down)) @@ -94,7 +95,7 @@ object EvaluationTests extends TestSuite{ } 'diamond - { import diamond._ - val check = new Checker(diamond) + val check = new Checker(mapping(diamond)) check(down, expValue = 0, expEvaled = OSet(up, left, right, down)) down.counter += 1 @@ -112,7 +113,7 @@ object EvaluationTests extends TestSuite{ } 'anonDiamond - { import anonDiamond._ - val check = new Checker(anonDiamond) + val check = new Checker(mapping(anonDiamond)) val left = down.inputs(0).asInstanceOf[TestUtil.Test] val right = down.inputs(1).asInstanceOf[TestUtil.Test] check(down, expValue = 0, expEvaled = OSet(up, left, right, down)) @@ -133,7 +134,7 @@ object EvaluationTests extends TestSuite{ 'bigSingleTerminal - { import bigSingleTerminal._ - val check = new Checker(bigSingleTerminal) + val check = new Checker(mapping(bigSingleTerminal)) check(j, expValue = 0, expEvaled = OSet(a, b, e, f, i, j), extraEvaled = 22) @@ -156,7 +157,7 @@ object EvaluationTests extends TestSuite{ // even though one depends on the other import separateGroups._ - val checker = new Checker(separateGroups) + val checker = new Checker(mapping(separateGroups)) val evaled1 = checker.evaluator.evaluate(OSet(right, left)) val filtered1 = evaled1.evaluated.filter(_.isInstanceOf[Target[_]]) assert(filtered1 == OSet(change, left, right)) @@ -173,7 +174,7 @@ object EvaluationTests extends TestSuite{ 'triangleTask - { import triangleTask._ - val checker = new Checker(triangleTask) + val checker = new Checker(mapping(triangleTask)) checker(right, 3, OSet(left, right), extraEvaled = -1) checker(left, 1, OSet(), extraEvaled = -1) @@ -181,7 +182,7 @@ object EvaluationTests extends TestSuite{ 'multiTerminalGroup - { import multiTerminalGroup._ - val checker = new Checker(multiTerminalGroup) + val checker = new Checker(mapping(multiTerminalGroup)) checker(right, 1, OSet(right), extraEvaled = -1) checker(left, 1, OSet(left), extraEvaled = -1) } @@ -190,7 +191,7 @@ object EvaluationTests extends TestSuite{ import multiTerminalBoundary._ - val checker = new Checker(multiTerminalBoundary) + val checker = new Checker(mapping(multiTerminalBoundary)) checker(task2, 4, OSet(right, left), extraEvaled = -1, secondRunNoOp = false) checker(task2, 4, OSet(), extraEvaled = -1, secondRunNoOp = false) } @@ -228,7 +229,7 @@ object EvaluationTests extends TestSuite{ // During the first evaluation, they get computed normally like any // cached target - val check = new Checker(build) + val check = new Checker(mapping(build)) assert(leftCount == 0, rightCount == 0) check(down, expValue = 10101, expEvaled = OSet(up, right, down), extraEvaled = 8) assert(leftCount == 1, middleCount == 1, rightCount == 1) diff --git a/core/src/test/scala/mill/eval/FailureTests.scala b/core/src/test/scala/mill/eval/FailureTests.scala index 4c3b6fca..84b13af5 100644 --- a/core/src/test/scala/mill/eval/FailureTests.scala +++ b/core/src/test/scala/mill/eval/FailureTests.scala @@ -2,6 +2,7 @@ package mill.eval import mill.define.Target import mill.discover.Discovered +import mill.discover.Discovered.mapping import mill.util.{DummyLogger, OSet} import utest._ import utest.framework.TestPath @@ -11,13 +12,13 @@ object FailureTests extends TestSuite{ def workspace(implicit tp: TestPath) = { ammonite.ops.pwd / 'target / 'workspace / 'failure / implicitly[TestPath].value } - class Checker[T: Discovered](base: T)(implicit tp: TestPath){ + class Checker(mapping: Discovered.Mapping[_])(implicit tp: TestPath){ - val evaluator = new Evaluator(workspace, Discovered.mapping(base), DummyLogger) + val evaluator = new Evaluator(workspace, mapping.value, DummyLogger) - def apply(target: T => Target[_], expectedFailCount: Int, expectedRawValues: Seq[Result[_]]) = { + def apply(target: Target[_], expectedFailCount: Int, expectedRawValues: Seq[Result[_]]) = { - val res = evaluator.evaluate(OSet(target(base))) + val res = evaluator.evaluate(OSet(target)) assert( res.rawValues == expectedRawValues, res.failing.keyCount == expectedFailCount @@ -31,9 +32,9 @@ object FailureTests extends TestSuite{ 'evaluateSingle - { ammonite.ops.rm(ammonite.ops.Path(workspace, ammonite.ops.pwd)) - val check = new Checker(singleton) + val check = new Checker(mapping(singleton)) check( - target = _.single, + target = singleton.single, expectedFailCount = 0, expectedRawValues = Seq(Result.Success(0)) ) @@ -41,7 +42,7 @@ object FailureTests extends TestSuite{ singleton.single.failure = Some("lols") check( - target = _.single, + target = singleton.single, expectedFailCount = 1, expectedRawValues = Seq(Result.Failure("lols")) ) @@ -49,7 +50,7 @@ object FailureTests extends TestSuite{ singleton.single.failure = None check( - target = _.single, + target = singleton.single, expectedFailCount = 0, expectedRawValues = Seq(Result.Success(0)) ) @@ -60,16 +61,16 @@ object FailureTests extends TestSuite{ check( - target = _.single, + target = singleton.single, expectedFailCount = 1, expectedRawValues = Seq(Result.Exception(ex)) ) } 'evaluatePair - { ammonite.ops.rm(ammonite.ops.Path(workspace, ammonite.ops.pwd)) - val check = new Checker(pair) + val check = new Checker(mapping(pair)) check( - _.down, + pair.down, expectedFailCount = 0, expectedRawValues = Seq(Result.Success(0)) ) @@ -77,7 +78,7 @@ object FailureTests extends TestSuite{ pair.up.failure = Some("lols") check( - _.down, + pair.down, expectedFailCount = 1, expectedRawValues = Seq(Result.Skipped) ) @@ -85,7 +86,7 @@ object FailureTests extends TestSuite{ pair.up.failure = None check( - _.down, + pair.down, expectedFailCount = 0, expectedRawValues = Seq(Result.Success(0)) ) @@ -93,7 +94,7 @@ object FailureTests extends TestSuite{ pair.up.exception = Some(new IndexOutOfBoundsException()) check( - _.down, + pair.down, expectedFailCount = 1, expectedRawValues = Seq(Result.Skipped) ) diff --git a/core/src/test/scala/mill/eval/JavaCompileJarTests.scala b/core/src/test/scala/mill/eval/JavaCompileJarTests.scala index 7639d8e2..356ffea1 100644 --- a/core/src/test/scala/mill/eval/JavaCompileJarTests.scala +++ b/core/src/test/scala/mill/eval/JavaCompileJarTests.scala @@ -51,14 +51,14 @@ object JavaCompileJarTests extends TestSuite{ val mapping = Discovered.mapping(Build) def eval[T](t: Task[T]): Either[Result.Failing, (T, Int)] = { - val evaluator = new Evaluator(workspacePath, mapping, DummyLogger) + val evaluator = new Evaluator(workspacePath, mapping.value, DummyLogger) val evaluated = evaluator.evaluate(OSet(t)) if (evaluated.failing.keyCount == 0){ Right(Tuple2( evaluated.rawValues(0).asInstanceOf[Result.Success[T]].value, evaluated.evaluated.collect{ - case t: Target[_] if mapping.contains(t) => t + case t: Target[_] if mapping.value.contains(t) => t case t: mill.define.Command[_] => t }.size )) @@ -68,12 +68,12 @@ object JavaCompileJarTests extends TestSuite{ } def check(targets: OSet[Task[_]], expected: OSet[Task[_]]) = { - val evaluator = new Evaluator(workspacePath, mapping, DummyLogger) + val evaluator = new Evaluator(workspacePath, mapping.value, DummyLogger) val evaluated = evaluator.evaluate(targets) .evaluated .flatMap(_.asTarget) - .filter(mapping.contains) + .filter(mapping.value.contains) assert(evaluated == expected) } diff --git a/core/src/test/scala/mill/main/MainTests.scala b/core/src/test/scala/mill/main/MainTests.scala index 4955112d..73060479 100644 --- a/core/src/test/scala/mill/main/MainTests.scala +++ b/core/src/test/scala/mill/main/MainTests.scala @@ -6,16 +6,16 @@ import mill.discover.{Discovered, Mirror} import mill.util.TestGraphs._ import mill.util.TestUtil.test import utest._ - +import Discovered.mapping object MainTests extends TestSuite{ - def check[T: Discovered](obj: T, - selectorString: String, - expected: Either[String, Task[_]]) = { - val mirror = implicitly[Discovered[T]].mirror + def check[T](mapping: Discovered.Mapping[T], + selectorString: String, + expected: Either[String, Task[_]]) = { + val resolved = for{ args <- mill.Main.parseArgs(selectorString) val crossSelectors = args.map{case Mirror.Segment.Cross(x) => x.toList.map(_.toString) case _ => Nil} - task <- mill.main.Resolve.resolve(args, mirror, obj, Nil, crossSelectors, Nil) + task <- mill.main.Resolve.resolve(args, mapping.mirror, mapping.base, Nil, crossSelectors, Nil) } yield task assert(resolved == expected) } @@ -23,39 +23,39 @@ object MainTests extends TestSuite{ val graphs = new mill.util.TestGraphs() import graphs._ 'single - { - 'pos - check(singleton, "single", Right(singleton.single)) - 'neg1 - check(singleton, "doesntExist", Left("Cannot resolve task doesntExist")) - 'neg2 - check(singleton, "single.doesntExist", Left("Cannot resolve module single")) - 'neg3 - check(singleton, "", Left("Selector cannot be empty")) + 'pos - check(mapping(singleton), "single", Right(singleton.single)) + 'neg1 - check(mapping(singleton), "doesntExist", Left("Cannot resolve task doesntExist")) + 'neg2 - check(mapping(singleton), "single.doesntExist", Left("Cannot resolve module single")) + 'neg3 - check(mapping(singleton), "", Left("Selector cannot be empty")) } 'nested - { - 'pos1 - check(nestedModule, "single", Right(nestedModule.single)) - 'pos2 - check(nestedModule, "nested.single", Right(nestedModule.nested.single)) - 'pos3 - check(nestedModule, "classInstance.single", Right(nestedModule.classInstance.single)) - 'neg1 - check(nestedModule, "doesntExist", Left("Cannot resolve task doesntExist")) - 'neg2 - check(nestedModule, "single.doesntExist", Left("Cannot resolve module single")) - 'neg3 - check(nestedModule, "nested.doesntExist", Left("Cannot resolve task nested.doesntExist")) - 'neg4 - check(nestedModule, "classInstance.doesntExist", Left("Cannot resolve task classInstance.doesntExist")) + 'pos1 - check(mapping(nestedModule), "single", Right(nestedModule.single)) + 'pos2 - check(mapping(nestedModule), "nested.single", Right(nestedModule.nested.single)) + 'pos3 - check(mapping(nestedModule), "classInstance.single", Right(nestedModule.classInstance.single)) + 'neg1 - check(mapping(nestedModule), "doesntExist", Left("Cannot resolve task doesntExist")) + 'neg2 - check(mapping(nestedModule), "single.doesntExist", Left("Cannot resolve module single")) + 'neg3 - check(mapping(nestedModule), "nested.doesntExist", Left("Cannot resolve task nested.doesntExist")) + 'neg4 - check(mapping(nestedModule), "classInstance.doesntExist", Left("Cannot resolve task classInstance.doesntExist")) } 'cross - { 'single - { - 'pos1 - check(singleCross, "cross[210].suffix", Right(singleCross.cross("210").suffix)) - 'pos2 - check(singleCross, "cross[211].suffix", Right(singleCross.cross("211").suffix)) - 'neg1 - check(singleCross, "cross[210].doesntExist", Left("Cannot resolve task cross[210].doesntExist")) - 'neg2 - check(singleCross, "cross[doesntExist].doesntExist", Left("Cannot resolve cross cross[doesntExist]")) - 'neg2 - check(singleCross, "cross[doesntExist].suffix", Left("Cannot resolve cross cross[doesntExist]")) + 'pos1 - check(mapping(singleCross), "cross[210].suffix", Right(singleCross.cross("210").suffix)) + 'pos2 - check(mapping(singleCross), "cross[211].suffix", Right(singleCross.cross("211").suffix)) + 'neg1 - check(mapping(singleCross), "cross[210].doesntExist", Left("Cannot resolve task cross[210].doesntExist")) + 'neg2 - check(mapping(singleCross), "cross[doesntExist].doesntExist", Left("Cannot resolve cross cross[doesntExist]")) + 'neg2 - check(mapping(singleCross), "cross[doesntExist].suffix", Left("Cannot resolve cross cross[doesntExist]")) } 'double - { 'pos1 - check( - doubleCross, + mapping(doubleCross), "cross[jvm,210].suffix", Right(doubleCross.cross("jvm", "210").suffix) ) 'pos2 - check( - doubleCross, + mapping(doubleCross), "cross[jvm,211].suffix", Right(doubleCross.cross("jvm", "211").suffix) ) @@ -63,24 +63,24 @@ object MainTests extends TestSuite{ 'nested - { 'indirect - { 'pos1 - check( - indirectNestedCrosses, + mapping(indirectNestedCrosses), "cross[210].cross2[js].suffix", Right(indirectNestedCrosses.cross("210").cross2("js").suffix) ) 'pos2 - check( - indirectNestedCrosses, + mapping(indirectNestedCrosses), "cross[211].cross2[jvm].suffix", Right(indirectNestedCrosses.cross("211").cross2("jvm").suffix) ) } 'direct - { 'pos1 - check( - nestedCrosses, + mapping(nestedCrosses), "cross[210].cross2[js].suffix", Right(nestedCrosses.cross("210").cross2("js").suffix) ) 'pos2 - check( - nestedCrosses, + mapping(nestedCrosses), "cross[211].cross2[jvm].suffix", Right(nestedCrosses.cross("211").cross2("jvm").suffix) ) diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala b/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala index cb59bdba..f720123d 100644 --- a/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala +++ b/scalaplugin/src/main/scala/mill/scalaplugin/GenIdea.scala @@ -9,31 +9,27 @@ import mill.util.{OSet, PrintLogger} object GenIdea { - def apply[T: Discovered](obj: T): Unit = { + def apply[T](mapping: Discovered.Mapping[T]): Unit = { val pp = new scala.xml.PrettyPrinter(999, 4) rm! pwd/".idea" rm! pwd/".idea_modules" - val discovered = implicitly[Discovered[T]] - val mapping = Discovered.mapping(obj)(discovered) val workspacePath = pwd / 'out - val evaluator = new Evaluator(workspacePath, mapping, new PrintLogger(true)) + val evaluator = new Evaluator(workspacePath, mapping.value, new PrintLogger(true)) - for((relPath, xml) <- xmlFileLayout(obj, evaluator, mapping)){ + for((relPath, xml) <- xmlFileLayout(mapping, evaluator)){ write.over(pwd/relPath, pp.format(xml)) } } - def xmlFileLayout[T: Discovered](obj: T, - evaluator: Evaluator, - mapping: Map[Target[_], LabelledTarget[_]]): Seq[(RelPath, scala.xml.Node)] = { + def xmlFileLayout[T](mapping: Discovered.Mapping[T], + evaluator: Evaluator): Seq[(RelPath, scala.xml.Node)] = { - val discovered = implicitly[Discovered[T]] val modules = Mirror - .traverse(obj, discovered.mirror){ (h, p) => - h.node(obj, p.reverse.map{case Mirror.Segment.Cross(vs) => vs.toList case _ => Nil}.toList) match { + .traverse(mapping.base, mapping.mirror){ (h, p) => + h.node(mapping.base, p.reverse.map{case Mirror.Segment.Cross(vs) => vs.toList case _ => Nil}.toList) match { case m: ScalaModule => Seq(p -> m) case _ => Nil } @@ -82,7 +78,7 @@ object GenIdea { val Seq(sourcePath: PathRef) = evaluator.evaluate(OSet(mod.sources)).values - val (destPath, jsonPath) = evaluator.resolveDestPaths(mapping(mod.compile)) + val (destPath, jsonPath) = evaluator.resolveDestPaths(mapping.value(mod.compile)) val elem = moduleXmlTemplate( sourcePath.path, diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala index 185cffc8..deaa766e 100644 --- a/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala +++ b/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala @@ -37,7 +37,7 @@ object AcyclicTests extends TestSuite{ mkdir(workspacePath/up) cp(srcPath, workspacePath) val mapping = Discovered.mapping(AcyclicBuild) - def eval[T](t: Task[T]) = TestEvaluator.eval(mapping, workspacePath)(t) + def eval[T](t: Task[T]) = TestEvaluator.eval(mapping.value, workspacePath)(t) val packageScala = workspacePath/'src/'main/'scala/'acyclic/"package.scala" diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/BetterFilesTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/BetterFilesTests.scala index f4247094..c9c8618c 100644 --- a/scalaplugin/src/test/scala/mill/scalaplugin/BetterFilesTests.scala +++ b/scalaplugin/src/test/scala/mill/scalaplugin/BetterFilesTests.scala @@ -97,7 +97,7 @@ object BetterFilesTests extends TestSuite{ mkdir(workspacePath/up) cp(srcPath, workspacePath) val mapping = Discovered.mapping(BetterFilesBuild) - def eval[T](t: Task[T]) = TestEvaluator.eval(mapping, workspacePath)(t) + def eval[T](t: Task[T]) = TestEvaluator.eval(mapping.value, workspacePath)(t) 'test - { diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala index 239f6871..a5e52330 100644 --- a/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala +++ b/scalaplugin/src/test/scala/mill/scalaplugin/HelloWorldTests.scala @@ -47,7 +47,7 @@ object HelloWorldTests extends TestSuite { 'scalaVersion - { 'fromBuild - { val Right((result, evalCount)) = - eval(HelloWorld.scalaVersion, helloWorldMapping) + eval(HelloWorld.scalaVersion, helloWorldMapping.value) assert( result == "2.12.4", @@ -61,7 +61,7 @@ object HelloWorldTests extends TestSuite { val Right((result, evalCount)) = eval(HelloWorldScalaOverride.scalaVersion, - Discovered.mapping(HelloWorldScalaOverride)) + Discovered.mapping(HelloWorldScalaOverride).value) assert( result == "2.11.11", @@ -72,7 +72,7 @@ object HelloWorldTests extends TestSuite { 'scalacOptions - { 'emptyByDefault - { val Right((result, evalCount)) = - eval(HelloWorld.scalacOptions, helloWorldMapping) + eval(HelloWorld.scalacOptions, helloWorldMapping.value) assert( result.isEmpty, @@ -82,7 +82,7 @@ object HelloWorldTests extends TestSuite { 'override - { val Right((result, evalCount)) = eval(HelloWorldFatalWarnings.scalacOptions, - Discovered.mapping(HelloWorldFatalWarnings)) + Discovered.mapping(HelloWorldFatalWarnings).value) assert( result == Seq("-Ywarn-unused", "-Xfatal-warnings"), @@ -93,7 +93,7 @@ object HelloWorldTests extends TestSuite { 'compile - { 'fromScratch - { val Right((result, evalCount)) = - eval(HelloWorld.compile, helloWorldMapping) + eval(HelloWorld.compile, helloWorldMapping.value) val outPath = result.classes.path val analysisFile = result.analysisFile @@ -109,31 +109,31 @@ object HelloWorldTests extends TestSuite { // don't recompile if nothing changed val Right((_, unchangedEvalCount)) = - eval(HelloWorld.compile, helloWorldMapping) + eval(HelloWorld.compile, helloWorldMapping.value) assert(unchangedEvalCount == 0) } 'recompileOnChange - { val Right((_, freshCount)) = - eval(HelloWorld.compile, helloWorldMapping) + eval(HelloWorld.compile, helloWorldMapping.value) assert(freshCount > 0) write.append(mainObject, "\n") val Right((_, incCompileCount)) = - eval(HelloWorld.compile, helloWorldMapping) + eval(HelloWorld.compile, helloWorldMapping.value) assert(incCompileCount > 0, incCompileCount < freshCount) } 'failOnError - { write.append(mainObject, "val x: ") val Left(Result.Exception(err)) = - eval(HelloWorld.compile, helloWorldMapping) + eval(HelloWorld.compile, helloWorldMapping.value) assert(err.isInstanceOf[CompileFailed]) val (compilePath, compileMetadataPath) = TestEvaluator.resolveDestPaths(outputPath)( - helloWorldMapping(HelloWorld.compile)) + helloWorldMapping.value(HelloWorld.compile)) assert( ls.rec(compilePath / 'classes).isEmpty, @@ -144,7 +144,7 @@ object HelloWorldTests extends TestSuite { // compilation fails because of "-Xfatal-warnings" flag val Left(Result.Exception(err)) = eval(HelloWorldFatalWarnings.compile, - Discovered.mapping(HelloWorldFatalWarnings)) + Discovered.mapping(HelloWorldFatalWarnings).value) assert(err.isInstanceOf[CompileFailed]) } @@ -152,7 +152,7 @@ object HelloWorldTests extends TestSuite { 'runMain - { 'runMainObject - { val Right((_, evalCount)) = - eval(HelloWorld.runMain("Main"), helloWorldMapping) + eval(HelloWorld.runMain("Main"), helloWorldMapping.value) assert(evalCount > 0) @@ -164,7 +164,7 @@ object HelloWorldTests extends TestSuite { } 'notRunInvalidMainObject - { val Left(Result.Exception(err)) = - eval(HelloWorld.runMain("Invalid"), helloWorldMapping) + eval(HelloWorld.runMain("Invalid"), helloWorldMapping.value) assert( err.isInstanceOf[InteractiveShelloutException] @@ -174,7 +174,7 @@ object HelloWorldTests extends TestSuite { write.append(mainObject, "val x: ") val Left(Result.Exception(err)) = - eval(HelloWorld.runMain("Main"), helloWorldMapping) + eval(HelloWorld.runMain("Main"), helloWorldMapping.value) assert( err.isInstanceOf[CompileFailed] @@ -184,7 +184,7 @@ object HelloWorldTests extends TestSuite { 'run - { 'runIfMainClassProvided - { val Right((_, evalCount)) = - eval(HelloWorldWithMain.run(), helloWorldWithMainMapping) + eval(HelloWorldWithMain.run(), helloWorldWithMainMapping.value) assert(evalCount > 0) @@ -196,7 +196,7 @@ object HelloWorldTests extends TestSuite { } 'notRunWithoutMainClass - { val Left(Result.Exception(err)) = - eval(HelloWorld.run(), helloWorldMapping) + eval(HelloWorld.run(), helloWorldMapping.value) assert( err.isInstanceOf[RuntimeException] @@ -206,7 +206,7 @@ object HelloWorldTests extends TestSuite { 'jar - { 'nonEmpty - { val Right((result, evalCount)) = - eval(HelloWorld.jar, helloWorldMapping) + eval(HelloWorld.jar, helloWorldMapping.value) assert( exists(result.path), @@ -219,7 +219,7 @@ object HelloWorldTests extends TestSuite { val manifestFiles = Seq( unJarPath / "META-INF", - unJarPath / "META-INF" / "MANIFEST.MF", + unJarPath / "META-INF" / "MANIFEST.MF" ) val expectedFiles = compileClassfiles(unJarPath) ++ manifestFiles @@ -231,7 +231,7 @@ object HelloWorldTests extends TestSuite { } 'runJar - { val Right((result, evalCount)) = - eval(HelloWorldWithMain.jar, helloWorldWithMainMapping) + eval(HelloWorldWithMain.jar, helloWorldWithMainMapping.value) assert( exists(result.path), @@ -247,7 +247,7 @@ object HelloWorldTests extends TestSuite { ) } 'logOutputToFile { - eval(HelloWorld.compile, helloWorldMapping) + eval(HelloWorld.compile, helloWorldMapping.value) val logFile = outputPath / "compile.log" assert(exists(logFile)) diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/JawnTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/JawnTests.scala index 0d876660..892857c9 100644 --- a/scalaplugin/src/test/scala/mill/scalaplugin/JawnTests.scala +++ b/scalaplugin/src/test/scala/mill/scalaplugin/JawnTests.scala @@ -74,7 +74,7 @@ object JawnTests extends TestSuite{ mkdir(workspacePath/up) cp(srcPath, workspacePath) val mapping = Discovered.mapping(JawnBuild) - def eval[T](t: Task[T]) = TestEvaluator.eval(mapping, workspacePath)(t) + def eval[T](t: Task[T]) = TestEvaluator.eval(mapping.value, workspacePath)(t) 'test - { def compileOutput = workspacePath / 'jawn / "2.12.3" / 'Parser / 'compile diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/TestEvaluator.scala b/scalaplugin/src/test/scala/mill/scalaplugin/TestEvaluator.scala index f0593e2a..58e4f5f3 100644 --- a/scalaplugin/src/test/scala/mill/scalaplugin/TestEvaluator.scala +++ b/scalaplugin/src/test/scala/mill/scalaplugin/TestEvaluator.scala @@ -13,9 +13,8 @@ object TestEvaluator { new Evaluator(workspacePath, Map.empty, DummyLogger).resolveDestPaths(t) } - def eval[T]( - mapping: Map[Target[_], Mirror.LabelledTarget[_]], - workspacePath: Path)(t: Task[T]): Either[Result.Failing, (T, Int)] = { + def eval[T](mapping: Map[Target[_], Mirror.LabelledTarget[_]], + workspacePath: Path)(t: Task[T]): Either[Result.Failing, (T, Int)] = { val evaluator = new Evaluator(workspacePath, mapping, DummyLogger) val evaluated = evaluator.evaluate(OSet(t)) |