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 := { fullServerHandlers := {
Seq( Seq(
LanguageServerProtocol.handler(fileConverter.value), LanguageServerProtocol.handler(fileConverter.value),
BuildServerProtocol BuildServerProtocol.handler(
.handler(sbtVersion.value, semanticdbEnabled.value, semanticdbVersion.value), loadedBuild.value,
bspWorkspace.value,
sbtVersion.value,
semanticdbEnabled.value,
semanticdbVersion.value
),
VirtualTerminal.handler, VirtualTerminal.handler,
) ++ serverHandlers.value :+ ServerHandler.fallback ) ++ serverHandlers.value :+ ServerHandler.fallback
}, },

View File

@ -398,6 +398,7 @@ object Keys {
val bspBuildTargetDependencySourcesItem = taskKey[DependencySourcesItem]("").withRank(DTask) val bspBuildTargetDependencySourcesItem = taskKey[DependencySourcesItem]("").withRank(DTask)
val bspBuildTargetCompile = inputKey[Unit]("").withRank(DTask) val bspBuildTargetCompile = inputKey[Unit]("").withRank(DTask)
val bspBuildTargetCompileItem = taskKey[Int]("").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 bspBuildTargetScalacOptions = inputKey[Unit]("").withRank(DTask)
val bspBuildTargetScalacOptionsItem = taskKey[ScalacOptionsItem]("").withRank(DTask) val bspBuildTargetScalacOptionsItem = taskKey[ScalacOptionsItem]("").withRank(DTask)
val bspScalaMainClasses = inputKey[Unit]("Corresponds to buildTarget/scalaMainClasses request").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.bsp._
import sbt.internal.langserver.ErrorCodes import sbt.internal.langserver.ErrorCodes
import sbt.internal.protocol.JsonRpcRequestMessage import sbt.internal.protocol.JsonRpcRequestMessage
import sbt.internal.util.Attributed
import sbt.internal.util.complete.{ Parser, Parsers }
import sbt.librarymanagement.Configuration import sbt.librarymanagement.Configuration
import sbt.util.Logger import sbt.util.Logger
import sjsonnew.shaded.scalajson.ast.unsafe.JNull import sjsonnew.shaded.scalajson.ast.unsafe.{ JNull, JValue }
import sjsonnew.shaded.scalajson.ast.unsafe.JValue import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter, Parser => JsonParser }
import sjsonnew.support.scalajson.unsafe.Converter
import scala.util.{ Failure, Success }
import scala.util.control.NonFatal import scala.util.control.NonFatal
object BuildServerProtocol { object BuildServerProtocol {
@ -34,6 +36,7 @@ object BuildServerProtocol {
private val capabilities = BuildServerCapabilities( private val capabilities = BuildServerCapabilities(
CompileProvider(BuildServerConnection.languages), CompileProvider(BuildServerConnection.languages),
RunProvider(BuildServerConnection.languages),
dependencySourcesProvider = true, dependencySourcesProvider = true,
canReload = true canReload = true
) )
@ -174,76 +177,106 @@ object BuildServerProtocol {
}, },
bspBuildTargetDependencySourcesItem := dependencySourcesItemTask.value, bspBuildTargetDependencySourcesItem := dependencySourcesItemTask.value,
bspBuildTargetCompileItem := bspCompileTask.value, bspBuildTargetCompileItem := bspCompileTask.value,
bspBuildTargetRun := bspRunTask.evaluated,
bspBuildTargetScalacOptionsItem := scalacOptionsTask.value, bspBuildTargetScalacOptionsItem := scalacOptionsTask.value,
bspInternalDependencyConfigurations := internalDependencyConfigurationsSetting.value, bspInternalDependencyConfigurations := internalDependencyConfigurationsSetting.value,
bspScalaMainClassesItem := scalaMainClassesTask.value bspScalaMainClassesItem := scalaMainClassesTask.value
) )
def handler( def handler(
loadedBuild: LoadedBuild,
workspace: Map[BuildTargetIdentifier, Scope],
sbtVersion: String, sbtVersion: String,
semanticdbEnabled: Boolean, semanticdbEnabled: Boolean,
semanticdbVersion: String semanticdbVersion: String
): ServerHandler = ServerHandler { callback => ): ServerHandler = {
ServerIntent( val configurationMap: Map[ConfigKey, Configuration] =
onRequest = { loadedBuild.allProjectRefs
case r: JsonRpcRequestMessage if r.method == "build/initialize" => .flatMap { case (_, p) => p.configurations }
val params = Converter.fromJson[InitializeBuildParams](json(r)).get .distinct
checkMetalsCompatibility(semanticdbEnabled, semanticdbVersion, params, callback.log) .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( val response = InitializeBuildResult(
"sbt", "sbt",
sbtVersion, sbtVersion,
BuildServerConnection.bspVersion, BuildServerConnection.bspVersion,
capabilities, capabilities,
None None
) )
callback.jsonRpcRespond(response, Some(r.id)); () callback.jsonRpcRespond(response, Some(r.id)); ()
case r: JsonRpcRequestMessage if r.method == "workspace/buildTargets" => case r: JsonRpcRequestMessage if r.method == "workspace/buildTargets" =>
val _ = callback.appendExec(Keys.bspWorkspaceBuildTargets.key.toString, Some(r.id)) val _ = callback.appendExec(Keys.bspWorkspaceBuildTargets.key.toString, Some(r.id))
case r: JsonRpcRequestMessage if r.method == "workspace/reload" => case r: JsonRpcRequestMessage if r.method == "workspace/reload" =>
val _ = callback.appendExec(s"$bspReload ${r.id}", None) 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" => case r: JsonRpcRequestMessage if r.method == "build/exit" =>
val _ = callback.appendExec(Shutdown, Some(r.id)) val _ = callback.appendExec(Shutdown, Some(r.id))
case r: JsonRpcRequestMessage if r.method == "buildTarget/sources" => case r: JsonRpcRequestMessage if r.method == "buildTarget/sources" =>
val param = Converter.fromJson[SourcesParams](json(r)).get val param = Converter.fromJson[SourcesParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ") val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspBuildTargetSources.key val command = Keys.bspBuildTargetSources.key
val _ = callback.appendExec(s"$command $targets", Some(r.id)) val _ = callback.appendExec(s"$command $targets", Some(r.id))
case r if r.method == "buildTarget/dependencySources" => case r if r.method == "buildTarget/dependencySources" =>
val param = Converter.fromJson[DependencySourcesParams](json(r)).get val param = Converter.fromJson[DependencySourcesParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ") val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspBuildTargetDependencySources.key val command = Keys.bspBuildTargetDependencySources.key
val _ = callback.appendExec(s"$command $targets", Some(r.id)) val _ = callback.appendExec(s"$command $targets", Some(r.id))
case r if r.method == "buildTarget/compile" => case r if r.method == "buildTarget/compile" =>
val param = Converter.fromJson[CompileParams](json(r)).get val param = Converter.fromJson[CompileParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ") val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspBuildTargetCompile.key val command = Keys.bspBuildTargetCompile.key
val _ = callback.appendExec(s"$command $targets", Some(r.id)) val _ = callback.appendExec(s"$command $targets", Some(r.id))
case r: JsonRpcRequestMessage if r.method == "buildTarget/scalacOptions" => case r if r.method == "buildTarget/run" =>
val param = Converter.fromJson[ScalacOptionsParams](json(r)).get val paramJson = json(r)
val targets = param.targets.map(_.uri).mkString(" ") val param = Converter.fromJson[RunParams](json(r)).get
val command = Keys.bspBuildTargetScalacOptions.key val scope = workspace.getOrElse(
val _ = callback.appendExec(s"$command $targets", Some(r.id)) 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" => case r: JsonRpcRequestMessage if r.method == "buildTarget/scalacOptions" =>
val param = Converter.fromJson[ScalacOptionsParams](json(r)).get val param = Converter.fromJson[ScalacOptionsParams](json(r)).get
val targets = param.targets.map(_.uri).mkString(" ") val targets = param.targets.map(_.uri).mkString(" ")
val command = Keys.bspScalaMainClasses.key val command = Keys.bspBuildTargetScalacOptions.key
val _ = callback.appendExec(s"$command $targets", Some(r.id)) val _ = callback.appendExec(s"$command $targets", Some(r.id))
},
onResponse = PartialFunction.empty, case r: JsonRpcRequestMessage if r.method == "buildTarget/scalaMainClasses" =>
onNotification = PartialFunction.empty, 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( 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 { private def internalDependencyConfigurationsSetting = Def.settingDyn {
val directDependencies = Keys.internalDependencyConfigurations.value.map { val directDependencies = Keys.internalDependencyConfigurations.value.map {
case (project, rawConfigs) => case (project, rawConfigs) =>

View File

@ -12,23 +12,24 @@ package sbt.internal.bsp
*/ */
final class BuildServerCapabilities private ( final class BuildServerCapabilities private (
val compileProvider: Option[sbt.internal.bsp.CompileProvider], val compileProvider: Option[sbt.internal.bsp.CompileProvider],
val runProvider: Option[sbt.internal.bsp.RunProvider],
val dependencySourcesProvider: Option[Boolean], val dependencySourcesProvider: Option[Boolean],
val canReload: Option[Boolean]) extends Serializable { val canReload: Option[Boolean]) extends Serializable {
override def equals(o: Any): Boolean = o match { 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 case _ => false
} }
override def hashCode: Int = { 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 = { 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 = { 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, dependencySourcesProvider, canReload) new BuildServerCapabilities(compileProvider, runProvider, dependencySourcesProvider, canReload)
} }
def withCompileProvider(compileProvider: Option[sbt.internal.bsp.CompileProvider]): BuildServerCapabilities = { def withCompileProvider(compileProvider: Option[sbt.internal.bsp.CompileProvider]): BuildServerCapabilities = {
copy(compileProvider = compileProvider) copy(compileProvider = compileProvider)
@ -36,6 +37,12 @@ final class BuildServerCapabilities private (
def withCompileProvider(compileProvider: sbt.internal.bsp.CompileProvider): BuildServerCapabilities = { def withCompileProvider(compileProvider: sbt.internal.bsp.CompileProvider): BuildServerCapabilities = {
copy(compileProvider = Option(compileProvider)) 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 = { def withDependencySourcesProvider(dependencySourcesProvider: Option[Boolean]): BuildServerCapabilities = {
copy(dependencySourcesProvider = dependencySourcesProvider) copy(dependencySourcesProvider = dependencySourcesProvider)
} }
@ -51,6 +58,6 @@ final class BuildServerCapabilities private (
} }
object BuildServerCapabilities { 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: 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, dependencySourcesProvider: Boolean, canReload: Boolean): BuildServerCapabilities = new BuildServerCapabilities(Option(compileProvider), Option(dependencySourcesProvider), Option(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 // DO NOT EDIT MANUALLY
package sbt.internal.bsp.codec package sbt.internal.bsp.codec
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } 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] { 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 = { override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.BuildServerCapabilities = {
__jsOpt match { __jsOpt match {
case Some(__js) => case Some(__js) =>
unbuilder.beginObject(__js) unbuilder.beginObject(__js)
val compileProvider = unbuilder.readField[Option[sbt.internal.bsp.CompileProvider]]("compileProvider") 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 dependencySourcesProvider = unbuilder.readField[Option[Boolean]]("dependencySourcesProvider")
val canReload = unbuilder.readField[Option[Boolean]]("canReload") val canReload = unbuilder.readField[Option[Boolean]]("canReload")
unbuilder.endObject() unbuilder.endObject()
sbt.internal.bsp.BuildServerCapabilities(compileProvider, dependencySourcesProvider, canReload) sbt.internal.bsp.BuildServerCapabilities(compileProvider, runProvider, dependencySourcesProvider, canReload)
case None => case None =>
deserializationError("Expected JsObject but found 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 = { override def write[J](obj: sbt.internal.bsp.BuildServerCapabilities, builder: Builder[J]): Unit = {
builder.beginObject() builder.beginObject()
builder.addField("compileProvider", obj.compileProvider) builder.addField("compileProvider", obj.compileProvider)
builder.addField("runProvider", obj.runProvider)
builder.addField("dependencySourcesProvider", obj.dependencySourcesProvider) builder.addField("dependencySourcesProvider", obj.dependencySourcesProvider)
builder.addField("canReload", obj.canReload) builder.addField("canReload", obj.canReload)
builder.endObject() builder.endObject()

View File

@ -17,6 +17,7 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol
with sbt.internal.bsp.codec.BuildClientCapabilitiesFormats with sbt.internal.bsp.codec.BuildClientCapabilitiesFormats
with sbt.internal.bsp.codec.InitializeBuildParamsFormats with sbt.internal.bsp.codec.InitializeBuildParamsFormats
with sbt.internal.bsp.codec.CompileProviderFormats with sbt.internal.bsp.codec.CompileProviderFormats
with sbt.internal.bsp.codec.RunProviderFormats
with sbt.internal.bsp.codec.BuildServerCapabilitiesFormats with sbt.internal.bsp.codec.BuildServerCapabilitiesFormats
with sbt.internal.bsp.codec.InitializeBuildResultFormats with sbt.internal.bsp.codec.InitializeBuildResultFormats
with sbt.internal.bsp.codec.PublishDiagnosticsParamsFormats 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.BspCompileResultFormats
with sbt.internal.bsp.codec.CompileTaskFormats with sbt.internal.bsp.codec.CompileTaskFormats
with sbt.internal.bsp.codec.CompileReportFormats 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.ScalaBuildTargetFormats
with sbt.internal.bsp.codec.SbtBuildTargetFormats with sbt.internal.bsp.codec.SbtBuildTargetFormats
with sbt.internal.bsp.codec.ScalacOptionsParamsFormats 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 # testProvider: TestProvider
# The languages the server supports run via method buildTarget/run # 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 # The server can provide a list of targets that contain a
# single text document via the method buildTarget/inverseSources # single text document via the method buildTarget/inverseSources
@ -198,6 +198,10 @@ type CompileProvider {
languageIds: [String] languageIds: [String]
} }
type RunProvider {
languageIds: [String]
}
## Publish Diagnostics ## Publish Diagnostics
type PublishDiagnosticsParams { type PublishDiagnosticsParams {
## The document where the diagnostics are published. ## The document where the diagnostics are published.
@ -367,6 +371,39 @@ type CompileReport {
time: Int 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 # Scala Extension
## Contains scala-specific metadata for compiling a target containing Scala sources. ## Contains scala-specific metadata for compiling a target containing Scala sources.