@@ -96,13 +96,15 @@ local function is_in_workspace(client, root_dir)
9696 return false
9797end
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()
213215end
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
222225end
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+
224269local 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
232280end
233281
234282vim .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