From 56632c389357e6caa1e358e163f85b4d47339e0f Mon Sep 17 00:00:00 2001 From: Samuel CLARENC Date: Thu, 17 Jun 2021 10:12:54 +0200 Subject: [PATCH 1/3] Add resources items to BSP contra --- .../sbt/internal/bsp/ResourcesItem.scala | 37 +++++++++++++++++++ .../sbt/internal/bsp/ResourcesParams.scala | 32 ++++++++++++++++ .../sbt/internal/bsp/ResourcesResult.scala | 33 +++++++++++++++++ .../sbt/internal/bsp/codec/JsonProtocol.scala | 3 ++ .../bsp/codec/ResourcesItemFormats.scala | 29 +++++++++++++++ .../bsp/codec/ResourcesParamsFormats.scala | 27 ++++++++++++++ .../bsp/codec/ResourcesResultFormats.scala | 27 ++++++++++++++ protocol/src/main/contraband/bsp.contra | 23 ++++++++++-- 8 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesItem.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesParams.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesResult.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesItemFormats.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesParamsFormats.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesResultFormats.scala diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesItem.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesItem.scala new file mode 100644 index 000000000..62ded2c9c --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesItem.scala @@ -0,0 +1,37 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp +/** @param resources List of resource files. */ +final class ResourcesItem private ( + val target: sbt.internal.bsp.BuildTargetIdentifier, + val resources: Vector[java.net.URI]) extends Serializable { + + + + override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match { + case x: ResourcesItem => (this.target == x.target) && (this.resources == x.resources) + case _ => false + }) + override def hashCode: Int = { + 37 * (37 * (37 * (17 + "sbt.internal.bsp.ResourcesItem".##) + target.##) + resources.##) + } + override def toString: String = { + "ResourcesItem(" + target + ", " + resources + ")" + } + private[this] def copy(target: sbt.internal.bsp.BuildTargetIdentifier = target, resources: Vector[java.net.URI] = resources): ResourcesItem = { + new ResourcesItem(target, resources) + } + def withTarget(target: sbt.internal.bsp.BuildTargetIdentifier): ResourcesItem = { + copy(target = target) + } + def withResources(resources: Vector[java.net.URI]): ResourcesItem = { + copy(resources = resources) + } +} +object ResourcesItem { + + def apply(target: sbt.internal.bsp.BuildTargetIdentifier, resources: Vector[java.net.URI]): ResourcesItem = new ResourcesItem(target, resources) +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesParams.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesParams.scala new file mode 100644 index 000000000..5233135e5 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesParams.scala @@ -0,0 +1,32 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp +final class ResourcesParams private ( + val targets: Vector[sbt.internal.bsp.BuildTargetIdentifier]) extends Serializable { + + + + override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match { + case x: ResourcesParams => (this.targets == x.targets) + case _ => false + }) + override def hashCode: Int = { + 37 * (37 * (17 + "sbt.internal.bsp.ResourcesParams".##) + targets.##) + } + override def toString: String = { + "ResourcesParams(" + targets + ")" + } + private[this] def copy(targets: Vector[sbt.internal.bsp.BuildTargetIdentifier] = targets): ResourcesParams = { + new ResourcesParams(targets) + } + def withTargets(targets: Vector[sbt.internal.bsp.BuildTargetIdentifier]): ResourcesParams = { + copy(targets = targets) + } +} +object ResourcesParams { + + def apply(targets: Vector[sbt.internal.bsp.BuildTargetIdentifier]): ResourcesParams = new ResourcesParams(targets) +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesResult.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesResult.scala new file mode 100644 index 000000000..ac6063d13 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/ResourcesResult.scala @@ -0,0 +1,33 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp +/** Build Target Resources response */ +final class ResourcesResult private ( + val items: Vector[sbt.internal.bsp.ResourcesItem]) extends Serializable { + + + + override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match { + case x: ResourcesResult => (this.items == x.items) + case _ => false + }) + override def hashCode: Int = { + 37 * (37 * (17 + "sbt.internal.bsp.ResourcesResult".##) + items.##) + } + override def toString: String = { + "ResourcesResult(" + items + ")" + } + private[this] def copy(items: Vector[sbt.internal.bsp.ResourcesItem] = items): ResourcesResult = { + new ResourcesResult(items) + } + def withItems(items: Vector[sbt.internal.bsp.ResourcesItem]): ResourcesResult = { + copy(items = items) + } +} +object ResourcesResult { + + def apply(items: Vector[sbt.internal.bsp.ResourcesItem]): ResourcesResult = new ResourcesResult(items) +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/JsonProtocol.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/JsonProtocol.scala index a5fd68958..6f606599f 100644 --- a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/JsonProtocol.scala +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/JsonProtocol.scala @@ -57,4 +57,7 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol with sbt.internal.bsp.codec.ScalaMainClassFormats with sbt.internal.bsp.codec.ScalaMainClassesItemFormats with sbt.internal.bsp.codec.ScalaMainClassesResultFormats + with sbt.internal.bsp.codec.ResourcesParamsFormats + with sbt.internal.bsp.codec.ResourcesItemFormats + with sbt.internal.bsp.codec.ResourcesResultFormats object JsonProtocol extends JsonProtocol \ No newline at end of file diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesItemFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesItemFormats.scala new file mode 100644 index 000000000..5852c98a9 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesItemFormats.scala @@ -0,0 +1,29 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp.codec +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } +trait ResourcesItemFormats { self: sbt.internal.bsp.codec.BuildTargetIdentifierFormats with sjsonnew.BasicJsonProtocol => +implicit lazy val ResourcesItemFormat: JsonFormat[sbt.internal.bsp.ResourcesItem] = new JsonFormat[sbt.internal.bsp.ResourcesItem] { + override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.ResourcesItem = { + __jsOpt match { + case Some(__js) => + unbuilder.beginObject(__js) + val target = unbuilder.readField[sbt.internal.bsp.BuildTargetIdentifier]("target") + val resources = unbuilder.readField[Vector[java.net.URI]]("resources") + unbuilder.endObject() + sbt.internal.bsp.ResourcesItem(target, resources) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.bsp.ResourcesItem, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("target", obj.target) + builder.addField("resources", obj.resources) + builder.endObject() + } +} +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesParamsFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesParamsFormats.scala new file mode 100644 index 000000000..1f07a52b3 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesParamsFormats.scala @@ -0,0 +1,27 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp.codec +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } +trait ResourcesParamsFormats { self: sbt.internal.bsp.codec.BuildTargetIdentifierFormats with sjsonnew.BasicJsonProtocol => +implicit lazy val ResourcesParamsFormat: JsonFormat[sbt.internal.bsp.ResourcesParams] = new JsonFormat[sbt.internal.bsp.ResourcesParams] { + override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.ResourcesParams = { + __jsOpt match { + case Some(__js) => + unbuilder.beginObject(__js) + val targets = unbuilder.readField[Vector[sbt.internal.bsp.BuildTargetIdentifier]]("targets") + unbuilder.endObject() + sbt.internal.bsp.ResourcesParams(targets) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.bsp.ResourcesParams, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("targets", obj.targets) + builder.endObject() + } +} +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesResultFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesResultFormats.scala new file mode 100644 index 000000000..6add5e459 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ResourcesResultFormats.scala @@ -0,0 +1,27 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp.codec +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } +trait ResourcesResultFormats { self: sbt.internal.bsp.codec.ResourcesItemFormats with sjsonnew.BasicJsonProtocol => +implicit lazy val ResourcesResultFormat: JsonFormat[sbt.internal.bsp.ResourcesResult] = new JsonFormat[sbt.internal.bsp.ResourcesResult] { + override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.ResourcesResult = { + __jsOpt match { + case Some(__js) => + unbuilder.beginObject(__js) + val items = unbuilder.readField[Vector[sbt.internal.bsp.ResourcesItem]]("items") + unbuilder.endObject() + sbt.internal.bsp.ResourcesResult(items) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.bsp.ResourcesResult, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("items", obj.items) + builder.endObject() + } +} +} diff --git a/protocol/src/main/contraband/bsp.contra b/protocol/src/main/contraband/bsp.contra index 4741cb738..568330499 100644 --- a/protocol/src/main/contraband/bsp.contra +++ b/protocol/src/main/contraband/bsp.contra @@ -342,11 +342,11 @@ type TaskFinishParams { type CompileParams { ## A sequence of build targets to compile targets: [sbt.internal.bsp.BuildTargetIdentifier] - + ## An optional unique identifier generated by the client to identify this request. ## The server may include this id in triggered notifications or response. originId: String - + ## Optional arguments to the compilation process arguments: [String] } @@ -355,7 +355,7 @@ type CompileParams { type BspCompileResult { ## An optional request id to know the origin of this report. originId: String - + ## A status code for the execution. statusCode: Int! @@ -635,3 +635,20 @@ type ScalaMainClass { ## Additional environment variables for the application. environmentVariables: [String] } + +# Resources Param + +type ResourcesParams { + targets: [sbt.internal.bsp.BuildTargetIdentifier] +} + +## Build Target Resources response +type ResourcesResult { + items: [sbt.internal.bsp.ResourcesItem] +} + +type ResourcesItem { + target: sbt.internal.bsp.BuildTargetIdentifier! + ## List of resource files. + resources: [java.net.URI] +} From a0e3d8985540f8aa45b03b9aa092e8b776dd536c Mon Sep 17 00:00:00 2001 From: Samuel CLARENC Date: Thu, 17 Jun 2021 11:09:08 +0200 Subject: [PATCH 2/3] Implement BSP buildTarget/resources command --- main/src/main/scala/sbt/Keys.scala | 2 ++ .../internal/server/BuildServerProtocol.scala | 31 +++++++++++++++++++ .../test/scala/testpkg/BuildServerTest.scala | 13 ++++++++ 3 files changed, 46 insertions(+) diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index bd2075346..33f4d628d 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -405,6 +405,8 @@ object Keys { val bspBuildTarget = taskKey[BuildTarget]("Description of the BSP build targets").withRank(DTask) val bspBuildTargetSources = inputKey[Unit]("").withRank(DTask) val bspBuildTargetSourcesItem = taskKey[SourcesItem]("").withRank(DTask) + val bspBuildTargetResources = inputKey[Unit]("").withRank(DTask) + val bspBuildTargetResourcesItem = taskKey[ResourcesItem]("").withRank(DTask) val bspBuildTargetDependencySources = inputKey[Unit]("").withRank(DTask) val bspBuildTargetDependencySourcesItem = taskKey[DependencySourcesItem]("").withRank(DTask) val bspBuildTargetCompile = inputKey[Unit]("").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 9a4acba8d..dd3b68bf9 100644 --- a/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala +++ b/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala @@ -117,6 +117,19 @@ object BuildServerProtocol { } }.evaluated, bspBuildTargetSources / aggregate := false, + bspBuildTargetResources := Def.inputTaskDyn { + val s = state.value + val workspace = bspWorkspace.value + val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri))) + val filter = ScopeFilter.in(targets.map(workspace)) + // run the worker task concurrently + Def.task { + val items = bspBuildTargetResourcesItem.all(filter).value + val result = ResourcesResult(items.toVector) + s.respondEvent(result) + } + }.evaluated, + bspBuildTargetResources / aggregate := false, bspBuildTargetDependencySources := Def.inputTaskDyn { val s = state.value val workspace = bspWorkspace.value @@ -201,6 +214,18 @@ object BuildServerProtocol { }) SourcesItem(id, items) }, + bspBuildTargetResourcesItem := { + val id = bspTargetIdentifier.value + // Trigger resource generation + val _ = managedResources.value + val uris = resourceDirectories.value.toVector + .map { resourceDirectory => + // Add any missing ending slash to the URI to explicitly mark it as a directory + // See https://github.com/build-server-protocol/build-server-protocol/issues/181 for more information + URI.create(s"${resourceDirectory.toURI.toString.replaceAll("([^/])$", "$1/")}") + } + ResourcesItem(id, uris) + }, bspBuildTargetDependencySourcesItem := dependencySourcesItemTask.value, bspBuildTargetCompileItem := bspCompileTask.value, bspBuildTargetRun := bspRunTask.evaluated, @@ -319,6 +344,12 @@ object BuildServerProtocol { val targets = param.targets.map(_.uri).mkString(" ") val command = Keys.bspScalaMainClasses.key val _ = callback.appendExec(s"$command $targets", Some(r.id)) + + case r if r.method == "buildTarget/resources" => + val param = Converter.fromJson[ResourcesParams](json(r)).get + val targets = param.targets.map(_.uri).mkString(" ") + val command = Keys.bspBuildTargetResources.key + val _ = callback.appendExec(s"$command $targets", Some(r.id)) }, onResponse = PartialFunction.empty, onNotification = { diff --git a/server-test/src/test/scala/testpkg/BuildServerTest.scala b/server-test/src/test/scala/testpkg/BuildServerTest.scala index e4c42c4fd..48c26658a 100644 --- a/server-test/src/test/scala/testpkg/BuildServerTest.scala +++ b/server-test/src/test/scala/testpkg/BuildServerTest.scala @@ -200,6 +200,19 @@ object BuildServerTest extends AbstractServerTest { }) } + test("buildTarget/resources") { _ => + val x = s"${svr.baseDirectory.getAbsoluteFile.toURI}#util/Compile" + svr.sendJsonRpc( + s"""{ "jsonrpc": "2.0", "id": "23", "method": "buildTarget/resources", "params": { + | "targets": [{ "uri": "$x" }] + |} }""".stripMargin + ) + assert(processing("buildTarget/resources")) + assert(svr.waitForString(10.seconds) { s => + (s contains """"id":"23"""") && (s contains "util/src/main/resources/") + }) + } + private def initializeRequest(): Unit = { svr.sendJsonRpc( """{ "jsonrpc": "2.0", "id": "10", "method": "build/initialize", From f3ec202a06f66e4ffa5b33115bcc26c3e2c14bc3 Mon Sep 17 00:00:00 2001 From: Samuel CLARENC Date: Thu, 17 Jun 2021 13:55:45 +0200 Subject: [PATCH 3/3] Add resourcesProvider flag to BuildServerCapabilities in BSP contra --- .../internal/server/BuildServerProtocol.scala | 1 + .../bsp/BuildServerCapabilities.scala | 21 ++++++++++++------- .../BuildServerCapabilitiesFormats.scala | 4 +++- protocol/src/main/contraband/bsp.contra | 2 +- .../test/scala/testpkg/BuildServerTest.scala | 3 ++- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala b/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala index dd3b68bf9..8f4f6164b 100644 --- a/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala +++ b/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala @@ -42,6 +42,7 @@ object BuildServerProtocol { TestProvider(BuildServerConnection.languages), RunProvider(BuildServerConnection.languages), dependencySourcesProvider = true, + resourcesProvider = true, canReload = true ) diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/BuildServerCapabilities.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/BuildServerCapabilities.scala index c9a08fee8..ccb10343c 100644 --- a/protocol/src/main/contraband-scala/sbt/internal/bsp/BuildServerCapabilities.scala +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/BuildServerCapabilities.scala @@ -16,22 +16,23 @@ final class BuildServerCapabilities private ( val testProvider: Option[sbt.internal.bsp.TestProvider], val runProvider: Option[sbt.internal.bsp.RunProvider], val dependencySourcesProvider: Option[Boolean], + val resourcesProvider: Option[Boolean], val canReload: Option[Boolean]) extends Serializable { override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match { - case x: BuildServerCapabilities => (this.compileProvider == x.compileProvider) && (this.testProvider == x.testProvider) && (this.runProvider == x.runProvider) && (this.dependencySourcesProvider == x.dependencySourcesProvider) && (this.canReload == x.canReload) + case x: BuildServerCapabilities => (this.compileProvider == x.compileProvider) && (this.testProvider == x.testProvider) && (this.runProvider == x.runProvider) && (this.dependencySourcesProvider == x.dependencySourcesProvider) && (this.resourcesProvider == x.resourcesProvider) && (this.canReload == x.canReload) case _ => false }) override def hashCode: Int = { - 37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.BuildServerCapabilities".##) + compileProvider.##) + testProvider.##) + runProvider.##) + dependencySourcesProvider.##) + canReload.##) + 37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.BuildServerCapabilities".##) + compileProvider.##) + testProvider.##) + runProvider.##) + dependencySourcesProvider.##) + resourcesProvider.##) + canReload.##) } override def toString: String = { - "BuildServerCapabilities(" + compileProvider + ", " + testProvider + ", " + runProvider + ", " + dependencySourcesProvider + ", " + canReload + ")" + "BuildServerCapabilities(" + compileProvider + ", " + testProvider + ", " + runProvider + ", " + dependencySourcesProvider + ", " + resourcesProvider + ", " + canReload + ")" } - private[this] def copy(compileProvider: Option[sbt.internal.bsp.CompileProvider] = compileProvider, testProvider: Option[sbt.internal.bsp.TestProvider] = testProvider, runProvider: Option[sbt.internal.bsp.RunProvider] = runProvider, dependencySourcesProvider: Option[Boolean] = dependencySourcesProvider, canReload: Option[Boolean] = canReload): BuildServerCapabilities = { - new BuildServerCapabilities(compileProvider, testProvider, runProvider, dependencySourcesProvider, canReload) + private[this] def copy(compileProvider: Option[sbt.internal.bsp.CompileProvider] = compileProvider, testProvider: Option[sbt.internal.bsp.TestProvider] = testProvider, runProvider: Option[sbt.internal.bsp.RunProvider] = runProvider, dependencySourcesProvider: Option[Boolean] = dependencySourcesProvider, resourcesProvider: Option[Boolean] = resourcesProvider, canReload: Option[Boolean] = canReload): BuildServerCapabilities = { + new BuildServerCapabilities(compileProvider, testProvider, runProvider, dependencySourcesProvider, resourcesProvider, canReload) } def withCompileProvider(compileProvider: Option[sbt.internal.bsp.CompileProvider]): BuildServerCapabilities = { copy(compileProvider = compileProvider) @@ -57,6 +58,12 @@ final class BuildServerCapabilities private ( def withDependencySourcesProvider(dependencySourcesProvider: Boolean): BuildServerCapabilities = { copy(dependencySourcesProvider = Option(dependencySourcesProvider)) } + def withResourcesProvider(resourcesProvider: Option[Boolean]): BuildServerCapabilities = { + copy(resourcesProvider = resourcesProvider) + } + def withResourcesProvider(resourcesProvider: Boolean): BuildServerCapabilities = { + copy(resourcesProvider = Option(resourcesProvider)) + } def withCanReload(canReload: Option[Boolean]): BuildServerCapabilities = { copy(canReload = canReload) } @@ -66,6 +73,6 @@ final class BuildServerCapabilities private ( } object BuildServerCapabilities { - def apply(compileProvider: Option[sbt.internal.bsp.CompileProvider], testProvider: Option[sbt.internal.bsp.TestProvider], runProvider: Option[sbt.internal.bsp.RunProvider], dependencySourcesProvider: Option[Boolean], canReload: Option[Boolean]): BuildServerCapabilities = new BuildServerCapabilities(compileProvider, testProvider, runProvider, dependencySourcesProvider, canReload) - def apply(compileProvider: sbt.internal.bsp.CompileProvider, testProvider: sbt.internal.bsp.TestProvider, runProvider: sbt.internal.bsp.RunProvider, dependencySourcesProvider: Boolean, canReload: Boolean): BuildServerCapabilities = new BuildServerCapabilities(Option(compileProvider), Option(testProvider), Option(runProvider), Option(dependencySourcesProvider), Option(canReload)) + def apply(compileProvider: Option[sbt.internal.bsp.CompileProvider], testProvider: Option[sbt.internal.bsp.TestProvider], runProvider: Option[sbt.internal.bsp.RunProvider], dependencySourcesProvider: Option[Boolean], resourcesProvider: Option[Boolean], canReload: Option[Boolean]): BuildServerCapabilities = new BuildServerCapabilities(compileProvider, testProvider, runProvider, dependencySourcesProvider, resourcesProvider, canReload) + def apply(compileProvider: sbt.internal.bsp.CompileProvider, testProvider: sbt.internal.bsp.TestProvider, runProvider: sbt.internal.bsp.RunProvider, dependencySourcesProvider: Boolean, resourcesProvider: Boolean, canReload: Boolean): BuildServerCapabilities = new BuildServerCapabilities(Option(compileProvider), Option(testProvider), Option(runProvider), Option(dependencySourcesProvider), Option(resourcesProvider), Option(canReload)) } diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/BuildServerCapabilitiesFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/BuildServerCapabilitiesFormats.scala index 37211376a..0947bd565 100644 --- a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/BuildServerCapabilitiesFormats.scala +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/BuildServerCapabilitiesFormats.scala @@ -15,9 +15,10 @@ implicit lazy val BuildServerCapabilitiesFormat: JsonFormat[sbt.internal.bsp.Bui val testProvider = unbuilder.readField[Option[sbt.internal.bsp.TestProvider]]("testProvider") val runProvider = unbuilder.readField[Option[sbt.internal.bsp.RunProvider]]("runProvider") val dependencySourcesProvider = unbuilder.readField[Option[Boolean]]("dependencySourcesProvider") + val resourcesProvider = unbuilder.readField[Option[Boolean]]("resourcesProvider") val canReload = unbuilder.readField[Option[Boolean]]("canReload") unbuilder.endObject() - sbt.internal.bsp.BuildServerCapabilities(compileProvider, testProvider, runProvider, dependencySourcesProvider, canReload) + sbt.internal.bsp.BuildServerCapabilities(compileProvider, testProvider, runProvider, dependencySourcesProvider, resourcesProvider, canReload) case None => deserializationError("Expected JsObject but found None") } @@ -28,6 +29,7 @@ implicit lazy val BuildServerCapabilitiesFormat: JsonFormat[sbt.internal.bsp.Bui builder.addField("testProvider", obj.testProvider) builder.addField("runProvider", obj.runProvider) builder.addField("dependencySourcesProvider", obj.dependencySourcesProvider) + builder.addField("resourcesProvider", obj.resourcesProvider) builder.addField("canReload", obj.canReload) builder.endObject() } diff --git a/protocol/src/main/contraband/bsp.contra b/protocol/src/main/contraband/bsp.contra index 568330499..02b0626bb 100644 --- a/protocol/src/main/contraband/bsp.contra +++ b/protocol/src/main/contraband/bsp.contra @@ -200,7 +200,7 @@ type BuildServerCapabilities { # The server provides all the resource dependencies # via method buildTarget/resources - # resourcesProvider: Boolean + resourcesProvider: Boolean ## Reloading the workspace state through workspace/reload is supported canReload: Boolean diff --git a/server-test/src/test/scala/testpkg/BuildServerTest.scala b/server-test/src/test/scala/testpkg/BuildServerTest.scala index 48c26658a..88bf7a6cf 100644 --- a/server-test/src/test/scala/testpkg/BuildServerTest.scala +++ b/server-test/src/test/scala/testpkg/BuildServerTest.scala @@ -16,7 +16,8 @@ object BuildServerTest extends AbstractServerTest { test("build/initialize") { _ => initializeRequest() assert(svr.waitForString(10.seconds) { s => - s contains """"id":"10"""" + (s contains """"id":"10"""") && + (s contains """"resourcesProvider":true""") }) }