diff --git a/README.md b/README.md index 53624533..8d6b63e2 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,9 @@ Reliable Neotest adapter for running Go tests in Neovim. - Supports all [Neotest usage](https://github.com/nvim-neotest/neotest#usage). - Supports table tests and nested test functions (based on treesitter AST parsing). -- DAP support with [leoluz/nvim-dap-go](https://github.com/leoluz/nvim-dap-go) - integration for debugging of tests using +- DAP support. Either with + [leoluz/nvim-dap-go](https://github.com/leoluz/nvim-dap-go) integration or + custom configuration for debugging of tests using [delve](https://github.com/go-delve/delve). - Monorepo support (detect, run and debug tests in sub-projects). - Inline diagnostics. @@ -220,10 +221,18 @@ See `go help test`, `go help testflag`, `go help build` for possible arguments. ### Example configuration: debugging To debug tests, make sure you depend on -[mfussenegger/nvim-dap](https://github.com/mfussenegger/nvim-dap), -[rcarriga/nvim-dap-ui](https://github.com/rcarriga/nvim-dap-ui) and -[leoluz/nvim-dap-go](https://github.com/leoluz/nvim-dap-go). For example, make -the following changes to your lua setup: +[mfussenegger/nvim-dap](https://github.com/mfussenegger/nvim-dap) and +[rcarriga/nvim-dap-ui](https://github.com/rcarriga/nvim-dap-ui). Then you have +two options: + +- Adapter-provided DAP configuration, leveraging + [leoluz/nvim-dap-go](https://github.com/leoluz/nvim-dap-go) (recommended). +- Use your own custom DAP configuration (no additional dependency needed). + +Example configurations: + +
+Adapter-provided configuration ```diff return { @@ -261,6 +270,51 @@ return { } ``` +
+ +
+Custom DAP configuration + +```diff +return { ++ { ++ "rcarriga/nvim-dap-ui", ++ dependencies = { ++ "nvim-neotest/nvim-nio", ++ "mfussenegger/nvim-dap", ++ }, ++ }, ++ + { + "nvim-neotest/neotest", + dependencies = { + "nvim-neotest/nvim-nio", + "nvim-lua/plenary.nvim", + "antoinemadec/FixCursorHold.nvim", + "nvim-treesitter/nvim-treesitter", + "fredrikaverpil/neotest-golang", -- Installation + }, + config = function() + require("neotest").setup({ + adapters = { ++ require("neotest-golang") { -- Registration ++ dap_mode = "manual", ++ dap_manual_config = { ++ name = "Debug go tests", ++ type = "go", -- Preconfigured DAP adapter name ++ request = "launch", ++ mode = "test", ++ } ++ }, + }, + }) + end, + }, +} +``` + +
+ Finally, set a keymap, like: ```lua diff --git a/lua/neotest-golang/features/dap/dap_go.lua b/lua/neotest-golang/features/dap/dap_go.lua new file mode 100644 index 00000000..8735f384 --- /dev/null +++ b/lua/neotest-golang/features/dap/dap_go.lua @@ -0,0 +1,68 @@ +--- DAP (dap-go) setup related functions. + +local options = require("neotest-golang.options") +local logger = require("neotest-golang.logging") + +local M = {} + +---This will prepare and setup nvim-dap-go for debugging. +---@param cwd string +function M.setup_debugging(cwd) + local dap_go_opts = options.get().dap_go_opts or {} + if type(dap_go_opts) == "function" then + dap_go_opts = dap_go_opts() + end + local dap_go_opts_original = vim.deepcopy(dap_go_opts) + if dap_go_opts.delve == nil then + dap_go_opts.delve = {} + end + dap_go_opts.delve.cwd = cwd + logger.debug({ "Provided dap_go_opts for DAP: ", dap_go_opts }) + require("dap-go").setup(dap_go_opts) + + -- reset nvim-dap-go (and cwd) after debugging with nvim-dap + require("dap").listeners.after.event_terminated["neotest-golang-debug"] = function() + logger.debug({ + "Resetting provided dap_go_opts for DAP: ", + dap_go_opts_original, + }) + require("dap-go").setup(dap_go_opts_original) + end +end + +--- @param test_path string +--- @param test_name_regex string? +--- @return table | nil +function M.get_dap_config(test_path, test_name_regex) + -- :help dap-configuration + local dap_config = { + type = "go", + name = "Neotest-golang", + request = "launch", + mode = "test", + program = test_path, + } + + if test_name_regex ~= nil then + dap_config.args = { "-test.run", test_name_regex } + end + + local dap_go_opts = options.get().dap_go_opts or {} + if dap_go_opts.delve ~= nil and dap_go_opts.delve.build_flags ~= nil then + dap_config.buildFlags = dap_go_opts.delve.build_flags + end + + return dap_config +end + +function M.assert_dap_prerequisites() + local dap_go_found = pcall(require, "dap-go") + if not dap_go_found then + local msg = "You must have leoluz/nvim-dap-go installed to use DAP strategy. " + .. "See the neotest-golang README for more information." + logger.error(msg) + error(msg) + end +end + +return M diff --git a/lua/neotest-golang/features/dap/dap_manual.lua b/lua/neotest-golang/features/dap/dap_manual.lua new file mode 100644 index 00000000..13a19d36 --- /dev/null +++ b/lua/neotest-golang/features/dap/dap_manual.lua @@ -0,0 +1,40 @@ +--- DAP (manual dap configuration) setup related functions. + +local options = require("neotest-golang.options") + +local M = {} + +---@param cwd string +function M.setup_debugging(cwd) + local dap_manual_config = options.get().dap_manual_config or {} + if type(dap_manual_config) == "function" then + dap_manual_config = dap_manual_config() + end + + dap_manual_config.cwd = cwd +end + +---This will setup a dap configuration to run tests +---@param test_path string +---@param test_name_regex string? +---@return table | nil +function M.get_dap_config(test_path, test_name_regex) + local dap_manual_config = options.get().dap_manual_config or {} + if type(dap_manual_config) == "function" then + dap_manual_config = dap_manual_config() + end + + dap_manual_config.program = test_path + + if test_name_regex ~= nil then + dap_manual_config.args = dap_manual_config.args or {} + table.insert(dap_manual_config.args, "-test.run") + table.insert(dap_manual_config.args, test_name_regex) + end + return dap_manual_config +end + +---Dummy function is needed to be corresponding to dap-go setup (just like trait implementation) +function M.assert_dap_prerequisites() end + +return M diff --git a/lua/neotest-golang/features/dap/init.lua b/lua/neotest-golang/features/dap/init.lua index f6e36537..f89f0673 100644 --- a/lua/neotest-golang/features/dap/init.lua +++ b/lua/neotest-golang/features/dap/init.lua @@ -5,64 +5,46 @@ local logger = require("neotest-golang.logging") local M = {} ----This will prepare and setup nvim-dap-go for debugging. ----@param cwd string -function M.setup_debugging(cwd) - local dap_go_opts = options.get().dap_go_opts or {} - if type(dap_go_opts) == "function" then - dap_go_opts = dap_go_opts() - end - local dap_go_opts_original = vim.deepcopy(dap_go_opts) - if dap_go_opts.delve == nil then - dap_go_opts.delve = {} +local function get_dap_implementation() + local dap_impl + local selected_dap_mode = options.get().dap_mode + if type(selected_dap_mode) == "function" then + selected_dap_mode = selected_dap_mode() end - dap_go_opts.delve.cwd = cwd - logger.debug({ "Provided dap_go_opts for DAP: ", dap_go_opts }) - require("dap-go").setup(dap_go_opts) - -- reset nvim-dap-go (and cwd) after debugging with nvim-dap - require("dap").listeners.after.event_terminated["neotest-golang-debug"] = function() - logger.debug({ - "Resetting provided dap_go_opts for DAP: ", - dap_go_opts_original, - }) - require("dap-go").setup(dap_go_opts_original) + if selected_dap_mode == "dap-go" then + dap_impl = require("neotest-golang.features.dap.dap_go") + elseif selected_dap_mode == "manual" then + dap_impl = require("neotest-golang.features.dap.dap_manual") + else + local msg = "Got dap-mode: `" + .. selected_dap_mode + .. "` that cannot be used. " + .. "See the neotest-golang README for more information." + logger.error(msg) + error(msg) end + + return dap_impl +end + +---@param cwd string +function M.setup_debugging(cwd) + local dap_impl = get_dap_implementation() + dap_impl.setup_debugging(cwd) end --- @param test_path string --- @param test_name_regex string? --- @return table | nil function M.get_dap_config(test_path, test_name_regex) - -- :help dap-configuration - local dap_config = { - type = "go", - name = "Neotest-golang", - request = "launch", - mode = "test", - program = test_path, - } - - if test_name_regex ~= nil then - dap_config.args = { "-test.run", test_name_regex } - end - - local dap_go_opts = options.get().dap_go_opts or {} - if dap_go_opts.delve ~= nil and dap_go_opts.delve.build_flags ~= nil then - dap_config.buildFlags = dap_go_opts.delve.build_flags - end - - return dap_config + local dap_impl = get_dap_implementation() + return dap_impl.get_dap_config(test_path, test_name_regex) end function M.assert_dap_prerequisites() - local dap_go_found = pcall(require, "dap-go") - if not dap_go_found then - local msg = "You must have leoluz/nvim-dap-go installed to use DAP strategy. " - .. "See the neotest-golang README for more information." - logger.error(msg) - error(msg) - end + local dap_impl = get_dap_implementation() + dap_impl.assert_dap_prerequisites() end return M diff --git a/lua/neotest-golang/options.lua b/lua/neotest-golang/options.lua index 8caa54b2..1c85e7b2 100644 --- a/lua/neotest-golang/options.lua +++ b/lua/neotest-golang/options.lua @@ -12,6 +12,8 @@ local opts = { gotestsum_args = { "--format=standard-verbose" }, -- NOTE: can also be a function go_list_args = {}, -- NOTE: can also be a function dap_go_opts = {}, -- NOTE: can also be a function + dap_mode = "dap-go", -- NOTE: or "manual" ; can also be a function + dap_manual_config = {}, -- NOTE: can also be a function testify_enabled = false, colorize_test_output = true, warn_test_name_dupes = true, diff --git a/tests/unit/options_spec.lua b/tests/unit/options_spec.lua index e7859406..9ca2de7b 100644 --- a/tests/unit/options_spec.lua +++ b/tests/unit/options_spec.lua @@ -13,6 +13,8 @@ describe("Options are set up", function() go_list_args = {}, gotestsum_args = { "--format=standard-verbose" }, dap_go_opts = {}, + dap_mode = "dap-go", + dap_manual_config = {}, testify_enabled = false, colorize_test_output = true, warn_test_name_dupes = true, @@ -37,6 +39,8 @@ describe("Options are set up", function() go_list_args = {}, gotestsum_args = { "--format=standard-verbose" }, dap_go_opts = {}, + dap_mode = "dap-go", + dap_manual_config = {}, testify_enabled = false, colorize_test_output = false, warn_test_name_dupes = true, @@ -65,6 +69,12 @@ describe("Options are set up", function() dap_go_opts = function() return {} end, + dap_mode = function() + return "dap-go" + end, + dap_manual_config = function() + return {} + end, testify_enabled = false, colorize_test_output = true, warn_test_name_dupes = true,