乐闻世界logo
搜索文章和话题

What is VS Code Debug Adapter Protocol (DAP)?

2月18日 18:08

The Debug Adapter Protocol (DAP) is a protocol proposed by VS Code that separates debugging functionality from debugger implementation, enabling the editor to support multiple debuggers.

DAP Architecture

Protocol Layers

  • Client: VS Code editor, responsible for debug UI and user interaction
  • Adapter: Debug adapter, converts DAP requests to debugger-specific commands
  • Debugger: Actual debugger implementation (such as GDB, LLDB, Chrome DevTools)

Communication Method

  • Uses JSON-RPC protocol
  • Communicates via standard input/output or WebSocket
  • Supports asynchronous message passing

Core Concepts

Session

A debug session represents a complete debugging process, from launch to termination.

Thread

Execution thread in the debugger, can contain multiple stack frames.

Stack Frame

One frame in the function call stack, containing local variables and execution position.

Scope

Logical grouping of variables, such as local variables, global variables, etc.

Variable

Variable in the debugger, can be viewed and modified.

DAP Request Types

Initialize Request

json
{ "seq": 1, "type": "request", "command": "initialize", "arguments": { "adapterID": "my-debugger", "pathFormat": "path", "linesStartAt1": true, "columnsStartAt1": true } }

Launch/Attach Request

json
{ "seq": 2, "type": "request", "command": "launch", "arguments": { "program": "/path/to/program", "stopOnEntry": false } }

Set Breakpoints Request

json
{ "seq": 3, "type": "request", "command": "setBreakpoints", "arguments": { "source": { "path": "/path/to/file.js" }, "breakpoints": [ { "line": 10 } ] } }

Continue Execution Request

json
{ "seq": 4, "type": "request", "command": "continue", "arguments": { "threadId": 1 } }

DAP Event Types

Initialized Event

json
{ "seq": 1, "type": "event", "event": "initialized" }

Stopped Event

json
{ "seq": 2, "type": "event", "event": "stopped", "body": { "reason": "breakpoint", "threadId": 1, "allThreadsStopped": false } }

Output Event

json
{ "seq": 3, "type": "event", "event": "output", "body": { "category": "console", "output": "Hello World\n" } }

Implementing Debug Adapter

Create Adapter Project

bash
npm init -y npm install @vscode/debugadapter

Basic Adapter Structure

typescript
import { DebugSession, InitializedEvent, TerminatedEvent, StoppedEvent, OutputEvent } from '@vscode/debugadapter'; class MyDebugSession extends DebugSession { constructor() { super(); } protected initializeRequest(response: DebugProtocol.InitializeResponse): void { response.body = { supportsConfigurationDoneRequest: true, supportsEvaluateForHovers: true, supportsStepBack: false }; this.sendResponse(response); } protected launchRequest(response: DebugProtocol.LaunchResponse, args: any): void { // Launch debugger this.sendResponse(response); } protected setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): void { // Set breakpoints response.body = { breakpoints: args.breakpoints.map(bp => ({ verified: true, line: bp.line })) }; this.sendResponse(response); } }

Configuring Debug Adapter

package.json Configuration

json
{ "contributes": { "debuggers": [ { "type": "my-debugger", "label": "My Debugger", "program": "./out/debugAdapter.js", "runtime": "node", "configurationAttributes": { "launch": { "required": ["program"], "properties": { "program": { "type": "string", "description": "Program to debug" } } } } } ] } }

launch.json Configuration

json
{ "version": "0.2.0", "configurations": [ { "type": "my-debugger", "request": "launch", "name": "Debug with My Debugger", "program": "${workspaceFolder}/app.js" } ] }

Debug Adapter Testing

Debugging the Adapter

  1. Press F5 to start extension development host
  2. Open project with debug configuration
  3. Start debug session
  4. Test various debug features

Testing Checklist

  • Breakpoint setting and triggering
  • Step execution
  • Variable viewing and modification
  • Call stack viewing
  • Expression evaluation

Advanced Features

Custom Evaluation

typescript
protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void { const result = this.evaluateExpression(args.expression); response.body = { result: String(result), variablesReference: 0 }; this.sendResponse(response); }

Custom Variables

typescript
protected variablesRequest(response: DebugProtocol.VariablesResponse, args: DebugProtocol.VariablesArguments): void { const variables = this.getVariables(args.variablesReference); response.body = { variables: variables.map(v => ({ name: v.name, value: String(v.value), variablesReference: v.children ? 1 : 0 })) }; this.sendResponse(response); }

Important Notes

  • Properly handle asynchronous operations
  • Provide clear error messages
  • Support cancellation operations
  • Consider performance optimization
  • Follow DAP specification
标签:VSCode