summaryrefslogtreecommitdiff
path: root/contrib/bsp/src
diff options
context:
space:
mode:
authorAlexandra Dima <alexandra.dima@jetbrains.com>2019-07-12 17:52:57 +0200
committerSamvel Abrahamyan <samvel1024@gmail.com>2019-10-12 14:33:03 +0200
commit2be400138fb32a63a3bb05e6fdec31508673331b (patch)
tree643b58b6b810f28509fdc4fbbcfa9495bc826164 /contrib/bsp/src
parent9c39dd6776944b15433f44c5c4fba994cdd7d152 (diff)
downloadmill-2be400138fb32a63a3bb05e6fdec31508673331b.tar.gz
mill-2be400138fb32a63a3bb05e6fdec31508673331b.tar.bz2
mill-2be400138fb32a63a3bb05e6fdec31508673331b.zip
Partially fixed test request by implementing a test reporter, adding it to each task context and sending it to the test task. Implemented BspContext to hold information about the test reporter and the additional bsp compiler arguments. Made a common data structure for different bsp parameters - TaskParameters.
Diffstat (limited to 'contrib/bsp/src')
-rw-r--r--contrib/bsp/src/mill/contrib/MainMillBuildServer.scala48
-rw-r--r--contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala1
-rw-r--r--contrib/bsp/src/mill/contrib/bsp/BspTestReporter.scala98
-rw-r--r--contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala113
4 files changed, 155 insertions, 105 deletions
diff --git a/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala b/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala
index b9e8ee8a..9627bff9 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, WorkspaceBuildTargetsResult}
+import ch.epfl.scala.bsp4j.{BspConnectionDetails, BuildClient, 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,8 +183,10 @@ object MainMillBuildServer extends ExternalModule {
}
millServer.client = client
for (module <- millServer.millModules) {
- if (millServer.moduleToTarget(module).getDisplayName == "random") {
- println(millServer.buildTargetCompile(new CompileParams(List(millServer.moduleToTargetId(module)).asJava)).get)
+ if (millServer.moduleToTarget(module).getDisplayName == "test") {
+ println(eval.evaluate(Strict.Agg(module.asInstanceOf[TestModule].test()
+ )).rawValues)
+ println(millServer.buildTargetTest(new TestParams(List(millServer.moduleToTargetId(module)).asJava)).get)
}
}
}
@@ -204,44 +206,4 @@ object MainMillBuildServer extends ExternalModule {
}
}
-}
-
-object foo extends mill.define.ExternalModule {
-
- implicit def millScoptEvaluatorReads[T] = new mill.main.EvaluatorScopt[T]()
- lazy val millDiscover: Discover[foo.this.type] = Discover[this.type]
-
- object bar extends ScalaModule {
- def scalaVersion = "2.12.4"
- override def ivyDeps = Agg(ivy"org.scalameta::metals:0.5.2")
- override def moduleDeps = Seq(baz)
- object test extends TestModule {
- override def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.6.0")
- def testFrameworks: Target[Seq[String]] = Seq("utest.runner.Framework")
- }
- }
-
- object baz extends scalajslib.ScalaJSModule {
- def scalaJSVersion = "1.0.0-M8"
- def scalaVersion = "2.12.8"
-
- }
-
- object mill_exercise extends ScalaModule {
- def scalaVersion = "2.12.8"
-
- override def scalacPluginIvyDeps = Agg(ivy"org.scala-lang:scala-compiler:2.12.8")
- override def ivyDeps = Agg(
- ivy"org.scala-lang:scala-reflect:2.12.8",
- ivy"org.scalameta::metals:0.5.2"
- )
-
- object test extends Tests {
- override def ivyDeps = Agg(//ivy"org.scalameta::metals:0.5.2",
- ivy"com.lihaoyi::utest:0.6.0",
- ivy"org.scalactic::scalactic:3.0.5")
-
- def testFrameworks: Target[Seq[String]] = Seq("utest.runner.Framework")
- }
- }
} \ No newline at end of file
diff --git a/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala b/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala
index 6d92cd16..eda25566 100644
--- a/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala
+++ b/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala
@@ -3,6 +3,7 @@ package mill.contrib.bsp
import java.io.File
import ch.epfl.scala.{bsp4j => bsp}
+import mill.api.BspContext
import sbt.internal.inc.ManagedLoggedReporter
import sbt.internal.inc.schema.Position
import sbt.internal.util.ManagedLogger
diff --git a/contrib/bsp/src/mill/contrib/bsp/BspTestReporter.scala b/contrib/bsp/src/mill/contrib/bsp/BspTestReporter.scala
new file mode 100644
index 00000000..23cadfcb
--- /dev/null
+++ b/contrib/bsp/src/mill/contrib/bsp/BspTestReporter.scala
@@ -0,0 +1,98 @@
+package mill.contrib.bsp
+
+import ch.epfl.scala.bsp4j._
+import mill.api.{BspContext, TestReporter}
+import sbt.testing._
+
+
+class BspTestReporter(
+ client: BuildClient,
+ targetId: BuildTargetIdentifier,
+ taskId: TaskId,
+ arguments: Seq[String]) extends BspContext {
+
+ var passed = 0
+ var failed = 0
+ var cancelled = 0
+ var ignored = 0
+ var skipped = 0
+ var totalTime: Long = 0
+
+ override def args: Seq[String] = arguments
+
+ override def logStart(event: Event): Unit = {
+ val taskStartParams = new TaskStartParams(taskId)
+ taskStartParams.setEventTime(System.currentTimeMillis())
+ taskStartParams.setDataKind("test-started")
+ taskStartParams.setData(new TestStart(getDisplayName(event)))
+ taskStartParams.setMessage("Starting running: " + getDisplayName(event))
+ client.onBuildTaskStart(taskStartParams)
+ }
+
+ override def logFinish(event: Event): Unit = {
+ totalTime += event.duration()
+ val taskFinishParams = new TaskFinishParams(taskId,
+ event.status() match {
+ case sbt.testing.Status.Canceled => StatusCode.CANCELLED
+ case sbt.testing.Status.Error => StatusCode.ERROR
+ case default => StatusCode.OK
+ })
+ taskFinishParams.setDataKind("test-finished")
+ val testFinish = new TestFinish(
+ getDisplayName(event),
+ event.status match {
+ case sbt.testing.Status.Success =>
+ passed += 1
+ TestStatus.PASSED
+ case sbt.testing.Status.Canceled =>
+ cancelled += 1
+ TestStatus.CANCELLED
+ case sbt.testing.Status.Error =>
+ failed += 1
+ TestStatus.FAILED
+ case sbt.testing.Status.Failure =>
+ failed += 1
+ TestStatus.FAILED
+ case sbt.testing.Status.Ignored =>
+ ignored += 1
+ TestStatus.IGNORED
+ case sbt.testing.Status.Skipped =>
+ skipped += 1
+ TestStatus.SKIPPED
+ case sbt.testing.Status.Pending =>
+ skipped += 1
+ TestStatus.SKIPPED //TODO: what to do here
+ })
+ taskFinishParams.setData(testFinish)
+ taskFinishParams.setEventTime(System.currentTimeMillis())
+ taskFinishParams.setMessage("Finished running: " + getDisplayName(event))
+
+ if (event.throwable.isDefined) {
+ val exception = event.throwable.get
+ taskFinishParams.setData( // send data about any potential exceptions thrown during testing
+ TestException(exception.getStackTrace.toString,
+ exception.getMessage,
+ exception.getClass.toString))
+ }
+ client.onBuildTaskFinish(taskFinishParams)
+ }
+
+ def getDisplayName(e: Event): String = {
+ e.selector() match{
+ case s: NestedSuiteSelector => s.suiteId()
+ case s: NestedTestSelector => s.suiteId() + "." + s.testName()
+ case s: SuiteSelector => s.toString
+ case s: TestSelector => s.testName()
+ case s: TestWildcardSelector => s.testWildcard()
+ }
+ }
+
+ def getTestReport: TestReport = {
+ val report = new TestReport(targetId, passed, failed, ignored, cancelled, skipped)
+ report.setTime(totalTime)
+ report
+ }
+
+}
+
+case class TestException(stackTrace: String, message: String, exClass: String)
diff --git a/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala b/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala
index b4635558..f3644060 100644
--- a/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala
+++ b/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala
@@ -10,7 +10,7 @@ import mill.scalalib.Lib.discoverTests
import ch.epfl.scala.bsp4j._
import ch.epfl.scala.{bsp4j => bsp}
import mill.{scalalib, _}
-import mill.api.{Loose, Result, Strict}
+import mill.api.{BspContext, Loose, Result, Strict}
import mill.contrib.bsp.ModuleUtils._
import mill.eval.Evaluator
import mill.scalalib._
@@ -276,10 +276,16 @@ class MillBuildServer(evaluator: Evaluator,
val result = millEvaluator.evaluate(Strict.Agg(compileTask),
Option(new BspLoggedReporter(client,
- targetId,
- getOriginId(compileParams),
- 10, getCompilationLogger)),
- params.getArguments.getOrElse(Seq.empty[String]))
+ 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 = {}
+ }
+ )
val endTime = System.currentTimeMillis()
compileTime += result.timings.map(timingTuple => timingTuple._2).sum
@@ -354,19 +360,21 @@ class MillBuildServer(evaluator: Evaluator,
testReport
}
- private[this] def getStatusCode(results: Seq[TestRunner.Result]): StatusCode = {
- if ( results.exists(res => res.status == "Failed") ) {
+ private[this] def getStatusCode(results: Evaluator.Results): StatusCode = {
+ if (results.rawValues.exists(r => r.isInstanceOf[Result.Failure[Any]])) {
StatusCode.ERROR
- } else if ( results.exists(res => res.status == "Cancelled") ) {
+ }
+
+ if (results.rawValues.contains(Result.Skipped) || results.rawValues.contains(Result.Aborted)) {
StatusCode.CANCELLED
- }else {
- StatusCode.OK
}
+
+ StatusCode.OK
}
override def buildTargetTest(testParams: TestParams): CompletableFuture[TestResult] = {
def getTestResult (implicit ctx: Ctx.Log with Ctx.Home ): TestResult = {
-
+ val params = TaskParameters.fromTestParams(testParams)
val argsMap = testParams.getData match {
case scalaTestParams: ScalaTestParams =>
(for (testItem <- scalaTestParams.getTestClasses.asScala)
@@ -381,7 +389,7 @@ class MillBuildServer(evaluator: Evaluator,
case m: TestModule => val testModule = m.asInstanceOf[TestModule]
val testTask = testModule.test(argsMap(targetId).mkString(" "))
- // send notification to client that testing of this target started
+ // notifying the client that the testing of this build target started
val taskStartParams = new TaskStartParams(new TaskId(testTask.hashCode().toString))
taskStartParams.setEventTime(System.currentTimeMillis())
taskStartParams.setMessage("Testing target: " + targetId)
@@ -389,65 +397,46 @@ class MillBuildServer(evaluator: Evaluator,
taskStartParams.setData(new TestTask(targetId))
client.onBuildTaskStart(taskStartParams)
- val runClasspath = getTaskResult(millEvaluator, testModule.runClasspath)
- val frameworks = getTaskResult(millEvaluator, testModule.testFrameworks)
- val compilationResult = getTaskResult(millEvaluator, testModule.compile)
-
- (runClasspath, frameworks, compilationResult) match {
- case (Success(classpath), Success(testFrameworks), Success(compResult)) =>
- val (msg, results) = TestRunner.runTests(
- TestRunner.frameworks(testFrameworks.asInstanceOf[Seq[String]]),
- classpath.asInstanceOf[Agg[PathRef]].map(_.path),
- Agg(compResult.asInstanceOf[scalalib.api.CompilationResult].classes.path),
- argsMap(targetId)
- )
- val endTime = System.currentTimeMillis()
- // send notification to client that testing of this target ended => test report
- val statusCode = getStatusCode(results)
- val taskFinishParams = new TaskFinishParams(
- new TaskId(testTask.hashCode().toString),
- getStatusCode(results)
- )
- taskFinishParams.setEventTime(endTime)
- taskFinishParams.setMessage("Finished testing target: " +
- moduleToTarget(targetIdToModule(targetId)).getDisplayName)
- taskFinishParams.setDataKind("test-report")
- taskFinishParams.setData(getTestReport(targetId, results))
- client.onBuildTaskFinish(taskFinishParams)
- statusCode match {
- case StatusCode.ERROR => overallStatusCode = StatusCode.ERROR
- case default =>
- }
- case default => val endTime = System.currentTimeMillis()
- val taskFinishParams = new TaskFinishParams(
- new TaskId(testTask.hashCode().toString),
- StatusCode.ERROR
- )
- taskFinishParams.setEventTime(endTime)
- taskFinishParams.setMessage("Testing target: " +
- moduleToTarget(targetIdToModule(targetId)).getDisplayName +
- "failed because one of the tasks it depended on failed. There might" +
- "be compilation errors.")
- taskFinishParams.setDataKind("test-report")
- taskFinishParams.setData(
- new TestReport(targetId, 0, 0, 0, 0, 0)
- )
- overallStatusCode = StatusCode.ERROR
- client.onBuildTaskFinish(taskFinishParams)
- buildTargetCompile(new CompileParams(List(targetId).asJava))
+ val bspContext = new BspTestReporter(
+ client, targetId,
+ new TaskId(testTask.hashCode().toString),
+ Seq.empty[String])
+
+ val results = millEvaluator.evaluate(
+ Strict.Agg(testTask),
+ Option(new BspLoggedReporter(client,
+ targetId,
+ params.getOriginId,
+ 10, getCompilationLogger)),
+ bspContext)
+ val endTime = System.currentTimeMillis()
+ val statusCode = getStatusCode(results)
+ statusCode match {
+ case StatusCode.ERROR => overallStatusCode = StatusCode.ERROR
+ case default =>
}
-
+ // notifying the client that the testing of this build target ended
+ val taskFinishParams = new TaskFinishParams(
+ new TaskId(testTask.hashCode().toString),
+ statusCode
+ )
+ taskFinishParams.setEventTime(endTime)
+ taskFinishParams.setMessage("Finished testing target: " +
+ moduleToTarget(targetIdToModule(targetId)).getDisplayName)
+ taskFinishParams.setDataKind("test-report")
+ taskFinishParams.setData(bspContext.getTestReport)
+ client.onBuildTaskFinish(taskFinishParams)
case default =>
}
}
val testResult = new TestResult(overallStatusCode)
- testParams.getOriginId match {
- case id: String =>
+ params.getOriginId match {
+ case None => testResult
+ case Some(id) =>
//TODO: Add the messages from mill to the data field?
testResult.setOriginId(id)
testResult
- case default => testResult
}
}
val future = new CompletableFuture[TestResult]()