Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dap): switch to using lldb adapter, dap-client configuration from config, load launch.json by default, probe-rs support #93

Merged
merged 8 commits into from
Dec 12, 2023
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 32 additions & 0 deletions doc/rustaceanvim.txt
mrcjkb marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
21 changes: 21 additions & 0 deletions lua/rustaceanvim/config/check.lua
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,27 @@ 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' },
Andrew-Collins marked this conversation as resolved.
Show resolved Hide resolved
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 },
sourceMap = { configuration.sourceMap, 'string', true },
mrcjkb marked this conversation as resolved.
Show resolved Hide resolved
coreConfigs = { configuration.coreConfigs, 'table', true },
})
end
if not ok then
return false, err
end
return true
end

Expand Down
18 changes: 17 additions & 1 deletion lua/rustaceanvim/config/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down Expand Up @@ -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
mrcjkb marked this conversation as resolved.
Show resolved Hide resolved
---@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
Expand Down
33 changes: 33 additions & 0 deletions lua/rustaceanvim/config/internal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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()
mrcjkb marked this conversation as resolved.
Show resolved Hide resolved
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,
}
Expand Down
80 changes: 44 additions & 36 deletions lua/rustaceanvim/dap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
mrcjkb marked this conversation as resolved.
Show resolved Hide resolved
---@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)
Expand Down
Loading