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

VS Code 调试适配器协议(DAP)是什么?

2月18日 18:08

调试适配器协议(Debug Adapter Protocol,DAP)是 VS Code 提出的一种协议,用于将调试功能与调试器实现分离,使编辑器能够支持多种调试器。

DAP 架构

协议层次

  • 客户端: VS Code 编辑器,负责调试 UI 和用户交互
  • 适配器: 调试适配器,将 DAP 请求转换为调试器特定命令
  • 调试器: 实际的调试器实现(如 GDB、LLDB、Chrome DevTools)

通信方式

  • 使用 JSON-RPC 协议
  • 通过标准输入/输出或 WebSocket 通信
  • 支持异步消息传递

核心概念

会话(Session)

调试会话表示一次完整的调试过程,从启动到结束。

线程(Thread)

调试器中的执行线程,可以包含多个栈帧。

栈帧(Stack Frame)

函数调用栈中的一个帧,包含局部变量和执行位置。

作用域(Scope)

变量的逻辑分组,如局部变量、全局变量等。

变量(Variable)

调试器中的变量,可以查看和修改其值。

DAP 请求类型

初始化请求

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

启动/附加请求

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

设置断点请求

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

继续执行请求

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

DAP 事件类型

初始化完成事件

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

停止事件

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

输出事件

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

实现调试适配器

创建适配器项目

bash
npm init -y npm install @vscode/debugadapter

基本适配器结构

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 { // 启动调试器 this.sendResponse(response); } protected setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): void { // 设置断点 response.body = { breakpoints: args.breakpoints.map(bp => ({ verified: true, line: bp.line })) }; this.sendResponse(response); } }

配置调试适配器

package.json 配置

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 配置

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

调试适配器测试

调试适配器

  1. 按 F5 启动扩展开发宿主
  2. 打开包含调试配置的项目
  3. 启动调试会话
  4. 测试各种调试功能

测试清单

  • 断点设置和触发
  • 单步执行
  • 变量查看和修改
  • 调用栈查看
  • 表达式求值

高级功能

自定义求值

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); }

自定义变量

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); }

注意事项

  • 正确处理异步操作
  • 提供清晰的错误信息
  • 支持取消操作
  • 考虑性能优化
  • 遵循 DAP 规范
标签:VSCode