Skip to content

bug: dap extension does not load logMessage #81

@zspher

Description

@zspher

Did you check the docs and existing issues?

  • I have read the docs
  • I have searched the existing issues

Neovim version (nvim -v)

v0.11.6

Operating system/version

NixOS

Describe the bug

the dap extension saves breakpoints and logMessage data. it just does not load it.

What is the severity of this bug?

minor (annoyance)

Steps To Reproduce

  1. nvim -u repro.lua test_file
  2. start debug
  3. make 3 breakpoints (use ) with one having a log message (use shift+)
  4. start and stop debugger
  5. save session
  6. quit
  7. nvim -u repro.lua test_file
  8. load file

Expected Behavior

log message breakpoint is loaded

Directory structure

No response

Repro

-- save as repro.lua
-- run with nvim -u repro.lua
-- DO NOT change the paths
local root = vim.fn.fnamemodify("./.repro", ":p")

-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "runtime", "cache" }) do
	vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
	-- bootstrap lazy.nvim
	vim.fn.system({
		"git",
		"clone",
		"--filter=blob:none",
		"https://github.com/folke/lazy.nvim.git",
		"--branch=stable",
		lazypath,
	})
end
vim.opt.runtimepath:prepend(lazypath)

---@param config {type?:string, args?:string[]|fun():string[]?}
local function get_args(config)
	local args = type(config.args) == "function" and (config.args() or {}) or config.args or {}
	local args_str = type(args) == "table" and table.concat(args, " ") or args

	config = vim.deepcopy(config)
	config.args = function()
		local new_args = vim.fn.expand(vim.fn.input("Run with args: ", args_str --[[@as string]]))
		if config.type and config.type == "java" then
			---@diagnostic disable-next-line: return-type-mismatch
			return new_args
		end
		return require("dap.utils").splitstr(new_args)
	end
	return config
end

local function edit_breakpoint()
	-- Search for an existing breakpoint on this line in this buffer
	---@return dap.SourceBreakpoint bp that was either found, or an empty placeholder
	local function find_bp()
		local buf_bps = require("dap.breakpoints").get(vim.fn.bufnr())[vim.fn.bufnr()]
		---@type dap.SourceBreakpoint
		local bp = {
			condition = "",
			logMessage = "",
			hitCondition = "",
			line = vim.fn.line("."),
		}
		for _, candidate in ipairs(buf_bps) do
			if candidate.line and candidate.line == vim.fn.line(".") then
				bp = candidate
				break
			end
		end
		return bp
	end

	-- Elicit customization via a UI prompt
	---@param bp dap.SourceBreakpoint a breakpoint
	local function customize_bp(bp)
		local props = {
			["Condition"] = {
				value = bp.condition,
				setter = function(v)
					bp.condition = v
				end,
			},
			["Hit Condition"] = {
				value = bp.hitCondition,
				setter = function(v)
					bp.hitCondition = v
				end,
			},
			["Log Message"] = {
				value = bp.logMessage,
				setter = function(v)
					bp.logMessage = v
				end,
			},
		}
		local menu_options = {}
		for k, v in pairs(props) do
			table.insert(menu_options, ("%s: %s"):format(k, v.value))
		end
		vim.ui.select(menu_options, {
			prompt = "Edit Breakpoint",
		}, function(choice)
			local prompt = (tostring(choice)):gsub(":.*", "")
			props[prompt].setter(vim.fn.input({
				prompt = prompt,
				default = props[prompt].value,
			}))

			-- Set breakpoint for current line, with customizations (see h:dap.set_breakpoint())
			require("dap").set_breakpoint(bp.condition, bp.hitCondition, bp.logMessage)
		end)
	end

	customize_bp(find_bp())
