mfussenegger / nvim-dap

Debug Adapter Protocol client implementation for Neovim
GNU General Public License v3.0
5.46k stars 194 forks source link

netcoredbg with attach: lua error table index nil in function rawset in lua/dap.lua:103 in function '__index' #1074

Closed WillEhrendreich closed 11 months ago

WillEhrendreich commented 11 months ago

Debug adapter definition and debug configuration

using lazyvim, installed via mason.

in an attempt to see what's going on, I simplified the dap util functions and gave them more verbose output, so i knew for sure that the picking wasn't the issue.

--- Return running processes as a list with { pid, name } tables.
---
---@return {pid: integer, name: string}[]
function DapGetProcesses()
  local is_windows = vim.fn.has("win32") == 1
  local separator = is_windows and "," or " \\+"
  local command = is_windows and { "tasklist", "/nh", "/fo", "csv" } or { "ps", "ah", "-U", os.getenv("USER") }
  -- output format for `tasklist /nh /fo` csv
  --    '"smss.exe","600","Services","0","1,036 K"'
  -- output format for `ps ah`
  --    " 107021 pts/4    Ss     0:00 /bin/zsh <args>"
  local get_pid = function(parts)
    if is_windows then
      return vim.fn.trim(parts[2], '"')
    else
      return parts[1]
    end
  end

  local get_process_name = function(parts)
    if is_windows then
      return vim.fn.trim(parts[1], '"')
    else
      return table.concat({ unpack(parts, 5) }, " ")
    end
  end

  local output = vim.fn.system(command)
  local lines = vim.split(output, "\n")
  local procs = {}

  local nvim_pid = vim.fn.getpid()
  for _, line in pairs(lines) do
    if line ~= "" then -- tasklist command outputs additional empty line in the end
      local parts = vim.fn.split(vim.fn.trim(line), separator)
      local pid, name = get_pid(parts), get_process_name(parts)
      pid = tonumber(pid)
      if pid and pid ~= nvim_pid then
        table.insert(procs, 1, { pid = pid, name = name })
        --   return a.pid > b.pid
      end
    end
  end

  return procs
end

