diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index a4fee0b85..68332cd13 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -398,6 +398,7 @@ object Keys { val usePipelining = settingKey[Boolean]("Use subproject pipelining for compilation.").withRank(BSetting) val exportPipelining = settingKey[Boolean]("Product early output so downstream subprojects can do pipelining.").withRank(BSetting) + // BSP keys val bspConfig = taskKey[Unit]("Create or update the BSP connection files").withRank(DSetting) val bspEnabled = SettingKey[Boolean](BasicKeys.bspEnabled) val bspSbtEnabled = settingKey[Boolean]("Should BSP export meta-targets for the SBT build itself?") @@ -420,6 +421,11 @@ object Keys { val bspBuildTargetCleanCache = inputKey[Unit]("Corresponds to buildTarget/cleanCache request").withRank(DTask) val bspBuildTargetScalacOptions = inputKey[Unit]("").withRank(DTask) val bspBuildTargetScalacOptionsItem = taskKey[ScalacOptionsItem]("").withRank(DTask) + + val bspBuildTargetJVMRunEnvironment = inputKey[Unit]("Corresponds to the buildTarget/jvmRunEnvironment request").withRank(DTask) + val bspBuildTargetJVMTestEnvironment = inputKey[Unit]("Corresponds to the buildTarget/jvmTestEnvironment request").withRank(DTask) + val bspBuildTargetJvmEnvironmentItem = taskKey[JvmEnvironmentItem]("Computes JVM environment item").withRank(DTask) + val bspScalaTestClasses = inputKey[Unit]("Corresponds to buildTarget/scalaTestClasses request").withRank(DTask) val bspScalaTestClassesItem = taskKey[Seq[ScalaTestClassesItem]]("").withRank(DTask) val bspScalaMainClasses = inputKey[Unit]("Corresponds to buildTarget/scalaMainClasses request").withRank(DTask) diff --git a/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala b/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala index 1cfae2054..78ffa74f5 100644 --- a/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala +++ b/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala @@ -315,6 +315,31 @@ object BuildServerProtocol { bspBuildTargetCompileItem := bspCompileTask.value, bspBuildTargetRun := bspRunTask.evaluated, bspBuildTargetScalacOptionsItem := scalacOptionsTask.value, + bspBuildTargetJVMRunEnvironment := Def.inputTaskDyn { + val s = state.value + val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri))) + val workspace = bspFullWorkspace.value.filter(targets) + val filter = ScopeFilter.in(workspace.scopes.values.toList) + Def.task { + val items = bspBuildTargetJvmEnvironmentItem.result.all(filter).value + val successfulItems = anyOrThrow(items) + val result = JvmRunEnvironmentResult(successfulItems.toVector, None) + s.respondEvent(result) + } + }.evaluated, + bspBuildTargetJVMTestEnvironment := Def.inputTaskDyn { + val s = state.value + val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri))) + val workspace = bspFullWorkspace.value.filter(targets) + val filter = ScopeFilter.in(workspace.scopes.values.toList) + Def.task { + val items = bspBuildTargetJvmEnvironmentItem.result.all(filter).value + val successfulItems = anyOrThrow(items) + val result = JvmTestEnvironmentResult(successfulItems.toVector, None) + s.respondEvent(result) + } + }.evaluated, + bspBuildTargetJvmEnvironmentItem := jvmEnvironmentItem().value, bspInternalDependencyConfigurations := internalDependencyConfigurationsSetting.value, bspScalaTestClassesItem := scalaTestClassesTask.value, bspScalaMainClassesItem := scalaMainClassesTask.value, @@ -344,6 +369,8 @@ object BuildServerProtocol { final val Run = "buildTarget/run" final val CleanCache = "buildTarget/cleanCache" final val ScalacOptions = "buildTarget/scalacOptions" + final val JvmRunEnvironment = "buildTarget/jvmRunEnvironment" + final val JvmTestEnvironment = "buildTarget/jvmTestEnvironment" final val ScalaTestClasses = "buildTarget/scalaTestClasses" final val ScalaMainClasses = "buildTarget/scalaMainClasses" final val Exit = "build/exit" @@ -443,6 +470,18 @@ object BuildServerProtocol { val command = Keys.bspBuildTargetScalacOptions.key val _ = callback.appendExec(s"$command $targets", Some(r.id)) + case r if r.method == Method.JvmRunEnvironment => + val param = Converter.fromJson[JvmRunEnvironmentParams](json(r)).get + val targets = param.targets.map(_.uri).mkString(" ") + val command = Keys.bspBuildTargetJVMRunEnvironment.key + val _ = callback.appendExec(s"$command $targets", Some(r.id)) + + case r if r.method == Method.JvmTestEnvironment => + val param = Converter.fromJson[JvmTestEnvironmentParams](json(r)).get + val targets = param.targets.map(_.uri).mkString(" ") + val command = Keys.bspBuildTargetJVMTestEnvironment.key + val _ = callback.appendExec(s"$command $targets", Some(r.id)) + case r if r.method == Method.ScalaTestClasses => val param = Converter.fromJson[ScalaTestClassesParams](json(r)).get val targets = param.targets.map(_.uri).mkString(" ") @@ -648,6 +687,33 @@ object BuildServerProtocol { ) } + private def jvmEnvironmentItem(): Initialize[Task[JvmEnvironmentItem]] = Def.taskDyn { + val target = Keys.bspTargetIdentifier.value + val baseDir = Keys.baseDirectory.value.toURI().toString() + val jvmOptions = Keys.javaOptions.value.toVector + val env = envVars.value + val externalDependencyClasspath = Keys.externalDependencyClasspath.value + + val internalDependencyClasspath = for { + (ref, configs) <- bspInternalDependencyConfigurations.value + config <- configs + } yield ref / config / Keys.classDirectory + + Def.task { + val classpath = + internalDependencyClasspath.join.value.distinct ++ + externalDependencyClasspath.map(_.data) + + JvmEnvironmentItem( + target, + classpath.map(_.toURI).toVector, + jvmOptions, + baseDir, + env + ) + } + } + private def scalacOptionsTask: Def.Initialize[Task[ScalacOptionsItem]] = Def.taskDyn { val target = Keys.bspTargetIdentifier.value val scalacOptions = Keys.scalacOptions.value @@ -878,6 +944,7 @@ object BuildServerProtocol { } } + // here private def scalaMainClassesTask: Initialize[Task[ScalaMainClassesItem]] = Def.task { val jvmOptions = Keys.javaOptions.value.toVector val mainClasses = Keys.discoveredMainClasses.value.map(