From 9a67570ae953b02f6562de31efaad4d1cba15983 Mon Sep 17 00:00:00 2001 From: Alexandra Dima Date: Wed, 17 Jul 2019 13:54:08 +0200 Subject: Improved compilation by sending all requested targets to the mill evaluator to be compiled together rather than in different evaluation sessions. This avoids duplicated compilation results and side effects like diagnostics and task progress notifications. --- .../bsp/src/mill/contrib/MainMillBuildServer.scala | 16 ++-- .../src/mill/contrib/bsp/BspLoggedReporter.scala | 26 +++++- .../bsp/src/mill/contrib/bsp/MillBuildServer.scala | 98 +++++++--------------- 3 files changed, 60 insertions(+), 80 deletions(-) (limited to 'contrib') diff --git a/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala b/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala index d932fbcb..bfe23444 100644 --- a/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala +++ b/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala @@ -7,7 +7,7 @@ import java.nio.file.FileAlreadyExistsException import java.util.concurrent.{CancellationException, CompletableFuture, ExecutorService, Executors, Future} import upickle.default._ -import ch.epfl.scala.bsp4j.{BspConnectionDetails, BuildClient, CompileParams, DidChangeBuildTarget, LogMessageParams, PublishDiagnosticsParams, ScalaTestClassesParams, ShowMessageParams, TaskFinishParams, TaskProgressParams, TaskStartParams, TestParams, WorkspaceBuildTargetsResult} +import ch.epfl.scala.bsp4j.{BspConnectionDetails, BuildClient, CleanCacheParams, CompileParams, DidChangeBuildTarget, LogMessageParams, PublishDiagnosticsParams, ScalaTestClassesParams, ShowMessageParams, TaskFinishParams, TaskProgressParams, TaskStartParams, TestParams, WorkspaceBuildTargetsResult} import mill._ import mill.api.Strict import mill.contrib.bsp.{BspLoggedReporter, MillBuildServer, ModuleUtils} @@ -183,14 +183,12 @@ object MainMillBuildServer extends ExternalModule { ??? } millServer.client = client - for (module <- millServer.millModules) { - if (millServer.moduleToTarget(module).getDisplayName == "test") { -// println(eval.evaluate(Strict.Agg(module.asInstanceOf[TestModule].testLocal() -// )).rawValues) - millServer.initialized = true - println(millServer.buildTargetTest(new TestParams(List(millServer.moduleToTargetId(module)).asJava)).get) - } - } + millServer.initialized = true + println(millServer.buildTargetCleanCache( + new CleanCacheParams(millServer.millModules.map(m => millServer.moduleToTargetId(m)).asJava)).get) + println(millServer.buildTargetCompile( + new CompileParams(millServer.millModules.map(m => millServer.moduleToTargetId(m)).asJava)).get) + println("Diagnostics: " + client.diagnostics) } /** diff --git a/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala b/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala index eda25566..846ffd42 100644 --- a/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala +++ b/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala @@ -2,6 +2,7 @@ package mill.contrib.bsp import java.io.File +import ch.epfl.scala.bsp4j.{BuildServer, BuildTargetIdentifier, InverseSourcesParams, ScalaBuildServer, TextDocumentIdentifier} import ch.epfl.scala.{bsp4j => bsp} import mill.api.BspContext import sbt.internal.inc.ManagedLoggedReporter @@ -14,24 +15,30 @@ import scala.compat.java8.OptionConverters._ import scala.io.Source class BspLoggedReporter(client: bsp.BuildClient, - targetId: bsp.BuildTargetIdentifier, + targetId: BuildTargetIdentifier, compilationOriginId: Option[String], maxErrors: Int, logger: ManagedLogger) extends ManagedLoggedReporter(maxErrors, logger) { + var errors = 0 + var warnings = 0 + var infos = 0 + override def logError(problem: Problem): Unit = { client.onBuildPublishDiagnostics(getDiagnostics(problem, targetId, compilationOriginId)) + errors += 1 super.logError(problem) } override def logInfo(problem: Problem): Unit = { - logger.info("Problem: " + problem.toString) - client.onBuildPublishDiagnostics(getDiagnostics(problem, targetId, compilationOriginId)) + client.onBuildPublishDiagnostics(getDiagnostics(problem, targetId, compilationOriginId)) + infos += 1 super.logInfo(problem) } override def logWarning(problem: Problem): Unit = { - client.onBuildPublishDiagnostics(getDiagnostics(problem, targetId, compilationOriginId)) + client.onBuildPublishDiagnostics(getDiagnostics(problem, targetId, compilationOriginId)) + warnings += 1 super.logWarning(problem) } @@ -67,6 +74,17 @@ class BspLoggedReporter(client: bsp.BuildClient, params } + private[this] def getTragetId(problem: Problem, server: BuildServer with ScalaBuildServer): + Option[BuildTargetIdentifier] = { + problem.position().sourceFile().asScala match { + case Some(file) => Option( + server.buildTargetInverseSources( + new InverseSourcesParams(new TextDocumentIdentifier(file.toURI.toString)) + ).get.getTargets.asScala.head) + case None => Option.empty[BuildTargetIdentifier] + } + } + private[this] def getErrorCode(file: Option[File], start: bsp.Position, end: bsp.Position, position: xsbti.Position): String = { file match { case None => position.lineContent diff --git a/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala b/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala index bd06d29b..3937f1ab 100644 --- a/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala +++ b/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala @@ -52,6 +52,8 @@ class MillBuildServer(evaluator: Evaluator, var targetIdToModule: Predef.Map[BuildTargetIdentifier, JavaModule] = targetToModule(moduleToTargetId) var moduleToTarget: Predef.Map[JavaModule, BuildTarget] = ModuleUtils.millModulesToBspTargets(millModules, evaluator, List("scala", "java")) + var moduleCodeToTargetId: Predef.Map[Int, BuildTargetIdentifier] = + for ( (targetId, module) <- targetIdToModule ) yield (targetId, module.hashCode()).swap var initialized = false var clientInitialized = false @@ -236,72 +238,40 @@ class MillBuildServer(evaluator: Evaluator, l } + private[this] def getBspLoggedReporterPool(params: Parameters): Int => Option[ManagedLoggedReporter] = { + (int: Int) => + if (moduleCodeToTargetId.contains(int)) { + println("Module: " + int) + Option(new BspLoggedReporter(client, + moduleCodeToTargetId(int), + params.getOriginId, + 10, getCompilationLogger))} + else Option.empty[ManagedLoggedReporter] + } + //TODO: if the client wants to give compilation arguments and the module // already has some from the build file, what to do? override def buildTargetCompile(compileParams: CompileParams): CompletableFuture[CompileResult] = { def getCompileResult: CompileResult = { val params = TaskParameters.fromCompileParams(compileParams) - var numFailures = 0 - var compileTime = 0 - for (targetId <- params.getTargets) { - if (moduleToTarget(targetIdToModule(targetId)).getCapabilities.getCanCompile) { - val millModule = targetIdToModule(targetId) - val compileTask = millModule.compile - - // send notification to client that compilation of this target started - val taskStartParams = new TaskStartParams(new TaskId(compileTask.hashCode().toString)) - taskStartParams.setEventTime(System.currentTimeMillis()) - taskStartParams.setMessage("Compiling target: " + targetId) - taskStartParams.setDataKind("compile-task") - taskStartParams.setData(new CompileTask(targetId)) - client.onBuildTaskStart(taskStartParams) - - val result = millEvaluator.evaluate(Strict.Agg(compileTask), - Option(new BspLoggedReporter(client, - targetId, - getOriginId(compileParams), - 10, getCompilationLogger)), - new BspContext { - override def args: Seq[String] = params.getArguments.getOrElse(Seq.empty[String]) - override def logStart(event: Event): Unit = {} - - override def logFinish(event: Event): Unit = {} - }, - new MillBspLogger(client, compileTask.hashCode(), millEvaluator.log) - ) - val endTime = System.currentTimeMillis() - - compileTime += result.timings.map(timingTuple => timingTuple._2).sum - var statusCode = StatusCode.OK - - if (result.failing.keyCount > 0) { - statusCode = StatusCode.ERROR - numFailures += result.failing.keyCount - } - - // send notification to client that compilation of this target ended => compilation report - val taskFinishParams = new TaskFinishParams(new TaskId(compileTask.hashCode().toString), statusCode) - taskFinishParams.setEventTime(endTime) - taskFinishParams.setMessage("Finished compiling target: " + - moduleToTarget(targetIdToModule(targetId)).getDisplayName) - taskFinishParams.setDataKind("compile-report") - val compileReport = new CompileReport(targetId, numFailures, 0) - compileReport.setOriginId(compileParams.getOriginId) - compileReport.setTime(compileTime.toLong) - taskFinishParams.setData(compileReport) - client.onBuildTaskFinish(taskFinishParams) - } - } - - var overallStatusCode = StatusCode.OK - if (numFailures > 0) { - overallStatusCode = StatusCode.ERROR - } - val compileResult = new CompileResult(overallStatusCode) + val taskId = params.hashCode() + val compileTasks = Strict.Agg(params.getTargets.map(targetId => targetIdToModule(targetId).compile):_*) + + val result = millEvaluator.evaluate(compileTasks, + getBspLoggedReporterPool(params), + new BspContext { + override def args: Seq[String] = params.getArguments.getOrElse(Seq.empty[String]) + override def logStart(event: Event): Unit = {} + + override def logFinish(event: Event): Unit = {} + }, + new MillBspLogger(client, taskId, millEvaluator.log) + ) + val compileResult = new CompileResult(getStatusCode(result)) compileResult.setOriginId(compileParams.getOriginId) compileResult //TODO: See what form IntelliJ expects data about products of compilation in order to set data field - } + } handleExceptions[String, CompileResult]((in) => getCompileResult, "") } @@ -312,10 +282,7 @@ class MillBuildServer(evaluator: Evaluator, val args = params.getArguments.getOrElse(Seq.empty[String]) val runTask = module.run(args.mkString(" ")) val runResult = millEvaluator.evaluate(Strict.Agg(runTask), - Option(new BspLoggedReporter(client, - params.getTargets.head, - params.getOriginId, - 10, getCompilationLogger)), + getBspLoggedReporterPool(params), logger = new MillBspLogger(client, runTask.hashCode(), millEvaluator.log)) if (runResult.failing.keyCount > 0) { new RunResult(StatusCode.ERROR) @@ -328,7 +295,7 @@ class MillBuildServer(evaluator: Evaluator, private[this] def getStatusCode(results: Evaluator.Results): StatusCode = { System.err.println("Results: " + results.rawValues) - if (results.rawValues.exists(r => r.isInstanceOf[Result.Failure[Any]])) { + if (results.failing.keyCount > 0) { StatusCode.ERROR } @@ -374,10 +341,7 @@ class MillBuildServer(evaluator: Evaluator, val results = millEvaluator.evaluate( Strict.Agg(testTask), - Option(new BspLoggedReporter(client, - targetId, - params.getOriginId, - 10, getCompilationLogger)), + getBspLoggedReporterPool(params), bspContext, new MillBspLogger(client, testTask.hashCode, millEvaluator.log)) val endTime = System.currentTimeMillis() -- cgit v1.2.3