Skip to content

Commit

Permalink
feat(neotest): support dap strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
mrcjkb committed Jan 31, 2024
1 parent 28d8c92 commit 38558fa
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 60 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
buffer to which the LSP client is attached.
If you do so, `tools.test_executor` will default to a new `'neotest'`
executor, which will use neotest to run `testables` or `runnables` that are tests.
- Support for `require('neotest').run.run { strategy = 'dap' }`.
This will use the same logic as `:RustLsp debuggables` to set neotest's
DAP strategy. No extra configuration needed!
- `:RustLsp testables`: Prettier selection options.

## [4.3.0] - 2024-01-31
Expand Down
4 changes: 2 additions & 2 deletions lua/rustaceanvim/cached_commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local M = {}

---@class CommandCache
local cache = {
---@type RADebuggableArgs | nil
---@type RARunnableArgs | nil
last_debuggable = nil,
---@type { choice: integer, runnables: RARunnable[] }
last_runnable = nil,
Expand All @@ -28,7 +28,7 @@ M.set_last_testable = function(choice, runnables)
}
end

---@param args RADebuggableArgs
---@param args RARunnableArgs
M.set_last_debuggable = function(args)
cache.last_debuggable = args
end
Expand Down
29 changes: 10 additions & 19 deletions lua/rustaceanvim/commands/debuggables.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,7 @@ end
---@type { [string]: boolean? } Used to prevent this plugin from adding the same configuration twice
local _dap_configuration_added = {}

---@class RADebuggableArgs
---@field cargoArgs string[]
---@field cargoExtraArgs string[]
---@field executableArgs string[]
---@field workspaceRoot string | nil

---@param args RADebuggableArgs
---@param args RARunnableArgs
---@return string
local function build_label(args)
local ret = ''
Expand All @@ -38,10 +32,7 @@ local function build_label(args)
return ret
end

---@class RADebuggable
---@field args RADebuggableArgs

---@param result RADebuggable[]
---@param result RARunnable[]
---@return string[] option_strings
local function get_options(result)
---@type string[]
Expand All @@ -56,7 +47,7 @@ local function get_options(result)
return option_strings
end

---@param args RADebuggableArgs
---@param args RARunnableArgs
---@return boolean
local function is_valid_test(args)
local is_not_cargo_check = args.cargoArgs[1] ~= 'check'
Expand All @@ -69,11 +60,11 @@ end
-- This function also makes it so that the debuggable commands are more
-- debugging friendly. For example, we move cargo run to cargo build, and cargo
-- test to cargo test --no-run.
---@param result RADebuggable[]
---@param result RARunnable[]
local function sanitize_results_for_debugging(result)
---@type RADebuggable[]
---@type RARunnable[]
local ret = vim.tbl_filter(function(value)
---@cast value RADebuggable
---@cast value RARunnable
return is_valid_test(value.args)
end, result or {})

Expand All @@ -85,7 +76,7 @@ local function sanitize_results_for_debugging(result)
return ret
end

---@param debuggables RADebuggable[]
---@param debuggables RARunnable[]
---@param executableArgsOverride? string[]
local function ui_select_debuggable(debuggables, executableArgsOverride)
if type(executableArgsOverride) == 'table' and #executableArgsOverride > 0 then
Expand Down Expand Up @@ -116,7 +107,7 @@ local function ui_select_debuggable(debuggables, executableArgsOverride)
end)
end

---@param debuggables RADebuggable[]
---@param debuggables RARunnable[]
local function add_debuggables_to_nvim_dap(debuggables)
local ok, dap = pcall(require, 'dap')
if not ok then
Expand All @@ -136,10 +127,10 @@ local function add_debuggables_to_nvim_dap(debuggables)
end
end

---@param callback fun(result:RADebuggable[])
---@param callback fun(result:RARunnable[])
local function mk_handler(callback)
return function(_, result, _, _)
---@cast result RADebuggable[]
---@cast result RARunnable[]
if result == nil then
return
end
Expand Down
49 changes: 21 additions & 28 deletions lua/rustaceanvim/dap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local compat = require('rustaceanvim.compat')
local shell = require('rustaceanvim.shell')
local types = require('rustaceanvim.types.internal')

---@param err string
local function scheduled_error(err)
vim.schedule(function()
vim.notify(err, vim.log.levels.ERROR)
Expand All @@ -12,9 +13,10 @@ end
local ok, _ = pcall(require, 'dap')
if not ok then
return {
---@param _ RADebuggableArgs
start = function(_)
scheduled_error('nvim-dap not found.')
---@param on_error fun(err:string)
start = function(_, _, _, on_error)
on_error = on_error or scheduled_error
on_error('nvim-dap not found.')
end,
}
end
Expand Down Expand Up @@ -212,7 +214,7 @@ local function add_dynamic_library_paths(adapter, workspace_root)
end

---@param adapter DapExecutableConfig | DapServerConfig
---@param args RADebuggableArgs
---@param args RARunnableArgs
local function handle_configured_options(adapter, args)
local is_generate_source_map_enabled = types.evaluate(config.dap.auto_generate_source_map)
---@cast is_generate_source_map_enabled boolean
Expand All @@ -233,22 +235,23 @@ local function handle_configured_options(adapter, args)
end
end

---@param args RADebuggableArgs
---@param args RARunnableArgs
---@param verbose? boolean
---@param callback? fun(config: DapClientConfig)
function M.start(args, verbose, callback)
if verbose == nil then
verbose = true
---@param on_error? fun(err: string)
function M.start(args, verbose, callback, on_error)
if verbose then
on_error = on_error or scheduled_error
else
on_error = on_error or function() end
end
if type(callback) ~= 'function' then
callback = dap.run
end
local adapter = types.evaluate(config.dap.adapter)
--- @cast adapter DapExecutableConfig | DapServerConfig | disable
if adapter == false then
if verbose then
vim.notify('Debug adapter is disabled.', vim.log.levels.ERROR)
end
on_error('Debug adapter is disabled.')
return
end

Expand All @@ -263,12 +266,10 @@ function M.start(args, verbose, callback)
---@cast sc vim.SystemCompleted
local output = sc.stdout
if sc.code ~= 0 or output == nil then
if verbose then
scheduled_error(
'An error occurred while compiling. Please fix all compilation issues and try again'
.. (sc.stderr and ': ' .. sc.stderr or '.')
)
end
on_error(
'An error occurred while compiling. Please fix all compilation issues and try again'
.. (sc.stderr and ': ' .. sc.stderr or '.')
)
return
end
vim.schedule(function()
Expand Down Expand Up @@ -301,15 +302,11 @@ function M.start(args, verbose, callback)
end
-- only 1 executable is allowed for debugging - error out if zero or many were found
if #executables <= 0 then
if verbose then
scheduled_error('No compilation artifacts found.')
end
on_error('No compilation artifacts found.')
return
end
if #executables > 1 then
if verbose then
scheduled_error('Multiple compilation artifacts are not supported.')
end
on_error('Multiple compilation artifacts are not supported.')
return
end

Expand All @@ -333,11 +330,7 @@ function M.start(args, verbose, callback)
--- @cast final_config DapClientConfig

if dap.adapters[final_config.type] == nil then
if verbose then
scheduled_error(
'No adapter exists named "' .. final_config.type .. '". See ":h dap-adapter" for more information'
)
end
on_error('No adapter exists named "' .. final_config.type .. '". See ":h dap-adapter" for more information')
return
end

Expand Down
55 changes: 44 additions & 11 deletions lua/rustaceanvim/neotest/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
local lib = require('neotest.lib')
local nio = require('nio')
local trans = require('rustaceanvim.neotest.trans')
local async = require('neotest.async')

---@type neotest.Adapter
local NeotestAdapter = { name = 'rustaceanvim' }
Expand Down Expand Up @@ -143,28 +144,60 @@ function NeotestAdapter.build_spec(run_args)
if not tree then
return
end
local pos = run_args.tree
local data = pos:data()
---@cast data rustaceanvim.neotest.Position
if not vim.tbl_contains(supported_types, data.type) then
local pos = tree:data()
---@cast pos rustaceanvim.neotest.Position
if not vim.tbl_contains(supported_types, pos.type) then
return
end
local runnable = data.runnable
local runnable = pos.runnable
if not runnable then
return
end
local context = {
file = pos.path,
pos_id = pos.id,
type = pos.type,
tree = tree,
}
local exe, args, cwd = require('rustaceanvim.runnables').get_command(runnable)
if run_args.strategy == 'dap' then
local dap = require('rustaceanvim.dap')
local overrides = require('rustaceanvim.overrides')
overrides.sanitize_command_for_debugging(runnable.args.cargoArgs)
local future = nio.control.future()
dap.start(runnable.args, false, function(strategy)
future.set(strategy)
end, function(err)
future.set_error(err)
end)
local ok, strategy = pcall(future.wait)
if not ok then
---@cast strategy string
lib.notify(strategy, vim.log.levels.ERROR)
end
---@cast strategy DapClientConfig
local types = require('rustaceanvim.types.internal')
local config = require('rustaceanvim.config.internal')
local adapter = types.evaluate(config.dap.adapter)
--- @cast adapter DapExecutableConfig | DapServerConfig
local is_codelldb = adapter.type == 'server'
if is_codelldb then
strategy['stdio'] = { nil, async.fn.tempname() }
end
---@type rustaceanvim.neotest.RunSpec
local run_spec = {
cwd = cwd,
context = context,
strategy = strategy,
}
return run_spec
end
---@type rustaceanvim.neotest.RunSpec
---@diagnostic disable-next-line: missing-fields
local run_spec = {
command = vim.list_extend({ exe }, args),
cwd = cwd,
context = {
file = data.path,
pos_id = data.id,
type = data.type,
tree = pos,
},
context = context,
}
return run_spec
end
Expand Down

0 comments on commit 38558fa

Please sign in to comment.