mason.nvim icon indicating copy to clipboard operation
mason.nvim copied to clipboard

Using solargraph through mason.nvim

Open renatolond opened this issue 1 year ago • 9 comments

I've searched open issues for similar requests

  • [X] Yes

I've manually reviewed logs to find potential errors

  • [X] Yes

I've recently downloaded the latest plugin version of mason.nvim

  • [X] Yes

Problem description

I use multiple versions of ruby in my day-to-day. If I install solargraph through mason, it will create a folder with vendored versions of the gems and then it starts giving errors such as this one:

[ERROR][2023-05-09 12:10:19] .../vim/lsp/rpc.lua:734	"rpc"	"solargraph"	"stderr"	"#<Thread:0x00007f0da313f508 /home/renatolond/.local/share/nvim/mason/packages/solargraph/gems/solargraph-0.49.0/lib/solargraph/language_server/host/message_worker.rb:43 run> terminated with exception (report_on_exception is true):\n<internal:/home/renatolond/.rvm/rubies/ruby-3.2.2-jemalloc/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require': linked to incompatible /home/renatolond/.rvm/rubies/ruby-3.1.4-jemalloc/lib/libruby.so.3.1 - /home/renatolond/.local/share/nvim/mason/packages/solargraph/gems/rbs-2.8.4/lib/rbs_extension.so (LoadError)\n\tfrom <internal:/home/renatolond/.rvm/rubies/ruby-3.2.2-jemalloc/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:85:in `require'\n"

rbs is linked to ruby a 3.1 so and that's not compatible. Removing the generated solargraph folder fixes the issue (I then can install solargraph manually in each of the versions)

Expected behavior

I'm not really sure what's the expected behavior here, should mason refuse to install solargraph if it detects a rvm or rbenv? Or try to install through those?

Steps to reproduce

  1. Using rvm, select version 3.1 of ruby, open nvim and install solargraph
  2. exit nvim, switch to version 3.2 and open nvim again

Affected packages

solargraph

Neovim version (>= 0.7)

NVIM v0.9.0 Build type: Release LuaJIT 2.1.0-beta3

Operating system/version

Linux 6.3.1-arch1-1 #1 SMP PREEMPT_DYNAMIC Mon, 01 May 2023 17:42:39 +0000 x86_64 GNU/Linux [

Healthcheck

==============================================================================
mason: require("mason.health").check()

mason.nvim ~
- OK mason.nvim version v1.0.1
- OK neovim version >= 0.7.0

mason.nvim [Registries] ~
- OK Registry `github.com/mason-org/mason-registry version: 2023-05-08-intact-susan` is installed.

mason.nvim [Core utils] ~
- OK unzip: `UnZip 6.00 of 20 April 2009, by Info-ZIP.  Maintained by C. Spieler.  Send`
- OK wget: `GNU Wget 1.21.3 built on linux-gnu.`
- OK curl: `curl 8.0.1 (x86_64-pc-linux-gnu) libcurl/8.0.1 OpenSSL/3.0.8 zlib/1.2.13 brotli/1.0.9 zstd/1.5.5 libidn2/2.3.4 libpsl/0.21.2 (+libidn2/2.3.4) libssh2/1.10.0 nghttp2/1.52.0`
- OK gzip: `gzip 1.12`
- OK tar: `tar (GNU tar) 1.34`
- OK bash: `GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)`
- OK sh: `Ok`

mason.nvim [Languages] ~
- WARNING luarocks: not available
  - ADVICE:
    - spawn: luarocks failed with exit code - and signal -. luarocks is not executable
- WARNING Composer: not available
  - ADVICE:
    - spawn: composer failed with exit code - and signal -. composer is not executable
- WARNING PHP: not available
  - ADVICE:
    - spawn: php failed with exit code - and signal -. php is not executable
- OK Ruby: `ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]`
- OK Go: `go version go1.20.4 linux/amd64`
- OK cargo: `cargo 1.69.0`
- OK node: `v16.20.0`
- WARNING julia: not available
  - ADVICE:
    - spawn: julia failed with exit code - and signal -. julia is not executable
- OK python3: `Python 3.11.3`
- OK java: `openjdk version "20.0.1" 2023-04-18`
- OK javac: `javac 20.0.1`
- OK RubyGem: `3.4.10`
- OK npm: `8.19.2`
- OK pip3: `pip 23.1.2 from /usr/lib/python3.11/site-packages/pip (python 3.11)`

