diff --git a/backend/src/main/scala/bloop/io/ParallelOps.scala b/backend/src/main/scala/bloop/io/ParallelOps.scala index 44bd3acb70..4f2e79f87e 100644 --- a/backend/src/main/scala/bloop/io/ParallelOps.scala +++ b/backend/src/main/scala/bloop/io/ParallelOps.scala @@ -10,7 +10,9 @@ import java.nio.file.attribute.BasicFileAttributes import java.util.concurrent.ConcurrentHashMap import scala.concurrent.Promise +import scala.util.control.NonFatal +import bloop.logging.Logger import bloop.task.Task import monix.eval.{Task => MonixTask} @@ -22,8 +24,6 @@ import monix.execution.cancelables.CompositeCancelable import monix.reactive.Consumer import monix.reactive.MulticastStrategy import monix.reactive.Observable -import bloop.logging.Logger -import scala.util.control.NonFatal object ParallelOps { diff --git a/backend/src/main/scala/bloop/task/Task.scala b/backend/src/main/scala/bloop/task/Task.scala index 6cb1dbe1d4..e1d37b4d5f 100644 --- a/backend/src/main/scala/bloop/task/Task.scala +++ b/backend/src/main/scala/bloop/task/Task.scala @@ -54,7 +54,7 @@ sealed trait Task[+A] { self => } final def doOnCancel(f: => Task[Unit]): Task[A] = - applyCancel(() => f.runAsync(monix.execution.Scheduler.Implicits.global)) + applyCancel { () => f.runAsync(monix.execution.Scheduler.Implicits.global); () } final def doOnFinish(f: Option[Throwable] => Task[Unit]): Task[A] = self.materialize.flatMap { v => diff --git a/backend/src/main/scala/sbt/internal/inc/BloopComponentCompiler.scala b/backend/src/main/scala/sbt/internal/inc/BloopComponentCompiler.scala index 32d84a8405..afd4ef72ca 100644 --- a/backend/src/main/scala/sbt/internal/inc/BloopComponentCompiler.scala +++ b/backend/src/main/scala/sbt/internal/inc/BloopComponentCompiler.scala @@ -14,6 +14,8 @@ import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths +import scala.util.control.NonFatal + import _root_.bloop.io.AbsolutePath import _root_.bloop.logging.DebugFilter import _root_.bloop.logging.{Logger => BloopLogger} @@ -27,7 +29,6 @@ import xsbti.ComponentProvider import xsbti.Logger import xsbti.compile.ClasspathOptionsUtil import xsbti.compile.CompilerBridgeProvider -import scala.util.control.NonFatal object BloopComponentCompiler { import xsbti.compile.ScalaInstance diff --git a/backend/src/main/scala/sbt/internal/inc/bloop/internal/BloopAnalysisCallback.scala b/backend/src/main/scala/sbt/internal/inc/bloop/internal/BloopAnalysisCallback.scala index 3c2534104c..e684717999 100644 --- a/backend/src/main/scala/sbt/internal/inc/bloop/internal/BloopAnalysisCallback.scala +++ b/backend/src/main/scala/sbt/internal/inc/bloop/internal/BloopAnalysisCallback.scala @@ -4,6 +4,8 @@ import java.io.File import java.nio.file.Path import java.{util => ju} +import scala.collection.JavaConverters._ + import sbt.internal.inc.Analysis import sbt.internal.inc.Compilation import sbt.internal.inc.Incremental @@ -15,6 +17,9 @@ import sbt.util.InterfaceUtil import xsbt.api.APIUtil import xsbt.api.HashAPI import xsbt.api.NameHashing +import xsbti.Action +import xsbti.DiagnosticCode +import xsbti.DiagnosticRelatedInformation import xsbti.Position import xsbti.Problem import xsbti.Severity @@ -35,9 +40,6 @@ import xsbti.compile.ClassFileManager import xsbti.compile.IncOptions import xsbti.compile.Output import xsbti.compile.analysis.ReadStamps -import xsbti.{Action, DiagnosticCode, DiagnosticRelatedInformation} - -import collection.JavaConverters._ trait IBloopAnalysisCallback extends xsbti.AnalysisCallback2 { def get: Analysis diff --git a/backend/src/main/scala/sbt/internal/inc/bloop/internal/ConcurrentAnalysisCallback.scala b/backend/src/main/scala/sbt/internal/inc/bloop/internal/ConcurrentAnalysisCallback.scala index af98b499e8..437dc6a090 100644 --- a/backend/src/main/scala/sbt/internal/inc/bloop/internal/ConcurrentAnalysisCallback.scala +++ b/backend/src/main/scala/sbt/internal/inc/bloop/internal/ConcurrentAnalysisCallback.scala @@ -4,6 +4,8 @@ import java.io.File import java.nio.file.Path import java.{util => ju} +import scala.collection.JavaConverters._ + import sbt.internal.inc.Analysis import sbt.internal.inc.Compilation import sbt.internal.inc.Incremental @@ -15,6 +17,9 @@ import sbt.util.InterfaceUtil import xsbt.api.APIUtil import xsbt.api.HashAPI import xsbt.api.NameHashing +import xsbti.Action +import xsbti.DiagnosticCode +import xsbti.DiagnosticRelatedInformation import xsbti.Position import xsbti.Problem import xsbti.Severity @@ -35,9 +40,6 @@ import xsbti.compile.ClassFileManager import xsbti.compile.IncOptions import xsbti.compile.Output import xsbti.compile.analysis.ReadStamps -import xsbti.{Action, DiagnosticCode, DiagnosticRelatedInformation} - -import collection.JavaConverters._ /** * This class provides a thread-safe implementation of `xsbti.AnalysisCallback` which is required to compile with the diff --git a/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala b/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala index e272f1a958..70c0a328a2 100644 --- a/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala +++ b/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala @@ -137,7 +137,7 @@ final class BloopBspServices( .requestAsync(endpoints.BuildTarget.run)(p => schedule(run(p))) .requestAsync(endpoints.BuildTarget.cleanCache)(p => schedule(clean(p))) .requestAsync(endpoints.BuildTarget.scalaMainClasses)(p => schedule(scalaMainClasses(p))) - .requestAsync(ScalaTestClasses.endpoint)(p => schedule(scalaTestClasses(p))) + .requestAsync(endpoints.BuildTarget.scalaTestClasses)(p => schedule(scalaTestClasses(p))) .requestAsync(endpoints.BuildTarget.dependencySources)(p => schedule(dependencySources(p))) .requestAsync(endpoints.DebugSession.start)(p => schedule(startDebugSession(p))) .requestAsync(endpoints.BuildTarget.jvmTestEnvironment)(p => schedule(jvmTestEnvironment(p))) @@ -316,6 +316,7 @@ final class BloopBspServices( jvmRunEnvironmentProvider = Some(true), canReload = Some(false) ), + None, None ) ) @@ -567,12 +568,12 @@ final class BloopBspServices( def scalaTestClasses( params: bsp.ScalaTestClassesParams - ): BspEndpointResponse[ScalaTestClassesResult] = + ): BspEndpointResponse[bsp.ScalaTestClassesResult] = ifInitialized(params.originId) { (state: State, logger: BspServerLogger) => mapToProjects(params.targets, state) match { case Left(error) => logger.error(error) - Task.now((state, Right(ScalaTestClassesResult(Nil)))) + Task.now((state, Right(bsp.ScalaTestClassesResult(Nil)))) case Right(projects) => val subTasks = projects.toList.filter(p => TestTask.isTestProject(p._2)).map { @@ -583,7 +584,7 @@ final class BloopBspServices( .groupBy(_.framework) .map { case (framework, classes) => - ScalaTestClassesItem(id, classes.flatMap(_.classes), Some(framework)) + bsp.ScalaTestClassesItem(id, Some(framework), classes.flatMap(_.classes)) } .toList } @@ -591,7 +592,7 @@ final class BloopBspServices( } Task.sequence(subTasks).map { items => - val result = ScalaTestClassesResult(items.flatten) + val result = bsp.ScalaTestClassesResult(items.flatten) (state, Right(result)) } } @@ -608,33 +609,43 @@ final class BloopBspServices( def convert[A: JsonValueCodec]( f: A => Either[String, Debuggee] ): Either[Response.Error, Debuggee] = { - Try(readFromArray[A](params.data.value)) match { - case Failure(error) => - Left(Response.invalidRequest(error.getMessage())) - case Success(params) => - f(params) match { - case Right(adapter) => Right(adapter) - case Left(error) => Left(Response.invalidRequest(error)) + params.data match { + case Some(data) => + Try(readFromArray[A](data.value)) match { + case Failure(error) => + Left(Response.invalidRequest(error.getMessage())) + case Success(params) => + f(params) match { + case Right(adapter) => Right(adapter) + case Left(error) => Left(Response.invalidRequest(error)) + } } + case None => + Left(Response.invalidRequest("No debug data available")) } + } params.dataKind match { - case bsp.DebugSessionParamsDataKind.ScalaMainClass => + case Some(bsp.DebugSessionParamsDataKind.ScalaMainClass) => convert[bsp.ScalaMainClass](main => BloopDebuggeeRunner.forMainClass(projects, main, state, ioScheduler) ) - case bsp.DebugSessionParamsDataKind.ScalaTestSuites => + case Some(bsp.TestParamsDataKind.ScalaTestSuites) => implicit val codec = JsonCodecMaker.make[List[String]] convert[List[String]](classNames => { - val testClasses = ScalaTestSuites(classNames) + val testClasses = bsp.ScalaTestSuites( + classNames.map(className => bsp.ScalaTestSuiteSelection(className, Nil)), + Nil, + Nil + ) BloopDebuggeeRunner.forTestSuite(projects, testClasses, state, ioScheduler) }) - case "scala-test-suites-selection" => - convert[ScalaTestSuites](testClasses => { + case Some(bsp.TestParamsDataKind.ScalaTestSuitesSelection) => + convert[bsp.ScalaTestSuites](testClasses => { BloopDebuggeeRunner.forTestSuite(projects, testClasses, state, ioScheduler) }) - case bsp.DebugSessionParamsDataKind.ScalaAttachRemote => + case Some(bsp.DebugSessionParamsDataKind.ScalaAttachRemote) => Right(BloopDebuggeeRunner.forAttachRemote(state, ioScheduler, projects)) case dataKind => Left(Response.invalidRequest(s"Unsupported data kind: $dataKind")) } @@ -684,7 +695,9 @@ final class BloopBspServices( .map(_ => backgroundDebugServers -= handler.uri) .runAsync(ioScheduler) backgroundDebugServers += handler.uri -> listenAndUnsubscribe - Task.now((state, Right(new bsp.DebugSessionAddress(handler.uri.toString)))) + Task.now( + (state, Right(new bsp.DebugSessionAddress(bsp.Uri(handler.uri.toString())))) + ) case Left(error) => Task.now((state, Left(error))) @@ -704,7 +717,7 @@ final class BloopBspServices( List(project), Nil, testFilter, - ScalaTestSuites.empty, + bsp.ScalaTestSuites(Nil, Nil, Nil), handler, mode = RunMode.Normal ) @@ -804,13 +817,13 @@ final class BloopBspServices( def findMainClasses(state: State, project: Project): List[bsp.ScalaMainClass] = for { className <- Tasks.findMainClasses(state, project) - } yield bsp.ScalaMainClass(className, Nil, Nil, Nil) + } yield bsp.ScalaMainClass(className, Nil, Nil, None) ifInitialized(params.originId) { (state: State, logger: BspServerLogger) => mapToProjects(params.targets, state) match { case Left(error) => logger.error(error) - Task.now((state, Right(bsp.ScalaMainClassesResult(Nil)))) + Task.now((state, Right(bsp.ScalaMainClassesResult(Nil, params.originId)))) case Right(projects) => val items = for { @@ -818,7 +831,7 @@ final class BloopBspServices( mainClasses = findMainClasses(state, project) } yield bsp.ScalaMainClassesItem(id, mainClasses) - val result = new bsp.ScalaMainClassesResult(items) + val result = new bsp.ScalaMainClassesResult(items, params.originId) Task.now((state, Right(result))) } } @@ -843,7 +856,7 @@ final class BloopBspServices( val cmd = Commands.Run(List(project.name)) Interpreter.getMainClass(state, project, cmd.main) match { case Right(name) => - Right(new bsp.ScalaMainClass(name, cmd.args, Nil, Nil)) + Right(new bsp.ScalaMainClass(name, cmd.args, Nil, None)) case Left(_) => Left(new IllegalStateException(s"Main class for project $project not found")) } @@ -871,16 +884,16 @@ final class BloopBspServices( project, config, cwd, - mainClass.`class`, + mainClass.className, mainArgs, skipJargs = false, - mainClass.environmentVariables, + mainClass.environmentVariables.getOrElse(Nil), RunMode.Normal ) case platform @ Platform.Native(config, _, _) => val cmd = Commands.Run(List(project.name)) val target = ScalaNativeToolchain.linkTargetFrom(project, config) - linkMainWithNative(cmd, project, state, mainClass.`class`, target, platform) + linkMainWithNative(cmd, project, state, mainClass.className, target, platform) .flatMap { state => val args = (target.syntax +: cmd.args).toArray if (!state.status.isOk) Task.now(state) @@ -889,7 +902,7 @@ final class BloopBspServices( case platform @ Platform.Js(config, _, _) => val cmd = Commands.Run(List(project.name)) val target = ScalaJsToolchain.linkTargetFrom(project, config) - linkMainWithJs(cmd, project, state, mainClass.`class`, target, platform) + linkMainWithJs(cmd, project, state, mainClass.className, target, platform) .flatMap { state => // We use node to run the program (is this a special case?) val args = ("node" +: target.syntax +: cmd.args).toArray @@ -1040,10 +1053,10 @@ final class BloopBspServices( } val capabilities = bsp.BuildTargetCapabilities( - canCompile = true, - canTest = true, - canRun = true, - canDebug = true + canCompile = Some(true), + canTest = Some(true), + canRun = Some(true), + canDebug = Some(true) ) val isJavaOnly = p.scalaInstance.isEmpty val languageIds = @@ -1256,8 +1269,8 @@ final class BloopBspServices( bsp.ScalacOptionsItem( target = target, options = project.scalacOptions.toList, - classpath = classpath, - classDirectory = classesDir + classpath = classpath.map(_.value), + classDirectory = classesDir.value ) }.toList ) @@ -1290,8 +1303,8 @@ final class BloopBspServices( bsp.JavacOptionsItem( target = target, options = project.javacOptions.toList, - classpath = classpath, - classDirectory = classesDir + classpath = classpath.map(_.value), + classDirectory = classesDir.value ) }.toList ) diff --git a/frontend/src/main/scala/bloop/bsp/BloopLanguageClient.scala b/frontend/src/main/scala/bloop/bsp/BloopLanguageClient.scala index 67f8e68a1b..f0f6f62393 100644 --- a/frontend/src/main/scala/bloop/bsp/BloopLanguageClient.scala +++ b/frontend/src/main/scala/bloop/bsp/BloopLanguageClient.scala @@ -39,11 +39,21 @@ class BloopLanguageClient( def notify[A]( endpoint: Endpoint[A, Unit], - params: A, - headers: Map[String, String] = Map.empty + params: A + ): Future[Ack] = notify(endpoint, Some(params), Map.empty) + + def notify[A]( + endpoint: Endpoint[A, Unit], + params: Option[A] + ): Future[Ack] = notify(endpoint, params, Map.empty) + + def notify[A]( + endpoint: Endpoint[A, Unit], + params: Option[A], + headers: Map[String, String] ): Future[Ack] = { import endpoint.codecA - val msg = Notification(endpoint.method, Some(toJson(params)), headers) + val msg = Notification(endpoint.method, params.map(toJson(_)), headers) // Send notifications in the order they are sent by the caller notificationsLock.synchronized { @@ -53,14 +63,24 @@ class BloopLanguageClient( def request[A, B]( endpoint: Endpoint[A, B], - params: A, - headers: Map[String, String] = Map.empty + params: A + ): Task[RpcResponse[B]] = request(endpoint, Some(params), Map.empty) + + def request[A, B]( + endpoint: Endpoint[A, B], + params: Option[A] + ): Task[RpcResponse[B]] = request(endpoint, params, Map.empty) + + def request[A, B]( + endpoint: Endpoint[A, B], + params: Option[A], + headers: Map[String, String] ): Task[RpcResponse[B]] = { import endpoint.{codecA, codecB} val reqId = RequestId(counter.incrementAndGet()) val response = Task.create[Response] { (s, cb) => val scheduled = s.scheduleOnce(Duration(0, "s")) { - val json = Request(endpoint.method, Some(toJson(params)), reqId, headers) + val json = Request(endpoint.method, params.map(toJson(_)), reqId, headers) activeServerRequests.put(reqId, cb) out.onNext(json) () diff --git a/frontend/src/main/scala/bloop/bsp/ProjectUris.scala b/frontend/src/main/scala/bloop/bsp/ProjectUris.scala index eb8e15a54a..ac4d99cf24 100644 --- a/frontend/src/main/scala/bloop/bsp/ProjectUris.scala +++ b/frontend/src/main/scala/bloop/bsp/ProjectUris.scala @@ -44,8 +44,8 @@ object ProjectUris { ) } - def toPath(uri: Uri): Path = { - val existingUri = new URI(uri.value) + def toPath(uri: String) = { + val existingUri = new URI(uri) val uriWithNoQuery = new URI( existingUri.getScheme, existingUri.getUserInfo, @@ -58,4 +58,6 @@ object ProjectUris { java.nio.file.Paths.get(uriWithNoQuery) } + def toPath(uri: Uri): Path = toPath(uri.value) + } diff --git a/frontend/src/main/scala/bloop/bsp/ScalaTestSuites.scala b/frontend/src/main/scala/bloop/bsp/ScalaTestSuites.scala deleted file mode 100644 index 7ebe8c3e31..0000000000 --- a/frontend/src/main/scala/bloop/bsp/ScalaTestSuites.scala +++ /dev/null @@ -1,42 +0,0 @@ -package bloop.bsp - -import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec -import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker - -/** - * Below datatypes are based on https://github.com/build-server-protocol/build-server-protocol/issues/249#issuecomment-983435766 - */ -case class ScalaTestSuites( - suites: List[ScalaTestSuiteSelection], - jvmOptions: List[String], - environmentVariables: List[String] -) { - def classNames: List[String] = suites.map(_.className) -} - -object ScalaTestSuites { - implicit val jsonCodec: JsonValueCodec[ScalaTestSuites] = - JsonCodecMaker.makeWithRequiredCollectionFields - val empty: ScalaTestSuites = ScalaTestSuites(Nil, Nil, Nil) - - def apply(classes: List[String]): ScalaTestSuites = ScalaTestSuites( - classes.map(className => ScalaTestSuiteSelection(className, Nil)), - Nil, - Nil - ) - - def forSuiteSelection(classes: List[ScalaTestSuiteSelection]): ScalaTestSuites = ScalaTestSuites( - classes, - Nil, - Nil - ) -} - -case class ScalaTestSuiteSelection( - className: String, - tests: List[String] -) -object ScalaTestSuiteSelection { - implicit val jsonCodec: JsonValueCodec[ScalaTestSuiteSelection] = - JsonCodecMaker.makeWithRequiredCollectionFields -} diff --git a/frontend/src/main/scala/bloop/bsp/ScalaTestSuitesResult.scala b/frontend/src/main/scala/bloop/bsp/ScalaTestSuitesResult.scala deleted file mode 100644 index 226bf7325e..0000000000 --- a/frontend/src/main/scala/bloop/bsp/ScalaTestSuitesResult.scala +++ /dev/null @@ -1,34 +0,0 @@ -package bloop.bsp - -import ch.epfl.scala.bsp.BuildTargetIdentifier -import ch.epfl.scala.bsp.ScalaTestClassesParams - -import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec -import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker -import jsonrpc4s.Endpoint - -object ScalaTestClasses { - val endpoint = - new Endpoint[ScalaTestClassesParams, ScalaTestClassesResult]("buildTarget/scalaTestClasses") -} - -final case class ScalaTestClassesResult( - items: List[ScalaTestClassesItem] -) - -object ScalaTestClassesResult { - implicit val jsonCodec: JsonValueCodec[ScalaTestClassesResult] = - JsonCodecMaker.makeWithRequiredCollectionFields -} - -final case class ScalaTestClassesItem( - target: BuildTargetIdentifier, - // Fully qualified names of test classes - classes: List[String], - // Name of the sbt's test framework - framework: Option[String] -) -object ScalaTestClassesItem { - implicit val jsonCodec: JsonValueCodec[ScalaTestClassesItem] = - JsonCodecMaker.makeWithRequiredCollectionFields -} diff --git a/frontend/src/main/scala/bloop/dap/BloopDebuggee.scala b/frontend/src/main/scala/bloop/dap/BloopDebuggee.scala index d6e35c89a0..1dddac6482 100644 --- a/frontend/src/main/scala/bloop/dap/BloopDebuggee.scala +++ b/frontend/src/main/scala/bloop/dap/BloopDebuggee.scala @@ -2,10 +2,10 @@ package bloop.dap import scala.collection.mutable +import ch.epfl.scala.bsp import ch.epfl.scala.bsp.ScalaMainClass import ch.epfl.scala.debugadapter._ -import bloop.bsp.ScalaTestSuites import bloop.cli.ExitStatus import bloop.data.ClientInfo import bloop.data.JdkConfig @@ -55,7 +55,7 @@ private final class MainClassDebugAdapter( scalaVersion: Option[String] ) extends BloopDebuggee(initialState, ioScheduler, scalaVersion) { val javaRuntime: Option[JavaRuntime] = JavaRuntime(env.javaHome.underlying) - def name: String = s"${getClass.getSimpleName}(${project.name}, ${mainClass.`class`})" + def name: String = s"${getClass.getSimpleName}(${project.name}, ${mainClass.className})" def start(state: State, listener: DebuggeeListener): Task[ExitStatus] = { // TODO: https://github.com/scalacenter/bloop/issues/1456 // Metals used to add the `-J` prefix but it is not needed anymore @@ -66,10 +66,10 @@ private final class MainClassDebugAdapter( project, env, project.workspaceDirectory.getOrElse(project.baseDirectory), - mainClass.`class`, + mainClass.className, mainClass.arguments.toArray, jvmOptions.toArray, - mainClass.environmentVariables, + mainClass.environmentVariables.getOrElse(Nil), RunMode.Debug ) runState.map(_.status) @@ -78,7 +78,7 @@ private final class MainClassDebugAdapter( private final class TestSuiteDebugAdapter( projects: Seq[Project], - testClasses: ScalaTestSuites, + testClasses: bsp.ScalaTestSuites, val modules: Seq[Module], val libraries: Seq[Library], val unmanagedEntries: Seq[UnmanagedEntry], @@ -170,13 +170,15 @@ object BloopDebuggeeRunner { def forTestSuite( projects: Seq[Project], - testClasses: ScalaTestSuites, + testClasses: bsp.ScalaTestSuites, state: State, ioScheduler: Scheduler ): Either[String, Debuggee] = { projects match { case Seq() => - Left(s"No projects specified for the test suites: [${testClasses.classNames.sorted}]") + Left( + s"No projects specified for the test suites: [${testClasses.suites.map(_.className).sorted}]" + ) case Seq(project) if project.platform.isInstanceOf[Platform.Jvm] => val dag = state.build.getDagFor(project) val modules = getModules(dag, state.client) diff --git a/frontend/src/main/scala/bloop/engine/Interpreter.scala b/frontend/src/main/scala/bloop/engine/Interpreter.scala index 675c51adfc..d48ea75239 100644 --- a/frontend/src/main/scala/bloop/engine/Interpreter.scala +++ b/frontend/src/main/scala/bloop/engine/Interpreter.scala @@ -9,7 +9,6 @@ import scala.concurrent.Promise import bloop.ScalaInstance import bloop.bsp.BspServer -import bloop.bsp.ScalaTestSuites import bloop.cli.Commands.CompilingCommand import bloop.cli.Validate import bloop.cli._ @@ -371,7 +370,7 @@ object Interpreter { projectsToTest, cmd.args, testFilter, - ScalaTestSuites.empty, + ch.epfl.scala.bsp.ScalaTestSuites(Nil, Nil, Nil), handler, cmd.parallel, RunMode.Normal diff --git a/frontend/src/main/scala/bloop/engine/caches/SemanticDBCache.scala b/frontend/src/main/scala/bloop/engine/caches/SemanticDBCache.scala index e711a8de70..09e8b4187a 100644 --- a/frontend/src/main/scala/bloop/engine/caches/SemanticDBCache.scala +++ b/frontend/src/main/scala/bloop/engine/caches/SemanticDBCache.scala @@ -1,9 +1,11 @@ package bloop.engine.caches import java.nio.file.Path +import java.util.concurrent.ConcurrentHashMap import scala.collection.JavaConverters._ import scala.concurrent.Await +import scala.concurrent.Future import scala.concurrent.duration.FiniteDuration import scala.util.Failure import scala.util.Success @@ -15,13 +17,10 @@ import bloop.engine.ExecutionContext import bloop.io.AbsolutePath import bloop.io.Paths import bloop.logging.Logger -import bloop.task.Task import sbt.internal.inc.BloopComponentCompiler import sbt.internal.inc.BloopComponentManager import sbt.internal.inc.IfMissing -import java.util.concurrent.ConcurrentHashMap -import scala.concurrent.Future object SemanticDBCache { // to avoid resolving the same fallback semanticdb version multiple times diff --git a/frontend/src/main/scala/bloop/engine/tasks/Tasks.scala b/frontend/src/main/scala/bloop/engine/tasks/Tasks.scala index ef6dec13ad..b1df2daf6a 100644 --- a/frontend/src/main/scala/bloop/engine/tasks/Tasks.scala +++ b/frontend/src/main/scala/bloop/engine/tasks/Tasks.scala @@ -3,9 +3,9 @@ package bloop.engine.tasks import java.nio.file.Files import java.nio.file.Path +import ch.epfl.scala.bsp import ch.epfl.scala.debugadapter.testing.TestSuiteEvent -import bloop.bsp.ScalaTestSuites import bloop.cli.ExitStatus import bloop.data.JdkConfig import bloop.data.Project @@ -124,7 +124,7 @@ object Tasks { projectsToTest: List[Project], userTestOptions: List[String], testFilter: String => Boolean, - testClasses: ScalaTestSuites, + testClasses: bsp.ScalaTestSuites, testEventHandler: BloopTestSuiteEventHandler, runInParallel: Boolean = false, mode: RunMode diff --git a/frontend/src/main/scala/bloop/engine/tasks/TestTask.scala b/frontend/src/main/scala/bloop/engine/tasks/TestTask.scala index ecd9cd1503..e7b92d6a70 100644 --- a/frontend/src/main/scala/bloop/engine/tasks/TestTask.scala +++ b/frontend/src/main/scala/bloop/engine/tasks/TestTask.scala @@ -4,7 +4,8 @@ import scala.util.Failure import scala.util.Success import scala.util.control.NonFatal -import bloop.bsp.ScalaTestSuites +import ch.epfl.scala.bsp + import bloop.cli.ExitStatus import bloop.config.Config import bloop.config.Tag @@ -74,7 +75,7 @@ object TestTask { cwd: AbsolutePath, rawTestOptions: List[String], testFilter: String => Boolean, - testClasses: ScalaTestSuites, + testClasses: bsp.ScalaTestSuites, handler: LoggingEventHandler, mode: RunMode ): Task[Int] = { @@ -292,7 +293,7 @@ object TestTask { frameworks: List[Framework], analysis: CompileAnalysis, testFilter: String => Boolean, - testClasses: ScalaTestSuites + testClasses: bsp.ScalaTestSuites ): Map[Framework, List[TaskDef]] = { import state.logger val tests = discoverTests(analysis, frameworks) diff --git a/frontend/src/main/scala/bloop/logging/BspServerLogger.scala b/frontend/src/main/scala/bloop/logging/BspServerLogger.scala index 9044d9a26c..68ee95528a 100644 --- a/frontend/src/main/scala/bloop/logging/BspServerLogger.scala +++ b/frontend/src/main/scala/bloop/logging/BspServerLogger.scala @@ -179,7 +179,7 @@ final class BspServerLogger private ( bsp.ScalaTextEdit(range, edit.newText()) } } - val workspaceEdit = bsp.ScalaWorkspaceEdit(Option(edits.toList)) + val workspaceEdit = bsp.ScalaWorkspaceEdit(edits.toList) bsp.ScalaAction(action.title(), description, Some(workspaceEdit)) } bsp.ScalaDiagnostic(Some(bspActions.toList)) @@ -310,10 +310,11 @@ final class BspServerLogger private ( event.taskId, Some(now), Some(event.msg), - Some(bsp.TaskDataKind.CompileTask), + Some(bsp.TaskStartDataKind.CompileTask), Some(RawJson(encoded)) ) ) + bsp.TaskFinishDataKind () } @@ -368,7 +369,7 @@ final class BspServerLogger private ( Some(now), Some(s"Compiled '${event.projectName}'"), event.code, - Some(bsp.TaskDataKind.CompileReport), + Some(bsp.TaskFinishDataKind.CompileReport), Some(RawJson(encoded)) ) ) diff --git a/frontend/src/test/scala/bloop/bsp/BspBaseSuite.scala b/frontend/src/test/scala/bloop/bsp/BspBaseSuite.scala index bd2a4cb896..54de43c3d6 100644 --- a/frontend/src/test/scala/bloop/bsp/BspBaseSuite.scala +++ b/frontend/src/test/scala/bloop/bsp/BspBaseSuite.scala @@ -98,8 +98,13 @@ abstract class BspBaseSuite extends BaseSuite with BspClientTest { def rpcRequest[A, B]( endpoint: Endpoint[A, B], params: A + ): Task[B] = rpcRequest(endpoint, Some(params)) + + def rpcRequest[A, B]( + endpoint: Endpoint[A, B], + params: Option[A] ): Task[B] = { - client0.request(endpoint, params).map { + client0.request(endpoint, params, Map.empty).map { case RpcFailure(_, e) => fail(s"The request ${endpoint.method} failed with $e") case RpcSuccess(a, _) => a } @@ -107,7 +112,7 @@ abstract class BspBaseSuite extends BaseSuite with BspClientTest { def findBuildTarget(project: TestProject): bsp.BuildTarget = { val workspaceTargetTask = { - rpcRequest(Workspace.buildTargets, bsp.WorkspaceBuildTargetsRequest()).map { ts => + rpcRequest(Workspace.buildTargets, None).map { ts => ts.targets.map(t => t.id -> t).find(_._1 == project.bspId) match { case Some((_, target)) => target case None => fail(s"Target ${project.bspId} is missing in the workspace! Found ${ts}") @@ -120,7 +125,7 @@ abstract class BspBaseSuite extends BaseSuite with BspClientTest { def workspaceTargets: bsp.WorkspaceBuildTargetsResult = { val workspaceTargetsTask = - rpcRequest(Workspace.buildTargets, bsp.WorkspaceBuildTargetsRequest()) + rpcRequest(Workspace.buildTargets, None) TestUtil.await(FiniteDuration(5, "s"))(workspaceTargetsTask) } @@ -128,7 +133,7 @@ abstract class BspBaseSuite extends BaseSuite with BspClientTest { def runAfterTargets[T]( project: TestProject )(f: bsp.BuildTargetIdentifier => Task[T]): Task[T] = { - rpcRequest(Workspace.buildTargets, bsp.WorkspaceBuildTargetsRequest()).flatMap { ts => + rpcRequest(Workspace.buildTargets, None).flatMap { ts => ts.targets.map(_.id).find(_ == project.bspId) match { case Some(target) => f(target) case None => fail(s"Target ${project.bspId} is missing in the workspace! Found ${ts}") @@ -398,10 +403,10 @@ abstract class BspBaseSuite extends BaseSuite with BspClientTest { TestUtil.await(FiniteDuration(5, "s"))(task) } - def testClasses(project: TestProject): ScalaTestClassesResult = { + def testClasses(project: TestProject): bsp.ScalaTestClassesResult = { val task = runAfterTargets(project) { target => val params = bsp.ScalaTestClassesParams(List(target), None) - rpcRequest(ScalaTestClasses.endpoint, params) + rpcRequest(endpoints.BuildTarget.scalaTestClasses, params) } TestUtil.await(FiniteDuration(5, "s"))(task) @@ -419,7 +424,7 @@ abstract class BspBaseSuite extends BaseSuite with BspClientTest { val session = for { address <- sessionAddress - uri = URI.create(address.uri) + uri = URI.create(address.uri.value) client = DebugTestClient(uri)(defaultScheduler) result <- f(client) } yield result @@ -804,6 +809,7 @@ abstract class BspBaseSuite extends BaseSuite with BspClientTest { BuildInfo.bspVersion, rootUri = bsp.Uri(cwd.toAbsolutePath.toUri), capabilities = bsp.BuildClientCapabilities(List("scala", "java")), + None, additionalData ) ) @@ -813,14 +819,14 @@ abstract class BspBaseSuite extends BaseSuite with BspClientTest { (startedServer *> initializeServer) .flatMap { _ => Task.fromFuture( - lsClient.notify(endpoints.Build.initialized, bsp.InitializedBuildParams()) + lsClient.notify(endpoints.Build.initialized, None) ) } } val closeTask = { - lsClient.request(endpoints.Build.shutdown, bsp.Shutdown()).flatMap { _ => - Task.fromFuture(lsClient.notify(endpoints.Build.exit, bsp.Exit())).map { _ => + lsClient.request(endpoints.Build.shutdown, None).flatMap { _ => + Task.fromFuture(lsClient.notify(endpoints.Build.exit, None)).map { _ => try { socket.close() } catch { diff --git a/frontend/src/test/scala/bloop/bsp/BspClientTest.scala b/frontend/src/test/scala/bloop/bsp/BspClientTest.scala index 1610be53fc..082bdec6c9 100644 --- a/frontend/src/test/scala/bloop/bsp/BspClientTest.scala +++ b/frontend/src/test/scala/bloop/bsp/BspClientTest.scala @@ -157,22 +157,23 @@ trait BspClientTest { lsClient.request( endpoints.Build.initialize, bsp.InitializeBuildParams( - "test-bloop-client", - "1.0.0", - BuildInfo.bspVersion, + displayName = "test-bloop-client", + version = "1.0.0", + bspVersion = BuildInfo.bspVersion, rootUri = bsp.Uri(cwd.toAbsolutePath.toUri), capabilities = bsp.BuildClientCapabilities(List("scala")), - None + dataKind = None, + data = None ) ) for { // Delay the task to let the bloop server go live initializeResult <- initializeServer.delayExecution(FiniteDuration(1, "s")) - _ = lsClient.notify(endpoints.Build.initialized, bsp.InitializedBuildParams()) + _ = lsClient.notify(endpoints.Build.initialized, params = None) otherCalls <- runEndpoints(lsClient) - _ <- lsClient.request(endpoints.Build.shutdown, bsp.Shutdown()) - _ = lsClient.notify(endpoints.Build.exit, bsp.Exit()) + _ <- lsClient.request(endpoints.Build.shutdown, params = None) + _ = lsClient.notify(endpoints.Build.exit, params = None) } yield { socket.close() otherCalls match { @@ -258,7 +259,7 @@ trait BspClientTest { ): BloopRpcServices => BloopRpcServices = { (s: BloopRpcServices) => s.notification(endpoints.Build.taskStart) { taskStart => taskStart.dataKind match { - case Some(bsp.TaskDataKind.CompileTask) => + case Some(bsp.TaskStartDataKind.CompileTask) => val json = taskStart.data.get Try(readFromArray[bsp.CompileTask](json.value)) match { case Failure(_) => () @@ -283,7 +284,7 @@ trait BspClientTest { () }.notification(endpoints.Build.taskFinish) { taskFinish => taskFinish.dataKind match { - case Some(bsp.TaskDataKind.CompileReport) => + case Some(bsp.TaskFinishDataKind.CompileReport) => val json = taskFinish.data.get Try(readFromArray[bsp.CompileReport](json.value)) match { case Failure(_) => () diff --git a/frontend/src/test/scala/bloop/bsp/BspCompileSpec.scala b/frontend/src/test/scala/bloop/bsp/BspCompileSpec.scala index acdb7f7bbc..122456d6d3 100644 --- a/frontend/src/test/scala/bloop/bsp/BspCompileSpec.scala +++ b/frontend/src/test/scala/bloop/bsp/BspCompileSpec.scala @@ -44,10 +44,10 @@ class BspCompileSpec( assertNoDiff( allButInitializeRequest.mkString(lineSeparator), s"""| --> content: ${TestConstants.buildInitialize} - | --> content: {"method":"build/initialized","params":{},"jsonrpc":"2.0"} - | --> content: {"method":"build/shutdown","params":{},"id":3,"jsonrpc":"2.0"} + | --> content: {"method":"build/initialized","jsonrpc":"2.0"} + | --> content: {"method":"build/shutdown","id":3,"jsonrpc":"2.0"} | --> content: {"result":{},"id":3,"jsonrpc":"2.0"} - | --> content: {"method":"build/exit","params":{},"jsonrpc":"2.0"}""".stripMargin + | --> content: {"method":"build/exit","jsonrpc":"2.0"}""".stripMargin ) } diff --git a/frontend/src/test/scala/bloop/bsp/BspConnectionSpec.scala b/frontend/src/test/scala/bloop/bsp/BspConnectionSpec.scala index 47b22a41e3..56cfcfc391 100644 --- a/frontend/src/test/scala/bloop/bsp/BspConnectionSpec.scala +++ b/frontend/src/test/scala/bloop/bsp/BspConnectionSpec.scala @@ -97,7 +97,7 @@ class BspConnectionSpec( allButInitializeRequest.mkString(lineSeparator), s"""| | --> content: ${TestConstants.buildInitialize} - | --> content: {"method":"build/initialized","params":{},"jsonrpc":"2.0"}""".stripMargin + | --> content: {"method":"build/initialized","jsonrpc":"2.0"}""".stripMargin ) } diff --git a/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala b/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala index e2394c6e2e..d09f1d3072 100644 --- a/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala +++ b/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala @@ -82,9 +82,9 @@ class BspProtocolSpec( assert(result.items.size == 1) val optionsItem = result.items.head assert(optionsItem.options == expectedOptions) - assert(optionsItem.classDirectory.toPath == expectedClassesDir) + assert(ProjectUris.toPath(optionsItem.classDirectory) == expectedClassesDir) assert(optionsItem.target == expectedId) - val pathClasspath = optionsItem.classpath.map(_.toPath) + val pathClasspath = optionsItem.classpath.map(ProjectUris.toPath) expectedProjectEntries.foreach { expectedProjectEntry => // Ensure there is only one match per every entry val matches = pathClasspath.filter(_ == expectedProjectEntry) @@ -220,26 +220,30 @@ class BspProtocolSpec( loadBspState(workspace, projects, logger, bloopExtraParams = extraBloopParams) { bspState => val (_, options) = bspState.scalaOptions(`A`) firstScalacOptions = options.items - firstScalacOptions.foreach(d => assertIsDirectory(AbsolutePath(d.classDirectory.toPath))) + firstScalacOptions.foreach(d => + assertIsDirectory(AbsolutePath(ProjectUris.toPath(d.classDirectory))) + ) } // Start second client and query for scalac options which should use same dirs as before loadBspState(workspace, projects, logger, bloopExtraParams = extraBloopParams) { bspState => val (_, options) = bspState.scalaOptions(`A`) secondScalacOptions = options.items - secondScalacOptions.foreach(d => assertIsDirectory(AbsolutePath(d.classDirectory.toPath))) + secondScalacOptions.foreach(d => + assertIsDirectory(AbsolutePath(ProjectUris.toPath(d.classDirectory))) + ) } firstScalacOptions.zip(secondScalacOptions).foreach { case (firstItem, secondItem) => assertNoDiff( - firstItem.classDirectory.value, - secondItem.classDirectory.value + firstItem.classDirectory, + secondItem.classDirectory ) } firstScalacOptions.foreach { option => - assertIsDirectory(AbsolutePath(option.classDirectory.toPath)) + assertIsDirectory(AbsolutePath(ProjectUris.toPath(option.classDirectory))) } } } @@ -284,7 +288,7 @@ class BspProtocolSpec( val items = mainClasses.items assert(items.size == 1) - val classes = items.head.classes.map(_.`class`).toSet + val classes = items.head.classes.map(_.className).toSet assert(classes == expectedClasses) } } @@ -304,7 +308,7 @@ class BspProtocolSpec( ("ScalaTest", List("hello.ScalaTestTest", "hello.WritingTest", "hello.ResourcesTest")) ).map { case (framework, classes) => - ScalaTestClassesItem(project.bspId, classes, Some(framework)) + bsp.ScalaTestClassesItem(project.bspId, Some(framework), classes) } val testSuites = compiledState.testClasses(project) diff --git a/frontend/src/test/scala/bloop/bsp/TestConstants.scala b/frontend/src/test/scala/bloop/bsp/TestConstants.scala index 22137c0173..db3b4359b2 100644 --- a/frontend/src/test/scala/bloop/bsp/TestConstants.scala +++ b/frontend/src/test/scala/bloop/bsp/TestConstants.scala @@ -18,8 +18,8 @@ object TestConstants { "dependencySourcesProvider": true, "resourcesProvider": true, "buildTargetChangedProvider": false, - "jvmTestEnvironmentProvider": true, "jvmRunEnvironmentProvider": true, + "jvmTestEnvironmentProvider": true, "canReload": false } }, diff --git a/frontend/src/test/scala/bloop/dap/DebugProtocolSpec.scala b/frontend/src/test/scala/bloop/dap/DebugProtocolSpec.scala index 3975b0b493..d58cebb64a 100644 --- a/frontend/src/test/scala/bloop/dap/DebugProtocolSpec.scala +++ b/frontend/src/test/scala/bloop/dap/DebugProtocolSpec.scala @@ -4,7 +4,6 @@ import java.nio.charset.StandardCharsets import java.nio.file.Files import ch.epfl.scala.bsp -import ch.epfl.scala.bsp.DebugSessionParamsDataKind._ import bloop.logging.RecordingLogger import bloop.util.TestProject @@ -176,9 +175,13 @@ object DebugProtocolSpec extends DebugBspBaseSuite { def mainClassParams(mainClass: String): bsp.BuildTargetIdentifier => bsp.DebugSessionParams = { target => val targets = List(target) - val data = bsp.ScalaMainClass(mainClass, Nil, Nil, Nil) + val data = bsp.ScalaMainClass(mainClass, Nil, Nil, None) val json = writeToArray[bsp.ScalaMainClass](data) - bsp.DebugSessionParams(targets, ScalaMainClass, RawJson(json)) + bsp.DebugSessionParams( + targets, + Some(bsp.DebugSessionParamsDataKind.ScalaMainClass), + Some(RawJson(json)) + ) } def testSuiteParams( @@ -187,6 +190,10 @@ object DebugProtocolSpec extends DebugBspBaseSuite { val targets = List(target) implicit val codec = JsonCodecMaker.make[List[String]] val json = writeToArray[List[String]](filters) - bsp.DebugSessionParams(targets, ScalaTestSuites, RawJson(json)) + bsp.DebugSessionParams( + targets, + Some(bsp.TestParamsDataKind.ScalaTestSuites), + Some(RawJson(json)) + ) } } diff --git a/frontend/src/test/scala/bloop/dap/DebugServerSpec.scala b/frontend/src/test/scala/bloop/dap/DebugServerSpec.scala index aa3ea4d562..6ca1da360c 100644 --- a/frontend/src/test/scala/bloop/dap/DebugServerSpec.scala +++ b/frontend/src/test/scala/bloop/dap/DebugServerSpec.scala @@ -18,8 +18,7 @@ import ch.epfl.scala.bsp.ScalaMainClass import ch.epfl.scala.debugadapter._ import bloop.ScalaInstance -import bloop.bsp.ScalaTestSuiteSelection -import bloop.bsp.ScalaTestSuites +import ch.epfl.scala.bsp import bloop.cli.ExitStatus import bloop.data.Platform import bloop.data.Project @@ -851,9 +850,9 @@ object DebugServerSpec extends DebugBspBaseSuite { loadBspStateWithTask(workspace, List(project), logger) { state => val testClasses = - ScalaTestSuites( + bsp.ScalaTestSuites( List( - ScalaTestSuiteSelection( + bsp.ScalaTestSuiteSelection( "MySuite", List("test1") ) @@ -979,7 +978,8 @@ object DebugServerSpec extends DebugBspBaseSuite { private def testRunner( project: TestProject, state: ManagedBspTestState, - testClasses: ScalaTestSuites = ScalaTestSuites(List("MySuite")) + testClasses: bsp.ScalaTestSuites = + bsp.ScalaTestSuites(List(bsp.ScalaTestSuiteSelection("MySuite", Nil)), Nil, Nil) ): Debuggee = { val testState = state.compile(project).toTestState BloopDebuggeeRunner.forTestSuite( @@ -1003,7 +1003,7 @@ object DebugServerSpec extends DebugBspBaseSuite { val testState = state.compile(project).toTestState BloopDebuggeeRunner.forMainClass( Seq(testState.getProjectFor(project)), - new ScalaMainClass("Main", arguments, jvmOptions, environmentVariables), + new ScalaMainClass("Main", arguments, jvmOptions, Some(environmentVariables)), testState.state, defaultScheduler ) match { diff --git a/launcher-test/src/test/scala/bloop/launcher/LauncherBaseSuite.scala b/launcher-test/src/test/scala/bloop/launcher/LauncherBaseSuite.scala index 7b49c59c3a..1bfd033770 100644 --- a/launcher-test/src/test/scala/bloop/launcher/LauncherBaseSuite.scala +++ b/launcher-test/src/test/scala/bloop/launcher/LauncherBaseSuite.scala @@ -249,17 +249,19 @@ abstract class LauncherBaseSuite( bspVersion, rootUri = bsp.Uri(Environment.cwd.toUri), capabilities = bsp.BuildClientCapabilities(List("scala")), + None, None ) ) for { + // Delay the task to let the bloop server go live initializeResult <- initializeServer - _ = lsClient.notify(endpoints.Build.initialized, bsp.InitializedBuildParams()) + _ = lsClient.notify(endpoints.Build.initialized, None) otherCalls <- runEndpoints(lsClient) - _ <- lsClient.request(endpoints.Build.shutdown, bsp.Shutdown()) - _ = lsClient.notify(endpoints.Build.exit, bsp.Exit()) + _ <- lsClient.request(endpoints.Build.shutdown, None) + _ = lsClient.notify(endpoints.Build.exit, None) } yield { closeForcibly(in) closeForcibly(out) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index fda0286b13..7a900ba52b 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -18,7 +18,7 @@ object Dependencies { // Keep in sync in BloopComponentCompiler val zincVersion = "1.9.3" - val bspVersion = "2.1.0-M5" + val bspVersion = "2.1.0-M6" val scalazVersion = "7.3.7" val lmVersion = "1.9.2"