414 lines
8.2 KiB
Markdown
414 lines
8.2 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```json
|
|
{
|
|
"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
|
|
|
|
```bash
|
|
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
|
|
|
|
```json
|
|
{
|
|
"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
|
|
|
|
```bash
|
|
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
|
|
|
|
```json
|
|
{
|
|
"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
|