Add BSP buildTarget/run endpoint

This commit is contained in:
Adrien Piquerez 2020-09-17 11:52:42 +02:00
parent 92fb69f370
commit 9f04358fce
13 changed files with 460 additions and 66 deletions

View File

@ -412,8 +412,13 @@ object Defaults extends BuildCommon {
fullServerHandlers := {
Seq(
LanguageServerProtocol.handler(fileConverter.value),
BuildServerProtocol
.handler(sbtVersion.value, semanticdbEnabled.value, semanticdbVersion.value),
BuildServerProtocol.handler(
loadedBuild.value,
bspWorkspace.value,
sbtVersion.value,
semanticdbEnabled.value,
semanticdbVersion.value
),
VirtualTerminal.handler,
) ++ serverHandlers.value :+ ServerHandler.fallback
},

View File

@ -398,6 +398,7 @@ object Keys {
val bspBuildTargetDependencySourcesItem = taskKey[DependencySourcesItem]("").withRank(DTask)
val bspBuildTargetCompile = inputKey[Unit]("").withRank(DTask)
val bspBuildTargetCompileItem = taskKey[Int]("").withRank(DTask)
val bspBuildTargetRun = inputKey[Unit]("Corresponds to buildTarget/run request").withRank(DTask)
val bspBuildTargetScalacOptions = inputKey[Unit]("").withRank(DTask)
val bspBuildTargetScalacOptionsItem = taskKey[ScalacOptionsItem]("").withRank(DTask)
val bspScalaMainClasses = inputKey[Unit]("Corresponds to buildTarget/scalaMainClasses request").withRank(DTask)

View File

@ -21,12 +21,14 @@ import sbt.StandardMain.exchange
import sbt.internal.bsp._
import sbt.internal.langserver.ErrorCodes
import sbt.internal.protocol.JsonRpcRequestMessage
import sbt.internal.util.Attributed
import sbt.internal.util.complete.{ Parser, Parsers }
import sbt.librarymanagement.Configuration
import sbt.util.Logger
import sjsonnew.shaded.scalajson.ast.unsafe.JNull
import sjsonnew.shaded.scalajson.ast.unsafe.JValue
import sjsonnew.support.scalajson.unsafe.Converter
import sjsonnew.shaded.scalajson.ast.unsafe.{ JNull, JValue }
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter, Parser => JsonParser }
import scala.util.{ Failure, Success }
import scala.util.control.NonFatal
object BuildServerProtocol {
@ -34,6 +36,7 @@ object BuildServerProtocol {
private val capabilities = BuildServerCapabilities(
CompileProvider(BuildServerConnection.languages),
RunProvider(BuildServerConnection.languages),
dependencySourcesProvider = true,
canReload = true
)
@ -174,76 +177,106 @@ object BuildServerProtocol {
},
bspBuildTargetDependencySourcesItem := dependencySourcesItemTask.value,
bspBuildTargetCompileItem := bspCompileTask.value,
bspBuildTargetRun := bspRunTask.evaluated,
bspBuildTargetScalacOptionsItem := scalacOptionsTask.value,
bspInternalDependencyConfigurations := internalDependencyConfigurationsSetting.value,
bspScalaMainClassesItem := scalaMainClassesTask.value
)
def handler(
loadedBuild: LoadedBuild,
workspace: Map[BuildTargetIdentifier, Scope],
sbtVersion: String,
semanticdbEnabled: Boolean,
semanticdbVersion: String
): ServerHandler = ServerHandler { callback =>
ServerIntent(
onRequest = {
case r: JsonRpcRequestMessage if r.method == "build/initialize" =>
val params = Converter.fromJson[InitializeBuildParams](json(r)).get
checkMetalsCompatibility(semanticdbEnabled, semanticdbVersion, params, callback.log)
): ServerHandler = {
val configurationMap: Map[ConfigKey, Configuration] =
loadedBuild.allProjectRefs
.flatMap { case (_, p) => p.configurations }
.distinct
.map(c => ConfigKey(c.name) -> c)
.toMap
ServerHandler { callback =>
ServerIntent(
onRequest = {
case r: JsonRpcRequestMessage if r.method == "build/initialize" =>
val params = Converter.fromJson[InitializeBuildParams](json(r)).get
checkMetalsCompatibility(semanticdbEnabled, semanticdbVersion, params, callback.log)
val response = InitializeBuildResult(
"sbt",
sbtVersion,
BuildServerConnection.bspVersion,
capabilities,
None
)
callback.jsonRpcRespond(response, Some(r.id)); ()
val response = InitializeBuildResult(
"sbt",
sbtVersion,
BuildServerConnection.bspVersion,
capabilities,
None
)
callback.jsonRpcRespond(response, Some(r.id)); ()
case r: JsonRpcRequestMessage if r.method == "workspace/buildTargets" =>
val _ = callback.appendExec(Keys.bspWorkspaceBuildTargets.key.toString, Some(r.id))
case r: JsonRpcRequestMessage if r.method == "workspace/buildTargets" =>
val _ = callback.appendExec(Keys.bspWorkspaceBuildTargets.key.toString, Some(r.id))
case r: JsonRpcRequestMessage if r.method == "workspace/reload" =>
val _ = callback.appendExec(s"$bspReload ${r.id}", None)
case r: JsonRpcRequestMessage if r.method == "workspace/reload" =>
val _ = callback.appendExec(s"$bspReload ${r.id}", None)
case r: JsonRpcRequestMessage if r.method == "build/shutdown" =>
()
case r: JsonRpcRequestMessage if r.method == "build/shutdown" =>
()
case r: JsonRpcRequestMessage if r.method == "build/exit" =>
val _ = callback.appendExec(Shutdown, Some(r.id))
case r: JsonRpcRequestMessage if r.method == "build/exit" =>
val _ = callback.appendExec(Shutdown, Some(r.id))
case r: JsonRpcRequestMessage if r.method == "buildTarget/sources" =>
val param = Converter.fromJson[SourcesParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspBuildTargetSources.key
val _ = callback.appendExec(s"$command $targets", Some(r.id))
case r: JsonRpcRequestMessage if r.method == "buildTarget/sources" =>
val param = Converter.fromJson[SourcesParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspBuildTargetSources.key
val _ = callback.appendExec(s"$command $targets", Some(r.id))
case r if r.method == "buildTarget/dependencySources" =>
val param = Converter.fromJson[DependencySourcesParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspBuildTargetDependencySources.key
val _ = callback.appendExec(s"$command $targets", Some(r.id))
case r if r.method == "buildTarget/dependencySources" =>
val param = Converter.fromJson[DependencySourcesParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspBuildTargetDependencySources.key
val _ = callback.appendExec(s"$command $targets", Some(r.id))
case r if r.method == "buildTarget/compile" =>
val param = Converter.fromJson[CompileParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspBuildTargetCompile.key
val _ = callback.appendExec(s"$command $targets", Some(r.id))
case r if r.method == "buildTarget/compile" =>
val param = Converter.fromJson[CompileParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspBuildTargetCompile.key
val _ = callback.appendExec(s"$command $targets", Some(r.id))
case r: JsonRpcRequestMessage if r.method == "buildTarget/scalacOptions" =>
val param = Converter.fromJson[ScalacOptionsParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspBuildTargetScalacOptions.key
val _ = callback.appendExec(s"$command $targets", Some(r.id))
case r if r.method == "buildTarget/run" =>
val paramJson = json(r)
val param = Converter.fromJson[RunParams](json(r)).get
val scope = workspace.getOrElse(
param.target,
throw LangServerError(
ErrorCodes.InvalidParams,
s"'${param.target}' is not a valid build target identifier"
)
)
val project = scope.project.toOption.get.asInstanceOf[ProjectRef].project
val config = configurationMap(scope.config.toOption.get).id
val task = bspBuildTargetRun.key
val paramStr = CompactPrinter(paramJson)
val _ = callback.appendExec(
s"$project / $config / $task $paramStr",
Some(r.id)
)
case r: JsonRpcRequestMessage if r.method == "buildTarget/scalaMainClasses" =>
val param = Converter.fromJson[ScalacOptionsParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspScalaMainClasses.key
val _ = callback.appendExec(s"$command $targets", Some(r.id))
},
onResponse = PartialFunction.empty,
onNotification = PartialFunction.empty,
)
case r: JsonRpcRequestMessage if r.method == "buildTarget/scalacOptions" =>
val param = Converter.fromJson[ScalacOptionsParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspBuildTargetScalacOptions.key
val _ = callback.appendExec(s"$command $targets", Some(r.id))
case r: JsonRpcRequestMessage if r.method == "buildTarget/scalaMainClasses" =>
val param = Converter.fromJson[ScalaMainClassesParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspScalaMainClasses.key
val _ = callback.appendExec(s"$command $targets", Some(r.id))
},
onResponse = PartialFunction.empty,
onNotification = PartialFunction.empty,
)
}
}
private def checkMetalsCompatibility(
@ -398,6 +431,73 @@ object BuildServerProtocol {
}
}
private val jsonParser: Parser[JValue] = (Parsers.any *)
.map(_.mkString)
.map(JsonParser.parseUnsafe)
private def bspRunTask: Def.Initialize[InputTask[Unit]] = Def.inputTaskDyn {
val runParams = jsonParser.map(json => Converter.fromJson[RunParams](json).get).parsed
val defaultClass = Keys.mainClass.value
val defaultJvmOptions = Keys.javaOptions.value
val mainClass = runParams.dataKind match {
case Some("scala-main-class") =>
val data = runParams.data.getOrElse(JNull)
Converter.fromJson[ScalaMainClass](data) match {
case Failure(e) =>
throw LangServerError(
ErrorCodes.ParseError,
e.getMessage
)
case Success(value) => value
}
case Some(dataKind) =>
throw LangServerError(
ErrorCodes.InvalidParams,
s"Unexpected data of kind '$dataKind', 'scala-main-class' is expected"
)
case None =>
ScalaMainClass(
defaultClass.getOrElse(
throw LangServerError(
ErrorCodes.InvalidParams,
"No default main class is defined"
)
),
runParams.arguments,
defaultJvmOptions.toVector
)
}
runMainClassTask(mainClass, runParams.originId)
}
private def runMainClassTask(mainClass: ScalaMainClass, originId: Option[String]) = Def.task {
val state = Keys.state.value
val logger = Keys.streams.value.log
val classpath = Attributed.data(fullClasspath.value)
val forkOpts = ForkOptions(
javaHome = javaHome.value,
outputStrategy = outputStrategy.value,
// bootJars is empty by default because only jars on the user's classpath should be on the boot classpath
bootJars = Vector(),
workingDirectory = Some(baseDirectory.value),
runJVMOptions = mainClass.jvmOptions,
connectInput = connectInput.value,
envVars = envVars.value
)
val runner = new ForkRun(forkOpts)
val statusCode = runner
.run(mainClass.`class`, classpath, mainClass.arguments, logger)
.fold(
_ => StatusCode.Error,
_ => StatusCode.Success
)
state.respondEvent(RunResult(originId, statusCode))
}
private def internalDependencyConfigurationsSetting = Def.settingDyn {
val directDependencies = Keys.internalDependencyConfigurations.value.map {
case (project, rawConfigs) =>

View File

@ -12,23 +12,24 @@ package sbt.internal.bsp
*/
final class BuildServerCapabilities private (
val compileProvider: Option[sbt.internal.bsp.CompileProvider],
val runProvider: Option[sbt.internal.bsp.RunProvider],
val dependencySourcesProvider: Option[Boolean],
val canReload: Option[Boolean]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: BuildServerCapabilities => (this.compileProvider == x.compileProvider) && (this.dependencySourcesProvider == x.dependencySourcesProvider) && (this.canReload == x.canReload)
case x: BuildServerCapabilities => (this.compileProvider == x.compileProvider) && (this.runProvider == x.runProvider) && (this.dependencySourcesProvider == x.dependencySourcesProvider) && (this.canReload == x.canReload)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.BuildServerCapabilities".##) + compileProvider.##) + dependencySourcesProvider.##) + canReload.##)
37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.BuildServerCapabilities".##) + compileProvider.##) + runProvider.##) + dependencySourcesProvider.##) + canReload.##)
}
override def toString: String = {
"BuildServerCapabilities(" + compileProvider + ", " + dependencySourcesProvider + ", " + canReload + ")"
"BuildServerCapabilities(" + compileProvider + ", " + runProvider + ", " + dependencySourcesProvider + ", " + canReload + ")"
}
private[this] def copy(compileProvider: Option[sbt.internal.bsp.CompileProvider] = compileProvider, dependencySourcesProvider: Option[Boolean] = dependencySourcesProvider, canReload: Option[Boolean] = canReload): BuildServerCapabilities = {
new BuildServerCapabilities(compileProvider, dependencySourcesProvider, canReload)
private[this] def copy(compileProvider: Option[sbt.internal.bsp.CompileProvider] = compileProvider, runProvider: Option[sbt.internal.bsp.RunProvider] = runProvider, dependencySourcesProvider: Option[Boolean] = dependencySourcesProvider, canReload: Option[Boolean] = canReload): BuildServerCapabilities = {
new BuildServerCapabilities(compileProvider, runProvider, dependencySourcesProvider, canReload)
}
def withCompileProvider(compileProvider: Option[sbt.internal.bsp.CompileProvider]): BuildServerCapabilities = {
copy(compileProvider = compileProvider)
@ -36,6 +37,12 @@ final class BuildServerCapabilities private (
def withCompileProvider(compileProvider: sbt.internal.bsp.CompileProvider): BuildServerCapabilities = {
copy(compileProvider = Option(compileProvider))
}
def withRunProvider(runProvider: Option[sbt.internal.bsp.RunProvider]): BuildServerCapabilities = {
copy(runProvider = runProvider)
}
def withRunProvider(runProvider: sbt.internal.bsp.RunProvider): BuildServerCapabilities = {
copy(runProvider = Option(runProvider))
}
def withDependencySourcesProvider(dependencySourcesProvider: Option[Boolean]): BuildServerCapabilities = {
copy(dependencySourcesProvider = dependencySourcesProvider)
}
@ -51,6 +58,6 @@ final class BuildServerCapabilities private (
}
object BuildServerCapabilities {
def apply(compileProvider: Option[sbt.internal.bsp.CompileProvider], dependencySourcesProvider: Option[Boolean], canReload: Option[Boolean]): BuildServerCapabilities = new BuildServerCapabilities(compileProvider, dependencySourcesProvider, canReload)
def apply(compileProvider: sbt.internal.bsp.CompileProvider, dependencySourcesProvider: Boolean, canReload: Boolean): BuildServerCapabilities = new BuildServerCapabilities(Option(compileProvider), Option(dependencySourcesProvider), Option(canReload))
def apply(compileProvider: Option[sbt.internal.bsp.CompileProvider], runProvider: Option[sbt.internal.bsp.RunProvider], dependencySourcesProvider: Option[Boolean], canReload: Option[Boolean]): BuildServerCapabilities = new BuildServerCapabilities(compileProvider, runProvider, dependencySourcesProvider, canReload)
def apply(compileProvider: sbt.internal.bsp.CompileProvider, runProvider: sbt.internal.bsp.RunProvider, dependencySourcesProvider: Boolean, canReload: Boolean): BuildServerCapabilities = new BuildServerCapabilities(Option(compileProvider), Option(runProvider), Option(dependencySourcesProvider), Option(canReload))
}

View File

@ -0,0 +1,71 @@
/**
* This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.bsp
/**
* Run Request
* The run request is sent from the client to the server to run a build target.
* The server communicates during the initialize handshake whether this method is supported or not.
* An empty run request is valid.
* @param target The build target to run.
* @param originId An option identifier gnerated by the client to identify this request.
The server may include this id in triggered notifications or responses.
* @param arguments Optional arguments to the executed application.
* @param dataKind Kind of data to expect in the data field.
If this field is not set, the kind of data is not specified.
* @param data Language-specific metadata for this execution.
*/
final class RunParams private (
val target: sbt.internal.bsp.BuildTargetIdentifier,
val originId: Option[String],
val arguments: Vector[String],
val dataKind: Option[String],
val data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: RunParams => (this.target == x.target) && (this.originId == x.originId) && (this.arguments == x.arguments) && (this.dataKind == x.dataKind) && (this.data == x.data)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.RunParams".##) + target.##) + originId.##) + arguments.##) + dataKind.##) + data.##)
}
override def toString: String = {
"RunParams(" + target + ", " + originId + ", " + arguments + ", " + dataKind + ", " + data + ")"
}
private[this] def copy(target: sbt.internal.bsp.BuildTargetIdentifier = target, originId: Option[String] = originId, arguments: Vector[String] = arguments, dataKind: Option[String] = dataKind, data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue] = data): RunParams = {
new RunParams(target, originId, arguments, dataKind, data)
}
def withTarget(target: sbt.internal.bsp.BuildTargetIdentifier): RunParams = {
copy(target = target)
}
def withOriginId(originId: Option[String]): RunParams = {
copy(originId = originId)
}
def withOriginId(originId: String): RunParams = {
copy(originId = Option(originId))
}
def withArguments(arguments: Vector[String]): RunParams = {
copy(arguments = arguments)
}
def withDataKind(dataKind: Option[String]): RunParams = {
copy(dataKind = dataKind)
}
def withDataKind(dataKind: String): RunParams = {
copy(dataKind = Option(dataKind))
}
def withData(data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): RunParams = {
copy(data = data)
}
def withData(data: sjsonnew.shaded.scalajson.ast.unsafe.JValue): RunParams = {
copy(data = Option(data))
}
}
object RunParams {
def apply(target: sbt.internal.bsp.BuildTargetIdentifier, originId: Option[String], arguments: Vector[String], dataKind: Option[String], data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): RunParams = new RunParams(target, originId, arguments, dataKind, data)
def apply(target: sbt.internal.bsp.BuildTargetIdentifier, originId: String, arguments: Vector[String], dataKind: String, data: sjsonnew.shaded.scalajson.ast.unsafe.JValue): RunParams = new RunParams(target, Option(originId), arguments, Option(dataKind), Option(data))
}

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 RunProvider private (
val languageIds: Vector[String]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: RunProvider => (this.languageIds == x.languageIds)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (17 + "sbt.internal.bsp.RunProvider".##) + languageIds.##)
}
override def toString: String = {
"RunProvider(" + languageIds + ")"
}
private[this] def copy(languageIds: Vector[String] = languageIds): RunProvider = {
new RunProvider(languageIds)
}
def withLanguageIds(languageIds: Vector[String]): RunProvider = {
copy(languageIds = languageIds)
}
}
object RunProvider {
def apply(languageIds: Vector[String]): RunProvider = new RunProvider(languageIds)
}

View File

@ -0,0 +1,45 @@
/**
* This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.bsp
/**
* Run Result
* @param originId An optional request id to know the origin of this report.
* @param statusCode A status code fore the execution.
*/
final class RunResult private (
val originId: Option[String],
val statusCode: Int) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: RunResult => (this.originId == x.originId) && (this.statusCode == x.statusCode)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (17 + "sbt.internal.bsp.RunResult".##) + originId.##) + statusCode.##)
}
override def toString: String = {
"RunResult(" + originId + ", " + statusCode + ")"
}
private[this] def copy(originId: Option[String] = originId, statusCode: Int = statusCode): RunResult = {
new RunResult(originId, statusCode)
}
def withOriginId(originId: Option[String]): RunResult = {
copy(originId = originId)
}
def withOriginId(originId: String): RunResult = {
copy(originId = Option(originId))
}
def withStatusCode(statusCode: Int): RunResult = {
copy(statusCode = statusCode)
}
}
object RunResult {
def apply(originId: Option[String], statusCode: Int): RunResult = new RunResult(originId, statusCode)
def apply(originId: String, statusCode: Int): RunResult = new RunResult(Option(originId), statusCode)
}

View File

@ -5,17 +5,18 @@
// DO NOT EDIT MANUALLY
package sbt.internal.bsp.codec
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
trait BuildServerCapabilitiesFormats { self: sbt.internal.bsp.codec.CompileProviderFormats with sjsonnew.BasicJsonProtocol =>
trait BuildServerCapabilitiesFormats { self: sbt.internal.bsp.codec.CompileProviderFormats with sbt.internal.bsp.codec.RunProviderFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val BuildServerCapabilitiesFormat: JsonFormat[sbt.internal.bsp.BuildServerCapabilities] = new JsonFormat[sbt.internal.bsp.BuildServerCapabilities] {
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.BuildServerCapabilities = {
__jsOpt match {
case Some(__js) =>
unbuilder.beginObject(__js)
val compileProvider = unbuilder.readField[Option[sbt.internal.bsp.CompileProvider]]("compileProvider")
val runProvider = unbuilder.readField[Option[sbt.internal.bsp.RunProvider]]("runProvider")
val dependencySourcesProvider = unbuilder.readField[Option[Boolean]]("dependencySourcesProvider")
val canReload = unbuilder.readField[Option[Boolean]]("canReload")
unbuilder.endObject()
sbt.internal.bsp.BuildServerCapabilities(compileProvider, dependencySourcesProvider, canReload)
sbt.internal.bsp.BuildServerCapabilities(compileProvider, runProvider, dependencySourcesProvider, canReload)
case None =>
deserializationError("Expected JsObject but found None")
}
@ -23,6 +24,7 @@ implicit lazy val BuildServerCapabilitiesFormat: JsonFormat[sbt.internal.bsp.Bui
override def write[J](obj: sbt.internal.bsp.BuildServerCapabilities, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("compileProvider", obj.compileProvider)
builder.addField("runProvider", obj.runProvider)
builder.addField("dependencySourcesProvider", obj.dependencySourcesProvider)
builder.addField("canReload", obj.canReload)
builder.endObject()

View File

@ -17,6 +17,7 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol
with sbt.internal.bsp.codec.BuildClientCapabilitiesFormats
with sbt.internal.bsp.codec.InitializeBuildParamsFormats
with sbt.internal.bsp.codec.CompileProviderFormats
with sbt.internal.bsp.codec.RunProviderFormats
with sbt.internal.bsp.codec.BuildServerCapabilitiesFormats
with sbt.internal.bsp.codec.InitializeBuildResultFormats
with sbt.internal.bsp.codec.PublishDiagnosticsParamsFormats
@ -34,6 +35,8 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol
with sbt.internal.bsp.codec.BspCompileResultFormats
with sbt.internal.bsp.codec.CompileTaskFormats
with sbt.internal.bsp.codec.CompileReportFormats
with sbt.internal.bsp.codec.RunParamsFormats
with sbt.internal.bsp.codec.RunResultFormats
with sbt.internal.bsp.codec.ScalaBuildTargetFormats
with sbt.internal.bsp.codec.SbtBuildTargetFormats
with sbt.internal.bsp.codec.ScalacOptionsParamsFormats

View File

@ -0,0 +1,35 @@
/**
* 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 RunParamsFormats { self: sbt.internal.bsp.codec.BuildTargetIdentifierFormats with sbt.internal.util.codec.JValueFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val RunParamsFormat: JsonFormat[sbt.internal.bsp.RunParams] = new JsonFormat[sbt.internal.bsp.RunParams] {
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.RunParams = {
__jsOpt match {
case Some(__js) =>
unbuilder.beginObject(__js)
val target = unbuilder.readField[sbt.internal.bsp.BuildTargetIdentifier]("target")
val originId = unbuilder.readField[Option[String]]("originId")
val arguments = unbuilder.readField[Vector[String]]("arguments")
val dataKind = unbuilder.readField[Option[String]]("dataKind")
val data = unbuilder.readField[Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]]("data")
unbuilder.endObject()
sbt.internal.bsp.RunParams(target, originId, arguments, dataKind, data)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.bsp.RunParams, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("target", obj.target)
builder.addField("originId", obj.originId)
builder.addField("arguments", obj.arguments)
builder.addField("dataKind", obj.dataKind)
builder.addField("data", obj.data)
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 RunProviderFormats { self: sjsonnew.BasicJsonProtocol =>
implicit lazy val RunProviderFormat: JsonFormat[sbt.internal.bsp.RunProvider] = new JsonFormat[sbt.internal.bsp.RunProvider] {
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.RunProvider = {
__jsOpt match {
case Some(__js) =>
unbuilder.beginObject(__js)
val languageIds = unbuilder.readField[Vector[String]]("languageIds")
unbuilder.endObject()
sbt.internal.bsp.RunProvider(languageIds)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.bsp.RunProvider, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("languageIds", obj.languageIds)
builder.endObject()
}
}
}

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 RunResultFormats { self: sjsonnew.BasicJsonProtocol =>
implicit lazy val RunResultFormat: JsonFormat[sbt.internal.bsp.RunResult] = new JsonFormat[sbt.internal.bsp.RunResult] {
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.RunResult = {
__jsOpt match {
case Some(__js) =>
unbuilder.beginObject(__js)
val originId = unbuilder.readField[Option[String]]("originId")
val statusCode = unbuilder.readField[Int]("statusCode")
unbuilder.endObject()
sbt.internal.bsp.RunResult(originId, statusCode)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.bsp.RunResult, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("originId", obj.originId)
builder.addField("statusCode", obj.statusCode)
builder.endObject()
}
}
}

View File

@ -172,7 +172,7 @@ type BuildServerCapabilities {
# testProvider: TestProvider
# The languages the server supports run via method buildTarget/run
# runProvider: RunProvider
runProvider: sbt.internal.bsp.RunProvider
# The server can provide a list of targets that contain a
# single text document via the method buildTarget/inverseSources
@ -198,6 +198,10 @@ type CompileProvider {
languageIds: [String]
}
type RunProvider {
languageIds: [String]
}
## Publish Diagnostics
type PublishDiagnosticsParams {
## The document where the diagnostics are published.
@ -367,6 +371,39 @@ type CompileReport {
time: Int
}
## Run Request
## The run request is sent from the client to the server to run a build target.
## The server communicates during the initialize handshake whether this method is supported or not.
## An empty run request is valid.
type RunParams {
## The build target to run.
target: sbt.internal.bsp.BuildTargetIdentifier!
## An option identifier gnerated by the client to identify this request.
## The server may include this id in triggered notifications or responses.
originId: String
## Optional arguments to the executed application.
arguments: [String]
## Kind of data to expect in the data field.
## If this field is not set, the kind of data is not specified.
dataKind: String
## Language-specific metadata for this execution.
data: sjsonnew.shaded.scalajson.ast.unsafe.JValue
}
## Run Result
type RunResult {
## An optional request id to know the origin of this report.
originId: String
## A status code fore the execution.
statusCode: Int!
}
# Scala Extension
## Contains scala-specific metadata for compiling a target containing Scala sources.