mason.nvim [GitHub] ~
- OK GitHub API rate limit. Used: 0. Remaining: 60. Limit: 60. Reset: Tue 09 May 2023 14:11:53.
  Install and authenticate via gh-cli to increase rate limit.

Screenshots or recordings

No response

renatolond avatar May 09 '23 11:05 renatolond

i think you may be at a limitation of rvm on this one or even mason 🤔. were you expecting solargraph installed within your 3.1 installation to work with your ruby 3.2.2 installation?

i spent a few hours working with solargraph yesterday, and opted not to install it via mason but to install it using gem install and updating my neovim config accordingly, keep in mind this is all new to me. i'll paste my neovim config below pertaining to this. obviously you'd have to adjust the ruby version in your neovim config to work with the version you're using for your particular ruby project (less than ideal).

and then all of that kindof begs the question is mason handled / setup to work with multiple versions of ruby especially if one (the $USER) uses a ruby version manager such as rvm, asdf, or even chruby.

-- PLUGIN / neovim native lsp / ruby / solargraph
require'lspconfig'.solargraph.setup{
  -- cmd = { os.getenv( "HOME" ) .. "/.rvm/shims/solargraph", 'stdio' },
  cmd = { os.getenv( "HOME" ) .. "/.rvm/gems/ruby-3.2.2/wrappers/solargraph", 'stdio' },
  root_dir = nvim_lsp.util.root_pattern("Gemfile", ".git", "."),
  settings = {
    solargraph = {
      autoformat = false,
      formatting = false,
      completion = true,
      diagnostic = true,
      folding = true,
      references = true,
      rename = true,
      symbols = true
    }
  }
}

hope that helps

ipatch avatar Aug 17 '23 16:08 ipatch

Well, I don't expect it to work across versions, but it took me a while to debug the issue (I did not know originally that mason was installing solargraph by itself on a separate folder).

I think what I would expect is that mason reaches for the installed solargraph version if it detects one (which was installed in my rvm installation already), more than that, maybe it should install the solargraph gem in the default user dir instead of a particular mason dir (this would avoid the issue of pulling dependencies from a different ruby version).

I've been using it without installing through mason and it works fine, but for me it's more the installation step that is a bit unexpected.

renatolond avatar Aug 18 '23 08:08 renatolond

This is a recurring issue of sorts, but this specific case is solved by instructing RubyGems to enforce /usr/bin/env ruby shebang.

❯ cat .gemrc
install: --env-shebang
update: --env-shebang

This will force all binstubs for the installed gems to use /usr/bin/env ruby instead of whatever ruby is enabled at the moment of installation. Solargraph is fairly self-sufficient and should work just ok afterwards.

correction edit: Got a bit ahead of myself here in my glee of having figured out a problem I previously gave up on - shebang specificity. The overall problem of version switching is not solved with this. Solargraph won't work after switching ruby versions due to missing native extensions on key gems it relies on. What's worse, it will not work while keeping silent (nothing mason can do about it).

As a temporary workaround, updating it from :Mason UI will compile native extensions and fix it for the currently used ruby version. This does break it for every other version, though, so not much of an improvement here.


I do agree with the way Mason handles LSP servers installs - they are not language libraries, they are purpose installed tools. In said context, this specific issue could be dealt with by tracking specific ruby versions, and auto-installing ruby tools that are supposed to be installed when they are not detected in the current version.

Slotos avatar Oct 19 '23 14:10 Slotos

After some time, I was able to figure out a work-around solution for this issue using rvm. I can confirm this works with multiple applications with multiple ruby versions at the same time. When nvim starts, a new instance of solargraph will start automatically.

local nvim_lsp = require("lspconfig")
local capabilities = require('cmp_nvim_lsp').default_capabilities()

local handlers = {
    ["textDocument/publishDiagnostics"] = vim.lsp.with(
        vim.lsp.diagnostic.on_publish_diagnostics, {
            virtual_text = true
        }
    )
}

