Skip to content

Commit

Permalink
reduce complexity and make logic more concise
Browse files Browse the repository at this point in the history
  • Loading branch information
borngraced committed Oct 27, 2024
1 parent 8a7b846 commit 5d93ea2
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 58 deletions.
77 changes: 52 additions & 25 deletions lua/rustaceanvim/lsp/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ local server_status = require('rustaceanvim.server_status')
local cargo = require('rustaceanvim.cargo')
local os = require('rustaceanvim.os')

---Local rustc targets cache
local rustc_targets_cache = nil

local function override_apply_text_edits()
local old_func = vim.lsp.util.apply_text_edits
---@diagnostic disable-next-line
Expand Down Expand Up @@ -93,8 +96,37 @@ local function configure_file_watcher(server_cfg)
end
end

---Handles retrieving rustc target architectures and running the passed in callback
---to perform certain actions using the retrieved targets.
---@param callback fun(targets: string[])
local function with_rustc_target_architectures(callback)
if rustc_targets_cache then
return callback(rustc_targets_cache)
end
vim.system(
{ 'rustc', '--print', 'target-list' },
{ text = true },
---@param result vim.SystemCompleted
function(result)
if result.code ~= 0 then
error('Failed to retrieve rustc targets: ' .. result.stderr)
end
rustc_targets_cache = vim.iter(result.stdout:gmatch('[^\r\n]+')):fold(
{},
---@param acc table<string, boolean>
---@param target string
function(acc, target)
acc[target] = true
return acc
end
)
return callback(rustc_targets_cache)
end
)
end

---LSP restart internal implementations
---@param exclude_rustc_target? string Optional target architecture. Clients with target won't be restarted.
---@param exclude_rustc_target? string|nil Cargo target triple (e.g., 'x86_64-unknown-linux-gnu') to filter rust-analyzer clients
---@param callback? fun(client: vim.lsp.Client) Optional callback to run for each client before restarting.
---@return number|nil client_id
local function restart(exclude_rustc_target, callback)
Expand Down Expand Up @@ -253,11 +285,14 @@ end

---Stop the LSP client.
---@param bufnr? number The buffer number, defaults to the current buffer
---@param exclude_rustc_target? string Optional target architecture. Clients with target won't be stopped.
---@param exclude_rustc_target? string|nil Cargo target triple (e.g., 'x86_64-unknown-linux-gnu') to filter rust-analyzer clients
---@return vim.lsp.Client[] clients A list of clients that will be stopped
M.stop = function(bufnr, exclude_rustc_target)
bufnr = bufnr or vim.api.nvim_get_current_buf()
local clients = rust_analyzer.get_active_rustaceanvim_clients(bufnr, { exclude_rustc_target = exclude_rustc_target })
local clients = rust_analyzer.get_active_rustaceanvim_clients(
bufnr,
{ exclude_rustc_target = exclude_rustc_target or DEFAULT_RUSTC_TARGET }
)
vim.lsp.stop_client(clients)
if type(clients) == 'table' then
---@cast clients vim.lsp.Client[]
Expand Down Expand Up @@ -289,22 +324,21 @@ M.reload_settings = function()
end

---Updates LSP client target architecture setting.
---@param target_arch? string string The target architecture, defaults to the current buffer's target if not provided.
M.set_target_arch = function(target_arch)
-- Load target architectures if not already available
if not rust_analyzer.rustc_target_archs or rust_analyzer.os_rustc_target then
rust_analyzer.load_target_archs()
end
target_arch = target_arch or rust_analyzer.os_rustc_target
if not rust_analyzer.rustc_target_archs[target_arch] then
vim.notify('Invalid target architecture provided: ' .. tostring(target_arch), vim.log.levels.ERROR)
return
end
---@param exclude_rustc_target? string|nil Cargo target triple (e.g., 'x86_64-unknown-linux-gnu') to filter rust-analyzer clients
M.set_target_arch = function(exclude_rustc_target)
---@param client vim.lsp.Client
restart(target_arch, function(client)
client.settings['rust-analyzer'].cargo.target = target_arch
client.notify('workspace/didChangeConfiguration', { settings = client.config.settings })
vim.notify('Target architecture updated successfully to: ' .. target_arch, vim.log.levels.INFO)
restart(exclude_rustc_target, function(client)
with_rustc_target_architectures(function(rustc_targets)
if rustc_targets[exclude_rustc_target] then
client.settings['rust-analyzer'].cargo.target = exclude_rustc_target
client.notify('workspace/didchangeconfiguration', { settings = client.config.settings })
vim.notify('target architecture updated successfully to: ' .. exclude_rustc_target, vim.log.levels.info)
return
else
vim.notify('invalid target architecture provided: ' .. tostring(exclude_rustc_target), vim.log.levels.error)
return
end
end)
end)
end

Expand Down Expand Up @@ -357,11 +391,4 @@ vim.api.nvim_create_user_command('RustAnalyzer', rust_analyzer_cmd, {
end,
})

vim.api.nvim_create_autocmd('BufEnter', {
once = true,
callback = function()
rust_analyzer.load_target_archs()
end,
})

return M
66 changes: 33 additions & 33 deletions lua/rustaceanvim/rust_analyzer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,16 @@ local os = require('rustaceanvim.os')
---@class rustaceanvim.rust-analyzer.ClientAdapter
local M = {}

---Local OS rustc target architecture
M.os_rustc_target_arch = nil
---Local rustc target architectures
M.rustc_target_archs = nil
--- Default target value for rustc when no specific target is provided.
--- Used as a fallback to let rustc determine the appropriate target based on the OS.
DEFAULT_RUSTC_TARGET = 'OS'

local load_os_rustc_target_arch = function()
vim.system(
{ 'rustc', '-Vv' },
{ text = true },
---@param result vim.SystemCompleted
function(result)
if result.code ~= 0 then
error('Failed to retrieve OS rustc target: ' .. result.stderr)
end
---Local rustc targets cache
local rustc_targets_cache = nil

M.load_os_rustc_target = function()
vim.system({ 'rustc', '-Vv' }, { text = true }, function(result)
if result.code == 0 then
for line in result.stdout:gmatch('[^\r\n]+') do
local host = line:match('^host:%s*(.+)$')
if host then
Expand All @@ -27,10 +23,16 @@ local load_os_rustc_target_arch = function()
end
end
end
)
end)
end

local load_rustc_target_archs = function()
---Handles retrieving rustc target architectures and running the passed in callback
---to perform certain actions using the retrieved targets.
---@param callback fun(targets: string[])
M.with_rustc_target_architectures = function(callback)
if rustc_targets_cache then
return callback(rustc_targets_cache)
end
vim.system(
{ 'rustc', '--print', 'target-list' },
{ text = true },
Expand All @@ -39,21 +41,22 @@ local load_rustc_target_archs = function()
if result.code ~= 0 then
error('Failed to retrieve rustc targets: ' .. result.stderr)
end
M.rustc_target_archs = vim.iter(result.stdout:gmatch('[^\r\n]+')):fold({}, function(acc, target)
acc[target] = true
return acc
end)
rustc_targets_cache = vim.iter(result.stdout:gmatch('[^\r\n]+')):fold(
{},
---@param acc table<string, boolean>
---@param target string
function(acc, target)
acc[target] = true
return acc
end
)
return callback(rustc_targets_cache)
end
)
end

M.load_target_archs = function()
load_os_rustc_target_arch()
load_rustc_target_archs()
end

---@class rustaceanvim.lsp.get_clients.Filter: vim.lsp.get_clients.Filter
---@field exclude_rustc_target? string Optional cargo target to filter rust-analyzer clients
---@field exclude_rustc_target? string Cargo target triple (e.g., 'x86_64-unknown-linux-gnu') to filter rust-analyzer clients

---@param bufnr number | nil 0 for the current buffer, `nil` for no buffer filter
---@param filter? rustaceanvim.lsp.get_clients.Filter
Expand All @@ -69,16 +72,14 @@ M.get_active_rustaceanvim_clients = function(bufnr, filter)
local clients = vim.lsp.get_clients(client_filter)
if filter and filter.exclude_rustc_target then
clients = vim.tbl_filter(function(client)
--Rust analyzer uses nil for default OS target arch in config if not explicitly defined
local cargo_target_or_default = vim.tbl_get(client, 'config', 'settings', 'rust-analyzer', 'cargo', 'target')
or M.os_rustc_target
if cargo_target_or_default ~= filter.exclude_rustc_target then
return true
local cargo_target = vim.tbl_get(client, 'config', 'settings', 'rust-analyzer', 'cargo', 'target')
if filter.exclude_rustc_target == DEFAULT_RUSTC_TARGET and cargo_target == nil then
return false
end
vim.notify('Target architecture is already set to the default OS target.', vim.log.levels.INFO)
return false
return cargo_target ~= filter.exclude_rustc_target
end, clients)
end

return clients
end

Expand Down Expand Up @@ -127,7 +128,6 @@ M.get_client_for_file = function(file_path, method)
end
end
end

---@param method string LSP method name
---@param params table|nil Parameters to send to the server
M.notify = function(method, params)
Expand Down

0 comments on commit 5d93ea2

Please sign in to comment.