Files
nvim/docs/guides/debugging.md
Morten Olsen b3b70bceeb Improved flow
2026-01-26 23:04:14 +01:00

8.2 KiB

Debugging Guide

This guide covers debugging with DAP (Debug Adapter Protocol) for TypeScript, Python, and Go.

Overview

DAP provides IDE-like debugging:

  • Breakpoints (line, conditional, logpoints)
  • Step through code (into, over, out)
  • Variable inspection
  • Call stack navigation
  • Expression evaluation

Quick Start

Basic Debugging Flow

  1. Set breakpoint: <leader>db
  2. Start debugger: <leader>dc
  3. Step through: <leader>di (into), <leader>do (over)
  4. Inspect: <leader>du (toggle UI)
  5. Stop: <leader>dt

Key Bindings

Breakpoints

Key Action
<leader>db Toggle breakpoint
<leader>dB Conditional breakpoint
<leader>dl Log point (print without stopping)

Execution Control

Key Action
<leader>dc Continue (or start)
<leader>di Step into
<leader>do Step over
<leader>dO Step out
<leader>dC Run to cursor
<leader>dp Pause
<leader>dt Terminate
<leader>dr Toggle REPL

UI & Inspection

Key Action
<leader>du Toggle DAP UI
<leader>de Evaluate expression
<leader>dw Add to watch
<leader>ds View scopes

DAP UI Layout

When you press <leader>du, the UI shows:

┌─────────────┬─────────────────────┐
│ Scopes      │                     │
│ (variables) │    Source Code      │
├─────────────┤    (your file)      │
│ Breakpoints │                     │
├─────────────┤                     │
│ Call Stack  │                     │
├─────────────┼─────────────────────┤
│ Watch       │    Console/REPL     │
└─────────────┴─────────────────────┘

Scopes Panel

Shows variables in current scope:

  • Local variables
  • Function arguments
  • Global variables
  • Expand objects/arrays with <cr>

Call Stack Panel

Shows function call hierarchy:

  • Current function at top
  • Click to jump to that frame
  • See where you came from

Breakpoints Panel

Lists all breakpoints:

  • Toggle enable/disable
  • Delete breakpoints
  • See conditions

Watch Panel

Add expressions to monitor:

  • <leader>dw to add
  • Updates as you step

Debugging by Language

TypeScript/JavaScript

Prerequisites

npm install -g @vscode/js-debug

Debug Current File

  1. Open your .ts or .js file
  2. <leader>db - Set breakpoint
  3. <leader>dc - Start debugging
  4. Select "Node.js: Launch" or similar

Debug Tests

<leader>td    Debug test at cursor

This automatically sets up the test runner with debugging.

launch.json Example

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "pwa-node",
      "request": "launch",
      "name": "Debug Current File",
      "program": "${file}",
      "cwd": "${workspaceFolder}",
      "sourceMaps": true
    },
    {
      "type": "pwa-node",
      "request": "launch",
      "name": "Debug Server",
      "program": "${workspaceFolder}/src/index.ts",
      "preLaunchTask": "tsc: build",
      "outFiles": ["${workspaceFolder}/dist/**/*.js"]
    }
  ]
}

Python

Prerequisites

pip install debugpy

Debug Current File

  1. Open your .py file
  2. <leader>db - Set breakpoint
  3. <leader>dc - Start debugging
  4. Select "Python: Current File"

Debug Tests

<leader>td    Debug test at cursor

launch.json Example

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python: Current File",
      "type": "python",
      "request": "launch",
      "program": "${file}",
      "console": "integratedTerminal"
    },
    {
      "name": "Python: Flask",
      "type": "python",
      "request": "launch",
      "module": "flask",
      "args": ["run", "--debug"],
      "env": {
        "FLASK_APP": "app.py"
      }
    },
    {
      "name": "Python: Django",
      "type": "python",
      "request": "launch",
      "program": "${workspaceFolder}/manage.py",
      "args": ["runserver", "--noreload"]
    }
  ]
}

