Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(lsp): support textDocument/didWorkspaceChange #8

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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