Resilient Debugger — Debug Adapter Protocol (DAP)
Resilient includes a Debug Adapter Protocol (DAP) server for debugging Resilient programs in editors and IDEs that support DAP (VS Code, Neovim with nvim-dap, etc.).
The debugger allows you to:
- Set line breakpoints
- Step through code (step over, step into, step out)
- Inspect variables and scopes
- Evaluate expressions at runtime
- View stack frames and thread information
Launching the debugger
The Resilient DAP server is invoked via the CLI:
rz --dap
The server listens on stdin/stdout for DAP protocol messages. A DAP client (your editor or IDE) launches this command as a child process and communicates with it over the DAP JSON wire protocol.
Alternative: User-friendly debug alias
For interactive use, you can also use:
rz debug <file>
This starts the DAP server and prints guidance to stderr. The <file> argument is informational; the actual program path comes from the DAP launch request sent by your client.
VS Code setup
Prerequisites
Ensure you have the Resilient VS Code extension installed. The extension provides the DAP client integration.
Launch configuration
Create a .vscode/launch.json file in your Resilient project with the following configuration:
{
"version": "0.2.0",
"configurations": [
{
"type": "resilient",
"request": "launch",
"name": "Debug Resilient Program",
"program": "${file}",
"rz": "rz"
}
]
}
Configuration fields:
| Field | Description |
|---|---|
type |
Must be "resilient" (recognized by the Resilient VS Code extension) |
request |
Must be "launch" |
name |
Human-readable name for this debug configuration (appears in the VS Code launch dropdown) |
program |
Absolute or relative path to the .rz file to debug. Use "${file}" to debug the currently open file |
rz |
Path to the rz CLI binary (default: "rz" if in PATH) |
How to debug
- Open a
.rzfile in VS Code. - Set breakpoints by clicking on the line number gutter (a red dot appears).
- Open the Run and Debug panel (Ctrl+Shift+D on Linux/Windows, Cmd+Shift+D on macOS).
- Select “Debug Resilient Program” from the launch configuration dropdown.
- Click the green play button to start debugging.
- The program will run and stop at breakpoints. Use the Debug toolbar to:
- Continue (F5): Resume execution
- Step Over (F10): Execute the current line and pause at the next one
- Step Into (F11): Step into function calls
- Step Out (Shift+F11): Step out of the current function
The Debug Console shows program output and allows expression evaluation.
Supported DAP capabilities
| Capability | Supported |
|---|---|
| Breakpoints | Line breakpoints (setBreakpoints request) |
| Execution control | Continue, step over, step into, step out |
| Stack frames | Full stack trace with source location and column info |
| Variables | Inspect local variables and scopes |
| Expression evaluation | Evaluate arbitrary expressions at runtime |
| Threads | Single main thread (single-threaded runtime) |
| Stop events | Breakpoint, step, exception |
| Output events | Program stdout captured and displayed |
| Termination | Graceful shutdown and disconnect |
Unsupported capabilities (planned future)
The following DAP capabilities are not yet supported:
| Capability | Notes |
|---|---|
| Conditional breakpoints | Breakpoints with expressions; blocked on expression evaluator completeness |
| Function breakpoints | Set breakpoints by function name |
| Step back / reverse debugging | Not applicable to the current execution model |
| Hover evaluation | Evaluate expressions by hovering in the editor |
| Watch expressions | Persistent expression watches across frames |
| Set variable | Modify variable values during debugging |
| Restart frame | Restart a function and re-run it |
| Goto targets | Jump to a specific line or target |
| Completions | Auto-complete in the debug console |
| Modules request | Introspect loaded modules |
| Exception options | Customize exception handling behavior |
DAP requests implemented
The server implements the following DAP requests:
| Request | Handler | Notes |
|---|---|---|
initialize |
Lines 155–179 | Handshake; reports supported capabilities |
launch |
Lines 181–200 | Start a debug session with a program path |
setBreakpoints |
Lines 202–244 | Set line breakpoints in a source file |
configurationDone |
Lines 246–256 | Signal readiness; begins execution |
continue |
Lines 289–300 | Resume execution from a breakpoint |
next |
Lines 302–308 | Step over (next statement) |
stepIn |
Lines 310–316 | Step into a function call |
stepOut |
Lines 318–324 | Step out of the current function |
threads |
Lines 326–338 | List threads (always returns one “main” thread) |
stackTrace |
Lines 340–365 | Retrieve the call stack |
scopes |
Lines 367–394 | List scopes (locals) for a frame |
variables |
Lines 396–436 | Inspect variables in a scope |
evaluate |
Lines 438–479 | Evaluate an expression during a pause |
disconnect |
Lines 481–489 | Close the debug session |
terminate |
Lines 491–497 | Terminate the running program |
All other requests return a success response to avoid stalling the client.
DAP events emitted
The server sends the following events:
| Event | Description | Source |
|---|---|---|
initialized |
Sent after initialize to signal configuration can begin |
Line 177 |
stopped |
Program paused; includes reason (breakpoint/step/exception) and frame info | Lines 561–581 |
output |
Program output (stdout) | Line 583 |
terminated |
Program terminated; debugging session has ended | Line 592 |
Debugging flow
- Client launches the server:
rz --dap(started as a child process by the editor) - Initialize handshake:
- Client sends
initializerequest - Server responds with capabilities +
initializedevent
- Client sends
- Configure session:
- Client sends
launchrequest with program path - Client sends
setBreakpointsfor each source file with breakpoints - Client sends
configurationDoneto signal ready
- Client sends
- Execution:
- Server spawns a
DebugStatethread that runs the program - Events (output, stopped, terminated) stream to the client
- Client sends continue/step requests; server relays them to the debug thread
- Server spawns a
- Cleanup:
- Client sends
disconnectwhen done - Server releases resources and exits
- Client sends
Implementation reference
The DAP server is implemented in /resilient/src/dap_server.rs (~810 lines):
- Message framing (lines 21–64): Content-Length header protocol (matching LSP)
- Server state (lines 84–119): Tracks breakpoints, frames, scopes, and execution state
- Request handlers (lines 155–497): Implement each DAP request type
- Event loop (lines 607–666): Main message-handling loop
- CLI dispatch (lines 670–695): Entry point for
rz --dapflag
The actual program execution is delegated to crate::debugger::DebugState, which runs on a background thread and communicates with the DAP server via MPSC channels.
Troubleshooting
“No program path specified”
The launch request did not include a program field, or the field was empty. Check that your launch configuration has a valid program path.
Program output not appearing
Ensure your program uses println! or other stdout/stderr output. The debugger captures all output and displays it in the Debug Console.
Debugger hangs during evaluation
Expression evaluation has a 5-second timeout. If the expression is very complex or causes infinite loops, it will timeout and return an error. Ensure your expressions are simple and well-formed.
Breakpoint not hit
- Verify the breakpoint line is in actual executable code (not comments or declarations).
- Confirm the program path matches the file being debugged.
- Check that
setBreakpointswas called beforeconfigurationDone.
Multiple threads
The current implementation supports only single-threaded debugging. Multi-threaded programs will show only the main thread.