From fb8c75c01f86f41a62e549eb03953789658f7cae Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Mon, 19 Feb 2018 14:44:15 -0800 Subject: Improve error reporting for NamedTasks with the wrong number of parameters --- build.sc | 4 +- core/src/mill/define/Discover.scala | 26 ++++++++++- core/src/mill/define/Task.scala | 2 +- main/test/src/mill/define/MacroErrorTests.scala | 62 +++++++++++++++++++++++++ readme.md | 11 ++++- 5 files changed, 98 insertions(+), 7 deletions(-) diff --git a/build.sc b/build.sc index 110086c0..f7f22c7d 100755 --- a/build.sc +++ b/build.sc @@ -212,13 +212,13 @@ def devAssembly = T{ ) } -def dev(args: String*) = T.command{ +def dev(wd: Path, args: String*) = T.command{ mill.modules.Jvm.interactiveSubprocess( "mill.Main", Agg.from(assemblyClasspath().flatten.map(_.path)), jvmArgs = scalalib.testArgs() ++ scalajslib.testArgs() ++ scalaworker.testArgs(), mainArgs = args, - workingDir = pwd + workingDir = wd ) } diff --git a/core/src/mill/define/Discover.scala b/core/src/mill/define/Discover.scala index 1b6b002a..f0c668e6 100644 --- a/core/src/mill/define/Discover.scala +++ b/core/src/mill/define/Discover.scala @@ -42,22 +42,44 @@ object Discover { } rec(weakTypeOf[T]) + def assertParamListCounts(methods: Iterable[router.c.universe.MethodSymbol], + cases: (c.Type, Int, String)*) = { + for (m <- methods.toList){ + for ((tt, n, label) <- cases){ + if (m.returnType <:< tt.asInstanceOf[router.c.Type] && + m.paramLists.length != n){ + c.abort( + m.pos.asInstanceOf[c.Position], + s"$label definitions must have $n parameter list" + (if (n == 1) "" else "s") + ) + } + } + } + } val router = new mill.util.Router(c) val mapping = for{ discoveredModuleType <- seen val curCls = discoveredModuleType.asInstanceOf[router.c.Type] val methods = router.getValsOrMeths(curCls) val overridesRoutes = { + assertParamListCounts( + methods, + (weakTypeOf[mill.define.Sources], 0, "`T.sources`"), + (weakTypeOf[mill.define.Input[_]], 0, "`T.input`"), + (weakTypeOf[mill.define.Persistent[_]], 0, "`T.persistent`"), + (weakTypeOf[mill.define.Target[_]], 0, "`T{...}`"), + (weakTypeOf[mill.define.Command[_]], 1, "`T.command`") + ) + for{ m <- methods.toList if m.returnType <:< weakTypeOf[mill.define.Command[_]].asInstanceOf[router.c.Type] } yield (m.overrides.length, router.extractMethod(m, curCls).asInstanceOf[c.Tree]) + } if overridesRoutes.nonEmpty } yield { - val (overrides, routes) = overridesRoutes.unzip val lhs = q"classOf[${discoveredModuleType.typeSymbol.asClass}]" - val clsType = discoveredModuleType.typeSymbol.asClass val rhs = q"scala.Seq[(Int, mill.util.Router.EntryPoint[_])](..$overridesRoutes)" q"$lhs -> $rhs" } diff --git a/core/src/mill/define/Task.scala b/core/src/mill/define/Task.scala index 33f94453..17be54fe 100644 --- a/core/src/mill/define/Task.scala +++ b/core/src/mill/define/Task.scala @@ -231,7 +231,7 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul def persistent[T](t: Result[T])(implicit r: R[T], w: W[T], - ctx: mill.define.Ctx): Target[T] = macro persistentImpl[T] + ctx: mill.define.Ctx): Persistent[T] = macro persistentImpl[T] def persistentImpl[T: c.WeakTypeTag](c: Context) (t: c.Expr[T]) diff --git a/main/test/src/mill/define/MacroErrorTests.scala b/main/test/src/mill/define/MacroErrorTests.scala index a389feaa..c8b140fa 100644 --- a/main/test/src/mill/define/MacroErrorTests.scala +++ b/main/test/src/mill/define/MacroErrorTests.scala @@ -15,6 +15,68 @@ object MacroErrorTests extends TestSuite{ assert(err.msg == expectedMsg) } + 'badParameterSets - { + 'command - { + val e = compileError(""" + object foo extends mill.util.TestUtil.BaseModule{ + def w = T.command{1} + } + mill.define.Discover[foo.type] + """) + assert( + e.msg.contains("`T.command` definitions must have 1 parameter list"), + e.pos.contains("def w = ") + ) + } + 'target - { + val e = compileError(""" + object foo extends mill.util.TestUtil.BaseModule{ + def x() = T{1} + } + mill.define.Discover[foo.type] + """) + assert( + e.msg.contains("`T{...}` definitions must have 0 parameter lists"), + e.pos.contains("def x() = ") + ) + } + 'input - { + val e = compileError(""" + object foo extends mill.util.TestUtil.BaseModule{ + def y() = T.input{1} + } + mill.define.Discover[foo.type] + """) + assert( + e.msg.contains("`T.input` definitions must have 0 parameter lists"), + e.pos.contains("def y() = ") + ) + } + 'sources - { + val e = compileError(""" + object foo extends mill.util.TestUtil.BaseModule{ + def z() = T.sources{ammonite.ops.pwd} + } + mill.define.Discover[foo.type] + """) + assert( + e.msg.contains("`T.sources` definitions must have 0 parameter lists"), + e.pos.contains("def z() = ") + ) + } + 'persistent - { + val e = compileError(""" + object foo extends mill.util.TestUtil.BaseModule{ + def a() = T.persistent{1} + } + mill.define.Discover[foo.type] + """) + assert( + e.msg.contains("`T.persistent` definitions must have 0 parameter lists"), + e.pos.contains("def a() = ") + ) + } + } 'badTmacro - { // Make sure we can reference values from outside the T{...} block as part // of our `Target#apply()` calls, but we cannot reference any values that diff --git a/readme.md b/readme.md index 872a8839..67dd0053 100644 --- a/readme.md +++ b/readme.md @@ -73,8 +73,15 @@ it via: ```bash sbt "~bin/test:run main.test" sbt "~bin/test:run" -mill --watch dev main.test -mill --watch dev +mill --watch dev . main.test +mill --watch dev . +``` + +You can also test out your current Mill code with one of the hello-world example +repos via: + +```bash +mill dev docs/example-1 foo.run ``` Lastly, you can generate IntelliJ Scala project files using Mill via -- cgit v1.2.3