microsoft / vscode-languageserver-node

Language server protocol implementation for VSCode. This allows implementing language services in JS/TS running on node.js
MIT License
1.46k stars 327 forks source link

[BUG] LSP Client is not fully initialized when it starts listening, results in a bug with the progressPart #1575

Closed life2015 closed 3 days ago

life2015 commented 6 days ago

Issue: LSP Client is not fully initialized when it starts listening, results in a bug with the progressPart

Description: I've encountered an issue in the vscode-languageclient/node module where some initial LSP messages get dropped during communication under certain conditions. Specifically, in the following code:

connection.listen();
await this.initialize(connection);
resolve();

Image

The problem occurs because the listen function is called before the initialize function, which opens the LSP connection. If the LSP server starts and immediately begins sending messages, some of the earliest messages might be dropped, as the client is not yet fully initialized to handle incoming communication. This leads to unexpected behavior and a lack of proper message handling.

Steps to Reproduce:

  1. Set up a project with the vscode-languageclient/node module.
  2. Start an LSP server that sends messages very quickly after initialization.
  3. Observe that some of the first messages are dropped and not processed by the client.

Details:

Image

Image

We can see from the image above that right after the LSP Client starts and begins listening, it receives a ‘window/workDoneProgress/create’ request from the Server. However, at this point, the LSP Client has not yet been initialized, so there is no appropriate handler for this request. Additionally, due to the nature of the ProgressPart, the progress of this ongoing operation cannot be reported correctly afterward.

Expected Behavior: The client should be able to handle all incoming messages from the LSP server without dropping any, even if the messages arrive immediately after the connection is established.

Suggested Solution: One possible fix would be to ensure that the client is fully initialized before it starts listening to the connection. Reversing the order of operations—initializing first, then starting the listen process—may prevent messages from being dropped.

dbaeumer commented 3 days ago

Actually this is by design. See here https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize

Until the initialize handshake is complete only a limited number of message types can be exchanged. This is because some of the client behavior in terms of messages depend on the result of the initialize request.

If you want to report progress during initialize you can use the progress token on the initialize request. You need to let the VS Code LSP client know to insert such a token. See https://github.com/microsoft/vscode-languageserver-node/blob/main/client/src/common/client.ts#L362