--- Show a prompt to select a process pid
--- Requires `ps ah -u $USER` on Linux/Mac and `tasklist /nh /fo csv` on windows.
--
--- Takes an optional `opts` table with the following options:
---
--- - filter string|fun: A lua pattern or function to filter the processes.
---                      If a function the parameter is a table with
---                      {pid: integer, name: string}
---                      and it must return a boolean.
---                      Matches are included.
---
--- <pre>
--- require("dap.utils").pick_process({ filter = "sway" })
--- </pre>
---
--- <pre>
--- require("dap.utils").pick_process({
---   filter = function(proc) return vim.endswith(proc.name, "sway") end
--- })
--- </pre>
---
---@param opts? {filter: string|(fun(proc: {pid: integer, name: string}): boolean)}
function DapPickProcess(opts)
  opts = opts or {}
  local label_fn = function(proc)
    return string.format("id=%d name=%s", proc.pid, proc.name)
  end
  local procs = DapGetProcesses()
  if opts.filter then
    local filter
    if type(opts.filter) == "string" then
      filter = function(proc)
        return proc.name:find(opts.filter)
      end
    elseif type(opts.filter) == "function" then
      filter = function(proc)
        return opts.filter(proc)
      end
    else
      error("opts.filter must be a string or a function")
    end

    procs = vim.tbl_filter(filter, procs)
  end
  -- procs = table.sort(procs, function(a, b)
  vim.notify("filtering for: " .. vim.inspect(opts.filter))
  --   return a.pid > b.pid
  -- end)
  -- local co = coroutine.running()
  -- if co then
  --   vim.notify("running async coroutine process picking")
  --   return coroutine.create(function()
  --     require("dap.ui").pick_one(procs, "Select process: ", label_fn, function(choice)
  --       -- pick_one(procs, "Select process: ", label_fn, function(choice)
  --       coroutine.resume(co, choice and choice.pid or nil)
  --     end)
  --   end)
  -- else
  vim.notify("running sync coroutine process picking")

  local result = require("dap.ui").pick_one_sync(procs, "Select process: ", label_fn)
  -- local result = pick_one_sync(procs, "Select process: ", label_fn)
  vim.notify("result of pick process is.." .. vim.inspect(tonumber(result.pid)))
  return result and result.pid or nil
  -- end
end

{
  type = "coreclr",
  name = "attach - netcoredbg",
  -- processId = function()
  --   -- local result = require("dap.utils").pick_process_sync()
  --   local result = DapPickProcess()
  --
  --   return result
  -- end,
  -- processId = DapPickProcess({ filter = vim.g["DotnetProjectFileName"] }),
  -- processId = vim.schedule_wrap(function()
  --   local process = DapPickProcess({ filter = vim.fn.input("process name?") })
  --
  --   vim.inspect("process picked: " .. process)
  --   return tonumber(process)
  -- end),
  processId = function()
    local process = DapPickProcess({ filter = vim.fn.input("process name?") })

    vim.notify(vim.inspect("process picked: " .. process))

    vim.fn.setenv("NETCOREDBG_ATTACH_PID", process)
    vim.notify(vim.inspect("NETCOREDBG_ATTACH_PID set to : " .. (vim.fn.getenv("NETCOREDBG_ATTACH_PID") or "nil")))
    return tonumber(process)
  end,

Debug adapter version

0.6.0

Steps to Reproduce

it doesn't seem to matter what project im in, or what breakpoints i set.

trying to use the pick process functionality never seems to work.

Expected Result

I expect to pick a process, and that the debugger would connect to that.

Actual Result

I pick a process from the ui that pops up, then it gives this message

filtering for: "Fabload.exe"  Info 2:06:14 PM notify.info running sync coroutine process picking 2:06:14 PM msg_show process name?Fabload.exe Select process: 1: id=17528 name=Fabload.exe Type number and or click with the mouse (q or empty cancels): 2:06:16 PM msg_show process name?Fabload.exe 1  Info 2:06:17 PM notify.info result of pick process is..17528  Info 2:06:17 PM notify.info "process picked: 17528"  Info 2:06:17 PM notify.info "NETCOREDBG_ATTACH_PID set to : 17528"  Error 2:06:19 PM msg_show.lua_error Error executing vim.schedule lua callback: table index is nil stack traceback: [C]: in function 'rawset' C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap.lua:103: in function '__index' C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:974: in function <C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:972>  Warn 2:06:21 PM notify.warn DAP Debug adapter didn't respond. Either the adapter is slow (then wait and ignore this) or there is a problem with your adapter or coreclr configuration. Check the logs for errors (:help dap.set_log_level)

in the logs:


[ DEBUG ] 2023-10-30T14:26:01Z-0500 ] C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:1339 ]    "Spawning debug adapter"    {
  args = { "--interpreter=vscode" },
  command = "C:/.local/share/nvim-data/mason/packages/netcoredbg/netcoredbg/netcoredbg.exe",
  type = "executable"
}
[ DEBUG ] 2023-10-30T14:26:01Z-0500 ] C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:1634 ]    "request"   {
  arguments = {
    adapterID = "nvim-dap",
    clientId = "neovim",
    clientname = "neovim",
    columnsStartAt1 = true,
    linesStartAt1 = true,
    locale = "en_US",
    pathFormat = "path",
    supportsProgressReporting = true,
    supportsRunInTerminalRequest = true,
    supportsStartDebuggingRequest = true,
    supportsVariableType = true
  },
  command = "initialize",
  seq = 0,
  type = "request"
}
[ DEBUG ] 2023-10-30T14:26:02Z-0500 ] C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:932 ] 1   {
  body = {
    capabilities = {
      exceptionBreakpointFilters = { {
          filter = "all",
          label = "all"
        }, {
          filter = "user-unhandled",
          label = "user-unhandled"
        } },
      supportTerminateDebuggee = true,
      supportsCancelRequest = true,
      supportsConditionalBreakpoints = true,
      supportsConfigurationDoneRequest = true,
      supportsExceptionFilterOptions = true,
      supportsExceptionInfoRequest = true,
      supportsExceptionOptions = false,
      supportsFunctionBreakpoints = true,
      supportsSetExpression = true,
      supportsSetVariable = true,
      supportsTerminateRequest = true
    }
  },
  event = "capabilities",
  seq = "1",
  type = "event"
}
[ DEBUG ] 2023-10-30T14:26:02Z-0500 ] C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:932 ] 1   {
  body = vim.empty_dict(),
  event = "initialized",
  seq = "2",
  type = "event"
}
[ DEBUG ] 2023-10-30T14:26:02Z-0500 ] C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:932 ] 1   {
  body = {
    exceptionBreakpointFilters = { {
        filter = "all",
        label = "all"
      }, {
        filter = "user-unhandled",
        label = "user-unhandled"
      } },
    supportTerminateDebuggee = true,
    supportsCancelRequest = true,
    supportsConditionalBreakpoints = true,
    supportsConfigurationDoneRequest = true,
    supportsExceptionFilterOptions = true,
    supportsExceptionInfoRequest = true,
    supportsExceptionOptions = false,
    supportsFunctionBreakpoints = true,
    supportsSetExpression = true,
    supportsSetVariable = true,
    supportsTerminateRequest = true
  },
  command = "initialize",
  request_seq = 0,
  seq = "3",
  success = true,
  type = "response"
}
[ DEBUG ] 2023-10-30T14:26:03Z-0500 ] C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:1634 ]    "request"   {
  arguments = {
    filters = {}
  },
  command = "setExceptionBreakpoints",
  seq = 1,
  type = "request"
}

