Shopify / ruby-lsp

An opinionated language server for Ruby
https://shopify.github.io/ruby-lsp/
MIT License
1.33k stars 118 forks source link

vscode: Allow setting bundler path #1986

Closed g-arjones closed 2 weeks ago

g-arjones commented 2 weeks ago

I have checked that this feature is not already implemented

Use case

Many people like to keep their ruby environments isolated thus install gems in non standard locations (including bundler). This is generally handled by having shims or env files.

Description

I would like to be able to set a custom bundler path.

Implementation

Provide a config option in vscode and use that bundler.

st0012 commented 2 weeks ago

I'd like to learn more about the use case in detail so I can better assess this feature:

g-arjones commented 2 weeks ago

What's the main benefit of installing gems in non standard locations?

Isolation. What happens if you have projects that require conflicting versions of bundler? I need a way to tell ruby-lsp which bundler to use.

Can you provide an example on how that's achieved in your environment, and how do you make other tools work with that setup?

I have bundler shims that are basically sh scripts that set a bunch of environment variables and then call bundler. Something like:

#!/bin/sh
GEM_HOME=/<redacted>/gems/ruby/3.0.0
BUNDLE_BIN_PATH=/<redacted>/3.0.0/gems/bundler-2.4.18/exe/bundle
BUNDLER_VERSION=2.4.18
BUNDLER_SETUP=/<redacted>/gems/ruby/3.0.0/gems/bundler-2.4.18/lib/bundler/setup
RUBYLIB=/<redacted>/gems/ruby/3.0.0/gems/bundler-2.4.18/lib
... removed for brevity ...

exec "${BUNDLE_BIN_PATH}" "$@"

Everything works seamlessly as long as this shim is used as the bundler bin.

paracycle commented 2 weeks ago

Isolation. What happens if you have projects that require conflicting versions of bundler?

This is not a problem, Bundler already handles this properly. Since the version of Bundler used to create a lockfile is encoded inside the lockfile, Bundler knows which version of Bundler it needs to run, and does so appropriately.

Even if this was a problem, you can always run Bundler using bundler _<version_of_bundler_you_want_to_run>_ and it will do the right thing:

$ bundler version
Bundler version 2.5.7 (2024-03-22 commit 199531f621)
$ bundler _2.3.23_ version
Bundler version 2.3.23 (2022-10-05 commit 250d9d485d)
g-arjones commented 2 weeks ago

you can always run Bundler using bundler __ and it will do the right thing:

How do you maKe the vscode extension do that?

What you are suggesting the exact opposite of isolation.

paracycle commented 2 weeks ago

How do you maKe the vscode extension do that?

You don't need to, is what I am trying to say.

What you are suggesting the exact opposite of isolation.

Bundler is the tool that provides the correct isolation, you don't need any extra tooling on top of it.

g-arjones commented 2 weeks ago

you don't need any extra tooling on top of it.

I do, actually. I guess I will have to workaround that by using the custom version manager feature.

Could you please clarify under which situations will the extension install the dependencies automatically and when do I have to add them to my Gemfile? I would like to use the custom version manager option and the bundleGemfile option. Do I have to modify my Gemfile in that case? Is that documented somewhere?

st0012 commented 2 weeks ago

Could you please clarify under which situations will the extension install the dependencies automatically and when do I have to add them to my Gemfile?

You don't need to add ruby-lsp to your Gemfile if you use the VS Code extension.

I would like to use the custom version manager option and the bundleFile option.

If you follow the steps here to set up your custom version manager, Ruby LSP will use the Bundler installed for that Ruby automatically.

g-arjones commented 2 weeks ago

You don't need to add ruby-lsp to your Gemfile if you use the VS Code extension.

I don't think that's correct: https://github.com/Shopify/ruby-lsp/blob/b97e2a0085ca70710eb724963b3c75be8e721f7e/vscode/src/workspace.ts#L175-L183

The extension actually expects me to add ruby-lsp to my bundle if I use the rubyLsp.bundleGemfile option:

https://github.com/Shopify/ruby-lsp/blob/b97e2a0085ca70710eb724963b3c75be8e721f7e/vscode/src/client.ts#L45-L52

Anyway, I was able to make everything work for my use case after looking at the source code to understand how the extension does things. Thanks.

st0012 commented 2 weeks ago

No we don't want users to declare ruby-lsp in their Gemfile unless that's necessary (e.g. when they use non-VS Code editors). We explained how the activation work in this section:

To avoid having users include the ruby-lsp in their Gemfile, we currently create a custom bundle under the .ruby-lsp directory inside your project. That directory contains another Gemfile, that includes the ruby-lsp gem in addition to your project's dependencies. This approach allows us to automatically detect which formatter your project uses and which gems we need to index for features such as go to definition.

g-arjones commented 2 weeks ago

@st0012 Isn't that what the server is doing? What triggers the installation of the server in the first place? In the vscode extension source code it looks pretty clear to me that the extension will try to install it by running gem install ruby-lsp (and not by creating a hidden bundle as what you posted makes it sound like) but only if rubyLsp.bundleGemfile is not set otherwise the user is expected to add it to their Gemfile. Please, see the snippets below.

https://github.com/Shopify/ruby-lsp/blob/b97e2a0085ca70710eb724963b3c75be8e721f7e/vscode/src/workspace.ts#L175-L183