nvim_lsp.solargraph.setup {
    cmd = {
        "rvm",
        "@global",
        "do",
        "solargraph",
        "stdio"
    },
    filetypes = {
        "ruby"
    },
    flags = {
        debounce_text_changes = 150
    },
    --on_attach = on_attach,
    root_dir = nvim_lsp.util.root_pattern("Gemfile", ".git", "."),
    capabilities = capabilities,
    handlers = handlers,
    settings = {
        solargraph = {
            completion = true,
            autoformat = false,
            formatting = true,
            symbols = true,
            definitions = true,
            references = true,
            folding = true,
            highlights = true,
            diagnostics = true,
            rename = true,
            -- Enable this when running with docker compose
            --transport = 'external',
            --externalServer = {
            --    host = 'localhost',
            --    port = '7658',
            --}
        }
    }
}

Unfortunately, this does require installing solargraph manually in each ruby's @global gemset for the first time.

rvm use ruby-3.1.4
rvm @gloabl do gem install solargraph
rvm @global do gem regenerate_binstubs

* This is not a fix, just a work around to circumvent the mason's installed version of solargraph.

rnickmccandless avatar Nov 15 '23 05:11 rnickmccandless

I was curious how to handle this problem, because I'm certain that this will be a similar problem in any other programming languages that use a version manager (I'm thinking like node projects).

This problem is solved in VSCode by Shopify's vscode-ruby-lsp extension. That extension seems to:

  1. detect version manager (rvm, rbenv, asdf, etc)
  2. activate the correct Ruby version for that project/workspace
  3. attempt to install or update the LSP server (ruby-lsp in this case)

I think if Mason were to want to solve this for a variety of languages, that general flow should be do-able.

hectron avatar Jan 29 '24 21:01 hectron

Unfortunatelly also had to disable in mason to work with rvm.

So, some other home-made solution. Save it e.g. as ~/bin/auto-ruby-lsp.

#!/bin/sh

LOG=~/auto-ruby-lsp.log
TODAY=$(date '+%Y-%m-%d')

gem_version() {
  gem search ruby-lsp "$1" --exact | sed 's/^ruby-lsp (\(.*\))/\1/'
}

# refresh log every day and fetch latest lsp version
if ! grep -q "$TODAY" "$LOG" 2> /dev/null; then
  gem_version --remote > $LOG
fi

LSP_LOCAL=$(gem_version --local)
LSP_REMOTE=$(head -1 $LOG)

echo "[$(date '+%Y-%m-%d %H:%M:%S')] $(pwd) $LSP_LOCAL" >> $LOG

if [ -z "$LSP_LOCAL" ]; then
  gem install ruby-lsp >> $LOG
elif [ "$LSP_LOCAL" != "$LSP_REMOTE" ]; then
  gem update ruby-lsp >> $LOG
fi

ruby-lsp

It installs ruby-lsp if requested and lazily updates daily if needed.

Then in neovim just need require('ruby-lsp').setup({ cmd = { 'auto-ruby-lsp' })

Maybe mason sometimes can have some similar logic (or option vs installing into own folders).

dzirtusss avatar Feb 21 '24 11:02 dzirtusss

Had trouble with this as well. If anybody is using AstroNvim, the way I resolved this was to put it in the user config's init.lua to override thecmd to run solargraph. With this, you can still use the mason installed solargraph.

My environment is using chruby as the version manager, and using ruby-3.2.2 as the version running solargraph. You can change that as needed.

As mentioned earlier, you do still need to install solargraph LSP using mason.

Here's my config at ~/config/nvim/lua/user/init.lua

return {
  ...
  lsp = {
    ...
    config = {
      solargraph = function()
        return {
          cmd = {
            "chruby-exec",
            "ruby-3.2.2",
            "--",
            "solargraph",
            "stdio"
          }
        }
      end
    }
  }
  ...
}

dukz avatar Mar 30 '24 07:03 dukz

I can't seem to make it work to use the correct ruby version based on the project. Solargraph is installed but it doesn't get connected to the buffer.

patrykk21 avatar Apr 15 '24 13:04 patrykk21

For people using asdf as version manager, I am able to make a workaround with the same concept as described in Comment - Issue 1292. Here are the relevant parts

local server_options = {
  cmd = {
    "asdf",
    "exec",
    "solargraph",
    "stdio"
  },
  capabilities = capabilities,
  on_init = on_init,
...
}

lspconfig.solargraph.setup(server_options)

praveendhawan avatar Apr 29 '24 10:04 praveendhawan