VS Code 调试适配器协议(DAP)是什么?
调试适配器协议(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 请求类型初始化请求{ "seq": 1, "type": "request", "command": "initialize", "arguments": { "adapterID": "my-debugger", "pathFormat": "path", "linesStartAt1": true, "columnsStartAt1": true }}启动/附加请求{ "seq": 2, "type": "request", "command": "launch", "arguments": { "program": "/path/to/program", "stopOnEntry": false }}设置断点请求{ "seq": 3, "type": "request", "command": "setBreakpoints", "arguments": { "source": { "path": "/path/to/file.js" }, "breakpoints": [ { "line": 10 } ] }}继续执行请求{ "seq": 4, "type": "request", "command": "continue", "arguments": { "threadId": 1 }}DAP 事件类型初始化完成事件{ "seq": 1, "type": "event", "event": "initialized"}停止事件{ "seq": 2, "type": "event", "event": "stopped", "body": { "reason": "breakpoint", "threadId": 1, "allThreadsStopped": false }}输出事件{ "seq": 3, "type": "event", "event": "output", "body": { "category": "console", "output": "Hello World\n" }}实现调试适配器创建适配器项目npm init -ynpm install @vscode/debugadapter基本适配器结构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 配置{ "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 配置{ "version": "0.2.0", "configurations": [ { "type": "my-debugger", "request": "launch", "name": "Debug with My Debugger", "program": "${workspaceFolder}/app.js" } ]}调试适配器测试调试适配器按 F5 启动扩展开发宿主打开包含调试配置的项目启动调试会话测试各种调试功能测试清单断点设置和触发单步执行变量查看和修改调用栈查看表达式求值高级功能自定义求值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);}自定义变量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 规范