https://github.com/Shopify/ruby-lsp/blob/b97e2a0085ca70710eb724963b3c75be8e721f7e/vscode/src/workspace.ts#L195-L200

https://github.com/Shopify/ruby-lsp/blob/b97e2a0085ca70710eb724963b3c75be8e721f7e/vscode/src/client.ts#L45-L52

Documentation is a bit confusing, IMHO.

paracycle commented 2 weeks ago

In the vscode extension source code it looks pretty clear to me that the extension will try to install it by running gem install ruby-lsp (and not by creating a hidden bundle as what you posted makes it sound like)

@st0012 is correct. You don't see it in the extension code because the logic for creating the hidden bundle is inside the ruby-lsp gem source code. This is so that that logic works across all editors that support the language server protocol, and not just in VSCode.

The server is installed using gem install, it is then run using ruby-lsp (no bundle exec mind you), and that execution creates and installs a new bundle inside the .ruby-lsp folder, and once that is in place replaces the running process with bundle exec ruby-lsp against that bundle. That's the mechanism.

Documentation is a bit confusing, IMHO.

Which parts of the documentation is confusing and why?

I do, actually. I guess I will have to workaround that by using the custom version manager feature.

I still don't think that I was able to fully explain that Bundler is THE isolation tool for Ruby, and that's the whole point of its existence. It feels like you are working against that by creating a more complicated set up, but I can't tell you how to set up your projects at the end of the day.

g-arjones commented 2 weeks ago

@st0012 is correct.

I'm sorry to say this but he is not. I think there's a huge misunderstanding here so I will try to explain. My question (this whole thread, actually) was about the extension (I don't understand why he mentioned something that the server is doing). To quote exactly what I asked:

Could you please clarify under which situations will the extension install the dependencies automatically and when do I have to add them to my Gemfile?

His response was:

You don't need to add ruby-lsp to your Gemfile if you use the VS Code extension.

As I mentioned before (and pointed to specific bits of the extension's source code that confirm what I was saying) when using the rubyLsp.bundleGemfile config option the extension will not install ruby-lsp.

it is then run using ruby-lsp (no bundle exec mind you)

Again, not correct. I will paste the source code one more time because I think you didn't read it:

https://github.com/Shopify/ruby-lsp/blob/b97e2a0085ca70710eb724963b3c75be8e721f7e/vscode/src/client.ts#L45-L52

There's actually a very explicit and clear comment that says:

 // If there's a user defined custom bundle, we run the LSP with `bundle exec` and just trust the user configured 
 // their bundle. Otherwise, we run the global install of the LSP and use our custom bundle logic in the server 

Which parts of the documentation is confusing and why?

It's confusing because it doesn't say I have to add ruby-lsp to my Gemfile if I set rubyLsp.bundleGemfile (I had to read the source code to find that out). @st0012 accidentally added to the confusion by pasting documentation that was not about the extension.

EDIT: This user would probably be happy with better documentation or a clear warning that he must add ruby-lsp to his Gemfile when using rubyLsp.bundleGemfile. If you check the extensions ratings on the vscode market place you will realize that you should probably reconsider how you deal with this kind of feedback because your users are having trouble getting this to even launch.

paracycle commented 2 weeks ago

This user would probably be happy with better documentation or a clear warning that he must add ruby-lsp to his Gemfile when using rubyLsp.bundleGemfile.

Sure, we can probably make the docs better for this case.

If you check the extensions ratings on the vscode market place you will realize that you should probably reconsider how you deal with this kind of feedback because your users are having trouble getting this to even launch.

That's not really a concern for us. We develop this infrastructure primarily for our developers at Shopify, and we aim to make sure that people in the community can use it as well. But, we have, on purpose, described this tool as "An opinionated language server for Ruby".

If anybody is having problems, they can open an issue describing their problem, and we can see if we have the resources to tend to that. If they give random 1 star ratings, that's not helping anyone and we certainly wouldn't be bothered about it. One can't please everyone all the time, and that's just fine.

paracycle commented 2 weeks ago

@st0012 is correct.

I'm sorry to say this but he is not. I think there's a huge misunderstanding here so I will try to explain. My question (this whole thread, actually) was about the extension (I don't understand why he mentioned something that the server is doing). To quote exactly what I asked:

Could you please clarify under which situations will the extension install the dependencies automatically and when do I have to add them to my Gemfile?

His response was:

You don't need to add ruby-lsp to your Gemfile if you use the VS Code extension.

As I mentioned before (and pointed to specific bits of the extension's source code that confirm what I was saying) when using the rubyLsp.bundleGemfile config option the extension will not install ruby-lsp.

I will repeat again that @st0012 was correct, given your question. This issue's description says "I would like to be able to set a custom bundler path.". When you asked the question:

Could you please clarify under which situations will the extension install the dependencies automatically and when do I have to add them to my Gemfile?

there was no indication that you were asking anything about a custom gemfile. The question as posed makes it sound like the question is about adding the gem to your gemfile, which something you shouldn't be doing. So @st0012 was correct in his response and for the reasons what it was so.

It was only later on that you revealed that your issue/question was about the custom gemfile solution, and in that setting, yes, you are right, you need to bring in all of your dependencies, including the ruby-lsp gem. Basically, that custom gemfile is what replaces the internal Ruby LSP bundle that the gem would have created for you, so it should be equivalent to it.

g-arjones commented 2 weeks ago

We are running around in circles.

Thank you for taking the time to engage in this discussion. I hope something good comes out of it.