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

Support startDebugging #38

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ You must download and build a copy of [vscode-js-debug](https://github.com/micro
use {
"microsoft/vscode-js-debug",
opt = true,
run = "npm install --legacy-peer-deps && npm run compile"
run = "npm install --legacy-peer-deps && npx gulp dapDebugServer"
}
```

Expand All @@ -52,8 +52,7 @@ npm run compile
```lua
require("dap-vscode-js").setup({
-- node_path = "node", -- Path of node executable. Defaults to $NODE_PATH, and then "node"
-- debugger_path = "(runtimedir)/site/pack/packer/opt/vscode-js-debug", -- Path to vscode-js-debug installation.
-- debugger_cmd = { "js-debug-adapter" }, -- Command to use to launch the debug server. Takes precedence over `node_path` and `debugger_path`.
-- debugger_path = "(runtimedir)/site/pack/packer/opt/vscode-js-debug/dist/src/dapDebugServer.js", -- Path to vscode-js-debug installation.
adapters = { 'pwa-node', 'pwa-chrome', 'pwa-msedge', 'node-terminal', 'pwa-extensionHost' }, -- which adapters to register in nvim-dap
-- log_file_path = "(stdpath cache)/dap_vscode_js.log" -- Path for file logging
-- log_file_level = false -- Logging level for output to file. Set to false to disable file logging.
Expand Down
115 changes: 44 additions & 71 deletions lua/dap-vscode-js/adapter.lua
Original file line number Diff line number Diff line change
@@ -1,78 +1,51 @@
local M = {}
local uv = vim.loop
local js_session = require("dap-vscode-js.session")
local utils = require("dap-vscode-js.utils")
local logger = require("dap-vscode-js.log")
-- local logger = require("dap-vscode-js.log")
local dapjs_config = require("dap-vscode-js.config")
local dap = require("dap")

local function adapter_config(port, mode, proc, start_child)
return {
type = "server",
host = "127.0.0.1",
port = port,
id = mode,
reverse_request_handlers = {
attachedChildSession = function(parent, request)
logger.debug(
string.format(
"Got attachedChildSession request from port %d to start port %s",
parent.adapter.port,
request.arguments.config.__jsDebugChildServer
)
)
logger.trace("attachedChildSession request, port " .. tostring(port) .. ": " .. vim.inspect(request))

start_child(request, mode, parent, proc)
end,
},
}
end

local function start_child_session(request, mode, parent, proc)
local body = request.arguments
local session = nil
local child_port = tonumber(body.config.__jsDebugChildServer)

session = require("dap.session"):connect(
adapter_config(child_port, mode, proc, start_child_session),
{},
function(err)
if err then
logger.log("DAP connection failed to start: " .. err, vim.log.levels.ERROR)
else
logger.debug("Initializing child session on port " .. tostring(child_port))

session:initialize(body.config)

js_session.register_session(session, parent, proc)
end
end
)
end

function M.generate_adapter(mode, config)
config = config or dapjs_config

return function(callback)
local proc

proc = utils.start_debugger(config, function(port, proc)
logger.debug("Debugger process started on port " .. port)

js_session.register_port(port)
callback(adapter_config(port, mode, proc, start_child_session))
end, function(code, signal)
if code and code ~= 0 then
logger.error("JS Debugger exited with code " .. code .. "!")
end
end, function(err)
logger.error("Error trying to launch JS debugger: " .. err)
end, function(chunk)
-- logger.log("JS Debugger stderr: " .. chunk, vim.log.levels.ERROR)
logger.error("JS Debugger stderr: " .. chunk)
end)
end
function M.generate_adapter(_, user_config)
user_config = user_config or dapjs_config

return function(on_config, config, parent)
local target = config["__pendingTargetId"]
if target and parent then
local adapter = parent.adapter
on_config({
type = "server",
host = "localhost",
port = adapter.port
})
else
Comment on lines +9 to +18
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a further change in nvim-dap to automatically use the parent host+port if the adapter has both type server and an executable. See mfussenegger/nvim-dap#913. This should make it unnecessary to check for target and parent, you can instead always return the same definition.

local debug_executable = user_config.adapter_executable_config

if not debug_executable then
local debugger_path = user_config.debugger_executable

if not utils.file_exists(debugger_path) then
-- TODO: show user to README.md with directions
error("Debugger entrypoint file '" .. debugger_path .. "' does not exist. Did it build properly?")
end

local debugger_cmd_args = { debugger_path, "${port}" }

for _, arg in ipairs(user_config.debugger_args or {}) do
table.insert(debugger_cmd_args, arg)
end

debug_executable = {
command = user_config.node_path,
args = debugger_cmd_args,
}
end

on_config({
type = "server",
host = "localhost",
port = "${port}",
executable = debug_executable
})
end
end
end

return M
11 changes: 9 additions & 2 deletions lua/dap-vscode-js/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ local utils = require("dap-vscode-js.utils")

local defaults = {
node_path = os.getenv("NODE_PATH") or "node",
debugger_path = utils.join_paths(utils.get_runtime_dir(), "site/pack/packer/opt/vscode-js-debug"),
debugger_cmd = nil,
debugger_executable = utils.join_paths(utils.get_runtime_dir(), "site/pack/packer/opt/vscode-js-debug/dist/src/dapDebugServer.js"),
debugger_args = {},
adapter_executable_config = nil,

log_file_path = utils.join_paths(utils.get_cache_dir(), "dap_vscode_js.log"),
log_file_level = false,
log_console_level = vim.log.levels.WARN,

-- legacy
debugger_cmd = nil,
debugger_path = utils.join_paths(utils.get_runtime_dir(), "site/pack/packer/opt/vscode-js-debug"),
legacy_flat_debugger = false,
}

local config = vim.deepcopy(defaults)
Expand Down
6 changes: 3 additions & 3 deletions lua/dap-vscode-js/dap.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local M = {}
local dap = require("dap")
local js_adapter = require("dap-vscode-js.adapter")
-- local js_adapter = require("dap-vscode-js.adapter")

local DAP_TYPES = { "pwa-node", "pwa-chrome", "pwa-msedge", "node-terminal", "pwa-extensionHost" }

Expand All @@ -10,11 +10,11 @@ local function filter_adapters(list)
end, list)
end

function M.attach_adapters(config)
function M.attach_adapters(config, generate_adapter)
local adapter_list = filter_adapters(config.adapters or DAP_TYPES)

for _, adapter in ipairs(adapter_list) do
dap.adapters[adapter] = js_adapter.generate_adapter(adapter, config)
dap.adapters[adapter] = generate_adapter(adapter, config)
end
end

Expand Down
22 changes: 16 additions & 6 deletions lua/dap-vscode-js/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@

---@class Settings @Plugin configuration options
---@field node_path string: Path of node executable. Defaults to $NODE_PATH, and then "node"
---@field debugger_path string: Path to vscode-js-debug. Defaults to (runtimedir)/site/pack/packer/opt/vscode-js-debug
---@field debugger_cmd string[]: The command to use to launch the debug server. This option takes precedence over both `node_path` and `debugger_path`.
---@field debugger_executable string: Path to debugger executable (dapDebugServer.js). Defaults to (runtimedir)/site/pack/packer/opt/vscode-js-debug/dist/src/dapDebugServer.js
---@field debugger_args string[]: Arguments to pass to debugger command. Defaults to {}
---@field adapter_executable_config table: Overrides adapter debugger executable configuration - see nvim-dap for more info
---@field adapters string[]: List of adapters to configure. Options are 'pwa-node', 'pwa-chrome', 'pwa-msedge', 'node-terminal', 'pwa-extensionHost'. Defaults to all. See https://github.com/microsoft/vscode-js-debug/blob/main/OPTIONS.md for configuration options.
---@field log_file_path string: Log file path. Defaults to (stdpath cache)/dap_vscode_js.log
---@field log_file_level number: Logging level for output to file. Set to false to disable file logging. Default is false.
---@field log_console_level number: Logging level for output to console. Set to false to disable console output. Default is vim.log.levels.ERROR.
---@field legacy_flat_debugger boolean: Use legacy flat debugger, and use legacy custom session manager for dealing with child/parent sessions. This is not maintained anymore.
---@field debugger_path string: (LEGACY) Path to vscode-js-debug. Defaults to (runtimedir)/site/pack/packer/opt/vscode-js-debug
---@field debugger_cmd string[]: (LEGACY) The command to use to launch the debug server. This option takes precedence over both `node_path` and `debugger_path`.

local config = require("dap-vscode-js.config")
local js_session = require("dap-vscode-js.session")
local js_dap = require("dap-vscode-js.dap")
local logger = require("dap-vscode-js.log")
local legacy = require("dap-vscode-js.legacy")
local js_dap = require("dap-vscode-js.dap")
local js_adapter = require("dap-vscode-js.adapter")

local dapjs = {}

Expand All @@ -21,8 +26,13 @@ local dapjs = {}
---@param force boolean?
function dapjs.setup(settings, force)
config.__set_config(settings, force or true)
js_session.setup_hooks("dap-vscode-js", config)
js_dap.attach_adapters(config)

if legacy.use_legacy(config) then
legacy.setup(config)
else
-- use new adapter
js_dap.attach_adapters(config, js_adapter.generate_adapter)
end

logger.debug("Plugin initialized!")
end
Expand Down
79 changes: 79 additions & 0 deletions lua/dap-vscode-js/legacy/adapter.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
local M = {}
local uv = vim.loop
local js_session = require("dap-vscode-js.legacy.session")
local utils = require("dap-vscode-js.utils")
local logger = require("dap-vscode-js.log")
local dapjs_config = require("dap-vscode-js.config")
local dap = require("dap")

local function adapter_config(port, mode, proc, start_child)
return {
type = "server",
host = "127.0.0.1",
port = port,
id = mode,
reverse_request_handlers = {
attachedChildSession = function(parent, request)
logger.debug(
string.format(
"Got attachedChildSession request from port %d to start port %s",
parent.adapter.port,
request.arguments.config.__jsDebugChildServer
)
)
logger.trace("attachedChildSession request, port " .. tostring(port) .. ": " .. vim.inspect(request))

start_child(request, mode, parent, proc)
end,
},
}
end

local function start_child_session(request, mode, parent, proc)
local body = request.arguments
local session = nil
local child_port = tonumber(body.config.__jsDebugChildServer)

session = require("dap.session"):connect(
adapter_config(child_port, mode, proc, start_child_session),
{},
function(err)
if err then
logger.log("DAP connection failed to start: " .. err, vim.log.levels.ERROR)
else
logger.debug("Initializing child session on port " .. tostring(child_port))
if parent.children then
session.parent = parent
parent.children[session.id] = session
end
session:initialize(body.config)
js_session.register_session(session, parent, proc)
end
end
)
end

function M.generate_adapter(mode, config)
config = config or dapjs_config

return function(callback)
local proc

proc = utils.start_debugger(config, function(port, proc)
logger.debug("Debugger process started on port " .. port)

js_session.register_port(port)
callback(adapter_config(port, mode, proc, start_child_session))
end, function(code, signal)
if code and code ~= 0 then
logger.error("JS Debugger exited with code " .. code .. "!")
end
end, function(err)
logger.error("Error trying to launch JS debugger: " .. err)
end, function(chunk)
logger.error("JS Debugger stderr: " .. chunk)
end)
end
end

return M
20 changes: 20 additions & 0 deletions lua/dap-vscode-js/legacy/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
local js_adapter = require("dap-vscode-js.legacy.adapter")
local js_session = require("dap-vscode-js.legacy.session")
local js_dap = require("dap-vscode-js.dap")

local M = {}

--- Whether or not to use legacy module
--- @param config Settings
--- @return boolean
function M.use_legacy(config)
-- TODO: figure out if `startDebugging` is supported
return config.legacy_flat_debugger
end

function M.setup(config)
-- js_session.setup_hooks("dap-vscode-js", config)
-- js_dap.attach_adapters(config, js_adapter.generate_adapter)
end

return M
File renamed without changes.
4 changes: 2 additions & 2 deletions lua/dap-vscode-js/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ local function schedule_wrap_safe(func)
return (func and vim.schedule_wrap(func)) or function(...) end
end

local function file_exists(name)
function M.file_exists(name)
local f = io.open(name, "r")
if f ~= nil then
io.close(f)
Expand All @@ -60,7 +60,7 @@ local function get_spawn_cmd(config)
end
local entrypoint = debugger_entrypoint(config.debugger_path)

if not file_exists(entrypoint) then
if not M.file_exists(entrypoint) then
error("Debugger entrypoint file '" .. entrypoint .. "' does not exist. Did it build properly?")
end
return config.node_path, { entrypoint }
Expand Down
2 changes: 1 addition & 1 deletion scripts/setup_tests
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ __install_lib "mfussenegger" "nvim-dap"
__install_lib "rcarriga" "nvim-dap-ui"
__install_lib "microsoft" "vscode-js-debug"

(cd ./lib/vscode-js-debug && yarn install && yarn run compile)
(cd ./lib/vscode-js-debug && npm install --legacy-peer-deps && npx gulp dapDebugServer)
(cd ./tests/js/jest && yarn install)
2 changes: 1 addition & 1 deletion scripts/test
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export DAP_JS_ENABLE_LOGGING=$LOG

shift $(($OPTIND - 1))

rm "./lib/dap-vscode-js.log"
rm -f "./lib/dap-vscode-js.log"

tempfile=".test_output.tmp"

Expand Down
4 changes: 3 additions & 1 deletion tests/init.vim
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ set rtp+=./lib/nvim-dap
set rtp+=./lib/nvim-dap-ui
set rtp+=./tests

set noswapfile

" let $PLENARY_TEST_TIMEOUT=60000

runtime! plugin/plenary.vim
lua DEBUGGER_PATH="./lib/vscode-js-debug"
lua DEBUGGER_PATH="./lib/vscode-js-debug/dist/src/dapDebugServer.js"
lua LOG_PATH="./lib/dap-vscode-js.log"
6 changes: 1 addition & 5 deletions tests/integration/jest_spec.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
local breakpoints = require("dap.breakpoints")
local async = require("plenary.async.tests")
local wrap = require("plenary.async.async").wrap
local dapjs = require("dap-vscode-js")
local js_session = require("dap-vscode-js.session")
local dap = require("dap")
local test_utils = require("__dap_js_test_util")
local config = require("dap-vscode-js.config")

local workDir = test_utils.test_file("jest")

Expand Down Expand Up @@ -59,7 +55,7 @@ describe("pwa-node jest", function()

test_utils.open_test("jest/integration.test.ts")

test_utils.on_session_end(function()
test_utils.add_listener("before", "event_terminated", function ()
terminated = true

try_exit()
Expand Down
Loading