From 72143a7296c36bc9c20a52e5946b14ed11d15bf0 Mon Sep 17 00:00:00 2001 From: Martial Saunois Date: Wed, 10 Apr 2024 09:56:33 +0200 Subject: [PATCH 1/7] Set the Delve port dynamically Currently the Delve port can be defined either randomly or hard-coded by hand. Hard-coded port allows to know which port to use in debug configurations, but in practice with many Go projects, it would be great to set the Delve port in debug configurations. Luckily `nvim-dap` allows to set an `on_config` callback for an adapter, which can be used to resolve the adapter settings when a debug session starts. This PR implements this `nvim-dap` feature, which can be used with the support of VSCode `launch.json` files to greatly enhance the developer experience. This potentially resolves https://github.com/leoluz/nvim-dap-go/issues/73 --- README.md | 42 +++++++++++++++++++++++++++++++++++++++++- lua/dap-go.lua | 21 +++++++++++++++++++-- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 06d05b7..e8443b9 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ An extension for [nvim-dap][1] providing configurations for launching go debugge - Configuration to attach nvim-dap and Delve into a running process and start a debug session. - Configuration to start a debug session in the main function. - Configuration to run tests in a debug session. +- Final Delve configuration is resolved when a debug session starts. This allows to use different addresses and ports for each project or launch configs in a project. ## Pre-reqs @@ -67,7 +68,9 @@ lua require('dap-go').setup { initialize_timeout_sec = 20, -- a string that defines the port to start delve debugger. -- default to string "${port}" which instructs nvim-dap - -- to start the process in a random available port + -- to start the process in a random available port. + -- if you set a port in your debug configuration, its value will be + -- assigned dynamically. port = "${port}", -- additional args to pass to dlv args = {}, @@ -196,6 +199,43 @@ dlv debug -l 127.0.0.1:38697 --headless ./main.go -- subcommand --myflag=xyz nmap td :lua require('dap-go').debug_test() ``` +## VSCode launch config + +Defining the Go debug configurations for all your projects inside your Neovim configuration can be cumbersome and quite strict. +For more flexibility, `nvim-dap` supports the use of the VSCode launch configurations. To use that feature in combination with the pre-defined `nvim-dap-go` configurations (the ones for launching debug sessions in tests for instance), load the VSCode configurations **BEFORE** calling the `setup()` function of `nvim-dap-go`: + +```lua +require("dap.ext.vscode").load_launchjs() +require("dap-go").setup() +``` + +That allows for example to set the Delve port dynamically when you run a debug session. If you create this file in your project (`[root_project]/.vscode/launch.json`): + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Remote debug API server", + "type": "go", + "request": "attach", + "mode": "remote", + "port": 4444, + "host": "127.0.0.1", + "substitutePath": [ + { + "from": "${workspaceFolder}", "to": "/usr/src/app" + } + ] + } + ] +} +``` + +A debug session `Remote debug API server` will appear in the choices, and the Delve port will be dynamically set to `4444`. + +Please see `:h dap-launch.json` for more information. + ## Acknowledgement Thanks to the [nvim-dap-python][6] for the inspiration. diff --git a/lua/dap-go.lua b/lua/dap-go.lua index cfded30..b45a8b5 100644 --- a/lua/dap-go.lua +++ b/lua/dap-go.lua @@ -66,7 +66,7 @@ local function setup_delve_adapter(dap, config) local args = { "dap", "-l", "127.0.0.1:" .. config.delve.port } vim.list_extend(args, config.delve.args) - dap.adapters.go = { + local delve_config = { type = "server", port = config.delve.port, executable = { @@ -79,10 +79,23 @@ local function setup_delve_adapter(dap, config) initialize_timeout_sec = config.delve.initialize_timeout_sec, }, } + + dap.adapters.go = function(callback, client_config) + if client_config.mode ~= "remote" then + callback(delve_config) + return + end + + local listener_addr = client_config.host .. ":" .. client_config.port + delve_config.port = client_config.port + delve_config.executable.args = { "dap", "-l", listener_addr } + + callback(delve_config) + end end local function setup_go_configuration(dap, configs) - dap.configurations.go = { + local common_debug_configs = { { type = "go", name = "Debug", @@ -139,6 +152,10 @@ local function setup_go_configuration(dap, configs) }, } + for _, config in ipairs(common_debug_configs) do + table.insert(dap.configurations.go, config) + end + if configs == nil or configs.dap_configurations == nil then return end From a89030d68e816230e525179deb8ee3a09a8470be Mon Sep 17 00:00:00 2001 From: Martial Saunois Date: Wed, 10 Apr 2024 10:23:15 +0200 Subject: [PATCH 2/7] Fix textlint error --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8443b9..7ee3a5a 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,7 @@ nmap td :lua require('dap-go').debug_test() ## VSCode launch config Defining the Go debug configurations for all your projects inside your Neovim configuration can be cumbersome and quite strict. -For more flexibility, `nvim-dap` supports the use of the VSCode launch configurations. To use that feature in combination with the pre-defined `nvim-dap-go` configurations (the ones for launching debug sessions in tests for instance), load the VSCode configurations **BEFORE** calling the `setup()` function of `nvim-dap-go`: +For more flexibility, `nvim-dap` supports the use of the VSCode launch configurations. To use that feature in combination with the predefined `nvim-dap-go` configurations (the ones for launching debug sessions in tests for instance), load the VSCode configurations **BEFORE** calling the `setup()` function of `nvim-dap-go`: ```lua require("dap.ext.vscode").load_launchjs() From dd99e698823ad63d14fdbac9203569b78dfe44d9 Mon Sep 17 00:00:00 2001 From: Martial Saunois Date: Wed, 10 Apr 2024 17:11:07 +0200 Subject: [PATCH 3/7] Fix possible nil table for Go configs --- lua/dap-go.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lua/dap-go.lua b/lua/dap-go.lua index b45a8b5..719122a 100644 --- a/lua/dap-go.lua +++ b/lua/dap-go.lua @@ -152,6 +152,10 @@ local function setup_go_configuration(dap, configs) }, } + if dap.configurations.go == nil then + dap.configurations.go = {} + end + for _, config in ipairs(common_debug_configs) do table.insert(dap.configurations.go, config) end From d43aab35024dd58eea218a348a46606f27f4a9d4 Mon Sep 17 00:00:00 2001 From: Martial Saunois Date: Fri, 19 Jul 2024 14:52:18 +0200 Subject: [PATCH 4/7] Complete the documentation --- doc/nvim-dap-go.txt | 51 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/doc/nvim-dap-go.txt b/doc/nvim-dap-go.txt index f62e0ae..9efd047 100644 --- a/doc/nvim-dap-go.txt +++ b/doc/nvim-dap-go.txt @@ -17,7 +17,8 @@ CONTENTS *dap-go-toc* 5. Debugging With Command-Line Arguments . |dap-go-debug-cli-args| 6. Debugging With Build Flags ............ |dap-go-debug-cli-args| 7. Debugging With dlv in Headless Mode ... |dap-go-debug-headless| - 8. Mappings .............................. |dap-go-mappings| + 8. VSCode launch config .................. |dap-go-vscode-launch| + 9. Mappings .............................. |dap-go-mappings| ======================================================================== FEATURES *dap-go-features* @@ -36,6 +37,10 @@ FEATURES *dap-go-features* - Configuration to run tests in a debug session. +- Final Delve configuration is resolved when a debug session starts. + This allows to use different addresses and ports for each project or + launch configs in a project. + This plugin makes usage of treesitter to find the nearest test to debug. Make sure you have the Go treesitter parser installed. If using |nvim-treesitter| plugin you can install with `:TSInstall go`. @@ -80,7 +85,9 @@ The example bellow shows all the possible configurations: initialize_timeout_sec = 20, -- a string that defines the port to start delve debugger. -- default to string "${port}" which instructs nvim-dap - -- to start the process in a random available port + -- to start the process in a random available port. + -- if you set a port in your debug configuration, its value will be + -- assigned dynamically. port = "${port}", -- additional args to pass to dlv args = {}, @@ -207,6 +214,45 @@ Debugging With dlv in Headless Mode *dap-go-debug-headless* 3. Call `:lua require('dap').continue()` to start debugging. 4. Select the new registered option `Attach remote`. +----------------------------------------------------------------------- +VSCode launch config *dap-go-vscode-launch + + 1. In your neovim configuration, load the VSCode extension BEFORE + calling the `setup()` function: +>lua + require("dap.ext.vscode").load_launchjs() + require("dap-go").setup() +< + + 2. Create in your Go project a VSCode launch config file (by + default its path must be `.vscode/launch.json` relative to your + project's root directory): +>json + { + "version": "0.2.0", + "configurations": [ + { + "name": "Remote debug API server", + "type": "go", + "request": "attach", + "mode": "remote", + "port": 4444, + "host": "127.0.0.1", + "substitutePath": [ + { + "from": "${workspaceFolder}", "to": "/usr/src/app" + } + ] + } + ] + } +< + + 3. A debug session `Remote debug API server` will appear in the choices, + and the Delve port will be dynamically set to `4444`. + +Please see `:h dap-launch.json` for more information. + ======================================================================== MAPPINGS *dap-go-mappings* @@ -220,5 +266,4 @@ mappings. You can do this by adding the lines bellow to your vim.keymap.set("n", "dt", dapgo.debug_test) vim.keymap.set("n", "dl", dapgo.debug_last_test) < - vim:tw=78:et:ft=help:norl: From 61cd78d9c4c5ebe0fd3c6729b8b362dba5180a0c Mon Sep 17 00:00:00 2001 From: Martial Saunois Date: Fri, 19 Jul 2024 16:15:47 +0200 Subject: [PATCH 5/7] Validate the VSCode configuration --- lua/dap-go.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lua/dap-go.lua b/lua/dap-go.lua index 719122a..3d4e5a2 100644 --- a/lua/dap-go.lua +++ b/lua/dap-go.lua @@ -81,6 +81,19 @@ local function setup_delve_adapter(dap, config) } dap.adapters.go = function(callback, client_config) + local required_fields = { + "mode", + "port", + "host", + } + + for _, field in ipairs(required_fields) do + if client_config[field] == nil then + vim.notify(string.format("missing DAP config key %s", field), vim.log.levels.ERROR) + return + end + end + if client_config.mode ~= "remote" then callback(delve_config) return From 71361a9bf040752ad7d81563f90106a3306a4cce Mon Sep 17 00:00:00 2001 From: Martial Saunois Date: Tue, 23 Jul 2024 15:06:50 +0200 Subject: [PATCH 6/7] Update the doc according to the current version of nvim-dap --- README.md | 8 ++------ doc/nvim-dap-go.txt | 11 ++--------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 7ee3a5a..38974d2 100644 --- a/README.md +++ b/README.md @@ -202,12 +202,7 @@ nmap td :lua require('dap-go').debug_test() ## VSCode launch config Defining the Go debug configurations for all your projects inside your Neovim configuration can be cumbersome and quite strict. -For more flexibility, `nvim-dap` supports the use of the VSCode launch configurations. To use that feature in combination with the predefined `nvim-dap-go` configurations (the ones for launching debug sessions in tests for instance), load the VSCode configurations **BEFORE** calling the `setup()` function of `nvim-dap-go`: - -```lua -require("dap.ext.vscode").load_launchjs() -require("dap-go").setup() -``` +For more flexibility, `nvim-dap` supports the use of the VSCode launch configurations. That allows for example to set the Delve port dynamically when you run a debug session. If you create this file in your project (`[root_project]/.vscode/launch.json`): @@ -233,6 +228,7 @@ That allows for example to set the Delve port dynamically when you run a debug s ``` A debug session `Remote debug API server` will appear in the choices, and the Delve port will be dynamically set to `4444`. +The current version of nvim-dap always loads the file if it exists. Please see `:h dap-launch.json` for more information. diff --git a/doc/nvim-dap-go.txt b/doc/nvim-dap-go.txt index 9efd047..3252561 100644 --- a/doc/nvim-dap-go.txt +++ b/doc/nvim-dap-go.txt @@ -217,14 +217,7 @@ Debugging With dlv in Headless Mode *dap-go-debug-headless* ----------------------------------------------------------------------- VSCode launch config *dap-go-vscode-launch - 1. In your neovim configuration, load the VSCode extension BEFORE - calling the `setup()` function: ->lua - require("dap.ext.vscode").load_launchjs() - require("dap-go").setup() -< - - 2. Create in your Go project a VSCode launch config file (by + 1. Create in your Go project a VSCode launch config file (by default its path must be `.vscode/launch.json` relative to your project's root directory): >json @@ -248,7 +241,7 @@ VSCode launch config *dap-go-vscode-launch } < - 3. A debug session `Remote debug API server` will appear in the choices, + 2. A debug session `Remote debug API server` will appear in the choices, and the Delve port will be dynamically set to `4444`. Please see `:h dap-launch.json` for more information. From d8974487e76fa13d503652080efcabadc0eac920 Mon Sep 17 00:00:00 2001 From: Martial Saunois Date: Wed, 31 Jul 2024 09:49:27 +0200 Subject: [PATCH 7/7] Revert required fields The extension now decides if it should enable the remote debugging if a port is defined in the user configuration. --- lua/dap-go.lua | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/lua/dap-go.lua b/lua/dap-go.lua index 3d4e5a2..6e125a9 100644 --- a/lua/dap-go.lua +++ b/lua/dap-go.lua @@ -81,25 +81,17 @@ local function setup_delve_adapter(dap, config) } dap.adapters.go = function(callback, client_config) - local required_fields = { - "mode", - "port", - "host", - } - - for _, field in ipairs(required_fields) do - if client_config[field] == nil then - vim.notify(string.format("missing DAP config key %s", field), vim.log.levels.ERROR) - return - end - end - - if client_config.mode ~= "remote" then + if client_config.port == nil then callback(delve_config) return end - local listener_addr = client_config.host .. ":" .. client_config.port + local host = client_config.host + if host == nil then + host = "127.0.0.1" + end + + local listener_addr = host .. ":" .. client_config.port delve_config.port = client_config.port delve_config.executable.args = { "dap", "-l", listener_addr }