Seems to complain about there not being a command in this following request?

[ DEBUG ] 2023-10-30T14:26:03Z-0500 ] C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:1634 ]    "request"   {
  arguments = {
    cwd = "C:\\Users\\will.ehrendreich\\source\\repos\\fabload\\src",
    name = "attach - netcoredbg",
    outFiles = { "C:\\Users\\will.ehrendreich\\source\\repos\\fabload\\src/**" },
    processId = 17528,
    resolveSourceMapLocations = { "C:\\Users\\will.ehrendreich\\source\\repos\\fabload\\src/**" },
    sourceMaps = true,
    type = "coreclr"
  },
  seq = 2,
  type = "request"
}
[ DEBUG ] 2023-10-30T14:26:03Z-0500 ] C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:932 ] 1   {
  body = vim.empty_dict(),
  command = "setExceptionBreakpoints",
  request_seq = 1,
  seq = "4",
  success = true,
  type = "response"
}
[ DEBUG ] 2023-10-30T14:26:04Z-0500 ] C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:932 ] 1   {
  message = "can't parse: [json.exception.out_of_range.403] key 'command' not found",
  request_seq = 2,
  seq = "5",
  success = false,
  type = "response"
}
[ DEBUG ] 2023-10-30T14:26:04Z-0500 ] C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:1634 ]    "request"   {
  command = "configurationDone",
  seq = 3,
  type = "request"
}
[ DEBUG ] 2023-10-30T14:26:04Z-0500 ] C:/.local/share/nvim-data/lazy/nvim-dap/lua/dap/session.lua:932 ] 1   {
  body = vim.empty_dict(),
  command = "configurationDone",
  request_seq = 3,
  seq = "6",
  success = true,
  type = "response"
}
WillEhrendreich commented 11 months ago

ok.. so I was just wasting my day.. I see now that I needed to definitely have request="attach" in the config.

BUT it still won't work.

i get this after it initialzes:

   Info  2:48:17 PM notify.info {
  command = "configurationDone",
  message = "Failed command 'configurationDone' : 0x8013134b",
  request_seq = 3,
  seq = "6",
  success = false,
  type = "response"
}
   Error  2:48:17 PM notify.error DAP Failed command 'configurationDone' : 0x8013134b

What could cause this?

mfussenegger commented 11 months ago

Judging from what you've posted, you've messed up your configuration in some way that I can't guess. I'd need a minimal but complete reproduction that can be used with nvim --clean -u minimal.lua

Converting this to a discussion