Merge pull request #6552 from samuelClarencTeads/bspBuildTargetResources

Bsp build target resources
This commit is contained in:
eugene yokota 2021-06-21 14:51:49 -04:00 committed by GitHub
commit 9274a3e365
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 275 additions and 13 deletions

View File

@ -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)

View File

@ -42,6 +42,7 @@ object BuildServerProtocol {
TestProvider(BuildServerConnection.languages),
RunProvider(BuildServerConnection.languages),
dependencySourcesProvider = true,
resourcesProvider = true,
canReload = true
)
@ -117,6 +118,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 +215,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 +345,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 = {

View File

@ -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))
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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()
}

View File

@ -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

View File

@ -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()
}
}
}

View File

@ -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()
}
}
}

View File

@ -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()
}
}
}

View File

@ -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
@ -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]
}

View File

@ -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""")
})
}
@ -200,6 +201,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",