end
-- install plugins
local plugins = {
	"folke/tokyonight.nvim",
	{
		"stevearc/resession.nvim",
		lazy = false,
		opts = {
			extensions = {
				dap = {},
			},
		},
		keys = {
			{
				"<leader>ql",
				function()
					require("resession").load("test", { silence_errors = true })
				end,
				desc = "Restore Last Session",
			},
			{
				"<leader>qL",
				function()
					require("resession").load()
				end,
				desc = "List Sessions",
			},
			{
				"<leader>qs",
				function()
					require("resession").save("test")
				end,
				desc = "Save Current Session",
			},
			{
				"<leader>qd",
				function()
					require("resession").delete("test", { silence_errors = true })
				end,
				desc = "Delete Last Session",
			},
		},
	},
	-- add any other plugins here
	{
		"igorlfs/nvim-dap-view",
		lazy = false,
		keys = {
			{
				"<leader>du",
				function()
					require("dap-view").toggle()
				end,
				desc = "Dap UI",
			},
			{
				"<leader>de",
				function()
					require("dap-view").add_expr()
				end,
				desc = "Watch",
				mode = { "n", "x" },
			},
			{
				"<leader>ds",
				function()
					require("dap-view").show_view("sessions")
				end,
				desc = "Show Session",
			},
			{
				"<leader>dW",
				function()
					require("dap-view").show_view("watches")
				end,
				desc = "Show Watch",
			},
			{
				"<leader>dB",
				function()
					require("dap-view").show_view("breakpoints")
				end,
				desc = "Show Breakpoints",
			},
		},
		opts = {
			auto_toggle = "open_term",
			windows = {
				terminal = {
					size = 0.4,
					position = "right",
				},
			},
			winbar = {
				sections = {
					"watches",
					"scopes",
					"exceptions",
					"sessions",
					"breakpoints",
					"threads",
					"repl",
				},
			},
		},
		config = function(_, opts)
			local dap = require("dap")
			local dapview = require("dap-view")

			dapview.setup(opts)

			dap.listeners.after.event_initialized["dapui_config"] = function()
				dapview.open()
			end
		end,
	},
	{
		"mfussenegger/nvim-dap",
		dependencies = {
			"igorlfs/nvim-dap-view",
			-- virtual text for the debugger
			{
				"theHamsta/nvim-dap-virtual-text",
				opts = {},
			},
		},
		keys = {
			{
				"<leader>dc",
				function()
					require("dap").run_to_cursor()
				end,
				desc = "Run to Cursor",
			},
			{
				"<leader>dg",
				function()
					require("dap").goto_()
				end,
				desc = "Go to Line (No Execute)",
			},
			{
				"<leader>dj",
				function()
					require("dap").down()
				end,
				desc = "Down",
			},
			{
				"<leader>dk",
				function()
					require("dap").up()
				end,
				desc = "Up",
			},
			{
				"<leader>dl",
				function()
					require("dap").run_last()
				end,
				desc = "Run Last",
			},
			{
				"<leader>dr",
				function()
					require("dap").repl.toggle()
				end,
				desc = "Toggle REPL",
			},
			{
				"<leader>dw",
				function()
					require("dap.ui.widgets").hover()
				end,
				desc = "Widgets",
			},
			{
				"<leader>da",
				function()
					require("dap").continue({ before = get_args })
				end,
				desc = "Run with Args",
			},
			{
				"<F5>",
				function()
					require("dap").continue()
				end,
				desc = "Debugger: Start",
			},
			{
				"<F21>", -- Shift+F9
				edit_breakpoint,
				desc = "Set Condition Breakpoint",
			},
			{
				"<F9>",
				function()
					require("dap").toggle_breakpoint()
				end,
				desc = "Debugger: Toggle Breakpoint",
			},
			{
				"<F33>", -- Control+F9
				function()
					require("dap").clear_breakpoints()
				end,
				desc = "Debugger: Clear All Breakpoints",
			},
			{
				"<F17>", -- Shift+F5
				function()
					require("dap").terminate()
				end,
				desc = "Debugger: Stop",
			},
			{
				"<F29>", -- Control+F5
				function()
					require("dap").restart_frame()
				end,
				desc = "Debugger: Restart",
			},
			{
				"<F6>",
				function()
					require("dap").pause()
				end,
				desc = "Debugger: Pause",
			},
			{
				"<F7>",
				function()
					require("dap").reverse_continue()
				end,
				"Debugger: Reverse",
			},
			{
				"<F10>",
				function()
					require("dap").step_over()
				end,
				desc = "Debugger: Step Over",
			},
			{
				"<F11>",
				function()
					require("dap").step_into()
				end,
				desc = "Debugger: Step Into",
			},
			{
				"<F23>", -- Shift+F11
				function()
					require("dap").step_out()
				end,
				desc = "Debugger: Step Out",
			},
		},

		config = function()
			-- add jsonc support to launch.json support
			local vscode = require("dap.ext.vscode")
			---@diagnostic disable-next-line: duplicate-set-field

			local dap = require("dap")
			dap.adapters["netcoredbg"] = {
				type = "executable",
				command = "netcoredbg",
				args = { "--interpreter=vscode" },
			}
			dap.adapters["codelldb"] = {
				type = "executable",
				command = "codelldb",
			}
			-- js-debug
			for _, adapterType in ipairs({ "node", "chrome", "msedge" }) do
				local pwaType = "pwa-" .. adapterType

				dap.adapters[pwaType] = {
					type = "server",
					host = "localhost",
					port = "${port}",
					executable = {
						command = "js-debug",
						args = { "${port}" },
					},
				}

				-- Define adapters without the "pwa-" prefix for VSCode compatibility
				dap.adapters[adapterType] = function(cb, config)
					local nativeAdapter = dap.adapters[pwaType]

					config.type = pwaType

					if type(nativeAdapter) == "function" then
						nativeAdapter(cb, config)
					else
						cb(nativeAdapter)
					end
				end
			end

			vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" })

			local dap_icons = {
				Stopped = { "󰁕 ", "DiagnosticWarn", "DapStoppedLine" },
				Breakpoint = { "" },
				BreakpointCondition = { "" },
				BreakpointRejected = { "", "DiagnosticError" },
				LogPoint = { ".>" },
			}

			for name, sign in pairs(dap_icons) do
				vim.fn.sign_define("Dap" .. name, {
					text = sign[1],
					texthl = sign[2] or "DiagnosticInfo",
					linehl = sign[3],
					numhl = sign[3],
				})
			end

			for _, lang in ipairs({ "c", "cpp" }) do
				dap.configurations[lang] = {
					{
						name = "Launch file",
						type = "codelldb",
						request = "launch",
						program = "${command:pickFile}",
						cwd = "${workspaceFolder}",
						args = {},
						env = {
							UBSAN_OPTIONS = "print_stacktrace=1",
							ASAN_OPTIONS = "abort_on_error=1:fast_unwind_on_malloc=0:detect_leaks=0",
						},
					},
					{
						type = "codelldb",
						request = "attach",
						name = "Attach to process",
						processId = "${command:pickProcess}",
						cwd = "${workspaceFolder}",
					},
				}
			end
		end,
	},
}

vim.g.mapleader = " "
require("lazy").setup(plugins, {
	root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")
-- add anything else here

Did you check the bug with a clean config?

  • I have confirmed that the bug reproduces with nvim -u repro.lua using the repro.lua file above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions