From 4eacda9a7a615551a0e370b59db71ec14fad49b3 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Wed, 16 Oct 2024 00:42:29 +0100 Subject: [PATCH 1/8] implement change target arch support --- doc/rustaceanvim.txt | 3 + lua/rustaceanvim/init.lua | 4 + lua/rustaceanvim/lsp/init.lua | 55 +++++- lua/rustaceanvim/lsp/targets.lua | 292 +++++++++++++++++++++++++++++++ 4 files changed, 353 insertions(+), 1 deletion(-) create mode 100644 lua/rustaceanvim/lsp/targets.lua diff --git a/doc/rustaceanvim.txt b/doc/rustaceanvim.txt index 2c9e45a1..aa81b141 100644 --- a/doc/rustaceanvim.txt +++ b/doc/rustaceanvim.txt @@ -24,6 +24,9 @@ Commands: ':RustAnalyzer stop' - Stop the LSP client. ':RustAnalyzer restart' - Restart the LSP client. ':RustAnalyzer reloadSettings' - Reload settings for the LSP client. + ':RustAnalyzer target ' - Set the target architecture for the LSP client. + +The ':RustAnalyzer target' command can take a valid rustc target, such as 'wasm32-unknown-unknown', or it can be left empty to set the LSP client to use the default target architecture for the operating system. The ':RustLsp[!]' command is available after the LSP client has initialized. It accepts the following subcommands: diff --git a/lua/rustaceanvim/init.lua b/lua/rustaceanvim/init.lua index 22050a46..723cb4f8 100644 --- a/lua/rustaceanvim/init.lua +++ b/lua/rustaceanvim/init.lua @@ -16,6 +16,10 @@ --- ':RustAnalyzer stop' - Stop the LSP client. --- ':RustAnalyzer restart' - Restart the LSP client. --- ':RustAnalyzer reloadSettings' - Reload settings for the LSP client. +--- ':RustAnalyzer target ' - Set the target architecture for the LSP client. + +--- The ':RustAnalyzer target' command can take a valid rustc target, such as 'wasm32-unknown-unknown', +--- or it can be left empty to set the LSP client to use the default target architecture for the operating system. --- ---The ':RustLsp[!]' command is available after the LSP client has initialized. ---It accepts the following subcommands: diff --git a/lua/rustaceanvim/lsp/init.lua b/lua/rustaceanvim/lsp/init.lua index 4770d451..0b9fd442 100644 --- a/lua/rustaceanvim/lsp/init.lua +++ b/lua/rustaceanvim/lsp/init.lua @@ -6,6 +6,7 @@ local rust_analyzer = require('rustaceanvim.rust_analyzer') local server_status = require('rustaceanvim.server_status') local cargo = require('rustaceanvim.cargo') local os = require('rustaceanvim.os') +local targets = require('rustaceanvim.lsp.targets') local function override_apply_text_edits() local old_func = vim.lsp.util.apply_text_edits @@ -249,11 +250,55 @@ M.reload_settings = function(bufnr) return clients end +---Updates the target architecture setting for the LSP client associated with the given buffer. +---@param bufnr? number The buffer number, defaults to the current buffer +---@param target? string The target architecture. Defaults to the current buffer's target if not provided. +M.set_target_arch = function(bufnr, target) + local function update_target(client) + -- Get the current target from the client's settings + local current_target = client.config.settings + and client.config.settings['rust-analyzer'] + and client.config.settings['rust-analyzer'].cargo + and client.config.settings['rust-analyzer'].cargo.target + + if not target then + if not current_target then + vim.notify('Using default OS target architecture.', vim.log.levels.INFO) + else + vim.notify('Target architecture is already set to the default OS target.', vim.log.levels.INFO) + end + return + end + + if targets.target_is_valid_rustc_target(target) then + client.settings['rust-analyzer'].cargo.target = target + client.notify('workspace/didChangeConfiguration', { settings = client.config.settings }) + vim.notify('Target architecture updated successfully to: ' .. target, vim.log.levels.INFO) + return + else + -- TODO: Log error when logging is implemented + vim.notify('Invalid target architecture provided: ' .. tostring(target), vim.log.levels.ERROR) + return + end + end + + M.restart_impl(bufnr, update_target) +end + ---Restart the LSP client. ---Fails silently if the buffer's filetype is not one of the filetypes specified in the config. ---@param bufnr? number The buffer number (optional), defaults to the current buffer ---@return number|nil client_id The LSP client ID after restart M.restart = function(bufnr) + M.restart_impl(bufnr) +end + +---LSP restart ininer implementations +---@param bufnr? number +---@param set_target_callback? function(client) Optional callback to run for each client before restarting. +---@return number|nil client_id +M.restart_impl = function(bufnr, set_target_callback) + -- TODO: handle case for when requested target change is the same as client active active so we don't restart clients unnecessarily bufnr = bufnr or vim.api.nvim_get_current_buf() local clients = M.stop(bufnr) local timer, _, _ = vim.uv.new_timer() @@ -268,6 +313,10 @@ M.restart = function(bufnr) if client:is_stopped() then stopped_client_count = stopped_client_count + 1 vim.schedule(function() + -- Execute the callback, if provided, for additional actions before restarting + if set_target_callback then + set_target_callback(client) + end M.start(bufnr) end) end @@ -290,11 +339,13 @@ local RustAnalyzerCmd = { stop = 'stop', restart = 'restart', reload_settings = 'reloadSettings', + target = 'target', } local function rust_analyzer_cmd(opts) local fargs = opts.fargs local cmd = fargs[1] + local arch = fargs[2] ---@cast cmd RustAnalyzerCmd if cmd == RustAnalyzerCmd.start then M.start() @@ -304,12 +355,14 @@ local function rust_analyzer_cmd(opts) M.restart() elseif cmd == RustAnalyzerCmd.reload_settings then M.reload_settings() + elseif cmd == RustAnalyzerCmd.target then + M.set_target_arch(nil, arch) end end vim.api.nvim_create_user_command('RustAnalyzer', rust_analyzer_cmd, { nargs = '+', - desc = 'Starts or stops the rust-analyzer LSP client', + desc = 'Starts, stops the rust-analyzer LSP client or change target', complete = function(arg_lead, cmdline, _) local clients = rust_analyzer.get_active_rustaceanvim_clients() ---@type RustAnalyzerCmd[] diff --git a/lua/rustaceanvim/lsp/targets.lua b/lua/rustaceanvim/lsp/targets.lua new file mode 100644 index 00000000..dd559b0d --- /dev/null +++ b/lua/rustaceanvim/lsp/targets.lua @@ -0,0 +1,292 @@ +local T = {} + +local rustc_targets = { + 'aarch64-apple-darwin', + 'aarch64-apple-ios', + 'aarch64-apple-ios-macabi', + 'aarch64-apple-ios-sim', + 'aarch64-apple-tvos', + 'aarch64-apple-tvos-sim', + 'aarch64-apple-visionos', + 'aarch64-apple-visionos-sim', + 'aarch64-apple-watchos', + 'aarch64-apple-watchos-sim', + 'aarch64-fuchsia', + 'aarch64-kmc-solid_asp3', + 'aarch64-linux-android', + 'aarch64-nintendo-switch-freestanding', + 'aarch64-pc-windows-gnullvm', + 'aarch64-pc-windows-msvc', + 'aarch64-unknown-freebsd', + 'aarch64-unknown-fuchsia', + 'aarch64-unknown-hermit', + 'aarch64-unknown-illumos', + 'aarch64-unknown-linux-gnu', + 'aarch64-unknown-linux-gnu_ilp32', + 'aarch64-unknown-linux-musl', + 'aarch64-unknown-linux-ohos', + 'aarch64-unknown-netbsd', + 'aarch64-unknown-none', + 'aarch64-unknown-none-softfloat', + 'aarch64-unknown-nto-qnx700', + 'aarch64-unknown-nto-qnx710', + 'aarch64-unknown-openbsd', + 'aarch64-unknown-redox', + 'aarch64-unknown-teeos', + 'aarch64-unknown-trusty', + 'aarch64-unknown-uefi', + 'aarch64-uwp-windows-msvc', + 'aarch64-wrs-vxworks', + 'aarch64_be-unknown-linux-gnu', + 'aarch64_be-unknown-linux-gnu_ilp32', + 'aarch64_be-unknown-netbsd', + 'arm-linux-androideabi', + 'arm-unknown-linux-gnueabi', + 'arm-unknown-linux-gnueabihf', + 'arm-unknown-linux-musleabi', + 'arm-unknown-linux-musleabihf', + 'arm64_32-apple-watchos', + 'arm64e-apple-darwin', + 'arm64e-apple-ios', + 'arm64ec-pc-windows-msvc', + 'armeb-unknown-linux-gnueabi', + 'armebv7r-none-eabi', + 'armebv7r-none-eabihf', + 'armv4t-none-eabi', + 'armv4t-unknown-linux-gnueabi', + 'armv5te-none-eabi', + 'armv5te-unknown-linux-gnueabi', + 'armv5te-unknown-linux-musleabi', + 'armv5te-unknown-linux-uclibceabi', + 'armv6-unknown-freebsd', + 'armv6-unknown-netbsd-eabihf', + 'armv6k-nintendo-3ds', + 'armv7-linux-androideabi', + 'armv7-rtems-eabihf', + 'armv7-sony-vita-newlibeabihf', + 'armv7-unknown-freebsd', + 'armv7-unknown-linux-gnueabi', + 'armv7-unknown-linux-gnueabihf', + 'armv7-unknown-linux-musleabi', + 'armv7-unknown-linux-musleabihf', + 'armv7-unknown-linux-ohos', + 'armv7-unknown-linux-uclibceabi', + 'armv7-unknown-linux-uclibceabihf', + 'armv7-unknown-netbsd-eabihf', + 'armv7-unknown-trusty', + 'armv7-wrs-vxworks-eabihf', + 'armv7a-kmc-solid_asp3-eabi', + 'armv7a-kmc-solid_asp3-eabihf', + 'armv7a-none-eabi', + 'armv7a-none-eabihf', + 'armv7k-apple-watchos', + 'armv7r-none-eabi', + 'armv7r-none-eabihf', + 'armv7s-apple-ios', + 'armv8r-none-eabihf', + 'avr-unknown-gnu-atmega328', + 'bpfeb-unknown-none', + 'bpfel-unknown-none', + 'csky-unknown-linux-gnuabiv2', + 'csky-unknown-linux-gnuabiv2hf', + 'hexagon-unknown-linux-musl', + 'hexagon-unknown-none-elf', + 'i386-apple-ios', + 'i586-pc-nto-qnx700', + 'i586-pc-windows-msvc', + 'i586-unknown-linux-gnu', + 'i586-unknown-linux-musl', + 'i586-unknown-netbsd', + 'i686-apple-darwin', + 'i686-linux-android', + 'i686-pc-windows-gnu', + 'i686-pc-windows-gnullvm', + 'i686-pc-windows-msvc', + 'i686-unknown-freebsd', + 'i686-unknown-haiku', + 'i686-unknown-hurd-gnu', + 'i686-unknown-linux-gnu', + 'i686-unknown-linux-musl', + 'i686-unknown-netbsd', + 'i686-unknown-openbsd', + 'i686-unknown-redox', + 'i686-unknown-uefi', + 'i686-uwp-windows-gnu', + 'i686-uwp-windows-msvc', + 'i686-win7-windows-msvc', + 'i686-wrs-vxworks', + 'loongarch64-unknown-linux-gnu', + 'loongarch64-unknown-linux-musl', + 'loongarch64-unknown-none', + 'loongarch64-unknown-none-softfloat', + 'm68k-unknown-linux-gnu', + 'mips-unknown-linux-gnu', + 'mips-unknown-linux-musl', + 'mips-unknown-linux-uclibc', + 'mips64-openwrt-linux-musl', + 'mips64-unknown-linux-gnuabi64', + 'mips64-unknown-linux-muslabi64', + 'mips64el-unknown-linux-gnuabi64', + 'mips64el-unknown-linux-muslabi64', + 'mipsel-sony-psp', + 'mipsel-sony-psx', + 'mipsel-unknown-linux-gnu', + 'mipsel-unknown-linux-musl', + 'mipsel-unknown-linux-uclibc', + 'mipsel-unknown-netbsd', + 'mipsel-unknown-none', + 'mipsisa32r6-unknown-linux-gnu', + 'mipsisa32r6el-unknown-linux-gnu', + 'mipsisa64r6-unknown-linux-gnuabi64', + 'mipsisa64r6el-unknown-linux-gnuabi64', + 'msp430-none-elf', + 'nvptx64-nvidia-cuda', + 'powerpc-unknown-freebsd', + 'powerpc-unknown-linux-gnu', + 'powerpc-unknown-linux-gnuspe', + 'powerpc-unknown-linux-musl', + 'powerpc-unknown-linux-muslspe', + 'powerpc-unknown-netbsd', + 'powerpc-unknown-openbsd', + 'powerpc-wrs-vxworks', + 'powerpc-wrs-vxworks-spe', + 'powerpc64-ibm-aix', + 'powerpc64-unknown-freebsd', + 'powerpc64-unknown-linux-gnu', + 'powerpc64-unknown-linux-musl', + 'powerpc64-unknown-openbsd', + 'powerpc64-wrs-vxworks', + 'powerpc64le-unknown-freebsd', + 'powerpc64le-unknown-linux-gnu', + 'powerpc64le-unknown-linux-musl', + 'riscv32gc-unknown-linux-gnu', + 'riscv32gc-unknown-linux-musl', + 'riscv32i-unknown-none-elf', + 'riscv32im-risc0-zkvm-elf', + 'riscv32im-unknown-none-elf', + 'riscv32ima-unknown-none-elf', + 'riscv32imac-esp-espidf', + 'riscv32imac-unknown-none-elf', + 'riscv32imac-unknown-nuttx-elf', + 'riscv32imac-unknown-xous-elf', + 'riscv32imafc-esp-espidf', + 'riscv32imafc-unknown-none-elf', + 'riscv32imafc-unknown-nuttx-elf', + 'riscv32imc-esp-espidf', + 'riscv32imc-unknown-none-elf', + 'riscv32imc-unknown-nuttx-elf', + 'riscv64-linux-android', + 'riscv64gc-unknown-freebsd', + 'riscv64gc-unknown-fuchsia', + 'riscv64gc-unknown-hermit', + 'riscv64gc-unknown-linux-gnu', + 'riscv64gc-unknown-linux-musl', + 'riscv64gc-unknown-netbsd', + 'riscv64gc-unknown-none-elf', + 'riscv64gc-unknown-nuttx-elf', + 'riscv64gc-unknown-openbsd', + 'riscv64imac-unknown-none-elf', + 'riscv64imac-unknown-nuttx-elf', + 's390x-unknown-linux-gnu', + 's390x-unknown-linux-musl', + 'sparc-unknown-linux-gnu', + 'sparc-unknown-none-elf', + 'sparc64-unknown-linux-gnu', + 'sparc64-unknown-netbsd', + 'sparc64-unknown-openbsd', + 'sparcv9-sun-solaris', + 'thumbv4t-none-eabi', + 'thumbv5te-none-eabi', + 'thumbv6m-none-eabi', + 'thumbv6m-nuttx-eabi', + 'thumbv7a-pc-windows-msvc', + 'thumbv7a-uwp-windows-msvc', + 'thumbv7em-none-eabi', + 'thumbv7em-none-eabihf', + 'thumbv7em-nuttx-eabi', + 'thumbv7em-nuttx-eabihf', + 'thumbv7m-none-eabi', + 'thumbv7m-nuttx-eabi', + 'thumbv7neon-linux-androideabi', + 'thumbv7neon-unknown-linux-gnueabihf', + 'thumbv7neon-unknown-linux-musleabihf', + 'thumbv8m.base-none-eabi', + 'thumbv8m.base-nuttx-eabi', + 'thumbv8m.main-none-eabi', + 'thumbv8m.main-none-eabihf', + 'thumbv8m.main-nuttx-eabi', + 'thumbv8m.main-nuttx-eabihf', + 'wasm32-unknown-emscripten', + 'wasm32-unknown-unknown', + 'wasm32-wasi', + 'wasm32-wasip1', + 'wasm32-wasip1-threads', + 'wasm32-wasip2', + 'wasm64-unknown-unknown', + 'x86_64-apple-darwin', + 'x86_64-apple-ios', + 'x86_64-apple-ios-macabi', + 'x86_64-apple-tvos', + 'x86_64-apple-watchos-sim', + 'x86_64-fortanix-unknown-sgx', + 'x86_64-fuchsia', + 'x86_64-linux-android', + 'x86_64-pc-nto-qnx710', + 'x86_64-pc-solaris', + 'x86_64-pc-windows-gnu', + 'x86_64-pc-windows-gnullvm', + 'x86_64-pc-windows-msvc', + 'x86_64-unikraft-linux-musl', + 'x86_64-unknown-dragonfly', + 'x86_64-unknown-freebsd', + 'x86_64-unknown-fuchsia', + 'x86_64-unknown-haiku', + 'x86_64-unknown-hermit', + 'x86_64-unknown-hurd-gnu', + 'x86_64-unknown-illumos', + 'x86_64-unknown-l4re-uclibc', + 'x86_64-unknown-linux-gnu', + 'x86_64-unknown-linux-gnux32', + 'x86_64-unknown-linux-musl', + 'x86_64-unknown-linux-none', + 'x86_64-unknown-linux-ohos', + 'x86_64-unknown-netbsd', + 'x86_64-unknown-none', + 'x86_64-unknown-openbsd', + 'x86_64-unknown-redox', + 'x86_64-unknown-uefi', + 'x86_64-uwp-windows-gnu', + 'x86_64-uwp-windows-msvc', + 'x86_64-win7-windows-msvc', + 'x86_64-wrs-vxworks', + 'x86_64h-apple-darwin', + 'xtensa-esp32-espidf', + 'xtensa-esp32-none-elf', + 'xtensa-esp32s2-espidf', + 'xtensa-esp32s2-none-elf', + 'xtensa-esp32s3-espidf', + 'xtensa-esp32s3-none-elf', +} + +--- Validates if the provided target is a valid Rust compiler (rustc) target. +--- If no target is provided, it defaults to the system's architecture. +---@param target? string +---@return boolean +T.target_is_valid_rustc_target = function(target) + -- If target is nil, return true to let rust-analyzer use the default target architecture for the system + if target == nil then + return true + end + + -- Iterate through the available rustc targets and check if the target matches + for _, val in ipairs(rustc_targets) do + if val == target then + return true + end + end + + -- Return false if no matching target is found + return false +end + +return T From cc3bbf4d26d02cc21cd17753e5d255c228346027 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Wed, 16 Oct 2024 01:54:07 +0100 Subject: [PATCH 2/8] fix review notes --- lua/rustaceanvim/init.lua | 5 +- lua/rustaceanvim/lsp/init.lua | 91 +++++----- lua/rustaceanvim/lsp/targets.lua | 303 +++---------------------------- 3 files changed, 73 insertions(+), 326 deletions(-) diff --git a/lua/rustaceanvim/init.lua b/lua/rustaceanvim/init.lua index 723cb4f8..bf7ee927 100644 --- a/lua/rustaceanvim/init.lua +++ b/lua/rustaceanvim/init.lua @@ -18,8 +18,9 @@ --- ':RustAnalyzer reloadSettings' - Reload settings for the LSP client. --- ':RustAnalyzer target ' - Set the target architecture for the LSP client. ---- The ':RustAnalyzer target' command can take a valid rustc target, such as 'wasm32-unknown-unknown', ---- or it can be left empty to set the LSP client to use the default target architecture for the operating system. +--- The ':RustAnalyzer target' command can take a valid rustc target, +--- such as 'wasm32-unknown-unknown', or it can be left empty to set the LSP client +--- to use the default target architecture for the operating system. --- ---The ':RustLsp[!]' command is available after the LSP client has initialized. ---It accepts the following subcommands: diff --git a/lua/rustaceanvim/lsp/init.lua b/lua/rustaceanvim/lsp/init.lua index 0b9fd442..2bbff969 100644 --- a/lua/rustaceanvim/lsp/init.lua +++ b/lua/rustaceanvim/lsp/init.lua @@ -94,6 +94,45 @@ local function configure_file_watcher(server_cfg) end end +---LSP restart ininer implementations +---@param bufnr? number +---@param set_target_callback? function(client) Optional callback to run for each client before restarting. +---@return number|nil client_id +local function restart(bufnr, set_target_callback) + bufnr = bufnr or vim.api.nvim_get_current_buf() + local clients = M.stop(bufnr) + local timer, _, _ = vim.uv.new_timer() + if not timer then + -- TODO: Log error when logging is implemented + return + end + local attempts_to_live = 50 + local stopped_client_count = 0 + timer:start(200, 100, function() + for _, client in ipairs(clients) do + if client:is_stopped() then + stopped_client_count = stopped_client_count + 1 + vim.schedule(function() + -- Execute the callback, if provided, for additional actions before restarting + if set_target_callback then + set_target_callback(client) + end + M.start(bufnr) + end) + end + end + if stopped_client_count >= #clients then + timer:stop() + attempts_to_live = 0 + elseif attempts_to_live <= 0 then + vim.notify('rustaceanvim.lsp: Could not restart all LSP clients.', vim.log.levels.ERROR) + timer:stop() + attempts_to_live = 0 + end + attempts_to_live = attempts_to_live - 1 + end) +end + ---@class rustaceanvim.lsp.StartConfig: rustaceanvim.lsp.ClientConfig ---@field root_dir string | nil ---@field init_options? table @@ -256,10 +295,7 @@ end M.set_target_arch = function(bufnr, target) local function update_target(client) -- Get the current target from the client's settings - local current_target = client.config.settings - and client.config.settings['rust-analyzer'] - and client.config.settings['rust-analyzer'].cargo - and client.config.settings['rust-analyzer'].cargo.target + local current_target = vim.tbl_get(client, 'config', 'settings', 'rust-analyzer', 'cargo', 'target') if not target then if not current_target then @@ -276,13 +312,12 @@ M.set_target_arch = function(bufnr, target) vim.notify('Target architecture updated successfully to: ' .. target, vim.log.levels.INFO) return else - -- TODO: Log error when logging is implemented vim.notify('Invalid target architecture provided: ' .. tostring(target), vim.log.levels.ERROR) return end end - M.restart_impl(bufnr, update_target) + restart(bufnr, update_target) end ---Restart the LSP client. @@ -290,47 +325,7 @@ end ---@param bufnr? number The buffer number (optional), defaults to the current buffer ---@return number|nil client_id The LSP client ID after restart M.restart = function(bufnr) - M.restart_impl(bufnr) -end - ----LSP restart ininer implementations ----@param bufnr? number ----@param set_target_callback? function(client) Optional callback to run for each client before restarting. ----@return number|nil client_id -M.restart_impl = function(bufnr, set_target_callback) - -- TODO: handle case for when requested target change is the same as client active active so we don't restart clients unnecessarily - bufnr = bufnr or vim.api.nvim_get_current_buf() - local clients = M.stop(bufnr) - local timer, _, _ = vim.uv.new_timer() - if not timer then - -- TODO: Log error when logging is implemented - return - end - local attempts_to_live = 50 - local stopped_client_count = 0 - timer:start(200, 100, function() - for _, client in ipairs(clients) do - if client:is_stopped() then - stopped_client_count = stopped_client_count + 1 - vim.schedule(function() - -- Execute the callback, if provided, for additional actions before restarting - if set_target_callback then - set_target_callback(client) - end - M.start(bufnr) - end) - end - end - if stopped_client_count >= #clients then - timer:stop() - attempts_to_live = 0 - elseif attempts_to_live <= 0 then - vim.notify('rustaceanvim.lsp: Could not restart all LSP clients.', vim.log.levels.ERROR) - timer:stop() - attempts_to_live = 0 - end - attempts_to_live = attempts_to_live - 1 - end) + M.restart(bufnr) end ---@enum RustAnalyzerCmd @@ -362,7 +357,7 @@ end vim.api.nvim_create_user_command('RustAnalyzer', rust_analyzer_cmd, { nargs = '+', - desc = 'Starts, stops the rust-analyzer LSP client or change target', + desc = 'Starts, stops the rust-analyzer LSP client or changes the target', complete = function(arg_lead, cmdline, _) local clients = rust_analyzer.get_active_rustaceanvim_clients() ---@type RustAnalyzerCmd[] diff --git a/lua/rustaceanvim/lsp/targets.lua b/lua/rustaceanvim/lsp/targets.lua index dd559b0d..67356f39 100644 --- a/lua/rustaceanvim/lsp/targets.lua +++ b/lua/rustaceanvim/lsp/targets.lua @@ -1,292 +1,43 @@ local T = {} -local rustc_targets = { - 'aarch64-apple-darwin', - 'aarch64-apple-ios', - 'aarch64-apple-ios-macabi', - 'aarch64-apple-ios-sim', - 'aarch64-apple-tvos', - 'aarch64-apple-tvos-sim', - 'aarch64-apple-visionos', - 'aarch64-apple-visionos-sim', - 'aarch64-apple-watchos', - 'aarch64-apple-watchos-sim', - 'aarch64-fuchsia', - 'aarch64-kmc-solid_asp3', - 'aarch64-linux-android', - 'aarch64-nintendo-switch-freestanding', - 'aarch64-pc-windows-gnullvm', - 'aarch64-pc-windows-msvc', - 'aarch64-unknown-freebsd', - 'aarch64-unknown-fuchsia', - 'aarch64-unknown-hermit', - 'aarch64-unknown-illumos', - 'aarch64-unknown-linux-gnu', - 'aarch64-unknown-linux-gnu_ilp32', - 'aarch64-unknown-linux-musl', - 'aarch64-unknown-linux-ohos', - 'aarch64-unknown-netbsd', - 'aarch64-unknown-none', - 'aarch64-unknown-none-softfloat', - 'aarch64-unknown-nto-qnx700', - 'aarch64-unknown-nto-qnx710', - 'aarch64-unknown-openbsd', - 'aarch64-unknown-redox', - 'aarch64-unknown-teeos', - 'aarch64-unknown-trusty', - 'aarch64-unknown-uefi', - 'aarch64-uwp-windows-msvc', - 'aarch64-wrs-vxworks', - 'aarch64_be-unknown-linux-gnu', - 'aarch64_be-unknown-linux-gnu_ilp32', - 'aarch64_be-unknown-netbsd', - 'arm-linux-androideabi', - 'arm-unknown-linux-gnueabi', - 'arm-unknown-linux-gnueabihf', - 'arm-unknown-linux-musleabi', - 'arm-unknown-linux-musleabihf', - 'arm64_32-apple-watchos', - 'arm64e-apple-darwin', - 'arm64e-apple-ios', - 'arm64ec-pc-windows-msvc', - 'armeb-unknown-linux-gnueabi', - 'armebv7r-none-eabi', - 'armebv7r-none-eabihf', - 'armv4t-none-eabi', - 'armv4t-unknown-linux-gnueabi', - 'armv5te-none-eabi', - 'armv5te-unknown-linux-gnueabi', - 'armv5te-unknown-linux-musleabi', - 'armv5te-unknown-linux-uclibceabi', - 'armv6-unknown-freebsd', - 'armv6-unknown-netbsd-eabihf', - 'armv6k-nintendo-3ds', - 'armv7-linux-androideabi', - 'armv7-rtems-eabihf', - 'armv7-sony-vita-newlibeabihf', - 'armv7-unknown-freebsd', - 'armv7-unknown-linux-gnueabi', - 'armv7-unknown-linux-gnueabihf', - 'armv7-unknown-linux-musleabi', - 'armv7-unknown-linux-musleabihf', - 'armv7-unknown-linux-ohos', - 'armv7-unknown-linux-uclibceabi', - 'armv7-unknown-linux-uclibceabihf', - 'armv7-unknown-netbsd-eabihf', - 'armv7-unknown-trusty', - 'armv7-wrs-vxworks-eabihf', - 'armv7a-kmc-solid_asp3-eabi', - 'armv7a-kmc-solid_asp3-eabihf', - 'armv7a-none-eabi', - 'armv7a-none-eabihf', - 'armv7k-apple-watchos', - 'armv7r-none-eabi', - 'armv7r-none-eabihf', - 'armv7s-apple-ios', - 'armv8r-none-eabihf', - 'avr-unknown-gnu-atmega328', - 'bpfeb-unknown-none', - 'bpfel-unknown-none', - 'csky-unknown-linux-gnuabiv2', - 'csky-unknown-linux-gnuabiv2hf', - 'hexagon-unknown-linux-musl', - 'hexagon-unknown-none-elf', - 'i386-apple-ios', - 'i586-pc-nto-qnx700', - 'i586-pc-windows-msvc', - 'i586-unknown-linux-gnu', - 'i586-unknown-linux-musl', - 'i586-unknown-netbsd', - 'i686-apple-darwin', - 'i686-linux-android', - 'i686-pc-windows-gnu', - 'i686-pc-windows-gnullvm', - 'i686-pc-windows-msvc', - 'i686-unknown-freebsd', - 'i686-unknown-haiku', - 'i686-unknown-hurd-gnu', - 'i686-unknown-linux-gnu', - 'i686-unknown-linux-musl', - 'i686-unknown-netbsd', - 'i686-unknown-openbsd', - 'i686-unknown-redox', - 'i686-unknown-uefi', - 'i686-uwp-windows-gnu', - 'i686-uwp-windows-msvc', - 'i686-win7-windows-msvc', - 'i686-wrs-vxworks', - 'loongarch64-unknown-linux-gnu', - 'loongarch64-unknown-linux-musl', - 'loongarch64-unknown-none', - 'loongarch64-unknown-none-softfloat', - 'm68k-unknown-linux-gnu', - 'mips-unknown-linux-gnu', - 'mips-unknown-linux-musl', - 'mips-unknown-linux-uclibc', - 'mips64-openwrt-linux-musl', - 'mips64-unknown-linux-gnuabi64', - 'mips64-unknown-linux-muslabi64', - 'mips64el-unknown-linux-gnuabi64', - 'mips64el-unknown-linux-muslabi64', - 'mipsel-sony-psp', - 'mipsel-sony-psx', - 'mipsel-unknown-linux-gnu', - 'mipsel-unknown-linux-musl', - 'mipsel-unknown-linux-uclibc', - 'mipsel-unknown-netbsd', - 'mipsel-unknown-none', - 'mipsisa32r6-unknown-linux-gnu', - 'mipsisa32r6el-unknown-linux-gnu', - 'mipsisa64r6-unknown-linux-gnuabi64', - 'mipsisa64r6el-unknown-linux-gnuabi64', - 'msp430-none-elf', - 'nvptx64-nvidia-cuda', - 'powerpc-unknown-freebsd', - 'powerpc-unknown-linux-gnu', - 'powerpc-unknown-linux-gnuspe', - 'powerpc-unknown-linux-musl', - 'powerpc-unknown-linux-muslspe', - 'powerpc-unknown-netbsd', - 'powerpc-unknown-openbsd', - 'powerpc-wrs-vxworks', - 'powerpc-wrs-vxworks-spe', - 'powerpc64-ibm-aix', - 'powerpc64-unknown-freebsd', - 'powerpc64-unknown-linux-gnu', - 'powerpc64-unknown-linux-musl', - 'powerpc64-unknown-openbsd', - 'powerpc64-wrs-vxworks', - 'powerpc64le-unknown-freebsd', - 'powerpc64le-unknown-linux-gnu', - 'powerpc64le-unknown-linux-musl', - 'riscv32gc-unknown-linux-gnu', - 'riscv32gc-unknown-linux-musl', - 'riscv32i-unknown-none-elf', - 'riscv32im-risc0-zkvm-elf', - 'riscv32im-unknown-none-elf', - 'riscv32ima-unknown-none-elf', - 'riscv32imac-esp-espidf', - 'riscv32imac-unknown-none-elf', - 'riscv32imac-unknown-nuttx-elf', - 'riscv32imac-unknown-xous-elf', - 'riscv32imafc-esp-espidf', - 'riscv32imafc-unknown-none-elf', - 'riscv32imafc-unknown-nuttx-elf', - 'riscv32imc-esp-espidf', - 'riscv32imc-unknown-none-elf', - 'riscv32imc-unknown-nuttx-elf', - 'riscv64-linux-android', - 'riscv64gc-unknown-freebsd', - 'riscv64gc-unknown-fuchsia', - 'riscv64gc-unknown-hermit', - 'riscv64gc-unknown-linux-gnu', - 'riscv64gc-unknown-linux-musl', - 'riscv64gc-unknown-netbsd', - 'riscv64gc-unknown-none-elf', - 'riscv64gc-unknown-nuttx-elf', - 'riscv64gc-unknown-openbsd', - 'riscv64imac-unknown-none-elf', - 'riscv64imac-unknown-nuttx-elf', - 's390x-unknown-linux-gnu', - 's390x-unknown-linux-musl', - 'sparc-unknown-linux-gnu', - 'sparc-unknown-none-elf', - 'sparc64-unknown-linux-gnu', - 'sparc64-unknown-netbsd', - 'sparc64-unknown-openbsd', - 'sparcv9-sun-solaris', - 'thumbv4t-none-eabi', - 'thumbv5te-none-eabi', - 'thumbv6m-none-eabi', - 'thumbv6m-nuttx-eabi', - 'thumbv7a-pc-windows-msvc', - 'thumbv7a-uwp-windows-msvc', - 'thumbv7em-none-eabi', - 'thumbv7em-none-eabihf', - 'thumbv7em-nuttx-eabi', - 'thumbv7em-nuttx-eabihf', - 'thumbv7m-none-eabi', - 'thumbv7m-nuttx-eabi', - 'thumbv7neon-linux-androideabi', - 'thumbv7neon-unknown-linux-gnueabihf', - 'thumbv7neon-unknown-linux-musleabihf', - 'thumbv8m.base-none-eabi', - 'thumbv8m.base-nuttx-eabi', - 'thumbv8m.main-none-eabi', - 'thumbv8m.main-none-eabihf', - 'thumbv8m.main-nuttx-eabi', - 'thumbv8m.main-nuttx-eabihf', - 'wasm32-unknown-emscripten', - 'wasm32-unknown-unknown', - 'wasm32-wasi', - 'wasm32-wasip1', - 'wasm32-wasip1-threads', - 'wasm32-wasip2', - 'wasm64-unknown-unknown', - 'x86_64-apple-darwin', - 'x86_64-apple-ios', - 'x86_64-apple-ios-macabi', - 'x86_64-apple-tvos', - 'x86_64-apple-watchos-sim', - 'x86_64-fortanix-unknown-sgx', - 'x86_64-fuchsia', - 'x86_64-linux-android', - 'x86_64-pc-nto-qnx710', - 'x86_64-pc-solaris', - 'x86_64-pc-windows-gnu', - 'x86_64-pc-windows-gnullvm', - 'x86_64-pc-windows-msvc', - 'x86_64-unikraft-linux-musl', - 'x86_64-unknown-dragonfly', - 'x86_64-unknown-freebsd', - 'x86_64-unknown-fuchsia', - 'x86_64-unknown-haiku', - 'x86_64-unknown-hermit', - 'x86_64-unknown-hurd-gnu', - 'x86_64-unknown-illumos', - 'x86_64-unknown-l4re-uclibc', - 'x86_64-unknown-linux-gnu', - 'x86_64-unknown-linux-gnux32', - 'x86_64-unknown-linux-musl', - 'x86_64-unknown-linux-none', - 'x86_64-unknown-linux-ohos', - 'x86_64-unknown-netbsd', - 'x86_64-unknown-none', - 'x86_64-unknown-openbsd', - 'x86_64-unknown-redox', - 'x86_64-unknown-uefi', - 'x86_64-uwp-windows-gnu', - 'x86_64-uwp-windows-msvc', - 'x86_64-win7-windows-msvc', - 'x86_64-wrs-vxworks', - 'x86_64h-apple-darwin', - 'xtensa-esp32-espidf', - 'xtensa-esp32-none-elf', - 'xtensa-esp32s2-espidf', - 'xtensa-esp32s2-none-elf', - 'xtensa-esp32s3-espidf', - 'xtensa-esp32s3-none-elf', -} +local rustc_targets_cache = nil + +--- Get rustc targets, use cache if available +---@return table +local function get_rustc_targets() + if rustc_targets_cache then + return rustc_targets_cache + end + + local result = vim.system({ 'rustc', '--print', 'target-list' }):wait() + if result.code ~= 0 then + error('Failed to retrieve rustc targets: ' .. result.stderr) + end + + rustc_targets_cache = {} + for line in result.stdout:gmatch('[^\r\n]+') do + rustc_targets_cache[line] = true + end + + return rustc_targets_cache +end --- Validates if the provided target is a valid Rust compiler (rustc) target. --- If no target is provided, it defaults to the system's architecture. ---@param target? string ---@return boolean -T.target_is_valid_rustc_target = function(target) - -- If target is nil, return true to let rust-analyzer use the default target architecture for the system +function T.target_is_valid_rustc_target(target) if target == nil then return true end - -- Iterate through the available rustc targets and check if the target matches - for _, val in ipairs(rustc_targets) do - if val == target then - return true - end + local success, targets = pcall(get_rustc_targets) + if not success then + vim.notify('Error retrieving rustc targets: ' .. tostring(targets), vim.log.levels.ERROR) + return false end - -- Return false if no matching target is found - return false + return targets[target] or false end return T From 2803c7c3783673d720831b0dff736046d84974b7 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Wed, 16 Oct 2024 02:04:13 +0100 Subject: [PATCH 3/8] remove todo comment and let user know of timer init error --- lua/rustaceanvim/lsp/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/rustaceanvim/lsp/init.lua b/lua/rustaceanvim/lsp/init.lua index 2bbff969..a5049771 100644 --- a/lua/rustaceanvim/lsp/init.lua +++ b/lua/rustaceanvim/lsp/init.lua @@ -103,7 +103,7 @@ local function restart(bufnr, set_target_callback) local clients = M.stop(bufnr) local timer, _, _ = vim.uv.new_timer() if not timer then - -- TODO: Log error when logging is implemented + vim.notify('Failed to init timer for LSP client restart.', vim.log.levels.ERROR) return end local attempts_to_live = 50 From 9dcaecb62db8cba2fe8131f27499c71903201303 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Wed, 16 Oct 2024 19:56:05 +0100 Subject: [PATCH 4/8] fix nits --- lua/rustaceanvim/lsp/init.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lua/rustaceanvim/lsp/init.lua b/lua/rustaceanvim/lsp/init.lua index a5049771..aed604ac 100644 --- a/lua/rustaceanvim/lsp/init.lua +++ b/lua/rustaceanvim/lsp/init.lua @@ -96,9 +96,9 @@ end ---LSP restart ininer implementations ---@param bufnr? number ----@param set_target_callback? function(client) Optional callback to run for each client before restarting. +---@param callback? function(client) Optional callback to run for each client before restarting. ---@return number|nil client_id -local function restart(bufnr, set_target_callback) +local function restart(bufnr, callback) bufnr = bufnr or vim.api.nvim_get_current_buf() local clients = M.stop(bufnr) local timer, _, _ = vim.uv.new_timer() @@ -114,8 +114,8 @@ local function restart(bufnr, set_target_callback) stopped_client_count = stopped_client_count + 1 vim.schedule(function() -- Execute the callback, if provided, for additional actions before restarting - if set_target_callback then - set_target_callback(client) + if callback then + callback(client) end M.start(bufnr) end) From b43edb2dfa7e973efc79c189c1f33ce13c0d5e63 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Wed, 16 Oct 2024 21:13:09 +0100 Subject: [PATCH 5/8] avoid blocking Neovim's event loop --- lua/rustaceanvim/lsp/init.lua | 59 +++++++++++++++++++++++++------- lua/rustaceanvim/lsp/targets.lua | 43 ----------------------- 2 files changed, 46 insertions(+), 56 deletions(-) delete mode 100644 lua/rustaceanvim/lsp/targets.lua diff --git a/lua/rustaceanvim/lsp/init.lua b/lua/rustaceanvim/lsp/init.lua index aed604ac..9ec4bb94 100644 --- a/lua/rustaceanvim/lsp/init.lua +++ b/lua/rustaceanvim/lsp/init.lua @@ -6,7 +6,8 @@ local rust_analyzer = require('rustaceanvim.rust_analyzer') local server_status = require('rustaceanvim.server_status') local cargo = require('rustaceanvim.cargo') local os = require('rustaceanvim.os') -local targets = require('rustaceanvim.lsp.targets') + +local rustc_targets_cache = nil local function override_apply_text_edits() local old_func = vim.lsp.util.apply_text_edits @@ -94,6 +95,31 @@ local function configure_file_watcher(server_cfg) end end +---Handles retrieving rustc target archs and running on_valid callback +---to perform certain actions using the retrieved targets. +---@param on_valid function(rustc_targets) +local function validate_rustc_target(on_valid) + if rustc_targets_cache then + return rustc_targets_cache + end + + local on_exit = function(result) + if result.code ~= 0 then + error('Failed to retrieve rustc targets: ' .. result.stderr) + end + + rustc_targets_cache = {} + for line in result.stdout:gmatch('[^\r\n]+') do + rustc_targets_cache[line] = true + end + + return on_valid(rustc_targets_cache) + end + + -- Call vim.system with on_exit callback to avoid blocking Neovim's event loop. + vim.system({ 'rustc', '--print', 'target-list' }, { text = true }, on_exit) +end + ---LSP restart ininer implementations ---@param bufnr? number ---@param callback? function(client) Optional callback to run for each client before restarting. @@ -291,10 +317,10 @@ end ---Updates the target architecture setting for the LSP client associated with the given buffer. ---@param bufnr? number The buffer number, defaults to the current buffer ----@param target? string The target architecture. Defaults to the current buffer's target if not provided. +---@param target? string The target architecture. Defaults to nil(the current buffer's target if not provided). M.set_target_arch = function(bufnr, target) - local function update_target(client) - -- Get the current target from the client's settings + local on_update_target = function(client) + -- Get current user's rust-analyzer target local current_target = vim.tbl_get(client, 'config', 'settings', 'rust-analyzer', 'cargo', 'target') if not target then @@ -306,18 +332,25 @@ M.set_target_arch = function(bufnr, target) return end - if targets.target_is_valid_rustc_target(target) then - client.settings['rust-analyzer'].cargo.target = target - client.notify('workspace/didChangeConfiguration', { settings = client.config.settings }) - vim.notify('Target architecture updated successfully to: ' .. target, vim.log.levels.INFO) - return - else - vim.notify('Invalid target architecture provided: ' .. tostring(target), vim.log.levels.ERROR) - return + ---on_valid callback handles the main functionality in changing system's arch + ---by checking if rustc targets contains user's target or if user's provided target is nil. + ---Notifies user on unrecognized target arch request + local on_valid = function(rustc_tgs) + if target == nil or rustc_tgs[target] then + client.settings['rust-analyzer'].cargo.target = target + client.notify('workspace/didChangeConfiguration', { settings = client.config.settings }) + vim.notify('Target architecture updated successfully to: ' .. target, vim.log.levels.INFO) + return + else + vim.notify('Invalid target architecture provided: ' .. tostring(target), vim.log.levels.ERROR) + return + end end + + return validate_rustc_target(on_valid) end - restart(bufnr, update_target) + restart(bufnr, on_update_target) end ---Restart the LSP client. diff --git a/lua/rustaceanvim/lsp/targets.lua b/lua/rustaceanvim/lsp/targets.lua deleted file mode 100644 index 67356f39..00000000 --- a/lua/rustaceanvim/lsp/targets.lua +++ /dev/null @@ -1,43 +0,0 @@ -local T = {} - -local rustc_targets_cache = nil - ---- Get rustc targets, use cache if available ----@return table -local function get_rustc_targets() - if rustc_targets_cache then - return rustc_targets_cache - end - - local result = vim.system({ 'rustc', '--print', 'target-list' }):wait() - if result.code ~= 0 then - error('Failed to retrieve rustc targets: ' .. result.stderr) - end - - rustc_targets_cache = {} - for line in result.stdout:gmatch('[^\r\n]+') do - rustc_targets_cache[line] = true - end - - return rustc_targets_cache -end - ---- Validates if the provided target is a valid Rust compiler (rustc) target. ---- If no target is provided, it defaults to the system's architecture. ----@param target? string ----@return boolean -function T.target_is_valid_rustc_target(target) - if target == nil then - return true - end - - local success, targets = pcall(get_rustc_targets) - if not success then - vim.notify('Error retrieving rustc targets: ' .. tostring(targets), vim.log.levels.ERROR) - return false - end - - return targets[target] or false -end - -return T From c4896e7d93d65199b44e65a7ea7c882baca2aae1 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Wed, 16 Oct 2024 21:14:20 +0100 Subject: [PATCH 6/8] add comment to rustc cache var --- lua/rustaceanvim/lsp/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/rustaceanvim/lsp/init.lua b/lua/rustaceanvim/lsp/init.lua index 9ec4bb94..09a67d59 100644 --- a/lua/rustaceanvim/lsp/init.lua +++ b/lua/rustaceanvim/lsp/init.lua @@ -7,6 +7,7 @@ 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() From 288a76082d659162724f01cf66d70f8187f1bc73 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Wed, 16 Oct 2024 21:18:02 +0100 Subject: [PATCH 7/8] use cache if available --- lua/rustaceanvim/lsp/init.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lua/rustaceanvim/lsp/init.lua b/lua/rustaceanvim/lsp/init.lua index 09a67d59..32ac7b32 100644 --- a/lua/rustaceanvim/lsp/init.lua +++ b/lua/rustaceanvim/lsp/init.lua @@ -100,11 +100,12 @@ end ---to perform certain actions using the retrieved targets. ---@param on_valid function(rustc_targets) local function validate_rustc_target(on_valid) - if rustc_targets_cache then - return rustc_targets_cache - end - local on_exit = function(result) + -- Use cache if available. + if rustc_targets_cache then + return on_valid(rustc_targets_cache) + end + if result.code ~= 0 then error('Failed to retrieve rustc targets: ' .. result.stderr) end From 6859b18b0d2d2a4c0d314d5698cffd2319a696ab Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Wed, 16 Oct 2024 21:19:33 +0100 Subject: [PATCH 8/8] nit: update comment --- lua/rustaceanvim/lsp/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/rustaceanvim/lsp/init.lua b/lua/rustaceanvim/lsp/init.lua index 32ac7b32..acba95aa 100644 --- a/lua/rustaceanvim/lsp/init.lua +++ b/lua/rustaceanvim/lsp/init.lua @@ -101,7 +101,7 @@ end ---@param on_valid function(rustc_targets) local function validate_rustc_target(on_valid) local on_exit = function(result) - -- Use cache if available. + -- use cache if available. if rustc_targets_cache then return on_valid(rustc_targets_cache) end @@ -122,7 +122,7 @@ local function validate_rustc_target(on_valid) vim.system({ 'rustc', '--print', 'target-list' }, { text = true }, on_exit) end ----LSP restart ininer implementations +---LSP restart internal implementations ---@param bufnr? number ---@param callback? function(client) Optional callback to run for each client before restarting. ---@return number|nil client_id