From a3722644bf5822104bf4cd628e92ef838926e9a2 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Mon, 6 Dec 2021 18:01:15 +0800 Subject: [PATCH 01/18] . --- bsp/src/mill/bsp/MillBspLogger.scala | 3 +- bsp/src/mill/bsp/MillScalaBuildServer.scala | 5 +- build.sc | 30 ++++-- .../src/mill/contrib/bloop/BloopImpl.scala | 1 - contrib/scoverage/src/ScoverageReport.scala | 2 +- .../test/src/mill/testng/TestNGTests.scala | 2 +- main/api/src/mill/api/JsonFormatters.scala | 14 +++ main/core/src/mill/define/Discover.scala | 2 +- main/core/src/mill/define/Module.scala | 2 +- .../src/mill/{util => define}/ParseArgs.scala | 32 +++--- .../src/mill/{util => define}/Router.scala | 2 +- main/src/mill/main/MainModule.scala | 7 +- main/src/mill/main/MainRunner.scala | 3 +- main/src/mill/main/MainScopts.scala | 2 +- main/src/mill/main/ReplApplyHandler.scala | 3 +- main/src/mill/main/RunScript.scala | 6 +- main/src/mill/modules/Jvm.scala | 27 ++--- main/src/package.scala | 3 +- main/test/src/main/MainTests.scala | 2 +- main/test/src/util/ParseArgsTest.scala | 4 +- main/test/src/util/ScriptTestSuite.scala | 2 +- main/test/src/util/TestEvaluator.scala | 3 +- .../{core => util}/src/mill/util/Compat.scala | 0 .../src/mill/util/EitherOps.scala | 0 .../src/mill/util/EnclosingClass.scala | 0 main/util/src/mill/util/Jvm.scala | 34 +++++++ .../mill/util/LinePrefixOutputStream.scala | 0 .../src/mill/util/Loggers.scala | 23 +++-- .../src/mill/util/MultiBiMap.scala | 0 .../src/mill/util/Watched.scala | 0 .../src/mill/util/package.scala | 0 scalajslib/src/ScalaJSModule.scala | 3 +- scalajslib/test/src/HelloJSWorldTests.scala | 3 +- scalalib/src/Dep.scala | 2 +- .../src}/JsonFormatters.scala | 14 +-- scalalib/src/Lib.scala | 69 ------------- scalalib/src/TestModule.scala | 3 +- .../updates/ModuleDependenciesUpdates.scala | 2 +- scalalib/src/package.scala | 2 +- scalalib/test/src/TestRunnerTests.scala | 6 +- scalanativelib/src/ScalaNativeModule.scala | 3 +- .../test/src/HelloNativeWorldTests.scala | 3 +- {scalalib => testrunner}/src/TestRunner.scala | 99 ++++++++++++++++--- 43 files changed, 239 insertions(+), 184 deletions(-) rename main/core/src/mill/{util => define}/ParseArgs.scala (87%) rename main/core/src/mill/{util => define}/Router.scala (99%) rename main/{core => util}/src/mill/util/Compat.scala (100%) rename main/{core => util}/src/mill/util/EitherOps.scala (100%) rename main/{core => util}/src/mill/util/EnclosingClass.scala (100%) create mode 100644 main/util/src/mill/util/Jvm.scala rename main/{core => util}/src/mill/util/LinePrefixOutputStream.scala (100%) rename main/{core => util}/src/mill/util/Loggers.scala (93%) rename main/{core => util}/src/mill/util/MultiBiMap.scala (100%) rename main/{core => util}/src/mill/util/Watched.scala (100%) rename main/{core => util}/src/mill/util/package.scala (100%) rename {main/core/src/mill/util => scalalib/src}/JsonFormatters.scala (72%) rename {scalalib => testrunner}/src/TestRunner.scala (75%) diff --git a/bsp/src/mill/bsp/MillBspLogger.scala b/bsp/src/mill/bsp/MillBspLogger.scala index 0a66a91e26b..78b9f2fc111 100644 --- a/bsp/src/mill/bsp/MillBspLogger.scala +++ b/bsp/src/mill/bsp/MillBspLogger.scala @@ -20,7 +20,8 @@ import mill.util.{ColorLogger, ProxyLogger} class MillBspLogger(client: BuildClient, taskId: Int, logger: Logger) extends ProxyLogger(logger) with ColorLogger { - def colors = ammonite.util.Colors.BlackWhite + def infoColor = fansi.Color.Blue + def errorColor = fansi.Color.Red override def ticker(s: String): Unit = { try { diff --git a/bsp/src/mill/bsp/MillScalaBuildServer.scala b/bsp/src/mill/bsp/MillScalaBuildServer.scala index 0f1c941f9c0..e8ccec9f1eb 100644 --- a/bsp/src/mill/bsp/MillScalaBuildServer.scala +++ b/bsp/src/mill/bsp/MillScalaBuildServer.scala @@ -19,7 +19,8 @@ import ch.epfl.scala.bsp4j.{ ScalacOptionsResult } import mill.modules.Jvm -import mill.scalalib.{JavaModule, Lib, ScalaModule, TestModule, TestRunner} +import mill.scalalib.{JavaModule, Lib, ScalaModule, TestModule} +import mill.testrunner.TestRunner import mill.{Agg, T} import sbt.testing.Fingerprint @@ -101,7 +102,7 @@ trait MillScalaBuildServer extends ScalaBuildServer { this: MillBuildServer => closeContextClassLoaderWhenDone = false, cl => { val framework = TestRunner.framework(testFramework)(cl) - Lib.discoverTests( + TestRunner.discoverTests( cl, framework, Agg(compResult.classes.path) diff --git a/build.sc b/build.sc index 6377a59b32f..326b4eaa23e 100755 --- a/build.sc +++ b/build.sc @@ -72,6 +72,7 @@ object Deps { val acyclic = ivy"com.lihaoyi::acyclic:0.2.0" val ammonite = ivy"com.lihaoyi:::ammonite:2.4.1" + val ammoniteTerminal = ivy"com.lihaoyi::ammonite-terminal:2.4.1" // Exclude trees here to force the version of we have defined. We use this // here instead of a `forceVersion()` on scalametaTrees since it's not // respected in the POM causing issues for Coursier Mill users. @@ -122,6 +123,7 @@ object Deps { val windowsAnsi = ivy"io.github.alexarchambault.windows-ansi:windows-ansi:0.0.3" val zinc = ivy"org.scala-sbt::zinc:1.5.7" val bsp = ivy"ch.epfl.scala:bsp4j:2.0.0" + val fansi = ivy"com.lihaoyi::fansi:0.2.14" val jarjarabrams = ivy"com.eed3si9n.jarjarabrams::jarjar-abrams-core:1.8.0" } @@ -189,18 +191,18 @@ trait MillMimaConfig extends mima.Mima { main.core -> Seq( ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.define.Target.makeT"), ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.define.Target.args"), - ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.util.ParseArgs.standaloneIdent"), + ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.define.ParseArgs.standaloneIdent"), ProblemFilter.exclude[IncompatibleSignatureProblem]( - "mill.util.ParseArgs#BraceExpansionParser.plainChars" + "mill.define.ParseArgs#BraceExpansionParser.plainChars" ), ProblemFilter.exclude[IncompatibleSignatureProblem]( - "mill.util.ParseArgs#BraceExpansionParser.braceParser" + "mill.define.ParseArgs#BraceExpansionParser.braceParser" ), ProblemFilter.exclude[IncompatibleSignatureProblem]( - "mill.util.ParseArgs#BraceExpansionParser.parser" + "mill.define.ParseArgs#BraceExpansionParser.parser" ), ProblemFilter.exclude[IncompatibleSignatureProblem]( - "mill.util.ParseArgs#BraceExpansionParser.toExpand" + "mill.define.ParseArgs#BraceExpansionParser.toExpand" ), ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.eval.EvaluatorPaths.*"), ProblemFilter.exclude[DirectMissingMethodProblem]("mill.eval.EvaluatorPaths.*") @@ -264,8 +266,15 @@ object main extends MillModule { Deps.sbtTestInterface ) } - object core extends MillModule { + object util extends MillModule { override def moduleDeps = Seq(moduledefs, api) + def ivyDeps = Agg( + Deps.ammoniteTerminal, + Deps.fansi + ) + } + object core extends MillModule { + override def moduleDeps = Seq(moduledefs, api, util) override def compileIvyDeps = Agg( Deps.scalaReflect(scalaVersion()) @@ -358,11 +367,14 @@ object main extends MillModule { } } + +object testrunner extends MillModule { + override def moduleDeps = Seq(scalalib.api, main.util) +} object scalalib extends MillModule { - override def moduleDeps = Seq(main, scalalib.api) + override def moduleDeps = Seq(main, scalalib.api, testrunner) override def ivyDeps = Agg( - Deps.sbtTestInterface, Deps.scalafmtDynamic ) @@ -753,7 +765,7 @@ object scalanativelib extends MillModule { } object bsp extends MillModule { - override def compileModuleDeps = Seq(scalalib, scalajslib, scalanativelib) + override def compileModuleDeps = Seq(scalalib, scalajslib, scalanativelib, testrunner) override def ivyDeps = Agg( Deps.bsp, Deps.sbtTestInterface diff --git a/contrib/bloop/src/mill/contrib/bloop/BloopImpl.scala b/contrib/bloop/src/mill/contrib/bloop/BloopImpl.scala index 95c8650a33e..f402ca746ce 100644 --- a/contrib/bloop/src/mill/contrib/bloop/BloopImpl.scala +++ b/contrib/bloop/src/mill/contrib/bloop/BloopImpl.scala @@ -2,7 +2,6 @@ package mill.contrib.bloop import bloop.config.{Config => BloopConfig, Tag => BloopTag} import mill._ -import mill.api.Loose import mill.define.{Module => MillModule, _} import mill.eval.Evaluator import mill.scalajslib.ScalaJSModule diff --git a/contrib/scoverage/src/ScoverageReport.scala b/contrib/scoverage/src/ScoverageReport.scala index ac253bd661c..d5ca109bbdd 100644 --- a/contrib/scoverage/src/ScoverageReport.scala +++ b/contrib/scoverage/src/ScoverageReport.scala @@ -4,7 +4,7 @@ import mill.contrib.scoverage.api.ScoverageReportWorkerApi.ReportType import mill.define.{Command, Module, Task} import mill.eval.Evaluator import mill.main.RunScript -import mill.util.SelectMode +import mill.define.SelectMode import mill.{PathRef, T} import os.Path diff --git a/contrib/testng/test/src/mill/testng/TestNGTests.scala b/contrib/testng/test/src/mill/testng/TestNGTests.scala index 8c66e50f2ca..71bc2647a35 100644 --- a/contrib/testng/test/src/mill/testng/TestNGTests.scala +++ b/contrib/testng/test/src/mill/testng/TestNGTests.scala @@ -60,7 +60,7 @@ object TestNGTests extends TestSuite { } "Test case lookup from inherited annotations" - workspaceTest(demo) { eval => val Right((result, evalCount)) = eval.apply(demo.test.test()) - val tres = result.asInstanceOf[(String, Seq[mill.scalalib.TestRunner.Result])] + val tres = result.asInstanceOf[(String, Seq[mill.testrunner.TestRunner.Result])] assert( tres._2.size == 8 ) diff --git a/main/api/src/mill/api/JsonFormatters.scala b/main/api/src/mill/api/JsonFormatters.scala index 4041618e2cc..948e95e8a90 100644 --- a/main/api/src/mill/api/JsonFormatters.scala +++ b/main/api/src/mill/api/JsonFormatters.scala @@ -1,6 +1,8 @@ package mill.api import upickle.default.{ReadWriter => RW} + +import scala.reflect.ClassTag import scala.util.matching.Regex object JsonFormatters extends JsonFormatters @@ -45,4 +47,16 @@ trait JsonFormatters { json("lineNumber").num.toInt ) ) + + + implicit def enumFormat[T <: java.lang.Enum[_]: ClassTag]: RW[T] = + upickle.default.readwriter[String].bimap( + _.name(), + (s: String) => + implicitly[ClassTag[T]] + .runtimeClass + .getConstructor(classOf[String]) + .newInstance(s) + .asInstanceOf[T] + ) } diff --git a/main/core/src/mill/define/Discover.scala b/main/core/src/mill/define/Discover.scala index 81c840742a9..7c31d902cbf 100644 --- a/main/core/src/mill/define/Discover.scala +++ b/main/core/src/mill/define/Discover.scala @@ -4,5 +4,5 @@ import language.experimental.macros case class Discover[T](value: Map[Class[_], Seq[(Int, mainargs.MainData[_, _])]]) object Discover { - def apply[T]: Discover[T] = macro mill.util.Router.applyImpl[T] + def apply[T]: Discover[T] = macro mill.define.Router.applyImpl[T] } diff --git a/main/core/src/mill/define/Module.scala b/main/core/src/mill/define/Module.scala index cb93641704c..388e35260aa 100644 --- a/main/core/src/mill/define/Module.scala +++ b/main/core/src/mill/define/Module.scala @@ -2,7 +2,7 @@ package mill.define import java.lang.reflect.Modifier -import mill.util.ParseArgs +import mill.define.ParseArgs import scala.language.experimental.macros import scala.reflect.ClassTag diff --git a/main/core/src/mill/util/ParseArgs.scala b/main/core/src/mill/define/ParseArgs.scala similarity index 87% rename from main/core/src/mill/util/ParseArgs.scala rename to main/core/src/mill/define/ParseArgs.scala index c042624524e..3683add4f47 100644 --- a/main/core/src/mill/util/ParseArgs.scala +++ b/main/core/src/mill/define/ParseArgs.scala @@ -1,4 +1,4 @@ -package mill.util +package mill.define import scala.annotation.tailrec @@ -31,14 +31,14 @@ object ParseArgs { @deprecated("Use apply(Seq[String], SelectMode) instead", "mill after 0.10.0-M3") def apply( - scriptArgs: Seq[String], - multiSelect: Boolean - ): Either[String, TargetsWithParams] = extractAndValidate(scriptArgs, multiSelect) + scriptArgs: Seq[String], + multiSelect: Boolean + ): Either[String, TargetsWithParams] = extractAndValidate(scriptArgs, multiSelect) def apply( - scriptArgs: Seq[String], - selectMode: SelectMode - ): Either[String, Seq[TargetsWithParams]] = { + scriptArgs: Seq[String], + selectMode: SelectMode + ): Either[String, Seq[TargetsWithParams]] = { val MaskPattern = ("""\\+\Q""" + TargetSeparator + """\E""").r @@ -63,29 +63,29 @@ object ParseArgs { val parsed: Seq[Either[String, TargetsWithParams]] = parts.map(extractAndValidate(_, selectMode == SelectMode.Multi)) - val res1: Either[String, Seq[TargetsWithParams]] = EitherOps.sequence(parsed) + val res1: Either[String, Seq[TargetsWithParams]] = mill.util.EitherOps.sequence(parsed) res1 } private def extractAndValidate( - scriptArgs: Seq[String], - multiSelect: Boolean - ): Either[String, TargetsWithParams] = { + scriptArgs: Seq[String], + multiSelect: Boolean + ): Either[String, TargetsWithParams] = { val (selectors, args) = extractSelsAndArgs(scriptArgs, multiSelect) for { _ <- validateSelectors(selectors) - expandedSelectors <- EitherOps + expandedSelectors <- mill.util.EitherOps .sequence(selectors.map(expandBraces)) .map(_.flatten) - selectors <- EitherOps.sequence(expandedSelectors.map(extractSegments)) + selectors <- mill.util.EitherOps.sequence(expandedSelectors.map(extractSegments)) } yield (selectors.toList, args) } def extractSelsAndArgs( - scriptArgs: Seq[String], - multiSelect: Boolean - ): (Seq[String], Seq[String]) = { + scriptArgs: Seq[String], + multiSelect: Boolean + ): (Seq[String], Seq[String]) = { if (multiSelect) { val dd = scriptArgs.indexOf(MultiArgsSeparator) diff --git a/main/core/src/mill/util/Router.scala b/main/core/src/mill/define/Router.scala similarity index 99% rename from main/core/src/mill/util/Router.scala rename to main/core/src/mill/define/Router.scala index 770fb056c78..404073771c8 100644 --- a/main/core/src/mill/util/Router.scala +++ b/main/core/src/mill/define/Router.scala @@ -1,4 +1,4 @@ -package mill.util +package mill.define import mill.define.{Cross, Discover} diff --git a/main/src/mill/main/MainModule.scala b/main/src/mill/main/MainModule.scala index 51ec0bd7d31..75fe89869f5 100644 --- a/main/src/mill/main/MainModule.scala +++ b/main/src/mill/main/MainModule.scala @@ -5,7 +5,8 @@ import mill.{BuildInfo, T} import mill.api.{Ctx, PathRef, Result} import mill.define.{Command, NamedTask, Task} import mill.eval.{Evaluator, EvaluatorPaths} -import mill.util.{PrintLogger, SelectMode, Watched} +import mill.util.{PrintLogger, Watched} +import mill.define.SelectMode import pprint.{Renderer, Truncated} object MainModule { @@ -242,8 +243,8 @@ trait MainModule extends mill.Module { // When using `show`, redirect all stdout of the evaluated tasks so the // printed JSON is the only thing printed to stdout. baseLogger = evaluator.baseLogger match { - case PrintLogger(c1, d, c2, _, i, e, in, de, uc) => - PrintLogger(c1, d, c2, e, i, e, in, de, uc) + case PrintLogger(c1, d, c2, c3, _, i, e, in, de, uc) => + PrintLogger(c1, d, c2, c3, e, i, e, in, de, uc) case l => l } ), diff --git a/main/src/mill/main/MainRunner.scala b/main/src/mill/main/MainRunner.scala index 4a3c0ab09ed..f5433dca97c 100644 --- a/main/src/mill/main/MainRunner.scala +++ b/main/src/mill/main/MainRunner.scala @@ -105,7 +105,8 @@ class MainRunner( val logger = PrintLogger( colored = colored, disableTicker = disableTicker, - colors = colors, + infoColor = colors.info(), + errorColor = colors.error(), outStream = outprintStream, infoStream = errPrintStream, errStream = errPrintStream, diff --git a/main/src/mill/main/MainScopts.scala b/main/src/mill/main/MainScopts.scala index 7d83331b6f8..9b5b689ad49 100644 --- a/main/src/mill/main/MainScopts.scala +++ b/main/src/mill/main/MainScopts.scala @@ -1,7 +1,7 @@ package mill.main import mill.eval.Evaluator -import mill.util.SelectMode +import mill.define.SelectMode case class Tasks[T](value: Seq[mill.define.NamedTask[T]]) diff --git a/main/src/mill/main/ReplApplyHandler.scala b/main/src/mill/main/ReplApplyHandler.scala index 3156bb366cb..78bca76aae4 100644 --- a/main/src/mill/main/ReplApplyHandler.scala +++ b/main/src/mill/main/ReplApplyHandler.scala @@ -26,7 +26,8 @@ object ReplApplyHandler { val logger = new mill.util.PrintLogger( colors != ammonite.util.Colors.BlackWhite, disableTicker, - colors, + colors.info(), + colors.error(), System.out, System.err, System.err, diff --git a/main/src/mill/main/RunScript.scala b/main/src/mill/main/RunScript.scala index 9b1c873d38b..fb571cc6474 100644 --- a/main/src/mill/main/RunScript.scala +++ b/main/src/mill/main/RunScript.scala @@ -7,13 +7,15 @@ import ammonite.util.{Name, Res, Util} import mill.define import mill.define._ import mill.eval.{Evaluator, EvaluatorPaths} -import mill.util.{EitherOps, ParseArgs, PrintLogger, SelectMode, Watched} +import mill.util.{EitherOps, PrintLogger, Watched} +import mill.define.SelectMode +import mill.define.ParseArgs import mill.api.{Logger, PathRef, Result} import mill.api.Strict.Agg import scala.collection.mutable import scala.reflect.ClassTag -import mill.util.ParseArgs.TargetsWithParams +import mill.define.ParseArgs.TargetsWithParams /** * Custom version of ammonite.main.Scripts, letting us run the build.sc script diff --git a/main/src/mill/modules/Jvm.scala b/main/src/mill/modules/Jvm.scala index 401c6b6da4b..5367ee67c28 100644 --- a/main/src/mill/modules/Jvm.scala +++ b/main/src/mill/modules/Jvm.scala @@ -259,26 +259,13 @@ object Jvm { closeContextClassLoaderWhenDone: Boolean, body: ClassLoader => T )(implicit ctx: Ctx.Home): T = { - val urls = classPath.map(_.toIO.toURI.toURL) - val cl = - if (classLoaderOverrideSbtTesting) { - mill.api.ClassLoader.create(urls.toVector, null, sharedPrefixes = Seq("sbt.testing.")) - } else if (isolated) { - mill.api.ClassLoader.create(urls.toVector, null) - } else { - mill.api.ClassLoader.create(urls.toVector, getClass.getClassLoader) - } - - val oldCl = Thread.currentThread().getContextClassLoader - Thread.currentThread().setContextClassLoader(cl) - try { - body(cl) - } finally { - if (closeContextClassLoaderWhenDone) { - Thread.currentThread().setContextClassLoader(oldCl) - cl.close() - } - } + mill.util.Jvm.inprocess( + classPath, + classLoaderOverrideSbtTesting, + isolated, + closeContextClassLoaderWhenDone, + body + ) } def createManifest(mainClass: Option[String]): JarManifest = { diff --git a/main/src/package.scala b/main/src/package.scala index 1442ee06fac..47a42ae57c6 100644 --- a/main/src/package.scala +++ b/main/src/package.scala @@ -1,6 +1,5 @@ -import mill.util.JsonFormatters -package object mill extends JsonFormatters { +package object mill extends mill.api.JsonFormatters { val T = define.Target type T[T] = define.Target[T] val PathRef = mill.api.PathRef diff --git a/main/test/src/main/MainTests.scala b/main/test/src/main/MainTests.scala index d10d12b047b..bb893fd13a4 100644 --- a/main/test/src/main/MainTests.scala +++ b/main/test/src/main/MainTests.scala @@ -13,7 +13,7 @@ object MainTests extends TestSuite { val expected = expected0.map(_.map(_(module))) val resolved = for { - selectors <- mill.util.ParseArgs(Seq(selectorString), multiSelect = false).map(_._1.head) + selectors <- mill.define.ParseArgs(Seq(selectorString), multiSelect = false).map(_._1.head) crossSelectors = selectors._2.value.map { case Segment.Cross(x) => x.toList.map(_.toString) case _ => Nil diff --git a/main/test/src/util/ParseArgsTest.scala b/main/test/src/util/ParseArgsTest.scala index 104db6b816b..e23e6d9598f 100644 --- a/main/test/src/util/ParseArgsTest.scala +++ b/main/test/src/util/ParseArgsTest.scala @@ -1,8 +1,8 @@ package mill.util -import mill.define.{Segment, Segments} +import mill.define.{ParseArgs, Segment, Segments, SelectMode} import mill.define.Segment.{Cross, Label} -import mill.util.ParseArgs.{TargetSeparator, TargetsWithParams} +import mill.define.ParseArgs.{TargetSeparator, TargetsWithParams} import utest._ object ParseArgsTest extends TestSuite { diff --git a/main/test/src/util/ScriptTestSuite.scala b/main/test/src/util/ScriptTestSuite.scala index 379007e8c86..ea8171e86b4 100644 --- a/main/test/src/util/ScriptTestSuite.scala +++ b/main/test/src/util/ScriptTestSuite.scala @@ -67,7 +67,7 @@ abstract class ScriptTestSuite(fork: Boolean) extends TestSuite { } } def meta(s: String): String = { - val (List(selector), args) = ParseArgs.apply(Seq(s), multiSelect = false).right.get + val (List(selector), args) = mill.define.ParseArgs.apply(Seq(s), multiSelect = false).right.get val segments = selector._2.value.flatMap(_.pathSegments) os.read(wd / "out" / segments.init / s"${segments.last}.json") diff --git a/main/test/src/util/TestEvaluator.scala b/main/test/src/util/TestEvaluator.scala index ccc80d7a22b..0735edc4ae0 100644 --- a/main/test/src/util/TestEvaluator.scala +++ b/main/test/src/util/TestEvaluator.scala @@ -38,7 +38,8 @@ class TestEvaluator( val logger = new PrintLogger( colored = true, disableTicker = false, - ammonite.util.Colors.Default, + ammonite.util.Colors.Default.info(), + ammonite.util.Colors.Default.error(), outStream, outStream, outStream, diff --git a/main/core/src/mill/util/Compat.scala b/main/util/src/mill/util/Compat.scala similarity index 100% rename from main/core/src/mill/util/Compat.scala rename to main/util/src/mill/util/Compat.scala diff --git a/main/core/src/mill/util/EitherOps.scala b/main/util/src/mill/util/EitherOps.scala similarity index 100% rename from main/core/src/mill/util/EitherOps.scala rename to main/util/src/mill/util/EitherOps.scala diff --git a/main/core/src/mill/util/EnclosingClass.scala b/main/util/src/mill/util/EnclosingClass.scala similarity index 100% rename from main/core/src/mill/util/EnclosingClass.scala rename to main/util/src/mill/util/EnclosingClass.scala diff --git a/main/util/src/mill/util/Jvm.scala b/main/util/src/mill/util/Jvm.scala new file mode 100644 index 00000000000..523ece9b111 --- /dev/null +++ b/main/util/src/mill/util/Jvm.scala @@ -0,0 +1,34 @@ +package mill.util + +import mill.api.Loose.Agg +object Jvm { + + def inprocess[T]( + classPath: Agg[os.Path], + classLoaderOverrideSbtTesting: Boolean, + isolated: Boolean, + closeContextClassLoaderWhenDone: Boolean, + body: ClassLoader => T + )(implicit ctx: mill.api.Ctx.Home): T = { + val urls = classPath.map(_.toIO.toURI.toURL) + val cl = + if (classLoaderOverrideSbtTesting) { + mill.api.ClassLoader.create(urls.toVector, null, sharedPrefixes = Seq("sbt.testing.")) + } else if (isolated) { + mill.api.ClassLoader.create(urls.toVector, null) + } else { + mill.api.ClassLoader.create(urls.toVector, getClass.getClassLoader) + } + + val oldCl = Thread.currentThread().getContextClassLoader + Thread.currentThread().setContextClassLoader(cl) + try { + body(cl) + } finally { + if (closeContextClassLoaderWhenDone) { + Thread.currentThread().setContextClassLoader(oldCl) + cl.close() + } + } + } +} diff --git a/main/core/src/mill/util/LinePrefixOutputStream.scala b/main/util/src/mill/util/LinePrefixOutputStream.scala similarity index 100% rename from main/core/src/mill/util/LinePrefixOutputStream.scala rename to main/util/src/mill/util/LinePrefixOutputStream.scala diff --git a/main/core/src/mill/util/Loggers.scala b/main/util/src/mill/util/Loggers.scala similarity index 93% rename from main/core/src/mill/util/Loggers.scala rename to main/util/src/mill/util/Loggers.scala index 2daf78b99fc..e88c2d230f1 100755 --- a/main/core/src/mill/util/Loggers.scala +++ b/main/util/src/mill/util/Loggers.scala @@ -64,20 +64,22 @@ object PrintState { case object Middle extends PrintState } trait ColorLogger extends Logger { - def colors: ammonite.util.Colors + def infoColor: fansi.Attrs + def errorColor: fansi.Attrs } case class PrefixLogger(out: ColorLogger, context: String, tickerContext: String = "") extends ColorLogger { override def colored = out.colored - def colors = out.colors + def infoColor = out.infoColor + def errorColor = out.errorColor override val errorStream = new PrintStream(new LinePrefixOutputStream( - colors.info()(context).render, + infoColor(context).render, out.errorStream )) override val outputStream = new PrintStream(new LinePrefixOutputStream( - colors.info()(context).render, + infoColor(context).render, out.outputStream )) @@ -95,7 +97,8 @@ case class PrefixLogger(out: ColorLogger, context: String, tickerContext: String case class PrintLogger( colored: Boolean, disableTicker: Boolean, - colors: ammonite.util.Colors, + infoColor: fansi.Attrs, + errorColor: fansi.Attrs, outStream: PrintStream, infoStream: PrintStream, errStream: PrintStream, @@ -115,22 +118,22 @@ case class PrintLogger( def info(s: String) = synchronized { printState = PrintState.Newline - infoStream.println(colors.info()(context + s)) + infoStream.println(infoColor(context + s)) } def error(s: String) = synchronized { printState = PrintState.Newline - errStream.println((colors.info()(context) ++ colors.error()(s)).render) + errStream.println((infoColor(context) ++ errorColor(s)).render) } def ticker(s: String) = synchronized { if (!disableTicker) { printState match { case PrintState.Newline => - infoStream.println(colors.info()(s)) + infoStream.println(infoColor(s)) case PrintState.Middle => infoStream.println() - infoStream.println(colors.info()(s)) + infoStream.println(infoColor(s)) case PrintState.Ticker => val p = new PrintWriter(infoStream) // Need to make this more "atomic" @@ -140,7 +143,7 @@ case class PrintLogger( nav.left(9999) p.flush() - infoStream.println(colors.info()(s)) + infoStream.println(infoColor(s)) } printState = PrintState.Ticker } diff --git a/main/core/src/mill/util/MultiBiMap.scala b/main/util/src/mill/util/MultiBiMap.scala similarity index 100% rename from main/core/src/mill/util/MultiBiMap.scala rename to main/util/src/mill/util/MultiBiMap.scala diff --git a/main/core/src/mill/util/Watched.scala b/main/util/src/mill/util/Watched.scala similarity index 100% rename from main/core/src/mill/util/Watched.scala rename to main/util/src/mill/util/Watched.scala diff --git a/main/core/src/mill/util/package.scala b/main/util/src/mill/util/package.scala similarity index 100% rename from main/core/src/mill/util/package.scala rename to main/util/src/mill/util/package.scala diff --git a/scalajslib/src/ScalaJSModule.scala b/scalajslib/src/ScalaJSModule.scala index 080ba0eba8e..37d0cec9622 100644 --- a/scalajslib/src/ScalaJSModule.scala +++ b/scalajslib/src/ScalaJSModule.scala @@ -5,7 +5,8 @@ import ch.epfl.scala.bsp4j.{BuildTargetDataKind, ScalaBuildTarget, ScalaPlatform import mill.api.{Loose, PathRef, Result, internal} import mill.scalalib.api.Util.{isScala3, scalaBinaryVersion} import mill.scalalib.Lib.resolveDependencies -import mill.scalalib.{DepSyntax, Lib, TestModule, TestRunner} +import mill.scalalib.{DepSyntax, Lib, TestModule} +import mill.testrunner.TestRunner import mill.util.Ctx import mill.define.Task import mill.scalajslib.api._ diff --git a/scalajslib/test/src/HelloJSWorldTests.scala b/scalajslib/test/src/HelloJSWorldTests.scala index 16e823fae1f..6306c0aa2df 100644 --- a/scalajslib/test/src/HelloJSWorldTests.scala +++ b/scalajslib/test/src/HelloJSWorldTests.scala @@ -4,7 +4,8 @@ import java.util.jar.JarFile import mill._ import mill.define.Discover import mill.eval.{EvaluatorPaths, Result} -import mill.scalalib.{CrossScalaModule, DepSyntax, Lib, PublishModule, TestModule, TestRunner} +import mill.scalalib.{CrossScalaModule, DepSyntax, Lib, PublishModule, TestModule} +import mill.testrunner.TestRunner import mill.scalalib.api.Util.isScala3 import mill.scalalib.publish.{Developer, License, PomSettings, VersionControl} import mill.util.{TestEvaluator, TestUtil} diff --git a/scalalib/src/Dep.scala b/scalalib/src/Dep.scala index 15f63a48277..d05a78acd3d 100644 --- a/scalalib/src/Dep.scala +++ b/scalalib/src/Dep.scala @@ -1,5 +1,5 @@ package mill.scalalib -import mill.util.JsonFormatters._ +import JsonFormatters._ import upickle.default.{macroRW, ReadWriter => RW} import CrossVersion._ import mill.scalalib.api.Util.Scala3EarlyVersion diff --git a/main/core/src/mill/util/JsonFormatters.scala b/scalalib/src/JsonFormatters.scala similarity index 72% rename from main/core/src/mill/util/JsonFormatters.scala rename to scalalib/src/JsonFormatters.scala index 7be2c0fd512..c08184e6839 100644 --- a/main/core/src/mill/util/JsonFormatters.scala +++ b/scalalib/src/JsonFormatters.scala @@ -1,10 +1,10 @@ -package mill.util +package mill.scalalib import upickle.default.{ReadWriter => RW} import scala.reflect.ClassTag -trait JsonFormatters extends mill.api.JsonFormatters { +trait JsonFormatters { implicit lazy val publicationFormat: RW[coursier.core.Publication] = upickle.default.macroRW implicit lazy val extensionFormat: RW[coursier.core.Extension] = upickle.default.macroRW @@ -17,15 +17,5 @@ trait JsonFormatters extends mill.api.JsonFormatters { implicit lazy val typeFormat: RW[coursier.core.Type] = upickle.default.macroRW implicit lazy val classifierFormat: RW[coursier.core.Classifier] = upickle.default.macroRW - implicit def enumFormat[T <: java.lang.Enum[_]: ClassTag]: RW[T] = - upickle.default.readwriter[String].bimap( - _.name(), - (s: String) => - implicitly[ClassTag[T]] - .runtimeClass - .getConstructor(classOf[String]) - .newInstance(s) - .asInstanceOf[T] - ) } object JsonFormatters extends JsonFormatters diff --git a/scalalib/src/Lib.scala b/scalalib/src/Lib.scala index da21757acd6..868d0a5a5b7 100644 --- a/scalalib/src/Lib.scala +++ b/scalalib/src/Lib.scala @@ -120,75 +120,6 @@ object Lib { ivy"$scalaOrganization:scala-library:$scalaVersion".forceVersion() ) - def listClassFiles(base: os.Path): Iterator[String] = { - if (os.isDir(base)) - os.walk(base).iterator.filter(_.ext == "class").map(_.relativeTo(base).toString) - else { - val zip = new ZipInputStream(new FileInputStream(base.toIO)) - Iterator.continually(zip.getNextEntry).takeWhile(_ != null).map(_.getName).filter(_.endsWith( - ".class" - )) - } - } - - def discoverTests( - cl: ClassLoader, - framework: Framework, - classpath: Loose.Agg[os.Path] - ): Loose.Agg[(Class[_], Fingerprint)] = { - - val fingerprints = framework.fingerprints() - - val testClasses = classpath.flatMap { base => - // Don't blow up if there are no classfiles representing - // the tests to run Instead just don't run anything - if (!os.exists(base)) Nil - else listClassFiles(base).flatMap { path => - val cls = cl.loadClass(path.stripSuffix(".class").replace('/', '.')) - val publicConstructorCount = - cls.getConstructors.count(c => Modifier.isPublic(c.getModifiers)) - - if ( - Modifier.isAbstract(cls.getModifiers) || cls.isInterface || publicConstructorCount > 1 - ) { - None - } else { - (cls.getName.endsWith("$"), publicConstructorCount == 0) match { - case (true, true) => matchFingerprints(cl, cls, fingerprints, isModule = true) - case (false, false) => matchFingerprints(cl, cls, fingerprints, isModule = false) - case _ => None - } - } - } - } - - testClasses - } - def matchFingerprints( - cl: ClassLoader, - cls: Class[_], - fingerprints: Array[Fingerprint], - isModule: Boolean - ): Option[(Class[_], Fingerprint)] = { - fingerprints.find { - case f: SubclassFingerprint => - f.isModule == isModule && - cl.loadClass(f.superclassName()).isAssignableFrom(cls) - - case f: AnnotatedFingerprint => - val annotationCls = cl.loadClass(f.annotationName()).asInstanceOf[Class[Annotation]] - f.isModule == isModule && - ( - cls.isAnnotationPresent(annotationCls) || - cls.getDeclaredMethods.exists(_.isAnnotationPresent(annotationCls)) || - cls.getMethods.exists(m => - m.isAnnotationPresent(annotationCls) && Modifier.isPublic(m.getModifiers()) - ) - ) - - }.map { f => (cls, f) } - } - @deprecated( "User other overload instead. Only for binary backward compatibility.", "mill after 0.9.6" diff --git a/scalalib/src/TestModule.scala b/scalalib/src/TestModule.scala index c0e6d455c37..44067fec0ce 100644 --- a/scalalib/src/TestModule.scala +++ b/scalalib/src/TestModule.scala @@ -5,6 +5,7 @@ import mill.define.{Command, Task, TaskModule} import mill.eval.Result import mill.modules.Jvm import mill.scalalib.bsp.{BspBuildTarget, BspModule} +import mill.testrunner.TestRunner trait TestModule extends JavaModule with TaskModule { override def defaultCommandName() = "test" @@ -138,7 +139,7 @@ trait TestModule extends JavaModule with TaskModule { } Jvm.runSubprocess( - mainClass = "mill.scalalib.TestRunner", + mainClass = "mill.testrunner.TestRunner", classPath = zincWorker.scalalibClasspath().map(_.path), jvmArgs = jvmArgs, envArgs = forkEnv(), diff --git a/scalalib/src/dependency/updates/ModuleDependenciesUpdates.scala b/scalalib/src/dependency/updates/ModuleDependenciesUpdates.scala index a1120ee71de..1705edec671 100644 --- a/scalalib/src/dependency/updates/ModuleDependenciesUpdates.scala +++ b/scalalib/src/dependency/updates/ModuleDependenciesUpdates.scala @@ -22,7 +22,7 @@ final case class DependencyUpdates( ) object DependencyUpdates { - import mill.util.JsonFormatters.depFormat + import mill.scalalib.JsonFormatters.depFormat implicit val rw: upickle.default.ReadWriter[DependencyUpdates] = upickle.default.macroRW diff --git a/scalalib/src/package.scala b/scalalib/src/package.scala index 145d0198109..6d64cbaefd3 100644 --- a/scalalib/src/package.scala +++ b/scalalib/src/package.scala @@ -1,6 +1,6 @@ package mill -package object scalalib { +package object scalalib extends mill.scalalib.JsonFormatters { implicit class DepSyntax(ctx: StringContext) { def ivy(args: Any*) = Dep.parse { ( diff --git a/scalalib/test/src/TestRunnerTests.scala b/scalalib/test/src/TestRunnerTests.scala index c6185c779d6..a3f60409668 100644 --- a/scalalib/test/src/TestRunnerTests.scala +++ b/scalalib/test/src/TestRunnerTests.scala @@ -3,7 +3,7 @@ package mill.scalalib import mill.{Agg, T} import scala.util.Success -import mill.scalalib.TestRunner.TestArgs +import mill.testrunner.TestRunner.TestArgs import mill.util.{TestEvaluator, TestUtil} import org.scalacheck.Prop.forAll import utest._ @@ -73,7 +73,7 @@ object TestRunnerTests extends TestSuite { "TestRunner" - { "test case lookup" - workspaceTest(testrunner) { eval => val Right((result, _)) = eval.apply(testrunner.test.test()) - val test = result.asInstanceOf[(String, Seq[mill.scalalib.TestRunner.Result])] + val test = result.asInstanceOf[(String, Seq[mill.testrunner.TestRunner.Result])] assert( test._2.size == 3 ) @@ -81,7 +81,7 @@ object TestRunnerTests extends TestSuite { "testOnly" - { def testOnly(eval: TestEvaluator, args: Seq[String], size: Int) = { val Right((result1, _)) = eval.apply(testrunner.test.testOnly(args: _*)) - val testOnly = result1.asInstanceOf[(String, Seq[mill.scalalib.TestRunner.Result])] + val testOnly = result1.asInstanceOf[(String, Seq[mill.testrunner.TestRunner.Result])] assert( testOnly._2.size == size ) diff --git a/scalanativelib/src/ScalaNativeModule.scala b/scalanativelib/src/ScalaNativeModule.scala index ea164c3f162..9729619c416 100644 --- a/scalanativelib/src/ScalaNativeModule.scala +++ b/scalanativelib/src/ScalaNativeModule.scala @@ -8,7 +8,8 @@ import mill.api.internal import mill.define.{Target, Task} import mill.modules.Jvm import mill.scalalib.api.Util.scalaBinaryVersion -import mill.scalalib.{Dep, DepSyntax, Lib, SbtModule, ScalaModule, TestModule, TestRunner} +import mill.scalalib.{Dep, DepSyntax, Lib, SbtModule, ScalaModule, TestModule} +import mill.testrunner.TestRunner import mill.scalanativelib.api._ import scala.jdk.CollectionConverters._ diff --git a/scalanativelib/test/src/HelloNativeWorldTests.scala b/scalanativelib/test/src/HelloNativeWorldTests.scala index 9d810ef91ca..3598ee3d3ef 100644 --- a/scalanativelib/test/src/HelloNativeWorldTests.scala +++ b/scalanativelib/test/src/HelloNativeWorldTests.scala @@ -4,7 +4,8 @@ import java.util.jar.JarFile import mill._ import mill.define.Discover import mill.eval.{EvaluatorPaths, Result} -import mill.scalalib.{CrossScalaModule, DepSyntax, Lib, PublishModule, TestModule, TestRunner} +import mill.scalalib.{CrossScalaModule, DepSyntax, Lib, PublishModule, TestModule} +import mill.testrunner.TestRunner import mill.scalalib.publish.{Developer, License, PomSettings, VersionControl} import mill.scalanativelib.api._ import mill.util.{TestEvaluator, TestUtil} diff --git a/scalalib/src/TestRunner.scala b/testrunner/src/TestRunner.scala similarity index 75% rename from scalalib/src/TestRunner.scala rename to testrunner/src/TestRunner.scala index 10002571e7f..558ed194d71 100644 --- a/scalalib/src/TestRunner.scala +++ b/testrunner/src/TestRunner.scala @@ -1,20 +1,91 @@ -package mill.scalalib +package mill.testrunner -import ammonite.util.Colors -import mill.Agg -import mill.api.{DummyTestReporter, TestReporter} -import mill.modules.Jvm +import mill.api.Loose.Agg +import mill.api.{DummyTestReporter, Loose, TestReporter} +import mill.util.Jvm import mill.scalalib.api._ -import mill.scalalib.Lib.discoverTests import mill.util.{Ctx, PrintLogger} -import mill.util.JsonFormatters._ +import mill.api.JsonFormatters._ import sbt.testing._ +import java.io.FileInputStream +import java.lang.annotation.Annotation +import java.lang.reflect.Modifier import java.util.regex.Pattern +import java.util.zip.ZipInputStream import scala.collection.mutable import scala.util.Try object TestRunner { + def listClassFiles(base: os.Path): Iterator[String] = { + if (os.isDir(base)) + os.walk(base).iterator.filter(_.ext == "class").map(_.relativeTo(base).toString) + else { + val zip = new ZipInputStream(new FileInputStream(base.toIO)) + Iterator.continually(zip.getNextEntry).takeWhile(_ != null).map(_.getName).filter(_.endsWith( + ".class" + )) + } + } + + def discoverTests( + cl: ClassLoader, + framework: Framework, + classpath: Loose.Agg[os.Path] + ): Loose.Agg[(Class[_], Fingerprint)] = { + + val fingerprints = framework.fingerprints() + + val testClasses = classpath.flatMap { base => + // Don't blow up if there are no classfiles representing + // the tests to run Instead just don't run anything + if (!os.exists(base)) Nil + else listClassFiles(base).flatMap { path => + val cls = cl.loadClass(path.stripSuffix(".class").replace('/', '.')) + val publicConstructorCount = + cls.getConstructors.count(c => Modifier.isPublic(c.getModifiers)) + + if ( + Modifier.isAbstract(cls.getModifiers) || cls.isInterface || publicConstructorCount > 1 + ) { + None + } else { + (cls.getName.endsWith("$"), publicConstructorCount == 0) match { + case (true, true) => matchFingerprints(cl, cls, fingerprints, isModule = true) + case (false, false) => matchFingerprints(cl, cls, fingerprints, isModule = false) + case _ => None + } + } + } + } + + testClasses + } + + def matchFingerprints( + cl: ClassLoader, + cls: Class[_], + fingerprints: Array[Fingerprint], + isModule: Boolean + ): Option[(Class[_], Fingerprint)] = { + fingerprints.find { + case f: SubclassFingerprint => + f.isModule == isModule && + cl.loadClass(f.superclassName()).isAssignableFrom(cls) + + case f: AnnotatedFingerprint => + val annotationCls = cl.loadClass(f.annotationName()).asInstanceOf[Class[Annotation]] + f.isModule == isModule && + ( + cls.isAnnotationPresent(annotationCls) || + cls.getDeclaredMethods.exists(_.isAnnotationPresent(annotationCls)) || + cls.getMethods.exists(m => + m.isAnnotationPresent(annotationCls) && Modifier.isPublic(m.getModifiers()) + ) + ) + + }.map { f => (cls, f) } + } case class TestArgs( framework: String, @@ -137,8 +208,10 @@ object TestRunner { val log = PrintLogger( testArgs.colored, true, - if (testArgs.colored) Colors.Default - else Colors.BlackWhite, + if (testArgs.colored) fansi.Color.Blue + else fansi.Attrs.Empty, + if (testArgs.colored) fansi.Color.Red + else fansi.Attrs.Empty, System.out, System.err, System.err, @@ -186,7 +259,7 @@ object TestRunner { testClassfilePath: Agg[os.Path], args: Seq[String], testReporter: TestReporter - )(implicit ctx: Ctx.Log with Ctx.Home): (String, Seq[mill.scalalib.TestRunner.Result]) = { + )(implicit ctx: Ctx.Log with Ctx.Home): (String, Seq[mill.testrunner.TestRunner.Result]) = { runTestFramework( frameworkInstances = cl => frameworkInstances(cl).head, entireClasspath = entireClasspath, @@ -202,7 +275,7 @@ object TestRunner { testClassfilePath: Agg[os.Path], args: Seq[String], testReporter: TestReporter - )(implicit ctx: Ctx.Log with Ctx.Home): (String, Seq[mill.scalalib.TestRunner.Result]) = { + )(implicit ctx: Ctx.Log with Ctx.Home): (String, Seq[mill.testrunner.TestRunner.Result]) = { runTestFramework( frameworkInstances, entireClasspath, @@ -220,7 +293,7 @@ object TestRunner { args: Seq[String], testReporter: TestReporter, classFilter: Class[_] => Boolean - )(implicit ctx: Ctx.Log with Ctx.Home): (String, Seq[mill.scalalib.TestRunner.Result]) = { + )(implicit ctx: Ctx.Log with Ctx.Home): (String, Seq[mill.testrunner.TestRunner.Result]) = { // Leave the context class loader set and open so that shutdown hooks can access it Jvm.inprocess( entireClasspath, @@ -282,7 +355,7 @@ object TestRunner { val results = for (e <- events) yield { val ex = if (e.throwable().isDefined) Some(e.throwable().get) else None - mill.scalalib.TestRunner.Result( + mill.testrunner.TestRunner.Result( e.fullyQualifiedName(), e.selector() match { case s: NestedSuiteSelector => s.suiteId() From cfc8055e5030e6e9d1975c35b63b9ba70ea4cc17 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Mon, 6 Dec 2021 18:14:52 +0800 Subject: [PATCH 02/18] . --- build.sc | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/build.sc b/build.sc index 326b4eaa23e..0cd9276d7de 100755 --- a/build.sc +++ b/build.sc @@ -268,6 +268,7 @@ object main extends MillModule { } object util extends MillModule { override def moduleDeps = Seq(moduledefs, api) + def compileIvyDeps = Agg(Deps.scalaCompiler(scalaVersion())) def ivyDeps = Agg( Deps.ammoniteTerminal, Deps.fansi @@ -334,10 +335,8 @@ object main extends MillModule { object moduledefs extends MillPublishModule with ScalaModule { def scalaVersion = Deps.scalaVersion - override def ivyDeps = Agg( - Deps.scalaCompiler(scalaVersion()), - Deps.sourcecode - ) + def compileIvyDeps = Agg(Deps.scalaCompiler(scalaVersion())) + override def ivyDeps = Agg(Deps.sourcecode) } object client extends MillPublishModule { @@ -345,12 +344,7 @@ object main extends MillModule { Deps.ipcsocketExcludingJna ) object test extends Tests with TestModule.Junit4 { - override def ivyDeps = T { - Agg( - Deps.junitInterface, - Deps.lambdaTest - ) - } + override def ivyDeps = Agg(Deps.junitInterface, Deps.lambdaTest) } } From 9133cbe427cb2519a18719ace6920ca9c67d5dfd Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Mon, 6 Dec 2021 18:16:13 +0800 Subject: [PATCH 03/18] . --- main/api/src/mill/api/ClassLoader.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main/api/src/mill/api/ClassLoader.scala b/main/api/src/mill/api/ClassLoader.scala index e6924ed3c41..bc3b79c2f7c 100644 --- a/main/api/src/mill/api/ClassLoader.scala +++ b/main/api/src/mill/api/ClassLoader.scala @@ -38,9 +38,8 @@ object ClassLoader { makeUrls(urls).toArray, refinePlatformParent(parent) ) { - val allSharedPrefixes = sharedPrefixes :+ "com.sun.jna" override def findClass(name: String): Class[_] = { - if (allSharedPrefixes.exists(name.startsWith)) { + if (sharedPrefixes.exists(name.startsWith)) { logger.foreach( _.debug(s"About to load class [${name}] from shared classloader [${sharedLoader}]") ) From 99ea00dfa6c618bd819d52d3523a423ec22d2b20 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Mon, 6 Dec 2021 20:33:46 +0800 Subject: [PATCH 04/18] fix-formatting --- main/core/src/mill/define/ParseArgs.scala | 30 +++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/main/core/src/mill/define/ParseArgs.scala b/main/core/src/mill/define/ParseArgs.scala index 3683add4f47..edde732c732 100644 --- a/main/core/src/mill/define/ParseArgs.scala +++ b/main/core/src/mill/define/ParseArgs.scala @@ -31,14 +31,14 @@ object ParseArgs { @deprecated("Use apply(Seq[String], SelectMode) instead", "mill after 0.10.0-M3") def apply( - scriptArgs: Seq[String], - multiSelect: Boolean - ): Either[String, TargetsWithParams] = extractAndValidate(scriptArgs, multiSelect) + scriptArgs: Seq[String], + multiSelect: Boolean + ): Either[String, TargetsWithParams] = extractAndValidate(scriptArgs, multiSelect) def apply( - scriptArgs: Seq[String], - selectMode: SelectMode - ): Either[String, Seq[TargetsWithParams]] = { + scriptArgs: Seq[String], + selectMode: SelectMode + ): Either[String, Seq[TargetsWithParams]] = { val MaskPattern = ("""\\+\Q""" + TargetSeparator + """\E""").r @@ -63,29 +63,29 @@ object ParseArgs { val parsed: Seq[Either[String, TargetsWithParams]] = parts.map(extractAndValidate(_, selectMode == SelectMode.Multi)) - val res1: Either[String, Seq[TargetsWithParams]] = mill.util.EitherOps.sequence(parsed) + val res1: Either[String, Seq[TargetsWithParams]] = EitherOps.sequence(parsed) res1 } private def extractAndValidate( - scriptArgs: Seq[String], - multiSelect: Boolean - ): Either[String, TargetsWithParams] = { + scriptArgs: Seq[String], + multiSelect: Boolean + ): Either[String, TargetsWithParams] = { val (selectors, args) = extractSelsAndArgs(scriptArgs, multiSelect) for { _ <- validateSelectors(selectors) - expandedSelectors <- mill.util.EitherOps + expandedSelectors <- EitherOps .sequence(selectors.map(expandBraces)) .map(_.flatten) - selectors <- mill.util.EitherOps.sequence(expandedSelectors.map(extractSegments)) + selectors <- EitherOps.sequence(expandedSelectors.map(extractSegments)) } yield (selectors.toList, args) } def extractSelsAndArgs( - scriptArgs: Seq[String], - multiSelect: Boolean - ): (Seq[String], Seq[String]) = { + scriptArgs: Seq[String], + multiSelect: Boolean + ): (Seq[String], Seq[String]) = { if (multiSelect) { val dd = scriptArgs.indexOf(MultiArgsSeparator) From 7e266c7cfccdaf742091b3afb58fc488b3dc2c58 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Mon, 6 Dec 2021 22:06:55 +0800 Subject: [PATCH 05/18] . --- build.sc | 11 ++++++----- .../mill/util => core/src/mill/define}/Compat.scala | 2 +- .../src/mill/define}/EnclosingClass.scala | 4 ++-- main/core/src/mill/define/ParseArgs.scala | 1 + main/core/src/mill/define/Task.scala | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) rename main/{util/src/mill/util => core/src/mill/define}/Compat.scala (93%) rename main/{util/src/mill/util => core/src/mill/define}/EnclosingClass.scala (84%) diff --git a/build.sc b/build.sc index 0cd9276d7de..864eb99f93a 100755 --- a/build.sc +++ b/build.sc @@ -266,9 +266,8 @@ object main extends MillModule { Deps.sbtTestInterface ) } - object util extends MillModule { - override def moduleDeps = Seq(moduledefs, api) - def compileIvyDeps = Agg(Deps.scalaCompiler(scalaVersion())) + object util extends MillApiModule { + override def moduleDeps = Seq(api) def ivyDeps = Agg( Deps.ammoniteTerminal, Deps.fansi @@ -335,8 +334,10 @@ object main extends MillModule { object moduledefs extends MillPublishModule with ScalaModule { def scalaVersion = Deps.scalaVersion - def compileIvyDeps = Agg(Deps.scalaCompiler(scalaVersion())) - override def ivyDeps = Agg(Deps.sourcecode) + override def ivyDeps = Agg( + Deps.sourcecode, + Deps.scalaCompiler(scalaVersion()) + ) } object client extends MillPublishModule { diff --git a/main/util/src/mill/util/Compat.scala b/main/core/src/mill/define/Compat.scala similarity index 93% rename from main/util/src/mill/util/Compat.scala rename to main/core/src/mill/define/Compat.scala index 7e3eca391e9..1716cfedf56 100644 --- a/main/util/src/mill/util/Compat.scala +++ b/main/core/src/mill/define/Compat.scala @@ -1,4 +1,4 @@ -package mill.util +package mill.define import scala.reflect.macros.blackbox.Context diff --git a/main/util/src/mill/util/EnclosingClass.scala b/main/core/src/mill/define/EnclosingClass.scala similarity index 84% rename from main/util/src/mill/util/EnclosingClass.scala rename to main/core/src/mill/define/EnclosingClass.scala index 1fadcfced7b..62f950164fc 100644 --- a/main/util/src/mill/util/EnclosingClass.scala +++ b/main/core/src/mill/define/EnclosingClass.scala @@ -1,4 +1,4 @@ -package mill.util +package mill.define import sourcecode.Compat.Context import language.experimental.macros @@ -10,6 +10,6 @@ object EnclosingClass { import c.universe._ val cls = c.internal.enclosingOwner.owner.asType.asClass // q"new _root_.mill.define.EnclosingClass(classOf[$cls])" - q"new _root_.mill.util.EnclosingClass(this.getClass)" + q"new _root_.mill.define.EnclosingClass(this.getClass)" } } diff --git a/main/core/src/mill/define/ParseArgs.scala b/main/core/src/mill/define/ParseArgs.scala index edde732c732..0c6953d11bd 100644 --- a/main/core/src/mill/define/ParseArgs.scala +++ b/main/core/src/mill/define/ParseArgs.scala @@ -5,6 +5,7 @@ import scala.annotation.tailrec import fastparse._ import NoWhitespace._ import mill.define.{Segment, Segments} +import mill.util.EitherOps sealed trait SelectMode object SelectMode { diff --git a/main/core/src/mill/define/Task.scala b/main/core/src/mill/define/Task.scala index b68942a967a..9afe7356b0e 100644 --- a/main/core/src/mill/define/Task.scala +++ b/main/core/src/mill/define/Task.scala @@ -2,7 +2,7 @@ package mill.define import mill.api.{CompileProblemReporter, Logger, PathRef, Result, TestReporter} import mill.define.Applicative.Applyable -import mill.util.EnclosingClass +import mill.define.EnclosingClass import sourcecode.Compat.Context import upickle.default.{ReadWriter => RW, Reader => R, Writer => W} import scala.language.experimental.macros From 0884bca4e794488491d8fd73d3cc046e4dbb0a07 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Mon, 6 Dec 2021 22:16:58 +0800 Subject: [PATCH 06/18] . --- build.sc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sc b/build.sc index 864eb99f93a..cf9b20366d5 100755 --- a/build.sc +++ b/build.sc @@ -335,8 +335,8 @@ object main extends MillModule { object moduledefs extends MillPublishModule with ScalaModule { def scalaVersion = Deps.scalaVersion override def ivyDeps = Agg( - Deps.sourcecode, - Deps.scalaCompiler(scalaVersion()) + Deps.scalaCompiler(scalaVersion()), + Deps.sourcecode ) } From de79b6d6dd2dc590feb1d6ed0b279d1e77effceb Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Mon, 6 Dec 2021 22:18:06 +0800 Subject: [PATCH 07/18] . --- main/util/src/mill/util/Jvm.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/main/util/src/mill/util/Jvm.scala b/main/util/src/mill/util/Jvm.scala index 523ece9b111..e2fd62edf3d 100644 --- a/main/util/src/mill/util/Jvm.scala +++ b/main/util/src/mill/util/Jvm.scala @@ -4,12 +4,12 @@ import mill.api.Loose.Agg object Jvm { def inprocess[T]( - classPath: Agg[os.Path], - classLoaderOverrideSbtTesting: Boolean, - isolated: Boolean, - closeContextClassLoaderWhenDone: Boolean, - body: ClassLoader => T - )(implicit ctx: mill.api.Ctx.Home): T = { + classPath: Agg[os.Path], + classLoaderOverrideSbtTesting: Boolean, + isolated: Boolean, + closeContextClassLoaderWhenDone: Boolean, + body: ClassLoader => T + )(implicit ctx: Ctx.Home): T = { val urls = classPath.map(_.toIO.toURI.toURL) val cl = if (classLoaderOverrideSbtTesting) { From 3f421f40e14926fa010f9456bed371648e805c73 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Mon, 6 Dec 2021 22:19:48 +0800 Subject: [PATCH 08/18] . --- testrunner/src/TestRunner.scala | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/testrunner/src/TestRunner.scala b/testrunner/src/TestRunner.scala index 558ed194d71..3a0bf9d6b85 100644 --- a/testrunner/src/TestRunner.scala +++ b/testrunner/src/TestRunner.scala @@ -29,10 +29,10 @@ object TestRunner { } def discoverTests( - cl: ClassLoader, - framework: Framework, - classpath: Loose.Agg[os.Path] - ): Loose.Agg[(Class[_], Fingerprint)] = { + cl: ClassLoader, + framework: Framework, + classpath: Loose.Agg[os.Path] + ): Loose.Agg[(Class[_], Fingerprint)] = { val fingerprints = framework.fingerprints() @@ -63,11 +63,11 @@ object TestRunner { } def matchFingerprints( - cl: ClassLoader, - cls: Class[_], - fingerprints: Array[Fingerprint], - isModule: Boolean - ): Option[(Class[_], Fingerprint)] = { + cl: ClassLoader, + cls: Class[_], + fingerprints: Array[Fingerprint], + isModule: Boolean + ): Option[(Class[_], Fingerprint)] = { fingerprints.find { case f: SubclassFingerprint => f.isModule == isModule && @@ -76,13 +76,13 @@ object TestRunner { case f: AnnotatedFingerprint => val annotationCls = cl.loadClass(f.annotationName()).asInstanceOf[Class[Annotation]] f.isModule == isModule && - ( - cls.isAnnotationPresent(annotationCls) || - cls.getDeclaredMethods.exists(_.isAnnotationPresent(annotationCls)) || - cls.getMethods.exists(m => - m.isAnnotationPresent(annotationCls) && Modifier.isPublic(m.getModifiers()) - ) + ( + cls.isAnnotationPresent(annotationCls) || + cls.getDeclaredMethods.exists(_.isAnnotationPresent(annotationCls)) || + cls.getMethods.exists(m => + m.isAnnotationPresent(annotationCls) && Modifier.isPublic(m.getModifiers()) ) + ) }.map { f => (cls, f) } } From 1d33f41bd487bf4c2938e130ff46e41ea880837f Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Tue, 7 Dec 2021 15:40:36 +0800 Subject: [PATCH 09/18] . --- main/core/src/mill/define/BaseModule.scala | 1 - main/core/src/mill/define/Ctx.scala | 3 -- main/core/src/mill/define/Overrides.scala | 14 ------ main/core/src/mill/define/Task.scala | 7 +-- main/core/src/mill/eval/Evaluator.scala | 54 ++++++++++------------ main/test/src/util/TestUtil.scala | 1 - scratch/build.sc | 14 ++++-- 7 files changed, 36 insertions(+), 58 deletions(-) delete mode 100644 main/core/src/mill/define/Overrides.scala diff --git a/main/core/src/mill/define/BaseModule.scala b/main/core/src/mill/define/BaseModule.scala index 8e77be24e6d..3c4c208da6d 100644 --- a/main/core/src/mill/define/BaseModule.scala +++ b/main/core/src/mill/define/BaseModule.scala @@ -21,7 +21,6 @@ abstract class BaseModule( implicitly, BasePath(millSourcePath0), Segments(), - mill.define.Overrides(0), Ctx.External(external0), Ctx.Foreign(foreign0), millFile0, diff --git a/main/core/src/mill/define/Ctx.scala b/main/core/src/mill/define/Ctx.scala index ecfd8530cf4..c7692411e2c 100644 --- a/main/core/src/mill/define/Ctx.scala +++ b/main/core/src/mill/define/Ctx.scala @@ -64,7 +64,6 @@ case class Ctx( segment: Segment, millSourcePath: os.Path, segments: Segments, - overrides: Int, external: Boolean, foreign: Option[Segments], fileName: String, @@ -81,7 +80,6 @@ object Ctx { millName0: sourcecode.Name, millModuleBasePath0: BasePath, segments0: Segments, - overrides0: mill.define.Overrides, external0: External, foreign0: Foreign, fileName: sourcecode.File, @@ -93,7 +91,6 @@ object Ctx { Segment.Label(millName0.value), millModuleBasePath0.value, segments0, - overrides0.value, external0.value, foreign0.value, fileName.value, diff --git a/main/core/src/mill/define/Overrides.scala b/main/core/src/mill/define/Overrides.scala deleted file mode 100644 index a9f02ca1d05..00000000000 --- a/main/core/src/mill/define/Overrides.scala +++ /dev/null @@ -1,14 +0,0 @@ -package mill.define - -import scala.reflect.macros.blackbox.Context -import language.experimental.macros - -case class Overrides(value: Int) -object Overrides { - def apply()(implicit c: Overrides) = c.value - implicit def generate: Overrides = macro impl - def impl(c: Context): c.Tree = { - import c.universe._ - q"new _root_.mill.define.Overrides(${c.internal.enclosingOwner.overrides.length})" - } -} diff --git a/main/core/src/mill/define/Task.scala b/main/core/src/mill/define/Task.scala index 9afe7356b0e..4b125d508c9 100644 --- a/main/core/src/mill/define/Task.scala +++ b/main/core/src/mill/define/Task.scala @@ -209,23 +209,20 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul ctx: mill.define.Ctx, w: W[T], cls: EnclosingClass, - overrides: Overrides ): Command[T] = { - new Command(t, ctx, w, cls.value, overrides.value) + new Command(t, ctx, w, cls.value) } def command[T](t: Result[T])(implicit w: W[T], ctx: mill.define.Ctx, cls: EnclosingClass, - overrides: Overrides ): Command[T] = macro commandImpl[T] def commandImpl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T])( w: c.Expr[W[T]], ctx: c.Expr[mill.define.Ctx], cls: c.Expr[EnclosingClass], - overrides: c.Expr[Overrides] ): c.Expr[Command[T]] = { import c.universe._ reify( @@ -234,7 +231,6 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul ctx.splice, w.splice, cls.splice.value, - overrides.splice.value ) ) } @@ -317,7 +313,6 @@ class Command[+T]( ctx0: mill.define.Ctx, val writer: W[_], val cls: Class[_], - val overrides: Int ) extends NamedTaskImpl[T](ctx0, t) { override def asCommand = Some(this) } diff --git a/main/core/src/mill/eval/Evaluator.scala b/main/core/src/mill/eval/Evaluator.scala index d39543409b2..ac7686caa85 100644 --- a/main/core/src/mill/eval/Evaluator.scala +++ b/main/core/src/mill/eval/Evaluator.scala @@ -94,7 +94,15 @@ case class Evaluator( testReporter: TestReporter = DummyTestReporter ): Evaluator.Results = { val (sortedGroups, transitive) = Evaluator.plan(rootModule, goals) - + pprint.log(goals.toSeq) + val terminalNames = sortedGroups + .keys() + .map{ + case Left(x) => x + case Right(x) => (System.identityHashCode(x), x.task.ctx.lineNum, x.segments.render) + } + .toList + pprint.log(terminalNames.toList) val evaluated = new Agg.Mutable[Task[_]] val results = mutable.LinkedHashMap.empty[Task[_], mill.api.Result[(Any, Int)]] var someTaskFailed: Boolean = false @@ -659,44 +667,30 @@ object Evaluator { def plan(rootModule: BaseModule, goals: Agg[Task[_]]) = { val transitive = Graph.transitiveTargets(goals) val topoSorted = Graph.topoSorted(transitive) + val seen = collection.mutable.Set.empty[Segments] + val overriden = collection.mutable.Set.empty[Task[_]] + pprint.log(topoSorted.values.reverse) + topoSorted.values.reverse.foreach{ + case x: NamedTask[_] => + if (!seen.contains(x.ctx.segments)) seen.add(x.ctx.segments) + else overriden.add(x) + case _ => //donothing + } + pprint.log(overriden.size) + pprint.log(seen.size) + val sortedGroups = Graph.groupAroundImportantTargets(topoSorted) { case t: NamedTask[Any] => val segments = t.ctx.segments - val finalTaskOverrides = t match { - case t: Target[_] => - rootModule.millInternal.segmentsToTargets.get(segments).fold(0)(_.ctx.overrides) - - case c: mill.define.Command[_] => - def findMatching(cls: Class[_]): Option[Seq[(Int, MainData[_, _])]] = { - rootModule.millDiscover.value.get(cls) match { - case Some(v) => Some(v) - case None => - cls.getSuperclass match { - case null => None - case superCls => findMatching(superCls) - } - } - } - - 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 - } val additional = - if (finalTaskOverrides == t.ctx.overrides) Nil - else - Seq(Segment.Label("overriden")) ++ t.ctx.enclosing.split("\\.|#| ").map(Segment.Label) + if (!overriden(t)) Nil + else Seq(Segment.Label("overriden")) ++ t.ctx.enclosing.split("\\.|#| ").map(Segment.Label) Right(Labelled(t, segments ++ additional)) case t if goals.contains(t) => Left(t) } + (sortedGroups, transitive) } diff --git a/main/test/src/util/TestUtil.scala b/main/test/src/util/TestUtil.scala index ecc182a48b5..98176d94e25 100644 --- a/main/test/src/util/TestUtil.scala +++ b/main/test/src/util/TestUtil.scala @@ -28,7 +28,6 @@ object TestUtil { millModuleEnclosing0: sourcecode.Enclosing, millModuleLine0: sourcecode.Line, millName0: sourcecode.Name, - overrides: Overrides ) extends mill.define.BaseModule(getSrcPathBase() / millModuleEnclosing0.value.split("\\.| |#"))( implicitly, implicitly, diff --git a/scratch/build.sc b/scratch/build.sc index 08383d51147..16bac8d9929 100644 --- a/scratch/build.sc +++ b/scratch/build.sc @@ -1,6 +1,14 @@ import mill._ -import mill.scalalib._ -object foo extends ScalaModule{ - def scalaVersion = "2.13.2" +trait X extends Module{ + def f = T{ 1 } } +trait A extends X{ + override def f = T{ super.f() + 2 } +} + +trait B extends X{ + override def f = T{ super.f() + 3 } +} +object m extends A with B{ +} \ No newline at end of file From 2685600bc72179bfc480c4bf94cf41815f004d2b Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Tue, 7 Dec 2021 15:53:08 +0800 Subject: [PATCH 10/18] . --- main/core/src/mill/eval/Evaluator.scala | 6 +----- main/test/src/eval/EvaluationTests.scala | 27 ++++++++++++++++++++++++ main/test/src/util/TestGraphs.scala | 15 +++++++++++++ scratch/build.sc | 14 +++--------- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/main/core/src/mill/eval/Evaluator.scala b/main/core/src/mill/eval/Evaluator.scala index ac7686caa85..b07cce024f3 100644 --- a/main/core/src/mill/eval/Evaluator.scala +++ b/main/core/src/mill/eval/Evaluator.scala @@ -94,7 +94,6 @@ case class Evaluator( testReporter: TestReporter = DummyTestReporter ): Evaluator.Results = { val (sortedGroups, transitive) = Evaluator.plan(rootModule, goals) - pprint.log(goals.toSeq) val terminalNames = sortedGroups .keys() .map{ @@ -102,7 +101,7 @@ case class Evaluator( case Right(x) => (System.identityHashCode(x), x.task.ctx.lineNum, x.segments.render) } .toList - pprint.log(terminalNames.toList) + val evaluated = new Agg.Mutable[Task[_]] val results = mutable.LinkedHashMap.empty[Task[_], mill.api.Result[(Any, Int)]] var someTaskFailed: Boolean = false @@ -669,15 +668,12 @@ object Evaluator { val topoSorted = Graph.topoSorted(transitive) val seen = collection.mutable.Set.empty[Segments] val overriden = collection.mutable.Set.empty[Task[_]] - pprint.log(topoSorted.values.reverse) topoSorted.values.reverse.foreach{ case x: NamedTask[_] => if (!seen.contains(x.ctx.segments)) seen.add(x.ctx.segments) else overriden.add(x) case _ => //donothing } - pprint.log(overriden.size) - pprint.log(seen.size) val sortedGroups = Graph.groupAroundImportantTargets(topoSorted) { case t: NamedTask[Any] => diff --git a/main/test/src/eval/EvaluationTests.scala b/main/test/src/eval/EvaluationTests.scala index d920dc7ed84..75ae994101d 100644 --- a/main/test/src/eval/EvaluationTests.scala +++ b/main/test/src/eval/EvaluationTests.scala @@ -356,5 +356,32 @@ class EvaluationTests(threadCount: Option[Int]) extends TestSuite { assert(leftCount == 4, middleCount == 4, rightCount == 1) } } + "stackableOverrides" - { + // Make sure you can override commands, call their supers, and have the + // overriden command be allocated a spot within the overriden/ folder of + // the main publicly-available command + import StackableOverrides._ + + val checker = new Checker(canOverrideSuper) + checker( + m.f, + 6, + Agg(m.f), + extraEvaled = -1 + ) + + val overridePrefix = + os.sub / "overriden" / "mill" / "util" / "TestGraphs" / "StackableOverrides" + + assert( + os.read(checker.evaluator.outPath / "m" / "f" / overridePrefix / "X" / "f.json") + .contains(" 1,") + ) + assert( + os.read(checker.evaluator.outPath / "m" / "f" / overridePrefix / "A" / "f.json") + .contains(" 3,") + ) + assert(os.read(checker.evaluator.outPath / "m" / "f.json").contains(" 6,")) + } } } diff --git a/main/test/src/util/TestGraphs.scala b/main/test/src/util/TestGraphs.scala index 1207bef7c34..45514758817 100644 --- a/main/test/src/util/TestGraphs.scala +++ b/main/test/src/util/TestGraphs.scala @@ -263,4 +263,19 @@ object TestGraphs { } } } + + object StackableOverrides extends TestUtil.BaseModule { + trait X extends Module{ + def f = T{ 1 } + } + trait A extends X{ + override def f = T{ super.f() + 2 } + } + + trait B extends X{ + override def f = T{ super.f() + 3 } + } + object m extends A with B{ + } + } } diff --git a/scratch/build.sc b/scratch/build.sc index 16bac8d9929..e0219632467 100644 --- a/scratch/build.sc +++ b/scratch/build.sc @@ -1,14 +1,6 @@ import mill._ +import mill.scalalib._ -trait X extends Module{ - def f = T{ 1 } -} -trait A extends X{ - override def f = T{ super.f() + 2 } -} - -trait B extends X{ - override def f = T{ super.f() + 3 } -} -object m extends A with B{ +object foo extends ScalaModule{ + def scalaVersion = "2.13.2" } \ No newline at end of file From 61f8c8668988bef595fd653986a7485ca8b3dcc5 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Tue, 7 Dec 2021 15:59:31 +0800 Subject: [PATCH 11/18] . --- scratch/build.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scratch/build.sc b/scratch/build.sc index e0219632467..08383d51147 100644 --- a/scratch/build.sc +++ b/scratch/build.sc @@ -3,4 +3,4 @@ import mill.scalalib._ object foo extends ScalaModule{ def scalaVersion = "2.13.2" -} \ No newline at end of file +} From 8ed6d54a8532a0414715b9f930d958de0f7ad214 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Tue, 7 Dec 2021 22:00:07 +0800 Subject: [PATCH 12/18] . --- main/core/src/mill/define/Task.scala | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/main/core/src/mill/define/Task.scala b/main/core/src/mill/define/Task.scala index 4b125d508c9..b6d6d09d1d6 100644 --- a/main/core/src/mill/define/Task.scala +++ b/main/core/src/mill/define/Task.scala @@ -185,11 +185,11 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul ) ) } - def input[T](value: Result[T])(implicit rw: RW[T], ctx: mill.define.Ctx): Input[T] = + def input[T](value: Result[T])(implicit w: upickle.default.Writer[T], ctx: mill.define.Ctx): Input[T] = macro inputImpl[T] def inputImpl[T: c.WeakTypeTag](c: Context)(value: c.Expr[T])( - rw: c.Expr[RW[T]], + w: c.Expr[upickle.default.Writer[T]], ctx: c.Expr[mill.define.Ctx] ): c.Expr[Input[T]] = { import c.universe._ @@ -199,7 +199,7 @@ object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Resul new Input[T]( Applicative.impl[Task, T, mill.api.Ctx](c)(value).splice, ctx.splice, - rw.splice + w.splice ) ) ) @@ -328,9 +328,8 @@ class Persistent[+T](t: Task[T], ctx0: mill.define.Ctx, readWrite: RW[_]) override def flushDest = false } -class Input[T](t: Task[T], ctx0: mill.define.Ctx, val readWrite: RW[_]) - extends NamedTaskImpl[T](ctx0, t) - with Target[T] { +class Input[T](t: Task[T], ctx0: mill.define.Ctx, val writer: upickle.default.Writer[_]) + extends NamedTaskImpl[T](ctx0, t) { override def sideHash = util.Random.nextInt() } @@ -338,10 +337,7 @@ class Sources(t: Task[Seq[PathRef]], ctx0: mill.define.Ctx) extends Input[Seq[PathRef]]( t, ctx0, - RW.join( - upickle.default.SeqLikeReader[Seq, PathRef], - upickle.default.SeqLikeWriter[Seq, PathRef] - ) + upickle.default.SeqLikeWriter[Seq, PathRef] ) class Source(t: Task[PathRef], ctx0: mill.define.Ctx) From 1aa431c223baac96dcbb411b9d3f6ed98ec56d80 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Tue, 7 Dec 2021 22:00:33 +0800 Subject: [PATCH 13/18] . --- docs/antora/modules/ROOT/pages/Tasks.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/antora/modules/ROOT/pages/Tasks.adoc b/docs/antora/modules/ROOT/pages/Tasks.adoc index 54668788e1a..7a917b46840 100644 --- a/docs/antora/modules/ROOT/pages/Tasks.adoc +++ b/docs/antora/modules/ROOT/pages/Tasks.adoc @@ -306,7 +306,7 @@ different Task types: | |Target |Command |Source/Input |Anonymous Task |Persistent Target |Worker |Cached to Disk |X |X | | |X | -|Must be JSON Writable |X |X | | |X | +|Must be JSON Writable |X |X |X| |X | |Must be JSON Readable |X | | | |X | |Runnable from the Command Line |X |X | | |X | |Can Take Arguments | |X | |X | | From 194cdfa822df33bde22b59fb5a7c455671f9159a Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Tue, 7 Dec 2021 15:16:49 +0100 Subject: [PATCH 14/18] Updated bootstrap patch file --- ci/mill-bootstrap.patch | 142 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/ci/mill-bootstrap.patch b/ci/mill-bootstrap.patch index e69de29bb2d..bf7fbf6eca0 100644 --- a/ci/mill-bootstrap.patch +++ b/ci/mill-bootstrap.patch @@ -0,0 +1,142 @@ +diff --git a/build.sc b/build.sc +index cf9b2036..335e5ec0 100755 +--- a/build.sc ++++ b/build.sc +@@ -1,16 +1,16 @@ + import $file.ci.shared + import $file.ci.upload + import $ivy.`org.scalaj::scalaj-http:2.4.2` +-import $ivy.`de.tototec::de.tobiasroeser.mill.vcs.version::0.1.2-4-dcde72` +-import $ivy.`com.github.lolgab::mill-mima::0.0.6` ++//import $ivy.`de.tototec::de.tobiasroeser.mill.vcs.version::0.1.2-4-dcde72` ++//import $ivy.`com.github.lolgab::mill-mima::0.0.6` + import $ivy.`net.sourceforge.htmlcleaner:htmlcleaner:2.24` + import java.nio.file.attribute.PosixFilePermission + +-import com.github.lolgab.mill.mima +-import com.github.lolgab.mill.mima.ProblemFilter +-import com.typesafe.tools.mima.core.{DirectMissingMethodProblem, IncompatibleSignatureProblem} ++//import com.github.lolgab.mill.mima ++//import com.github.lolgab.mill.mima.ProblemFilter ++//import com.typesafe.tools.mima.core.{DirectMissingMethodProblem, IncompatibleSignatureProblem} + import coursier.maven.MavenRepository +-import de.tobiasroeser.mill.vcs.version.VcsVersion ++//import de.tobiasroeser.mill.vcs.version.VcsVersion + import mill._ + import mill.define.{Command, Source, Sources, Target, Task} + import mill.eval.Evaluator +@@ -127,12 +127,8 @@ object Deps { + val jarjarabrams = ivy"com.eed3si9n.jarjarabrams::jarjar-abrams-core:1.8.0" + } + +-def millVersion: T[String] = T { VcsVersion.vcsState().format() } +-def millLastTag: T[String] = T { +- VcsVersion.vcsState().lastTag.getOrElse( +- sys.error("No (last) git tag found. Your git history seems incomplete!") +- ) +-} ++def millVersion: T[String] = T { "0.0.0.test" } ++def millLastTag: T[String] = T { "0.0.0.test" } + def millBinPlatform: T[String] = T { + val tag = millLastTag() + if (tag.contains("-M")) tag +@@ -170,44 +166,44 @@ trait MillCoursierModule extends CoursierModule { + } + } + +-trait MillMimaConfig extends mima.Mima { +- override def mimaPreviousVersions: T[Seq[String]] = Settings.mimaBaseVersions +- override def mimaPreviousArtifacts = +- if (Settings.mimaBaseVersions.isEmpty) T { Agg[Dep]() } +- else super.mimaPreviousArtifacts +- override def mimaExcludeAnnotations: T[Seq[String]] = Seq( +- "mill.api.internal", +- "mill.api.experimental" +- ) +- override def mimaBinaryIssueFilters: Target[Seq[ProblemFilter]] = T { +- issueFilterByModule.getOrElse(this, Seq()) +- } +- lazy val issueFilterByModule: Map[MillMimaConfig, Seq[ProblemFilter]] = Map( +- main.api -> Seq( +- ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.api.Ctx.args"), +- ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.api.Ctx.this"), +- ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.api.Ctx#Args.args") +- ), +- main.core -> Seq( +- ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.define.Target.makeT"), +- ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.define.Target.args"), +- ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.define.ParseArgs.standaloneIdent"), +- ProblemFilter.exclude[IncompatibleSignatureProblem]( +- "mill.define.ParseArgs#BraceExpansionParser.plainChars" +- ), +- ProblemFilter.exclude[IncompatibleSignatureProblem]( +- "mill.define.ParseArgs#BraceExpansionParser.braceParser" +- ), +- ProblemFilter.exclude[IncompatibleSignatureProblem]( +- "mill.define.ParseArgs#BraceExpansionParser.parser" +- ), +- ProblemFilter.exclude[IncompatibleSignatureProblem]( +- "mill.define.ParseArgs#BraceExpansionParser.toExpand" +- ), +- ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.eval.EvaluatorPaths.*"), +- ProblemFilter.exclude[DirectMissingMethodProblem]("mill.eval.EvaluatorPaths.*") +- ) +- ) ++trait MillMimaConfig { ++// override def mimaPreviousVersions: T[Seq[String]] = Settings.mimaBaseVersions ++// override def mimaPreviousArtifacts = ++// if (Settings.mimaBaseVersions.isEmpty) T { Agg[Dep]() } ++// else super.mimaPreviousArtifacts ++// override def mimaExcludeAnnotations: T[Seq[String]] = Seq( ++// "mill.api.internal", ++// "mill.api.experimental" ++// ) ++// def mimaBinaryIssueFilters: Target[Seq[ProblemFilter]] = T { ++// issueFilterByModule.getOrElse(this, Seq()) ++// } ++// lazy val issueFilterByModule: Map[MillMimaConfig, Seq[ProblemFilter]] = Map( ++// main.api -> Seq( ++// ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.api.Ctx.args"), ++// ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.api.Ctx.this"), ++// ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.api.Ctx#Args.args") ++// ), ++// main.core -> Seq( ++// ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.define.Target.makeT"), ++// ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.define.Target.args"), ++// ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.define.ParseArgs.standaloneIdent"), ++// ProblemFilter.exclude[IncompatibleSignatureProblem]( ++// "mill.define.ParseArgs#BraceExpansionParser.plainChars" ++// ), ++// ProblemFilter.exclude[IncompatibleSignatureProblem]( ++// "mill.define.ParseArgs#BraceExpansionParser.braceParser" ++// ), ++// ProblemFilter.exclude[IncompatibleSignatureProblem]( ++// "mill.define.ParseArgs#BraceExpansionParser.parser" ++// ), ++// ProblemFilter.exclude[IncompatibleSignatureProblem]( ++// "mill.define.ParseArgs#BraceExpansionParser.toExpand" ++// ), ++// ProblemFilter.exclude[IncompatibleSignatureProblem]("mill.eval.EvaluatorPaths.*"), ++// ProblemFilter.exclude[DirectMissingMethodProblem]("mill.eval.EvaluatorPaths.*") ++// ) ++// ) + } + + trait MillApiModule +@@ -1255,12 +1251,11 @@ def launcher = T { + } + + def uploadToGithub(authKey: String) = T.command { +- val vcsState = VcsVersion.vcsState() +- val label = vcsState.format() ++// val vcsState = VcsVersion.vcsState() ++// val label = vcsState.format() ++ val label = millVersion() + if (label != millVersion()) sys.error("Modified mill version detected, aborting upload") +- val releaseTag = vcsState.lastTag.getOrElse(sys.error( +- "Incomplete git history. No tag found.\nIf on CI, make sure your git checkout job includes enough history." +- )) ++ val releaseTag = millLastTag() + + if (releaseTag == label) { + scalaj.http.Http( From d6a4a24420559ac973cb9b712c5ddcb0e2ef0b9d Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Tue, 7 Dec 2021 22:19:00 +0800 Subject: [PATCH 15/18] . --- main/core/src/mill/define/Task.scala | 10 ++++++++++ main/core/src/mill/eval/Evaluator.scala | 17 ++++------------- main/src/mill/main/Resolve.scala | 8 ++++---- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/main/core/src/mill/define/Task.scala b/main/core/src/mill/define/Task.scala index b6d6d09d1d6..6aacf54f196 100644 --- a/main/core/src/mill/define/Task.scala +++ b/main/core/src/mill/define/Task.scala @@ -45,10 +45,14 @@ trait NamedTask[+T] extends Task[T] { def ctx: mill.define.Ctx def label = ctx.segment match { case Segment.Label(v) => v } override def toString = ctx.segments.render + def readWriteOpt: Option[RW[_]] + def writeOpt: Option[W[_]] } trait Target[+T] extends NamedTask[T] { override def asTarget = Some(this) def readWrite: RW[_] + def readWriteOpt = Some(readWrite) + def writeOpt = Some(readWrite) } object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Result, mill.api.Ctx] { @@ -315,11 +319,15 @@ class Command[+T]( val cls: Class[_], ) extends NamedTaskImpl[T](ctx0, t) { override def asCommand = Some(this) + def readWriteOpt = None + def writeOpt = Some(writer) } class Worker[+T](t: Task[T], ctx0: mill.define.Ctx) extends NamedTaskImpl[T](ctx0, t) { override def flushDest = false override def asWorker = Some(this) + def readWriteOpt = None + def writeOpt = None } class Persistent[+T](t: Task[T], ctx0: mill.define.Ctx, readWrite: RW[_]) @@ -331,6 +339,8 @@ class Persistent[+T](t: Task[T], ctx0: mill.define.Ctx, readWrite: RW[_]) class Input[T](t: Task[T], ctx0: mill.define.Ctx, val writer: upickle.default.Writer[_]) extends NamedTaskImpl[T](ctx0, t) { override def sideHash = util.Random.nextInt() + def readWriteOpt = None + def writeOpt = Some(writer) } class Sources(t: Task[Seq[PathRef]], ctx0: mill.define.Ctx) diff --git a/main/core/src/mill/eval/Evaluator.scala b/main/core/src/mill/eval/Evaluator.scala index b07cce024f3..d1732165f28 100644 --- a/main/core/src/mill/eval/Evaluator.scala +++ b/main/core/src/mill/eval/Evaluator.scala @@ -18,17 +18,7 @@ import scala.jdk.CollectionConverters._ import scala.reflect.ClassTag import scala.util.control.NonFatal -case class Labelled[T](task: NamedTask[T], segments: Segments) { - def format = task match { - case t: Target[T] => Some(t.readWrite.asInstanceOf[upickle.default.ReadWriter[T]]) - case _ => None - } - def writer = task match { - case t: mill.define.Command[T] => Some(t.writer.asInstanceOf[upickle.default.Writer[T]]) - case t: Target[T] => Some(t.readWrite.asInstanceOf[upickle.default.ReadWriter[T]]) - case _ => None - } -} +case class Labelled[T](task: NamedTask[T], segments: Segments) /** * Evaluate tasks. @@ -329,7 +319,7 @@ case class Evaluator( try Some(upickle.default.read[Evaluator.Cached](paths.meta.toIO)) catch { case e: Throwable => None } if cached.inputsHash == inputsHash - reader <- labelledNamedTask.format + reader <- labelledNamedTask.task.readWriteOpt parsed <- try Some(upickle.default.read(cached.value)(reader)) catch { case e: Throwable => None } @@ -408,7 +398,8 @@ case class Evaluator( case Some(w) => synchronized { workerCache(w.ctx.segments) = (inputsHash, v) } case None => val terminalResult = labelledNamedTask - .writer + .task + .writeOpt .asInstanceOf[Option[upickle.default.Writer[Any]]] .map(w => upickle.default.writeJs(v)(w) -> v) diff --git a/main/src/mill/main/Resolve.scala b/main/src/mill/main/Resolve.scala index db285c9683e..a42128d4bbc 100644 --- a/main/src/mill/main/Resolve.scala +++ b/main/src/mill/main/Resolve.scala @@ -14,7 +14,7 @@ object ResolveMetadata extends Resolve[String] { val targets = obj .millInternal - .reflectAll[Target[_]] + .reflectAll[NamedTask[_]] .map(_.toString) val commands = for { @@ -192,15 +192,15 @@ object ResolveTasks extends Resolve[NamedTask[Any]] { Right( obj.millInternal.modules .filter(_ != obj) - .flatMap(m => m.millInternal.reflectAll[Target[_]]) + .flatMap(m => m.millInternal.reflectAll[NamedTask[_]]) ) - case "_" => Right(obj.millInternal.reflectAll[Target[_]]) + case "_" => Right(obj.millInternal.reflectAll[NamedTask[_]]) case _ => val target = obj .millInternal - .reflectSingle[Target[_]](last) + .reflectSingle[NamedTask[_]](last) .map(Right(_)) val command = Resolve.invokeCommand( From d93b6784cd0e773bae21172952540122916708d6 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Wed, 8 Dec 2021 07:38:27 +0800 Subject: [PATCH 16/18] . --- main/core/src/mill/eval/Evaluator.scala | 6 +++--- main/src/mill/main/MainModule.scala | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main/core/src/mill/eval/Evaluator.scala b/main/core/src/mill/eval/Evaluator.scala index b07cce024f3..5ed49f9bf3b 100644 --- a/main/core/src/mill/eval/Evaluator.scala +++ b/main/core/src/mill/eval/Evaluator.scala @@ -93,7 +93,7 @@ case class Evaluator( (int: Int) => Option.empty[CompileProblemReporter], testReporter: TestReporter = DummyTestReporter ): Evaluator.Results = { - val (sortedGroups, transitive) = Evaluator.plan(rootModule, goals) + val (sortedGroups, transitive) = Evaluator.plan(goals) val terminalNames = sortedGroups .keys() .map{ @@ -182,7 +182,7 @@ case class Evaluator( os.makeDir.all(outPath) val timeLog = new ParallelProfileLogger(outPath, System.currentTimeMillis()) - val (sortedGroups, transitive) = Evaluator.plan(rootModule, goals) + val (sortedGroups, transitive) = Evaluator.plan(goals) val interGroupDeps = findInterGroupDeps(sortedGroups) import scala.concurrent._ @@ -663,7 +663,7 @@ object Evaluator { def values = rawValues.collect { case mill.api.Result.Success(v) => v } } - def plan(rootModule: BaseModule, goals: Agg[Task[_]]) = { + def plan(goals: Agg[Task[_]]) = { val transitive = Graph.transitiveTargets(goals) val topoSorted = Graph.topoSorted(transitive) val seen = collection.mutable.Set.empty[Segments] diff --git a/main/src/mill/main/MainModule.scala b/main/src/mill/main/MainModule.scala index 75fe89869f5..8dddbf536e0 100644 --- a/main/src/mill/main/MainModule.scala +++ b/main/src/mill/main/MainModule.scala @@ -117,7 +117,7 @@ trait MainModule extends mill.Module { ) match { case Left(err) => Left(err) case Right(rs) => - val (sortedGroups, _) = Evaluator.plan(evaluator.rootModule, rs) + val (sortedGroups, _) = Evaluator.plan(rs) Right(sortedGroups.keys().collect { case Right(r) => r }.toArray) } } From 921c35462e5c263124b789806f4575dff24ab226 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Wed, 8 Dec 2021 07:41:25 +0800 Subject: [PATCH 17/18] . --- main/core/src/mill/eval/Evaluator.scala | 7 ------- 1 file changed, 7 deletions(-) diff --git a/main/core/src/mill/eval/Evaluator.scala b/main/core/src/mill/eval/Evaluator.scala index 5ed49f9bf3b..4083fc1f5e7 100644 --- a/main/core/src/mill/eval/Evaluator.scala +++ b/main/core/src/mill/eval/Evaluator.scala @@ -94,13 +94,6 @@ case class Evaluator( testReporter: TestReporter = DummyTestReporter ): Evaluator.Results = { val (sortedGroups, transitive) = Evaluator.plan(goals) - val terminalNames = sortedGroups - .keys() - .map{ - case Left(x) => x - case Right(x) => (System.identityHashCode(x), x.task.ctx.lineNum, x.segments.render) - } - .toList val evaluated = new Agg.Mutable[Task[_]] val results = mutable.LinkedHashMap.empty[Task[_], mill.api.Result[(Any, Int)]] From c272c8b5e3df7bdc5c91d567e391f64062bbed4f Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Wed, 8 Dec 2021 07:43:42 +0800 Subject: [PATCH 18/18] . --- main/core/src/mill/define/Task.scala | 10 ---------- main/core/src/mill/eval/Evaluator.scala | 18 ++++++++++++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/main/core/src/mill/define/Task.scala b/main/core/src/mill/define/Task.scala index 6aacf54f196..b6d6d09d1d6 100644 --- a/main/core/src/mill/define/Task.scala +++ b/main/core/src/mill/define/Task.scala @@ -45,14 +45,10 @@ trait NamedTask[+T] extends Task[T] { def ctx: mill.define.Ctx def label = ctx.segment match { case Segment.Label(v) => v } override def toString = ctx.segments.render - def readWriteOpt: Option[RW[_]] - def writeOpt: Option[W[_]] } trait Target[+T] extends NamedTask[T] { override def asTarget = Some(this) def readWrite: RW[_] - def readWriteOpt = Some(readWrite) - def writeOpt = Some(readWrite) } object Target extends TargetGenerated with Applicative.Applyer[Task, Task, Result, mill.api.Ctx] { @@ -319,15 +315,11 @@ class Command[+T]( val cls: Class[_], ) extends NamedTaskImpl[T](ctx0, t) { override def asCommand = Some(this) - def readWriteOpt = None - def writeOpt = Some(writer) } class Worker[+T](t: Task[T], ctx0: mill.define.Ctx) extends NamedTaskImpl[T](ctx0, t) { override def flushDest = false override def asWorker = Some(this) - def readWriteOpt = None - def writeOpt = None } class Persistent[+T](t: Task[T], ctx0: mill.define.Ctx, readWrite: RW[_]) @@ -339,8 +331,6 @@ class Persistent[+T](t: Task[T], ctx0: mill.define.Ctx, readWrite: RW[_]) class Input[T](t: Task[T], ctx0: mill.define.Ctx, val writer: upickle.default.Writer[_]) extends NamedTaskImpl[T](ctx0, t) { override def sideHash = util.Random.nextInt() - def readWriteOpt = None - def writeOpt = Some(writer) } class Sources(t: Task[Seq[PathRef]], ctx0: mill.define.Ctx) diff --git a/main/core/src/mill/eval/Evaluator.scala b/main/core/src/mill/eval/Evaluator.scala index c2fee4999df..fd90be671ef 100644 --- a/main/core/src/mill/eval/Evaluator.scala +++ b/main/core/src/mill/eval/Evaluator.scala @@ -18,7 +18,18 @@ import scala.jdk.CollectionConverters._ import scala.reflect.ClassTag import scala.util.control.NonFatal -case class Labelled[T](task: NamedTask[T], segments: Segments) +case class Labelled[T](task: NamedTask[T], segments: Segments){ + def format = task match { + case t: Target[T] => Some(t.readWrite.asInstanceOf[upickle.default.ReadWriter[T]]) + case _ => None + } + def writer = task match { + case t: mill.define.Command[T] => Some(t.writer.asInstanceOf[upickle.default.Writer[T]]) + case t: mill.define.Input[T] => Some(t.writer.asInstanceOf[upickle.default.Writer[T]]) + case t: Target[T] => Some(t.readWrite.asInstanceOf[upickle.default.ReadWriter[T]]) + case _ => None + } +} /** * Evaluate tasks. @@ -312,7 +323,7 @@ case class Evaluator( try Some(upickle.default.read[Evaluator.Cached](paths.meta.toIO)) catch { case e: Throwable => None } if cached.inputsHash == inputsHash - reader <- labelledNamedTask.task.readWriteOpt + reader <- labelledNamedTask.format parsed <- try Some(upickle.default.read(cached.value)(reader)) catch { case e: Throwable => None } @@ -391,8 +402,7 @@ case class Evaluator( case Some(w) => synchronized { workerCache(w.ctx.segments) = (inputsHash, v) } case None => val terminalResult = labelledNamedTask - .task - .writeOpt + .writer .asInstanceOf[Option[upickle.default.Writer[Any]]] .map(w => upickle.default.writeJs(v)(w) -> v)