Skip to content

Extension API: let extensions arbitrarily send and receive LSP messages #20042

@4teapo

Description

@4teapo

Check for existing issues

  • Completed

Describe the feature

Extensions currently cannot send or receive LSP messages. This may force extension authors to exclude a number of features, workarounds often being impossible. The extension API should therefore support arbitrarily sending and receiving LSP messages.

For example, luau-lsp has a list of optional features, where

  • custom $/command definition,
  • Roblox Studio plugin,
  • and bytecode generation

all require additional communication with the language server. Each one of these are are implemented in the Visual Studio Code extension for luau-lsp. The code for custom $/command definition support looks as follows:

client.onNotification("$/command", (params) => {
    vscode.commands.executeCommand(params.command, params.data);
});

It requires receiving LSP notifications, and additional infrastructure which is outside of the scope for this feature request. Zed's extension API could provide a Extension::handle_lsp_notification(&LanguageServerId, &Worktree, Notification, serde_json::Value) method in the Extension trait for this purpose.

It's possible to support the Roblox Studio plugin in Zed today, but it requires that the extension author creates an additional language server, wrapping luau-lsp but providing plugin-related functionality as well, since this feature doesn't necessitate any communication with Zed. This isn't ideal, however, requiring a disproportionate amount of work and bringing its own can of worms.

To support the Roblox Studio plugin, an extension must be able to spawn a local HTTP server (#20040), and send LSP messages to luau-lsp. An example of this is the following snippet from the Visual Studio Code extension's source code:

  app.post("/full", (req, res) => {
    if (!client) {
      return res.sendStatus(500);
    }

    if (req.body.tree) {
      client.sendNotification("$/plugin/full", req.body.tree);
      res.sendStatus(200);
    } else {
      res.sendStatus(400);
    }
  });

In Zed, it may make sense to have some zed::lsp::send_notification(&LanguageServerId, Notification) function.

Finally, it would be useful to have a slash command that displays bytecode for a certain file. Bytecode generation is handled here in the Visual Studio Code extension. The extension uses the following LSP requests to retrieve bytecode information:

  • luau-lsp/bytecode: { textDocument: TextDocumentIdentifier, optimizationLevel: number }, returns string
  • luau-lsp/compiler-remarks: { textDocument: TextDocumentIdentifier, optimizationLevel: number }, returns string

To support this, the extension API needs to allow retrieving the text document identifier, sending LSP requests, and awaiting their results. One way to handle this is to introduce a zed::lsp::send_request function which pauses the thread until a response is received and returns the response, as well as a zed::lsp::get_current_text_document_identifier function.

If applicable, add mockups / screenshots to help present your vision of the feature

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension infrastructureFeedback for extensions APIs, creation, management, etcfeature[core label]language serverAn umbrella label for all language servers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions