Skip to content

Commit

Permalink
fix(lsp): compatibility with Neovim 0.9
Browse files Browse the repository at this point in the history
  • Loading branch information
mrcjkb committed Oct 22, 2023
1 parent 90b7611 commit e8b3bb6
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 23 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Add support for `workspace/didChangeWorkspaceFolders` to prevent more than one
rust-analyzer server from spawning per Neovim instance [#7](https://github.com/mrcjkb/rustaceanvim/issues/7).
- Implement `vim.fs.joinpath` for Neovim 0.9 compatibility.
- Neovim 0.9 compatibility [#9](https://github.com/mrcjkb/rustaceanvim/issues/9).

## [3.0.0] - 2023-10-22

Expand Down
12 changes: 12 additions & 0 deletions lua/rustaceanvim/compat.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---@diagnostic disable: deprecated
---@mod rustaceanvim.compat Functions for backward compatibility with older Neovim versions

local M = {}

M.joinpath = vim.fs.joinpath or function(...)
return (table.concat({ ... }, '/'):gsub('//+', '/'))
end

M.get_clients = vim.lsp.get_clients or vim.lsp.get_active_clients

return M
23 changes: 6 additions & 17 deletions lua/rustaceanvim/lsp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ local M = {}
---@type RustaceanConfig
local config = require('rustaceanvim.config.internal')
local methods = require('vim.lsp.protocol').Methods

local joinpath = vim.fs.joinpath or function(...)
return (table.concat({ ... }, '/'):gsub('//+', '/'))
end
local compat = require('rustaceanvim.compat')
local rust_analyzer = require('rustaceanvim.rust_analyzer')
local joinpath = compat.joinpath

local function override_apply_text_edits()
local old_func = vim.lsp.util.apply_text_edits
Expand All @@ -26,7 +25,7 @@ local function is_library(fname)

for _, item in ipairs { toolchains, registry } do
if fname:sub(1, #item) == item then
local clients = vim.lsp.get_clients { name = 'rust-analyzer' }
local clients = rust_analyzer.get_active_rustaceanvim_clients()
return clients[#clients].config.root_dir
end
end
Expand Down Expand Up @@ -75,16 +74,6 @@ local function get_root_dir(fname)
})[1])
end

---@param bufnr? number
---@return lsp.Client[]
local function get_active_rustaceanvim_clients(bufnr)
local filter = { name = 'rust-analyzer' }
if bufnr then
filter.bufnr = bufnr
end
return vim.lsp.get_clients(filter)
end

local function is_in_workspace(client, root_dir)
if not client.workspace_folders then
return false
Expand All @@ -109,7 +98,7 @@ M.start = function()
lsp_start_opts.root_dir = root_dir

-- Check if a client is already running and add the workspace folder if necessary.
for _, client in pairs(get_active_rustaceanvim_clients()) do
for _, client in pairs(rust_analyzer.get_active_rustaceanvim_clients()) do
if not is_in_workspace(client, root_dir) then
local workspace_folder = { uri = vim.uri_from_fname(root_dir), name = root_dir }
local params = {
Expand Down Expand Up @@ -220,7 +209,7 @@ end
---@return table[] clients A list of clients that will be stopped
M.stop = function()
local bufnr = vim.api.nvim_get_current_buf()
local clients = get_active_rustaceanvim_clients(bufnr)
local clients = rust_analyzer.get_active_rustaceanvim_clients(bufnr)
vim.lsp.stop_client(clients)
return clients
end
Expand Down
18 changes: 16 additions & 2 deletions lua/rustaceanvim/rust_analyzer.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
---@mod rustaceanvim.rust_analyzer Functions for interacting with rust-analyzer

local compat = require('rustaceanvim.compat')

---@class RustAnalyzerClientAdapter
local M = {}

---@param bufnr? number
---@return lsp.Client[]
M.get_active_rustaceanvim_clients = function(bufnr)
local filter = { name = 'rust-analyzer' }
if bufnr then
filter.bufnr = bufnr
end
return compat.get_clients(filter)
end

---@param bufnr integer Buffer handle, or 0 for current.
---@param method string LSP method name
---@param params table|nil Parameters to send to the server
Expand All @@ -10,7 +24,7 @@ M.buf_request = function(bufnr, method, params, handler)
if bufnr == nil or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
for _, client in ipairs(vim.lsp.get_clients { name = 'rust-analyzer' }) do
for _, client in ipairs(M.get_active_rustaceanvim_clients()) do
if client.supports_method(method, { bufnr = bufnr }) then
client.request(method, params, handler, bufnr)
end
Expand All @@ -20,7 +34,7 @@ end
---@param method string LSP method name
---@param params table|nil Parameters to send to the server
M.notify = function(method, params)
for _, client in ipairs(vim.lsp.get_clients { name = 'rust-analyzer' }) do
for _, client in ipairs(M.get_active_rustaceanvim_clients()) do
if client.supports_method(method) then
client.notify(method, params)
end
Expand Down
5 changes: 4 additions & 1 deletion nix/ci-overlay.nix
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@
neovim = nvim-wrapped;

# luaPackages = ps: with ps; [];
# extraPackages = [];
extraPackages = with final; [
rust-analyzer
cargo
];

preCheck = ''
export HOME=$(realpath .)
Expand Down
13 changes: 11 additions & 2 deletions spec/lsp_spec.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
local uv = vim.uv or vim.loop
-- load RustAnalyzer command
require('rustaceanvim.lsp')

local stub = require('luassert.stub')
describe('LSP client API', function()
local RustaceanConfig = require('rustaceanvim.config.internal')
local Types = require('rustaceanvim.types.internal')
local ra_bin = Types.evaluate(RustaceanConfig.server.cmd)[1]
if vim.fn.executable(ra_bin) ~= 0 then
it('Can spin up rust-analyzer.', function()
--- TODO: Figure out how to add tests for this
print('TODO')
local lsp_start = stub(vim.lsp, 'start')
vim.cmd.e('test.rs')
vim.cmd.RustAnalyzer('start')
-- TODO: Use something less flaky, e.g. a timeout
uv.sleep(5000)
assert.stub(lsp_start).was_called()
end)
end
end)

0 comments on commit e8b3bb6

Please sign in to comment.