Skip to content

Commit

Permalink
feat(dap): switch to using lldb adapter, dap-client configuration f…
Browse files Browse the repository at this point in the history
…rom config, load `launch.json` by default, `probe-rs` support (#93)

Co-authored-by: Marc Jakobi <[email protected]>
Co-authored-by: Github Actions <actions@github>
Co-authored-by: andrewc <[email protected]>
Co-authored-by: Marc Jakobi <[email protected]>
  • Loading branch information
5 people authored Dec 12, 2023
1 parent 3ea1412 commit adeca59
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 37 deletions.
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
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
20 changes: 20 additions & 0 deletions lua/rustaceanvim/config/check.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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

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
---@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()
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
---@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

0 comments on commit adeca59

Please sign in to comment.