mirror of https://github.com/sbt/sbt.git
Merge pull request #5838 from adpi2/bsp-reload
Add BSP workspace/reload
This commit is contained in:
commit
75da49556c
|
|
@ -23,9 +23,8 @@ import sbt.internal.CommandStrings.BootCommand
|
|||
import sbt.internal._
|
||||
import sbt.internal.client.BspClient
|
||||
import sbt.internal.inc.ScalaInstance
|
||||
import sbt.internal.io.Retry
|
||||
import sbt.internal.nio.{ CheckBuildSources, FileTreeRepository }
|
||||
import sbt.internal.server.NetworkChannel
|
||||
import sbt.internal.server.{ BuildServerProtocol, NetworkChannel }
|
||||
import sbt.internal.util.Types.{ const, idFun }
|
||||
import sbt.internal.util._
|
||||
import sbt.internal.util.complete.{ Parser, SizeParser }
|
||||
|
|
@ -317,7 +316,10 @@ object BuiltinCommands {
|
|||
NetworkChannel.disconnect,
|
||||
waitCmd,
|
||||
promptChannel,
|
||||
) ++ allBasicCommands ++ ContinuousCommands.value
|
||||
) ++
|
||||
allBasicCommands ++
|
||||
ContinuousCommands.value ++
|
||||
BuildServerProtocol.commands
|
||||
|
||||
def DefaultBootCommands: Seq[String] =
|
||||
WriteSbtVersion :: LoadProject :: NotifyUsersAboutShell :: s"$IfLast $Shell" :: Nil
|
||||
|
|
|
|||
|
|
@ -17,11 +17,13 @@ import sbt.Def._
|
|||
import sbt.Keys._
|
||||
import sbt.ScopeFilter.Make._
|
||||
import sbt.SlashSyntax0._
|
||||
import sbt.StandardMain.exchange
|
||||
import sbt.internal.bsp._
|
||||
import sbt.internal.langserver.ErrorCodes
|
||||
import sbt.internal.protocol.JsonRpcRequestMessage
|
||||
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
|
||||
|
||||
|
|
@ -29,9 +31,44 @@ import scala.util.control.NonFatal
|
|||
|
||||
object BuildServerProtocol {
|
||||
import sbt.internal.bsp.codec.JsonProtocol._
|
||||
|
||||
private val capabilities = BuildServerCapabilities(
|
||||
CompileProvider(BuildServerConnection.languages),
|
||||
dependencySourcesProvider = true
|
||||
dependencySourcesProvider = true,
|
||||
canReload = true
|
||||
)
|
||||
|
||||
private val bspReload = "bspReload"
|
||||
private val bspReloadFailed = "bspReloadFailed"
|
||||
private val bspReloadSucceed = "bspReloadSucceed"
|
||||
|
||||
lazy val commands: Seq[Command] = Seq(
|
||||
Command.single(bspReload) { (state, reqId) =>
|
||||
import sbt.BasicCommandStrings._
|
||||
import sbt.internal.CommandStrings._
|
||||
val result = List(
|
||||
StashOnFailure,
|
||||
s"$OnFailure $bspReloadFailed $reqId",
|
||||
LoadProjectImpl,
|
||||
s"$bspReloadSucceed $reqId",
|
||||
PopOnFailure,
|
||||
FailureWall
|
||||
) ::: state
|
||||
result
|
||||
},
|
||||
Command.single(bspReloadFailed) { (state, reqId) =>
|
||||
exchange.respondError(
|
||||
ErrorCodes.InternalError,
|
||||
"reload failed",
|
||||
Some(reqId),
|
||||
state.source
|
||||
)
|
||||
state
|
||||
},
|
||||
Command.single(bspReloadSucceed) { (state, reqId) =>
|
||||
exchange.respondEvent(JNull, Some(reqId), state.source)
|
||||
state
|
||||
}
|
||||
)
|
||||
|
||||
lazy val globalSettings: Seq[Def.Setting[_]] = Seq(
|
||||
|
|
@ -59,7 +96,6 @@ object BuildServerProtocol {
|
|||
val filter = ScopeFilter.in(targets.map(workspace))
|
||||
// run the worker task concurrently
|
||||
Def.task {
|
||||
import sbt.internal.bsp.codec.JsonProtocol._
|
||||
val items = bspBuildTargetSourcesItem.all(filter).value
|
||||
val result = SourcesResult(items.toVector)
|
||||
s.respondEvent(result)
|
||||
|
|
@ -86,7 +122,6 @@ object BuildServerProtocol {
|
|||
val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
||||
val filter = ScopeFilter.in(targets.map(workspace))
|
||||
Def.task {
|
||||
import sbt.internal.bsp.codec.JsonProtocol._
|
||||
val statusCode = Keys.bspBuildTargetCompileItem.all(filter).value.max
|
||||
s.respondEvent(BspCompileResult(None, statusCode))
|
||||
}
|
||||
|
|
@ -155,6 +190,9 @@ object BuildServerProtocol {
|
|||
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 == "build/shutdown" =>
|
||||
()
|
||||
|
||||
|
|
|
|||
|
|
@ -8,25 +8,27 @@ package sbt.internal.bsp
|
|||
* @param compileProvider The languages the server supports compilation via method buildTarget/compile.
|
||||
* @param dependencySourcesProvider The server provides sources for library dependencies
|
||||
via method buildTarget/dependencySources
|
||||
* @param canReload Reloading the workspace state through workspace/reload is supported
|
||||
*/
|
||||
final class BuildServerCapabilities private (
|
||||
val compileProvider: Option[sbt.internal.bsp.CompileProvider],
|
||||
val dependencySourcesProvider: Option[Boolean]) extends Serializable {
|
||||
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)
|
||||
case x: BuildServerCapabilities => (this.compileProvider == x.compileProvider) && (this.dependencySourcesProvider == x.dependencySourcesProvider) && (this.canReload == x.canReload)
|
||||
case _ => false
|
||||
}
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (17 + "sbt.internal.bsp.BuildServerCapabilities".##) + compileProvider.##) + dependencySourcesProvider.##)
|
||||
37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.BuildServerCapabilities".##) + compileProvider.##) + dependencySourcesProvider.##) + canReload.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"BuildServerCapabilities(" + compileProvider + ", " + dependencySourcesProvider + ")"
|
||||
"BuildServerCapabilities(" + compileProvider + ", " + dependencySourcesProvider + ", " + canReload + ")"
|
||||
}
|
||||
private[this] def copy(compileProvider: Option[sbt.internal.bsp.CompileProvider] = compileProvider, dependencySourcesProvider: Option[Boolean] = dependencySourcesProvider): BuildServerCapabilities = {
|
||||
new BuildServerCapabilities(compileProvider, dependencySourcesProvider)
|
||||
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)
|
||||
}
|
||||
def withCompileProvider(compileProvider: Option[sbt.internal.bsp.CompileProvider]): BuildServerCapabilities = {
|
||||
copy(compileProvider = compileProvider)
|
||||
|
|
@ -40,9 +42,15 @@ final class BuildServerCapabilities private (
|
|||
def withDependencySourcesProvider(dependencySourcesProvider: Boolean): BuildServerCapabilities = {
|
||||
copy(dependencySourcesProvider = Option(dependencySourcesProvider))
|
||||
}
|
||||
def withCanReload(canReload: Option[Boolean]): BuildServerCapabilities = {
|
||||
copy(canReload = canReload)
|
||||
}
|
||||
def withCanReload(canReload: Boolean): BuildServerCapabilities = {
|
||||
copy(canReload = Option(canReload))
|
||||
}
|
||||
}
|
||||
object BuildServerCapabilities {
|
||||
|
||||
def apply(compileProvider: Option[sbt.internal.bsp.CompileProvider], dependencySourcesProvider: Option[Boolean]): BuildServerCapabilities = new BuildServerCapabilities(compileProvider, dependencySourcesProvider)
|
||||
def apply(compileProvider: sbt.internal.bsp.CompileProvider, dependencySourcesProvider: Boolean): BuildServerCapabilities = new BuildServerCapabilities(Option(compileProvider), Option(dependencySourcesProvider))
|
||||
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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@ implicit lazy val BuildServerCapabilitiesFormat: JsonFormat[sbt.internal.bsp.Bui
|
|||
unbuilder.beginObject(__js)
|
||||
val compileProvider = unbuilder.readField[Option[sbt.internal.bsp.CompileProvider]]("compileProvider")
|
||||
val dependencySourcesProvider = unbuilder.readField[Option[Boolean]]("dependencySourcesProvider")
|
||||
val canReload = unbuilder.readField[Option[Boolean]]("canReload")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.bsp.BuildServerCapabilities(compileProvider, dependencySourcesProvider)
|
||||
sbt.internal.bsp.BuildServerCapabilities(compileProvider, dependencySourcesProvider, canReload)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
|
|
@ -23,6 +24,7 @@ implicit lazy val BuildServerCapabilitiesFormat: JsonFormat[sbt.internal.bsp.Bui
|
|||
builder.beginObject()
|
||||
builder.addField("compileProvider", obj.compileProvider)
|
||||
builder.addField("dependencySourcesProvider", obj.dependencySourcesProvider)
|
||||
builder.addField("canReload", obj.canReload)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,6 +186,9 @@ type BuildServerCapabilities {
|
|||
# via method buildTarget/resources
|
||||
# resourcesProvider: Boolean
|
||||
|
||||
## Reloading the workspace state through workspace/reload is supported
|
||||
canReload: Boolean
|
||||
|
||||
# The server sends notifications to the client on build
|
||||
# target change events via buildTarget/didChange
|
||||
# buildTargetChangedProvider: Boolean
|
||||
|
|
|
|||
|
|
@ -74,6 +74,17 @@ object BuildServerTest extends AbstractServerTest {
|
|||
})
|
||||
}
|
||||
|
||||
test("workspace/reload") { _ =>
|
||||
svr.sendJsonRpc(
|
||||
"""{ "jsonrpc": "2.0", "id": "15", "method": "workspace/reload"}"""
|
||||
)
|
||||
assert(svr.waitForString(10.seconds) { s =>
|
||||
println(s)
|
||||
(s contains """"id":"15"""") &&
|
||||
(s contains """"result":null""")
|
||||
})
|
||||
}
|
||||
|
||||
def initializeRequest(): Unit = {
|
||||
svr.sendJsonRpc(
|
||||
"""{ "jsonrpc": "2.0", "id": "10", "method": "build/initialize",
|
||||
|
|
|
|||
Loading…
Reference in New Issue