diff --git a/CHANGELOG.md b/CHANGELOG.md index f20022a7..d4f802e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,18 @@ 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). +## Unreleased + +### Added + +- DAP: Load the `dap.adapter` config value into the `lldb` adapter, but only if the + `lldb` adapter is not already configured. +- DAP: Add `dap.configuration` entry to config with the default behaviour of loading + `launch.json`, or falling back to a basic configuration of the `lldb` adapter. + - Use the `dap.configuration` config value to configure the debug session, + falling back to the `rust` configuration. +- DAP: Support [`probe-rs`](https://probe.rs/). + ## [3.9.6] - 2023-12-06 ### Fixed diff --git a/doc/rustaceanvim.txt b/doc/rustaceanvim.txt index 9876a71f..81fbf363 100644 --- a/doc/rustaceanvim.txt +++ b/doc/rustaceanvim.txt @@ -205,6 +205,38 @@ dap_adapter_type_server *dap_adapter_type_server* +DapClientConfig *DapClientConfig* + + Fields: ~ + {type} (string) The dap adapter to use + {name} (string) + {request} (dap_config_request_launch|dap_config_request_attach|dap_config_request_custom) The type of dap session + {cwd?} (string) Current working directory + {program?} (string) Path to executable for most DAP clients + {args?} (string[]) Optional args to DAP client, not valid for all client types + {env?} (string) Environmental variables + {initCommands?} (string[]) Initial commands to run, `lldb` clients only + {coreConfigs?} (table) Essential config values for `probe-rs` client, see https://probe.rs/docs/tools/debugger/ + + +dap_config_request_launch *dap_config_request_launch* + + Type: ~ + + + +dap_config_request_attach *dap_config_request_attach* + + Type: ~ + + + +dap_config_request_custom *dap_config_request_custom* + + Type: ~ + + + *M.get_codelldb_adapter* M.get_codelldb_adapter({codelldb_path}, {liblldb_path}) For the heroes who want to use it. diff --git a/lua/rustaceanvim/config/check.lua b/lua/rustaceanvim/config/check.lua index 058932cf..26731674 100644 --- a/lua/rustaceanvim/config/check.lua +++ b/lua/rustaceanvim/config/check.lua @@ -109,6 +109,26 @@ function M.validate(cfg) if not ok then return false, err end + local configuration = types.evaluate(dap.configuration) + if configuration == false then + ok = true + else + ---@cast configuration DapClientConfig + ok, err = validate('dap.configuration', { + type = { configuration.type, 'string' }, + name = { configuration.name, 'string' }, + request = { configuration.request, 'string' }, + cwd = { configuration.cwd, 'string', true }, + program = { configuration.program, 'string', true }, + args = { configuration.args, 'table', true }, + env = { configuration.env, 'string', true }, + initCommands = { configuration.initCommands, 'string', true }, + coreConfigs = { configuration.coreConfigs, 'table', true }, + }) + end + if not ok then + return false, err + end return true end diff --git a/lua/rustaceanvim/config/init.lua b/lua/rustaceanvim/config/init.lua index 4d7ed1b4..36007f63 100644 --- a/lua/rustaceanvim/config/init.lua +++ b/lua/rustaceanvim/config/init.lua @@ -88,7 +88,8 @@ vim.g.rustaceanvim = vim.g.rustaceanvim ---@field logfile? string The path to the rust-analyzer log file. ---@class RustaceanDapOpts ----@field adapter? DapExecutableConfig | DapServerConfig | disable | fun():(DapExecutableConfig | DapServerConfig | disable) Defaults to a `DapServerConfig` if `codelldb` is detected, and to a `DapExecutableConfig` if `lldb` is detected. Set to `false` to disable. +---@field adapter? DapExecutableConfig | DapServerConfig | disable | fun():(DapExecutableConfig | DapServerConfig | disable) Defaults to creating the `rt_lldb` adapter, which is a `DapServerConfig` if `codelldb` is detected, and a `DapExecutableConfig` if `lldb` is detected. Set to `false` to disable. +---@field configuration? DapClientConfig | disable | fun():(DapClientConfig | disable) Dap client configuration. Defaults to a function that looks for a `launch.json` file or returns a `DapExecutableConfig` that launches the `rt_lldb` adapter. Set to `false` to disable. ---@field add_dynamic_library_paths? boolean | fun():boolean Accommodate dynamically-linked targets by passing library paths to lldb. Default: `true`. ---@field auto_generate_source_map? fun():boolean | boolean Whether to auto-generate a source map for the standard library. ---@field load_rust_types? fun():boolean | boolean Whether to get Rust types via initCommands (rustlib/etc/lldb_commands). Default: `true`. @@ -117,6 +118,21 @@ vim.g.rustaceanvim = vim.g.rustaceanvim ---@alias dap_adapter_type_executable "executable" ---@alias dap_adapter_type_server "server" +---@class DapClientConfig +---@field type string The dap adapter to use +---@field name string +---@field request dap_config_request_launch | dap_config_request_attach | dap_config_request_custom The type of dap session +---@field cwd? string Current working directory +---@field program? string Path to executable for most DAP clients +---@field args? string[] Optional args to DAP client, not valid for all client types +---@field env? string Environmental variables +---@field initCommands? string[] Initial commands to run, `lldb` clients only +---@field coreConfigs? table Essential config values for `probe-rs` client, see https://probe.rs/docs/tools/debugger/ + +---@alias dap_config_request_launch "launch" +---@alias dap_config_request_attach "attach" +---@alias dap_config_request_custom "custom" + ---For the heroes who want to use it. ---@param codelldb_path string Path to the codelldb executable ---@param liblldb_path string Path to the liblldb dynamic library diff --git a/lua/rustaceanvim/config/internal.lua b/lua/rustaceanvim/config/internal.lua index 77748a55..9723c0d4 100644 --- a/lua/rustaceanvim/config/internal.lua +++ b/lua/rustaceanvim/config/internal.lua @@ -265,6 +265,39 @@ local RustaceanDefaultConfig = { load_rust_types = function() return should_enable_dap_config_value(RustaceanConfig.dap.adapter) end, + --- @type DapClientConfig | disable | fun():(DapClientConfig | disable) + configuration = function() + local ok, _ = pcall(require, 'dap') + if not ok then + return false + end + + -- default + ---@type DapClientConfig + local dap_config = { + name = 'Rust debug client', + type = 'lldb', + request = 'launch', + stopOnEntry = false, + } + + ---@diagnostic disable-next-line: different-requires + local dap = require('dap') + -- Load configurations from a `launch.json`. + -- It is necessary to check for changes in the `dap.configurations` table, as + -- `load_launchjs` does not return anything, it loads directly into `dap.configurations`. + local pre_launch = vim.deepcopy(dap.configurations) or {} + require('dap.ext.vscode').load_launchjs() + for k, v in pairs(dap.configurations) do + if pre_launch[k] == nil or not vim.deep_equal(pre_launch[k], v) then + -- `configurations` are tables of `configuration` entries + -- use the first `configuration` + dap_config = v[1] + break + end + end + return dap_config + end, }, was_g_rustaceanvim_sourced = vim.g.rustaceanvim ~= nil, } diff --git a/lua/rustaceanvim/dap.lua b/lua/rustaceanvim/dap.lua index 7f5e32ae..6c6fc730 100644 --- a/lua/rustaceanvim/dap.lua +++ b/lua/rustaceanvim/dap.lua @@ -22,12 +22,6 @@ local dap = require('dap') local adapter = types.evaluate(config.dap.adapter) --- @cast adapter DapExecutableConfig | DapServerConfig | boolean -if adapter ~= false then - ---@TODO: Add nvim-dap to lua-ls lint - ---@diagnostic disable-next-line: assign-type-mismatch - dap.adapters.rt_lldb = adapter -end - local M = {} ---@deprecated Use require('rustaceanvim.config').get_codelldb_adapter @@ -270,41 +264,55 @@ function M.start(args) return end - -- create debug configuration - local dap_config = { - name = 'Rust tools debug', - type = 'rt_lldb', - request = 'launch', - program = executables[1], - args = args.executableArgs or {}, - cwd = args.workspaceRoot, - stopOnEntry = false, - - -- if you change `runInTerminal` to true, you might need to change the yama/ptrace_scope setting: - -- - -- echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope - -- - -- Otherwise you might get the following error: - -- - -- Error on launch: Failed to attach to the target process - -- - -- But you should be aware of the implications: - -- https://www.kernel.org/doc/html/latest/admin-guide/LSM/Yama.html - runInTerminal = false, - } - local final_config = next(init_commands) ~= nil - and vim.tbl_deep_extend('force', dap_config, { initCommands = init_commands[args.workspaceRoot] }) - or dap_config + -- If the `lldb` adapter is not defined elsewhere, use the adapter + -- defined in `config.dap.adapter` + if dap.adapters.lldb == nil and adapter ~= false then + ---@TODO: Add nvim-dap to lua-ls lint + ---@diagnostic disable-next-line: assign-type-mismatch + dap.adapters.lldb = adapter + end - local source_map = source_maps[args.workspaceRoot] - final_config = next(source_map) ~= nil - and vim.tbl_deep_extend('force', final_config, { sourceMap = format_source_map(source_map) }) - or final_config + -- Use the first configuration, if it exists + local _, dap_config = next(dap.configurations.rust or {}) + + local local_config = types.evaluate(config.dap.configuration) + --- @cast local_config DapClientConfig | boolean + local final_config = local_config ~= false and local_config or dap_config + --- @cast final_config DapClientConfig + + if dap.adapters[final_config.type] == nil then + scheduled_error( + 'No adapter exists named "' .. final_config.type .. '". See ":h dap-adapter" for more information' + ) + return + end + + -- common entries + -- `program` and `args` aren't supported in probe-rs but are safely ignored + final_config.cwd = args.workspaceRoot + final_config.program = executables[1] + final_config.args = args.executableArgs or {} local environment = environments[args.workspaceRoot] - final_config = next(environment) ~= nil and vim.tbl_deep_extend('force', final_config, { env = environment }) + final_config = next(environment or {}) ~= nil + and vim.tbl_deep_extend('force', final_config, { env = environment }) or final_config + if string.find(final_config.type, 'lldb') ~= nil then + -- lldb specific entries + final_config = next(init_commands or {}) ~= nil + and vim.tbl_deep_extend('force', final_config, { initCommands = init_commands[args.workspaceRoot] }) + or final_config + + local source_map = source_maps[args.workspaceRoot] + final_config = next(source_map or {}) ~= nil + and vim.tbl_deep_extend('force', final_config, { sourceMap = format_source_map(source_map) }) + or final_config + elseif string.find(final_config.type, 'probe%-rs') ~= nil then + -- probe-rs specific entries + final_config.coreConfigs[1].programBinary = final_config.program + end + -- start debugging dap.run(final_config) end)