Skip to content

Commit

Permalink
fix(lsp): support textDocument/didWorkspaceChange (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrcjkb authored Oct 22, 2023
1 parent 97809ad commit 507593f
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 13 deletions.
10 changes: 6 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.0.1] - 2023-10-23

### 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).

## [3.0.0] - 2023-10-22

### Changed

- Renamed this plugin to `rustaceanvim`,
to avoid potential clashes with [`vxpm/ferris.nvim`](https://github.com/vxpm/ferris.nvim),
`vxpm/ferris.nvim` was created just before I renamed my fork
Expand All @@ -17,7 +22,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [2.1.1] - 2023-10-22

### Fixed

- Open external docs: Use `xdg-open` or `open` (MacOS) by default
and fall back to `netrw`.
Remove redundant URL encoding.
Expand All @@ -40,7 +44,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [2.0.0] - 2023-10-21

### Breaking changes

- Don't pollute the command space:
Use a single command with subcommands and completions.
- `RustAnalyzer [start|stop]`
Expand All @@ -52,7 +55,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [1.0.1] - 2023-10-21

### Fixed

- Hover actions + command cache: module requires.

## [1.0.0] - 2023-10-21
Expand Down
2 changes: 1 addition & 1 deletion lua/rustaceanvim/config/internal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ local RustaceanDefaultConfig = {

--- all the opts to send to the LSP client
--- these override the defaults set by rust-tools.nvim
---class RustaceanLspClientConfig
---@class RustaceanLspClientConfig
server = {
---@type boolean | fun():boolean Whether to automatically attach the LSP client.
---Defaults to `true` if the `rust-analyzer` executable is found.
Expand Down
60 changes: 52 additions & 8 deletions lua/rustaceanvim/lsp.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local M = {}
---@type RustaceanConfig
local config = require('rustaceanvim.config.internal')
local methods = require('vim.lsp.protocol').Methods

local function override_apply_text_edits()
local old_func = vim.lsp.util.apply_text_edits
Expand All @@ -27,6 +28,8 @@ local function is_library(fname)
end
end

---@param fname string
---@return string
local function get_root_dir(fname)
local reuse_active = is_library(fname)
if reuse_active then
Expand Down Expand Up @@ -57,6 +60,7 @@ local function get_root_dir(fname)
end
if cm == 0 then
cargo_workspace_dir = vim.fn.json_decode(cargo_metadata)['workspace_root']
---@cast cargo_workspace_dir string
end
end
return cargo_workspace_dir
Expand All @@ -67,11 +71,59 @@ 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
end

for _, dir in ipairs(client.workspace_folders) do
if (root_dir .. '/'):sub(1, #dir.name + 1) == dir.name .. '/' then
return true
end
end

return false
end

-- Start or attach the LSP client
---@return integer|nil client_id The LSP client ID
M.start = function()
local client_config = config.server
---@type RustaceanLspClientConfig
local lsp_start_opts = vim.tbl_deep_extend('force', {}, client_config)
local root_dir = get_root_dir(vim.api.nvim_buf_get_name(0))
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
if not is_in_workspace(client, root_dir) then
local workspace_folder = { uri = vim.uri_from_fname(root_dir), name = root_dir }
local params = {
event = {
added = { workspace_folder },
removed = {},
},
}
client.rpc.notify(methods.workspace_didChangeWorkspaceFolders, params)
if not client.workspace_folders then
client.workspace_folders = {}
end
table.insert(client.workspace_folders, workspace_folder)
vim.lsp.buf_attach_client(0, client.id)
return
end
end

local types = require('rustaceanvim.types.internal')
local rust_analyzer_cmd = types.evaluate(client_config.cmd)
if #rust_analyzer_cmd == 0 or vim.fn.executable(rust_analyzer_cmd[1]) ~= 1 then
Expand Down Expand Up @@ -117,8 +169,6 @@ M.start = function()

lsp_start_opts.capabilities = vim.tbl_deep_extend('force', capabilities, lsp_start_opts.capabilities or {})

lsp_start_opts.root_dir = get_root_dir(vim.api.nvim_buf_get_name(0))

local custom_handlers = {}
custom_handlers['experimental/serverStatus'] = require('rustaceanvim.server_status').handler

Expand Down Expand Up @@ -162,12 +212,6 @@ M.start = function()
return vim.lsp.start(lsp_start_opts)
end

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

---Stop the LSP client.
---@return table[] clients A list of clients that will be stopped
M.stop = function()
Expand Down

0 comments on commit 507593f

Please sign in to comment.