Go

Prerequisites

go install github.com/go-delve/delve/cmd/dlv@latest

Debug Current File

  1. Open your .go file
  2. <leader>db - Set breakpoint
  3. <leader>dc - Start debugging
  4. Select "Go: Debug Package"

Debug Tests

<leader>td    Debug test at cursor

Works with table-driven tests too!

launch.json Example

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Package",
      "type": "go",
      "request": "launch",
      "mode": "debug",
      "program": "${fileDirname}"
    },
    {
      "name": "Debug Main",
      "type": "go",
      "request": "launch",
      "mode": "debug",
      "program": "${workspaceFolder}/cmd/server"
    },
    {
      "name": "Attach to Process",
      "type": "go",
      "request": "attach",
      "mode": "local",
      "processId": "${command:pickProcess}"
    }
  ]
}

Breakpoint Types

Line Breakpoint

Standard breakpoint - stops when line is reached:

<leader>db    Toggle on current line

Conditional Breakpoint

Only stops when condition is true:

<leader>dB    Prompts for condition

Example conditions:

  • x > 10
  • user.name == "test"
  • items.length > 0

Log Point

Prints message without stopping:

<leader>dl    Prompts for log message

Use {} for interpolation:

  • Value of x: {x}
  • User: {user.name}

Hit Count Breakpoint

Stop after N hits (set via conditional):

<leader>dB    Enter: hitCount > 5

Debugging Strategies

Step Through Unknown Code

  1. Set breakpoint at entry point
  2. <leader>dc - Start
  3. <leader>di - Step into functions to understand them
  4. <leader>do - Step over when you understand
  5. <leader>dO - Step out when done with function

Find Where Value Changes

  1. Set breakpoint where value is used
  2. <leader>dw - Add variable to watch
  3. Step through, watching for changes
  4. Or use conditional breakpoint: x != expectedValue

Debug Loops

  1. Set conditional breakpoint: i == problematicIndex
  2. Or use hit count: stop after N iterations
  3. Check variables at specific iteration

Remote Debugging

For processes running elsewhere:

  1. Start process with debug flag
  2. Use "attach" configuration
  3. Connect to debug port

Common Workflows

Finding a Bug

  1. Reproduce the bug path
  2. Set breakpoint before bug occurs
  3. <leader>dc - Start debugging
  4. Step through, inspecting variables
  5. Find where actual != expected
  6. Fix and re-test

Understanding New Code

  1. Set breakpoint at function entry
  2. <leader>dc - Start with a test case
  3. <leader>di - Step into each function
  4. Use watch to track key variables
  5. Build mental model of flow

Performance Investigation

Use log points to trace without stopping:

  1. <leader>dl at key points
  2. Log timing: Start: {Date.now()}
  3. Run normally
  4. Check console for timing

Tips

Quick Variable Inspection

Hover over variable with cursor - shows value in float.

REPL Usage

<leader>dr opens REPL where you can:

  • Evaluate expressions
  • Call functions
  • Modify variables (sometimes)

Restart Debugging

If you need to start over:

<leader>dt    Terminate
<leader>dc    Start again

Breakpoint Persistence

Breakpoints are saved per session. They'll be there when you reopen the file.

Troubleshooting

Debugger Won't Start

  1. Check adapter is installed
  2. :DapShowLog for errors
  3. Verify launch configuration

Breakpoints Not Hit

  1. Verify file paths match
  2. Check source maps (TypeScript)
  3. Ensure code is actually executed

Variables Not Showing

  1. Might be optimized out (Go)
  2. Check scope (local vs global)
  3. Try evaluating directly: <leader>de

Source Maps Issues (TypeScript)

  1. Ensure sourceMaps: true in launch.json
  2. Check tsconfig has sourceMap: true
  3. Verify outFiles pattern matches

Slow Debugging

  1. Reduce number of breakpoints
  2. Use conditional breakpoints
  3. Disable logging breakpoints when not needed