LSP4J:如何使语言服务器向客户端请求某些内容

问题描述

我正在使用LSP4J用Scala编写的语言服务器。我遵循了VS Code和LSP4J的文档,并达到可以在客户端和服务器之间来回发送通知的地步。我还设法使客户端从服务器请求内容,然后与它们一起使用。但是,我还没有完全设法解决其他问题。也就是说,我可以让服务器向客户端发出请求,但这些请求从未完成。

为您提供一些背景信息,这是我所做的:

  1. 为VS Code扩展实现了状态栏项。
  2. 注册一个命令,该命令将在单击该项目时向服务器发送通知
  3. 在服务器端为该通知实现了处理程序。
  4. 让处理程序向客户端发送请求。
  5. 在客户端上为该请求实现了处理程序。

到目前为止,太好了。我可以跟踪每个步骤,并且知道一切都按预期执行。现在,在服务器端,我应该找回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可以像Future那样对待。显然不是这样。取而代之的是,join -ing(或get -ting)来自CompletableFuture的结果的异步计算必须由Future包装。

也就是说,用以下内容替换c2sNotification中while循环周围的关键部分:

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)
    })
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...