Skip to content

Commit 8b3c225

Browse files
Marc Jakobimrcjkb
authored andcommitted
feat(lsp): :RustAnalyzer restart command
1 parent e4020e7 commit 8b3c225

File tree

2 files changed

+64
-12
lines changed

2 files changed

+64
-12
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file.
66
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
77
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
88

9+
## [3.15.0] - 2024-01-10
10+
11+
### Added
12+
13+
- `:RustAnalyzer restart` command.
14+
915
## [3.14.0] - 2024-01-10
1016

1117
### Added

lua/rustaceanvim/lsp.lua

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,15 @@ local function is_in_workspace(client, root_dir)
9696
return false
9797
end
9898

99-
-- Start or attach the LSP client
99+
--- Start or attach the LSP client
100+
---@param bufnr? number The buffer number (optional), defaults to the current buffer
100101
---@return integer|nil client_id The LSP client ID
101-
M.start = function()
102+
M.start = function(bufnr)
103+
bufnr = bufnr or vim.api.nvim_get_current_buf()
102104
local client_config = config.server
103105
---@type RustaceanLspClientConfig
104106
local lsp_start_opts = vim.tbl_deep_extend('force', {}, client_config)
105-
local root_dir = get_root_dir(vim.api.nvim_buf_get_name(0))
107+
local root_dir = get_root_dir(vim.api.nvim_buf_get_name(bufnr))
106108
lsp_start_opts.root_dir = root_dir
107109

108110
local settings = client_config.settings
@@ -123,7 +125,7 @@ M.start = function()
123125
client.workspace_folders = {}
124126
end
125127
table.insert(client.workspace_folders, workspace_folder)
126-
vim.lsp.buf_attach_client(0, client.id)
128+
vim.lsp.buf_attach_client(bufnr, client.id)
127129
return
128130
end
129131
end
@@ -213,32 +215,76 @@ M.start = function()
213215
end
214216

215217
---Stop the LSP client.
218+
---@param bufnr? number The buffer number, defaults to the current buffer
216219
---@return table[] clients A list of clients that will be stopped
217-
M.stop = function()
218-
local bufnr = vim.api.nvim_get_current_buf()
220+
M.stop = function(bufnr)
221+
bufnr = bufnr or vim.api.nvim_get_current_buf()
219222
local clients = rust_analyzer.get_active_rustaceanvim_clients(bufnr)
220223
vim.lsp.stop_client(clients)
221224
return clients
222225
end
223226

227+
---Restart the LSP client.
228+
---Fails silently if the buffer's filetype is not one of the filetypes specified in the config.
229+
---@param bufnr? number The buffer number (optional), defaults to the current buffer
230+
---@return number|nil client_id The LSP client ID after restart
231+
M.restart = function(bufnr)
232+
bufnr = bufnr or vim.api.nvim_get_current_buf()
233+
local clients = M.stop(bufnr)
234+
local timer, _, _ = compat.uv.new_timer()
235+
if not timer then
236+
-- TODO: Log error when logging is implemented
237+
return
238+
end
239+
local attempts_to_live = 50
240+
local stopped_client_count = 0
241+
timer:start(200, 100, function()
242+
for _, client in ipairs(clients) do
243+
if client:is_stopped() then
244+
stopped_client_count = stopped_client_count + 1
245+
vim.schedule(function()
246+
M.start(bufnr)
247+
end)
248+
end
249+
end
250+
if stopped_client_count >= #clients then
251+
timer:stop()
252+
attempts_to_live = 0
253+
elseif attempts_to_live <= 0 then
254+
vim.notify('rustaceanvim.lsp: Could not restart all LSP clients.', vim.log.levels.ERROR)
255+
timer:stop()
256+
attempts_to_live = 0
257+
end
258+
attempts_to_live = attempts_to_live - 1
259+
end)
260+
end
261+
262+
---@enum RustAnalyzerCmd
263+
local RustAnalyzerCmd = {
264+
start = 'start',
265+
stop = 'stop',
266+
restart = 'restart',
267+
}
268+
224269
local function rust_analyzer_cmd(opts)
225270
local fargs = opts.fargs
226271
local cmd = fargs[1]
227-
if cmd == 'start' then
272+
---@cast cmd RustAnalyzerCmd
273+
if cmd == RustAnalyzerCmd.start then
228274
M.start()
229-
elseif cmd == 'stop' then
275+
elseif cmd == RustAnalyzerCmd.stop then
230276
M.stop()
277+
elseif cmd == RustAnalyzerCmd.restart then
278+
M.restart()
231279
end
232280
end
233281

234282
vim.api.nvim_create_user_command('RustAnalyzer', rust_analyzer_cmd, {
235283
nargs = '+',
236284
desc = 'Starts or stops the rust-analyzer LSP client',
237285
complete = function(arg_lead, cmdline, _)
238-
local commands = {
239-
'start',
240-
'stop',
241-
}
286+
---@type RustAnalyzerCmd[]
287+
local commands = vim.tbl_keys(RustAnalyzerCmd)
242288
if cmdline:match('^RustAnalyzer%s+%w*$') then
243289
return vim.tbl_filter(function(command)
244290
return command:find(arg_lead) ~= nil

0 commit comments

Comments
 (0)