rubyide / vscode-ruby

Provides Ruby language and debugging support for Visual Studio Code
https://marketplace.visualstudio.com/items?itemName=rebornix.Ruby
MIT License
1.26k stars 285 forks source link

Language server does not load gemsets from RVM correctly #451

Open peret opened 5 years ago

peret commented 5 years ago

Your environment

Expected behavior

Language server should start and start linting files with rubocop

Actual behavior

Sorry to open another one of these, but recently the language server stopped working for me on one of my systems.

Debugger listening on ws://127.0.0.1:6009/150f4a70-2974-4c7e-8591-db1d1be62a0e
For help, see: https://nodejs.org/en/docs/inspector
[Info  - 8:07:25 PM] Initializing Ruby language server...
[Info  - 8:07:25 PM] Rebuilding tree-sitter for local Electron version
[Info  - 8:07:25 PM] Rebuild succeeded!
Changed file
Lint: executing rubocop -s /Users/peter/XXXXXX/test/models/xxxxxx.rb -f json -R...
Lint: Received invalid JSON from rubocop:

Ignoring jaro_winkler-1.5.2 because its extensions are not built.  Try: gem pristine jaro_winkler --version 1.5.2
Ignoring jaro_winkler-1.5.1 because its extensions are not built.  Try: gem pristine jaro_winkler --version 1.5.1
<more lines with more gems here>

