diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/api/src/mill/api/BuildReporter.scala | 97 | ||||
-rw-r--r-- | main/api/src/mill/api/Ctx.scala | 5 | ||||
-rw-r--r-- | main/core/src/eval/Evaluator.scala | 65 |
3 files changed, 145 insertions, 22 deletions
diff --git a/main/api/src/mill/api/BuildReporter.scala b/main/api/src/mill/api/BuildReporter.scala new file mode 100644 index 00000000..2b360a45 --- /dev/null +++ b/main/api/src/mill/api/BuildReporter.scala @@ -0,0 +1,97 @@ +package mill.api + +import java.io.File + +import sbt.testing.Event + +/** + * Test reporter class that can be + * injected into the test task and + * report information upon the start + * and the finish of testing events + */ +trait TestReporter { + def logStart(event: Event): Unit + + def logFinish(event: Event): Unit + + +} + +/** + * Dummy Test Reporter that doesn't report + * anything for any testing event. + */ +object DummyTestReporter extends TestReporter { + override def logStart(event: Event): Unit = { + + } + override def logFinish(event: Event): Unit = { + + } +} + +/** + * A listener trait for getting notified about + * build output like compiler warnings and errors + */ +trait BuildProblemReporter { + def logError(problem: Problem): Unit + + def logWarning(problem: Problem): Unit + + def logInfo(problem: Problem): Unit + + def printSummary(): Unit +} + +/** + * Contains general information about the build problem + */ +trait Problem { + def category: String + + def severity: Severity + + def message: String + + def position: ProblemPosition +} + +/** + * Indicates the exact location (source file, line, column) of the build problem + */ +trait ProblemPosition { + def line: Option[Int] + + def lineContent: String + + def offset: Option[Int] + + def pointer: Option[Int] + + def pointerSpace: Option[String] + + def sourcePath: Option[String] + + def sourceFile: Option[File] + + def startOffset: Option[Int] = Option.empty + + def endOffset: Option[Int] = Option.empty + + def startLine: Option[Int] = Option.empty + + def startColumn: Option[Int] = Option.empty + + def endLine: Option[Int] = Option.empty + + def endColumn: Option[Int] = Option.empty +} + +sealed trait Severity +case object Info extends Severity +case object Error extends Severity +case object Warn extends Severity + + diff --git a/main/api/src/mill/api/Ctx.scala b/main/api/src/mill/api/Ctx.scala index 69d01f7e..e86ad7f9 100644 --- a/main/api/src/mill/api/Ctx.scala +++ b/main/api/src/mill/api/Ctx.scala @@ -2,7 +2,6 @@ package mill.api import scala.annotation.{StaticAnnotation, compileTimeOnly} import scala.language.implicitConversions - import os.Path /** @@ -60,7 +59,9 @@ class Ctx( dest0: () => os.Path, val log: Logger, val home: os.Path, - val env: Map[String, String] + val env: Map[String, String], + val reporter: Int => Option[BuildProblemReporter], + val testReporter: TestReporter ) extends Ctx.Dest with Ctx.Log diff --git a/main/core/src/eval/Evaluator.scala b/main/core/src/eval/Evaluator.scala index f4ec8ff9..1b58660b 100644 --- a/main/core/src/eval/Evaluator.scala +++ b/main/core/src/eval/Evaluator.scala @@ -2,17 +2,18 @@ package mill.eval import java.net.URLClassLoader -import scala.collection.JavaConverters._ -import scala.collection.mutable -import scala.util.control.NonFatal - import ammonite.runtime.SpecialClassLoader -import mill.util.Router.EntryPoint -import mill.define.{Ctx => _, _} import mill.api.Result.{Aborted, OuterStack, Success} +import mill.api.Strict.Agg +import mill.api.{DummyTestReporter, TestReporter, BuildProblemReporter} +import mill.define.{Ctx => _, _} import mill.util +import mill.util.Router.EntryPoint import mill.util._ -import mill.api.Strict.Agg + +import scala.collection.JavaConverters._ +import scala.collection.mutable +import scala.util.control.NonFatal case class Labelled[T](task: NamedTask[T], segments: Segments){ @@ -40,9 +41,16 @@ case class Evaluator(home: os.Path, val classLoaderSignHash = classLoaderSig.hashCode() - def evaluate(goals: Agg[Task[_]]): Evaluator.Results = { + /** + * @param goals The tasks that need to be evaluated + * @param reporter A function that will accept a module id and provide a listener for build problems in that module + * @param testReporter Listener for test events like start, finish with success/error + */ + def evaluate(goals: Agg[Task[_]], + reporter: Int => Option[BuildProblemReporter] = (int: Int) => Option.empty[BuildProblemReporter], + testReporter: TestReporter = DummyTestReporter, + logger: Logger = log): Evaluator.Results = { os.makeDir.all(outPath) - val (sortedGroups, transitive) = Evaluator.plan(rootModule, goals) val evaluated = new Agg.Mutable[Task[_]] @@ -66,7 +74,10 @@ case class Evaluator(home: os.Path, terminal, group, results, - counterMsg + counterMsg, + reporter, + testReporter, + logger ) someTaskFailed = someTaskFailed || newResults.exists(task => !task._2.isInstanceOf[Success[_]]) @@ -111,7 +122,10 @@ case class Evaluator(home: os.Path, def evaluateGroupCached(terminal: Either[Task[_], Labelled[_]], group: Agg[Task[_]], results: collection.Map[Task[_], Result[(Any, Int)]], - counterMsg: String + counterMsg: String, + zincProblemReporter: Int => Option[BuildProblemReporter], + testReporter: TestReporter, + logger: Logger ): (collection.Map[Task[_], Result[(Any, Int)]], Seq[Task[_]], Boolean) = { val externalInputsHash = scala.util.hashing.MurmurHash3.orderedHash( @@ -133,7 +147,10 @@ case class Evaluator(home: os.Path, inputsHash, paths = None, maybeTargetLabel = None, - counterMsg = counterMsg + counterMsg = counterMsg, + zincProblemReporter, + testReporter, + logger ) (newResults, newEvaluated, false) case Right(labelledNamedTask) => @@ -185,7 +202,10 @@ case class Evaluator(home: os.Path, inputsHash, paths = Some(paths), maybeTargetLabel = Some(msgParts.mkString), - counterMsg = counterMsg + counterMsg = counterMsg, + zincProblemReporter, + testReporter, + logger ) newResults(labelledNamedTask.task) match{ @@ -259,7 +279,10 @@ case class Evaluator(home: os.Path, inputsHash: Int, paths: Option[Evaluator.Paths], maybeTargetLabel: Option[String], - counterMsg: String): (mutable.LinkedHashMap[Task[_], Result[(Any, Int)]], mutable.Buffer[Task[_]]) = { + counterMsg: String, + reporter: Int => Option[BuildProblemReporter], + testReporter: TestReporter, + logger: Logger): (mutable.LinkedHashMap[Task[_], Result[(Any, Int)]], mutable.Buffer[Task[_]]) = { val newEvaluated = mutable.Buffer.empty[Task[_]] @@ -276,11 +299,11 @@ case class Evaluator(home: os.Path, val logRun = inputResults.forall(_.isInstanceOf[Result.Success[_]]) val prefix = s"[$counterMsg] $targetLabel " - if(logRun) log.ticker(prefix) + if(logRun) logger.ticker(prefix) prefix + "| " } - val multiLogger = new ProxyLogger(resolveLogger(paths.map(_.log))) { + val multiLogger = new ProxyLogger(resolveLogger(paths.map(_.log), logger)) { override def ticker(s: String): Unit = { super.ticker(tickerPrefix.getOrElse("")+s) } @@ -319,7 +342,9 @@ case class Evaluator(home: os.Path, }, multiLogger, home, - env + env, + reporter, + testReporter ) val out = System.out @@ -359,9 +384,9 @@ case class Evaluator(home: os.Path, (newResults, newEvaluated) } - def resolveLogger(logPath: Option[os.Path]): Logger = logPath match{ - case None => log - case Some(path) => MultiLogger(log.colored, log, FileLogger(log.colored, path, debugEnabled = true)) + def resolveLogger(logPath: Option[os.Path], logger: Logger): Logger = logPath match{ + case None => logger + case Some(path) => MultiLogger(logger.colored, log, FileLogger(logger.colored, path, debugEnabled = true)) } } |