I'm working on a Language Server written in Scala using LSP4J. I was following the docs from both VS Code and the LSP4J and got to the point where I could send notifications back and forth between client and server. I have also managed to make the client request things from the server and to then work with them. However, I've not completely managed to go the other way around. I.e., I can get the server to make requests to the client, but these requests never complete.
To give you some context, this is what I did:
- Implemented a status bar item for the VS Code extension.
- Registered a command that would send a notification to the server when the item is clicked.
- Implemented a handler for that notification on the server side.
- Have that handler send a request to the client.
- Implemented a handler for that request on the client side.
So far, so good. I can trace each step and know that everything is executed as I expect. Now, on the server side, I should get back a CompletableFuture
. In my understanding of things, this CompletableFuture
should eventually complete with the value I returned by the request handler (on the client side).
Below are the relevant parts of the code described above.
trait IdeLanguageClient extends LanguageClient {
//...
//This is the request sent to the client
@JsonRequest("SomeRequest")
def s2c_request(): CompletableFuture[String]
}
class ExampleLanguageServer() extends LanguageClientAware {
private var client: Option[IdeLanguageClient] = None
//...
//This is the handler for the notification the client sends after clicking on the status bar.
@JsonNotification("sbi")
def c2s_notification(): Unit = {
client match {
case Some(c) =>
val completable_future = c.s2c_request()
while(!fut.isDone){
println("sleepy")
Thread.sleep(1000) // This goes on for ever!!
}
val s = fut.get()
println(s)
}
}
override def connect(client: LanguageClient): Unit = {
println("client is connected")
this.client = Some(client.asInstanceOf[IdeLanguageClient])
}
}
export function activate(context: ExtensionContext) {
//...
// Create the language client.
client = new LanguageClient(
'languageServerExample',
'Language Server Example',
startServer,
clientOptions
);
createStatusBarItem();
// Handler for the server's request
client.onReady().then(ready => {
client.onRequest("SomeRequest", () => {
"Some Responce to the request"
});
});
// Start the client. This will also launch the server
client.start();
function createStatusBarItem() {...}
// Invokes the jars of the language server
function startServer(): Promise<StreamInfo> {...}
}
The critical part is the while loop c2s_notification
. In my understanding, the future should eventually (given the minuscule task, pretty much immediately) be done and yield the value returned by the onRequest
handle. Instead, the loop just goes on printing "sleep" once per second. Did I misundestand something? Or am I just doing something wrong?
I hope the problem is stated clearly enough and that it includes all the necessary information.
Thanks for your help!