typescript - LSP4J:如何让语言服务器从客户端请求一些东西
问题描述
我正在开发使用 LSP4J 用 Scala 编写的语言服务器。我一直在关注 VS Code 和 LSP4J 的文档,并达到了可以在客户端和服务器之间来回发送通知的地步。我还设法让客户端从服务器请求东西,然后与它们一起工作。但是,我还没有完全设法反过来。即,我可以让服务器向客户端发出请求,但这些请求永远不会完成。
为了给你一些背景,这就是我所做的:
- 为 VS Code 扩展实现了一个状态栏项。
- 注册了一个命令,该命令将在单击项目时向服务器发送通知。
- 在服务器端为该通知实现了一个处理程序。
- 让该处理程序向客户端发送请求。
- 在客户端为该请求实现了一个处理程序。
到目前为止,一切都很好。我可以追踪每一步,并知道一切都按我的预期执行。现在,在服务器端,我应该返回一个CompletableFuture
. 根据我对事物的理解,这CompletableFuture
最终应该以请求处理程序(在客户端)返回的值完成。
以下是上述代码的相关部分。
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> {...}
}
关键部分是 while 循环c2s_notification
。在我的理解中,未来应该最终(考虑到微小的任务,几乎立即)完成并产生onRequest
句柄返回的值。相反,循环只是每秒打印一次“睡眠”。我是不是误会了什么?还是我只是做错了什么?
我希望问题表述得足够清楚,并且包含所有必要的信息。
谢谢你的帮助!
解决方案
我发现了问题所在。我认为CompletableFuture
s 可以像Future
s 一样对待。显然情况并非如此。相反,join
-ing(或get
-ting)来自 a 的结果的异步计算CompletableFuture
必须由 a 包装Future
。
即,用以下内容替换 while 循环周围的关键部分可以解决c2sNotification
问题:
client match {
case Some(c) =>
val f: Future[String] = Future {
val cf: CompletableFuture[String] = c.s2c_request()
val s = cf.join()
s
}
f.onComplete({
case Success(s) => println(s)
case Failure(e) => println(e)
})
}
推荐阅读
- c# - EF Core 迁移现有数据
- python - 为词干编写自己的词干分析器
- java - Spring Boot Application中JPA entityManager如何选择连接池?
- powershell - 每个用户的powershell交换共享邮箱
- c++ - 使一些对象可供用户使用
- php - 如何仅在产品发生任何更改时才将触发器限制在删除 woo Commerce Store 中的瞬态的操作?
- python - 用于多个仪表板的单个日期选择器
- verilog - 增量循环模拟,当灵敏度列表中的两个输入同时变化并且逻辑以这两个输入为条件时会发生什么
- html - Css Tricks,SearchBar 跟随水平 2 色背景
- javascript - Paypal Checkout 集成 - onShippingChange 不适用于新 SDK