codeface-io / LSPService

Use Local LSP Servers via WebSockets
MIT License
38 stars 3 forks source link
language-server language-server-protocol lsp sourcekit-lsp swift vapor websocket

LSPService

👩🏻‍🚀 This project is still a tad experimental. Contributors and pioneers welcome!

What?

LSPService is a local web service that allows editors to talk to any local LSP language server via WebSocket:

LSPService is itself written in Swift and also mainly tested with the Swift language server (sourcekit-lsp). But in principle, LSPService can connect to all language servers and Linux support can easily be added in the future.

The LSPService package itself comprises very little code because a) it heavily leverages Vapor and b) I extracted much of what it does into SwiftLSP and FoundationToolz.

Why?

The Language Server Protocol is the present and future of software development tools. But leveraging it for a tool project turned out to be difficult.

For instance, I distribute a developer tool via the Mac App Store, so it must be sandboxed, which makes it impossible to directly deal with language servers or any other "tooling" of the tech world.

So I thought: What if a language server was simply a local web service? Possible benefits:

How?

First of All: How to Configure LSPService

LSPService creates an LSPServiceConfig.json file on launch if the file doesn't exist yet. If the file exists, it loads server configurations from the file.

A user or admin should configure LSPService by editing LSPServiceConfig.json. In the future, the config file that LSPService creates will already contain entries for selected installed language servers. Right now, that automatic detection only works for Swift.

As the User of an Editor

  1. Download and open LSPService. It will run in terminal, and as long as it's running there, the service is available. Check: http://localhost:8080
  2. To add language servers, add corresponding entries to LSPServiceConfig.json and restart LSPService. The LSPServiceConfig.json file created by LSPService already contains at least one entry, and the JSON structure is quite self-explanatory.

As the Developer of an Editor

  1. Let your editor use LSPService:
    • Make a WebSocket connection to LSPService for a specified language.
    • If you write the editor in Swift, you may use LSPServiceKit.
    • If you want to put your editor into the Mac App Store: Ensure it's also valuable without LSPService. This may help with the review process.
  2. Provide downloads of the LSPService binaries (for Apple + Intel chips) to your users:
    • Either build them yourself:
    • swift build --configuration release --arch arm64
    • swift build --configuration release --arch x86_64
    • get them from .build/<target architecture>/release/LSPService
    • upload them somewhere ...
    • ... or just use the download links I provide for Codeface
  3. Let your editor encourage users to download and run LSPService:
    • Succinctly describe which features LSPService unlocks.
    • Offer a link to a user friendly download page (or similar), like this one.

Developing an Editor

Editor vs. LSPService – Who's Responsible?

The singular purpose of LSPService is to make local LSP language servers accessible via WebSockets.

LSPService forwards LSP messages from some editor (incoming via WebSockets) to some language server (outgoing to stdin) and vice versa. It knows nothing about the LSP standard itself (except for how to detect LSP packets in the output of language servers). Encoding and decoding LSP messages and generally representing LSP with proper types remains a concern of the editor.

The editor, on the other hand, knows nothing about how to talk to-, locate and launch language servers. Those remain concerns of LSPService.

The WebSocket

Architecture

Here is the internal architecture (composition and essential dependencies) of LSPService:

The above image was generated with Codeface.

Development Status

From version/tag 0.1.0 on, LSPService adheres to semantic versioning. So until it has reached 1.0.0, the REST API or setup mechanism may still break frequently, but this will be expressed in version bumps.

LSPService is already being used in production, but Codeface is still its primary client. LSPService will move to version 1.0.0 as soon as:

  1. Basic practicality and conceptual soundness have been validated by serving multiple real-world clients.
  2. LSPService has a versioning mechanism (see roadmap).

To Do / Roadmap

Rather Optional Stuff (Backlog)