/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:120:in `require': cannot load such file -- jaro_winkler (LoadError)
    from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:120:in `require'
    from /Users/peter/.rvm/gems/ruby-2.5.3@ptcshell/gems/rubocop-0.65.0/lib/rubocop/string_util.rb:3:in `<top (required)>'
    from /Users/peter/.rvm/gems/ruby-2.5.3@ptcshell/gems/rubocop-0.65.0/lib/rubocop.rb:21:in `require_relative'
    from /Users/peter/.rvm/gems/ruby-2.5.3@ptcshell/gems/rubocop-0.65.0/lib/rubocop.rb:21:in `<top (required)>'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:68:in `require'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:68:in `require'
    from /Users/peter/.rvm/gems/ruby-2.5.3@ptcshell/gems/rubocop-0.65.0/exe/rubocop:6:in `<top (required)>'
    from /Users/peter/.rvm/gems/ruby-2.5.3@ptcshell/bin/rubocop:26:in `load'
    from /Users/peter/.rvm/gems/ruby-2.5.3@ptcshell/bin/rubocop:26:in `<main>'
    from /Users/peter/.rvm/gems/ruby-2.5.3@ptcshell/bin/ruby_executable_hooks:24:in `eval'
    from /Users/peter/.rvm/gems/ruby-2.5.3@ptcshell/bin/ruby_executable_hooks:24:in `<main>'

I'm a little at a loss on how to debug this further... Running rubocop in VS Code's integrated terminal works and all the ENV variables are looking good. What's more, I tried printing the results of which rubocop and rvm current from the code and that produces the correct output, i.e. it seems to be using the same gemset and rubocop binary as the integrated terminal. I also tried running gem pristine --all and rvm gemset pristine to no avail. Any pointers on how to drill down further would be appreciated!

mec commented 5 years ago

What version of Rubocop are you using? I have a similar problem with 0.65.0, but 0.64.0 does not seem to have this issue?

wingrunr21 commented 5 years ago

I've been seeing this problem intermittently on both Ruby 2.5 and 2.6. It does not appear to be related to the RuboCop version in my case.

My hypothesis is that it depends on how the gem is initially installed (eg via bundler or via gem install).

Either way, I'm looking into this.

peret commented 5 years ago

Hey, thanks for looking into this! For me, it also wasn't dependent on the rubocop version. I managed to fix this specific error in the meantime, although I don't quite remember what did the trick for me. I think in my case it was actually a problem with my $PATH-setup in combination with rvm. I noticed that the environment in the language server seemed to duplicate the contents of my $PATH variable and I think that was related too. Not sure whether that's expected? I'm using zsh with oh-my-zsh btw. Sorry that I can't be more specific :-/

Also, although this error seems to be gone, I still can't use the Language Server in combination with Rubocop. It works if there's only one linter running and I let it finish. If I continue typing and a second linter run interrupts the first, I get this:

Lint: executing rubocop -s /Users/peter/XXXXX/app/models/XXXXX.rb -f json -R...
Lint: executing rubocop -s /Users/peter/XXXXX/app/models/XXXXX.rb -f json -R...
events.js:167
      throw er; // Unhandled 'error' event
      ^

Error: write EPIPE
    at WriteWrap.afterWrite [as oncomplete] (net.js:833:14)
Emitted 'error' event at:
    at onwriteError (_stream_writable.js:431:12)
    at onwrite (_stream_writable.js:456:5)
    at _destroy (internal/streams/destroy.js:40:7)
    at Socket._destroy (net.js:603:3)
    at Socket.destroy (internal/streams/destroy.js:32:8)
    at WriteWrap.afterWrite [as oncomplete] (net.js:835:10)
[Info  - 9:02:09 PM] Connection to server got closed. Server will restart.
[Info  - 9:02:09 PM] Initializing Ruby language server...
[Info  - 9:02:09 PM] Rebuilding tree-sitter for local Electron version
[Info  - 9:02:09 PM] Rebuild succeeded!

I'm not sure whether it's related at all, though. Should I rather create a new ticket for this?

wingrunr21 commented 5 years ago

I'm a chruby user so I think it is something related to load paths and jaro_winkler and its native extension not being there. Not sure yet.

As to the other one, there was an issue filed before that was related to that that I can't find right now. If you could open a new issue related to this I would appreciate it!

peret commented 5 years ago

Oh, by the way, something that might be related to all these errors: I never was able to just start VS Code and having the Ruby Extension pick up the correct path to the executables (e.g. rubocop, debugger). I always have to start it from my shell in order for the extension to use the correct rvm environment. My understanding is, that that should just work out of the box. Is that correct?

peret commented 5 years ago

As to the other one, there was an issue filed before that was related to that that I can't find right now.

Oh, do you mean https://github.com/rubyide/vscode-ruby/issues/460, maybe?

wingrunr21 commented 5 years ago

Yes, it should work out of the box. It if it is not that means it is unable to set the correct environment based on the shell configuration in the workspace root directory. And actually, when you are using the language server, it explicitly ignores the VSCode environment so how VSCode is launched does not matter.

Are you by chance using Bundler v2?

peret commented 5 years ago

Interesting. So, when I start VS Code (with ruby language server enabled) via Spotlight on Mac OS, I get this error in the logs unable to execute rubocop -s /Users/peter/XXXXXX/app/models/XXXXXX.rb -f json -R as the command could not be found When I start it using code . from my workspace/project directory, it works as expected.

I am using Bundler v2, but I made the switch only recently, i.e. last week I think. So these issues were also present with previous Bundler versions.

wingrunr21 commented 5 years ago

That's interesting. Is your system default shell the same as the shell you use (eg iTerm2 has the ability to override the system default shell)?

This line is what overrides the environment. The spawn should only use the environment that we load.

Good to know on Bundler v2. I still haven't been able to figure out how to reliably reproduce this so still tracking it down.

peret commented 5 years ago

I compared the content of this.config.env at that line when starting it normally and through the terminal and they are indeed different. E.g. this is GEM_HOME when starting it through the terminal: /Users/peter/.rvm/gems/ruby-2.5.3@gemset and when starting it normally: /Users/peter/.rvm/gems/ruby-2.5.3 (without the gemset!)

When I set rvm's default Ruby to something else, the latter GEM_HOME also changes. So it looks like neither the Ruby version nor the gemset of my project are picked up by the extension :-/ I do have .ruby-version and .ruby-gemset file in my workspace root.

peret commented 5 years ago

That's interesting. Is your system default shell the same as the shell you use (eg iTerm2 has the ability to override the system default shell)?

I'm fairly sure zsh is also my default system shell, yes.

wingrunr21 commented 5 years ago

Hmm. I'm not doing anything clever when it comes to choosing between various config files. I just let the shell figure itself out and then read the environment.

Do you see correct behavior using only .ruby-version or .ruby-gemset?

peret commented 5 years ago

Hmm.. no, removing .ruby-gemset doesn't make a difference. It does break the solargraph extension though. Which made me notice, that the solargraph extension apparently picks up the correct environment no matter how I start VS Code, which I find interesting.

wingrunr21 commented 5 years ago

Solargraph is running as a Ruby process so it's got an easier time figuring this stuff out.

wingrunr21 commented 5 years ago

Do you have the .ruby-version and the .ruby-gemset files in the workspace root? For some reason RVM is not setting the environment correctly via the environment detection shim.

Also, can you give me a directory listing of ~/.vscode/extensions/rebornix.ruby-0.22.3/client/out/util/shims?

peret commented 5 years ago

Yes, they are in the workspace root.

Here's the contents of that folder and the contents of the file.

peter_—_peter_Peters-MBP_—_-zsh_—_Solarized_Dark_Yosemite_—_207×53

Manually executing that shim in my workspace root does give the expected/correct result. But apparently it doesn't in the context of the language server. So yeah, for some reason RVM doesn't do it's magic.

wingrunr21 commented 5 years ago

Hmm, interesting. My current hypothesis is spawning the shell with a working directory in the workspace root is correct for RVM to figure out the Ruby version but in order for things like gemsets to be picked up I need to actually run cd.

Note I do not think this is the same thing as the jaro_winkler issue as I have it and I'm a chruby user.

wingrunr21 commented 5 years ago

I moved the jaro_winkler issue to #470 since this discussion is more focused on the RVM issue

peret commented 5 years ago

Not sure if it's relevant, but starting a different shell (i.e. bash) and executing the script in the workspace root does not give the correct result. Could that be related to why it doesn't work? I assume that the hasbang in the script is intended to switch to the correct environment, but that doesn't seem to work? Or at least it's not enough to trigger rvm?

Regarding your hypothesis: It also doesn't pick up the ruby version correctly! That was a little unclear maybe, but I did change the default ruby to something other than 2.5.3, to test that. So, when it doesn't work, my GEM_HOME is now /Users/peter/.rvm/gems/ruby-2.4.1. So neither the version nor gemset are correct.

And you are right, of course. Thanks for the cleanup :D

wingrunr21 commented 5 years ago

Do you have bash configured to load RVM correctly and all that jazz? If your profile isn't set up then I wouldn't expect a different shell to work.

Hmm, well that's no good. So that actually means the various hooks that RVM installs into the shell are not being run. I bet I need to actually cd to that directory then.

Quick experiment:

If you modify that shim to look like this:

#!/bin/zsh -i
cd $(pwd)
export

do things change? Otherwise I'll need to spin up a test environment for RVM (need to do this anyway as I have to figure out how to write CI tests against it).

peret commented 5 years ago

No, that doesn't change it :-( It might still be a configuration error on my part. But I just tested it with a different (Ubuntu) system I have and that has the same issue at least...

tnvr000 commented 4 years ago

If it helps, Solargraph does not work untill .ruby-version and .ruby-gemset files are added.

shaunakv1 commented 4 years ago

Any resolution or workaround to make this work with rvm yet?

mattcfox commented 4 years ago

Is there any update to this @wingrunr21? It seems to have been dormant for a long time.

arianf commented 4 years ago

The Problem

Just made the switch from Sublime Text to VS Code earlier today and wanted rubocop linting. After some investigation, I think I found the issue.

Using RVM and Zsh, I've placed the RVM source command in .zshrc:

[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*

The problem is .zshrc is only loaded for interactive shells, which is why the extension doesn't have rvm, or rubocop, or anything else fun. And also why when you load the project with code . while in your interactive shell everything works.

My attempts at fixing the issue (the parts that didn't work)

I tried moving the source command into .zprofile (which will be loaded for non-interactive), but for whatever reason, rvm was loaded with the default gemset instead of the applications gemset.

So I tried installing rubocop in the default gemset, with something like:

rvm 2.5.1@default do gem install rubocop --no-doc 

The errors went away but linting still didn't work, and I'm not sure why. And without anymore errors in the logs to debug, I tried tackling this from the shim instead.

Solution

The solution I used was to modify the shim file for zsh

~/.vscode/extensions/rebornix.ruby-0.27.0/dist/server/shims/env.bin.zsh.sh

Note: You may have a different version of rebornix.ruby-0.27.0

I edited the above file to include the rvm's source command:

#!/bin/zsh -i

[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*

export

and that's all I needed to get it working. Yay!

nicolasrouanne commented 4 years ago

@arianf could you have tried adding the -l flag instead of sourcing RVM from env.bin.zsh.sh? See https://github.com/rubyide/vscode-ruby/issues/620#issuecomment-632857207.

Let me know if it works as well.

arianf commented 4 years ago

@nicolasrouanne Hmm, that flag didn't work for me

Screen Shot 2020-11-20 at 8 45 33 AM

arianf commented 4 years ago

Okay did some further testing, the -l works

For those curious, I looked up what these flags do:

$ man zshoptions

Shell State
    INTERACTIVE (-i, ksh: -i)
          This  is  an  interactive  shell.  This option is set upon initialisation if the standard input is a tty and commands are being read from standard
          input.  (See the discussion of SHIN_STDIN.)  This heuristic may be overridden by specifying a state for this option  on  the  command  line.   The
          value of this option can only be changed via flags supplied at invocation of the shell.  It cannot be changed once zsh is running.

    LOGIN (-l, ksh: -l)
          This  is a login shell.  If this option is not explicitly set, the shell becomes a login shell if the first character of the argv[0] passed to the
          shell is a `-'.

The -l works to resolve my earlier attempt at fixing it via moving my rvm source command into .zprofile

[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*

So here's what I did.

~/.zshrc

# other zsh config stuff

# removed rvm from ~/.zshrc and moving it to ~/.zprofile
# [[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*

~/.zprofile

[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*

~/.vscode/extensions/rebornix.ruby-0.27.0/dist/server/shims/env.bin.zsh.sh

#!/bin/zsh -i -l
export
nicolasrouanne commented 4 years ago

@arianf Nice, Thanks. So I guess we could open a PR with -l per default. I don't know if there are side effects to defaulting to login shell. Will be waiting for answer to https://github.com/rubyide/vscode-ruby/issues/620#issuecomment-731101922

peyloride commented 3 years ago
#!/bin/zsh -i -l
export

I think -i parameter should removed, I got error when I tried to do that like below; /bin/zsh: bad option string: '-i -l'

Then i simply removed -i option and it worked.