sublimelsp / LSP

Client implementation of the Language Server Protocol for Sublime Text
https://lsp.sublimetext.io/
MIT License
1.65k stars 182 forks source link

Containerized development workflow #2385

Open sprat opened 9 months ago

sprat commented 9 months ago

Is your feature request related to a problem? Please describe.

I would like to use a containerized development workflow with Sublime Text: I want to avoid installing things on my local machine for various reasons, and for that purpose I tend to create a docker container (built from a Dockerfile) which have all the tools available (language interpreter/compiler, some development libraries, linters, etc.), e.g. https://containers.dev/, with the source code mounted into. The idea is to have a separate & reproducible development environment for each project and avoid sharing an interpreter, some libraries, or linters in specific versions. So I would like all the language servers to run commands not on my local machine but inside an existing docker container (which would eventually be launched beforehand). Another use-case (useless for me) would be to run the commands through SSH to a remote machine.

Describe the solution you'd like

Ideally, I would like to be able to choose where the commands will be applied, maybe by being able to add a "command prefix" on all commands that will be run by the language servers. All the language server plugins would need to use the implemented abstraction. It would be like choosing a "shell" interpreter.

Describe alternatives you've considered

Not using a containerized development workflow, it works fine (but have many drawbacks).

Or put Sublime Text inside the development container, but other Team mates generally want to use their own IDE, not the one I chose.

Additional context

There's no abstraction in Sublime Text or LSP utils to help in that respect AFAIK, so a global effort is needed in order to implement that. Maybe I should also open an issue in the Sublime Text issue tracker.

rchl commented 9 months ago

Not sure how the solution to that would look like...

You've mentioned "maybe by being able to add a "command prefix" on all commands" but that's not really how most servers work. The servers are started once and then communicate through stdin/stdout and there are many types of requests and notifications that can be triggered or received.

I guess the biggest obstacle is the fact that the file paths would be different in local vs. docker file system so that could confuse the server as some (many) of them also directly access the file system to analyze and read the whole project.

Kinda feels like the language server itself would have to have some docker-specific awareness to be able to translate the provided and reported paths but not sure...

Are you aware of some existing editor setups where this works currently. Especially non-vscode ones?

sprat commented 9 months ago

Thanks for the answer.

I think I must clarify what I meant.

I see containerized development as an ideal way to have both the developers workstations and CI use the exact same process & tools to lint, compile and test the code: you just run a docker build (eventually multi-stage/multiple targets) and you get all the artifacts afterwards if it builds (i.e. if the linter is ok, tests pass, etc.). And the missing piece in this puzzle is to tell the IDE use a docker image containing the tools I already use in my build workflow to lint/format/check the code interactively during development.

Also I agree that there are many ways to containerize a build workflow, and consequently different ways to run the language servers. I must admit that I am not very familiar with the language server protocol. As I understand it, the IDE acts as a client that send requests through a "connection" (stdin/stdout) to a language server replying to the requests. The language server launches for example a linter tool to get some feedback about the code and send it back to the client. To me there are 2 ways to containerize that:

  1. running the language server and tools inside a container, the IDE would then establish a connection to the running container.
  2. running the language server locally but the tools inside a container, so the language server would have to start a docker container to run the tools: that how I would like to do. But the language server have to support running commands inside containers: that was my idea with the prefix, instead of calling e.g. shellcheck, you can call docker run -it --rm my-ci-tools-image shellcheck. But adding a prefix on each command of each tool is a bit tedious.

And yes, with both solutions, the language servers would have to "re-map" the source files paths.

I've searched a little bit if there are other implementations of containerized LSP workflows:

rchl commented 9 months ago

The language server launches for example a linter tool to get some feedback about the code and send it back to the client.

Language server can be (and often is) a self-contained binary that doesn't run any external commands.

  1. running the language server and tools inside a container, the IDE would then establish a connection to the running container.

In that case all paths that we report to the server would have to be translated to "containerized" paths and vice-versa. Feels quite hacky to be honest and also it probably wouldn't handle 100% of the cases (for example links to files within documentation blobs would be hard to detect and convert).

@rwols did work on that in the past (https://github.com/sublimelsp/LSP/pull/1527) but it didn't get to production state.

2. running the language server locally but the tools inside a container, so the language server would have to start a docker container to run the tools

That's more a request for language servers and not this client though so I wouldn't go into discussing it here. Also for servers that actually run external tools, I think it would add a lot of overhead to run the container every time it wants to run a linter, for example.

  • I also found this repo which seems to support running language servers inside containers in NeoVIM, but it seems to be the solution 1.

This looks very relevant and similar to what @rwols tried before only with more helper functionality to also start and manage containers including mounting local paths.