入门 Zed Industries 2026-09-14 17:42:19 · 0 阅读

第9章 Zed 调试器详解:基于 DAP 协议的多语言支持

Zed 使用 调试适配器协议 (DAP) 提供跨多种编程语言的调试功能。 DAP 是一个标准协议,定义了调试器、编辑器和 IDE 之间的通信方式。 这使得 Zed 无需针对特定语言实现调试逻辑,即可支持多种调试器。 Zed 实现该协议的客户端部分,而各种调试适配器则实现服务端部分。

该协议支持在统一的方式下实现设置断点、单步执行、检查变量等功能,覆盖不同的编程语言和运行时环境。

支持的语言

若要调试特定语言编写的代码,Zed 需要找到该语言对应的调试适配器。部分调试适配器由 Zed 内置提供,无需额外配置;部分则由语言扩展提供。目前可用的调试适配器支持以下语言:

如果你的语言不在列表中,欢迎为它添加 debug adapter 做出贡献。详情请参阅我们的 debugger extensions 文档。

点击上述链接可查看特定语言和 adapter 的信息与示例;也可以继续阅读,了解适用于所有 adapter 的 Zed 通用调试功能。

快速上手

对大多数语言来说,最快的上手方式是运行 {#action debugger::Start}({#kb debugger::Start})。这会打开 new process modal(新进程弹窗),其中按当前项目上下文列出预配置的调试任务。调试任务来自测试、入口点(如 main 函数)等来源——具体支持哪些内容,请查阅你所使用语言的文档。

也可以点击调试面板右上角的“加号”按钮打开同一个弹窗。

对于没有预配置调试任务的语言(包括 C、C++ 以及部分由扩展支持的语言),你可以在项目根目录的 .zed/debug.json 文件中定义调试配置。该文件应为配置对象数组:

[
  {
    "adapter": "CodeLLDB",
    "label": "First configuration"
    // ...
  },
  {
    "adapter": "Debugpy",
    "label": "Second configuration"
    // ...
  }
]

针对典型用例的配置示例,请查阅相应语言的文档。把配置添加到 .zed/debug.json 后,它们就会出现在新进程弹窗的列表中。

如果 .zed/debug.json 中没有配置,Zed 还会从 .vscode/launch.json 加载调试配置,并显示在新进程弹窗中。

全局调试配置

如果你要在多个项目中使用相同的启动配置,可以将它们统一存储在用户配置文件中。从命令面板调用 {#action zed::OpenDebugTasks},即可打开全局 debug.json 文件。Zed 会将其创建在用户 settings.json 旁边,并与调试器界面保持同步。该文件路径为:

  • macOS: ~/Library/Application Support/Zed/debug.json
  • Linux/BSD: $XDG_CONFIG_HOME/zed/debug.json(若未设置则回退到 ~/.config/zed/debug.json
  • Windows: %APPDATA%\Zed\debug.json

在这个文件中填入与 .zed/debug.json 相同的对象数组。在这里定义的调试场景会被合并到每个工作区中,因此你常用的启动预设会自动出现在“新建调试会话”对话框里。

启动与附加

Zed 的调试器提供两种调试方式:你可以启动程序的新实例,或附加到已有的进程。选择哪种方式取决于你的具体目标。

启动新实例时,Zed(及其底层调试适配器)通常能更好地获取调试信息,因为它控制了程序的整个生命周期,而附加到现有进程则无法做到这一点。运行单元测试或调试构建的应用程序,适合使用启动方式。

相比之下,附加到现有进程看似不如启动方便,但事实并非如此。有些情况下,你无法重启程序,例如当 bug 仅在生产环境中复现,或受其他特定条件限制时。

配置

Zed 要求所有调试任务包含 adapterlabel 字段。此外,Zed 会使用 build 字段在调试器启动前运行必要的设置步骤(见下文),并接受 tcp_connection 字段以连接现有进程。

其他所有字段均由调试适配器提供,可包含任务变量。大多数适配器支持 requestprogramcwd

[
  {
    // 调试配置的标签,用于在调试面板和新进程对话框中标识调试会话
    "label": "Example Start debugger config",
    // Zed 用于调试程序的调试适配器
    "adapter": "Example adapter name",
    // Request:
    //  - launch: Zed 将启动该程序,或显示带有正确配置的调试终端
    //  - attach: Zed 将附加到正在运行的程序进行调试;如果未指定 process_id,则会显示进程选择器(目前仅支持 node)
    "request": "launch",
    // 要调试的程序。此字段支持使用 ~ 或 . 符号进行路径解析。
    "program": "path_to_program",
    // cwd: 默认为项目的工作目录 ($ZED_WORKTREE_ROOT)
    "cwd": "$ZED_WORKTREE_ROOT"
  }
]

有关所支持字段的详细信息,请参阅您的调试适配器文档。

构建任务

Zed 允许在 build 字段中嵌入一个 Zed 任务,该任务会在调试器启动前运行。这对于在调试器启动前设置环境或执行必要的初始化步骤非常有用。

[
  {
    "label": "Build Binary",
    "adapter": "CodeLLDB",
    "program": "path_to_program",
    "request": "launch",
    "build": {
      "command": "make",
      "args": ["build", "-j8"]
    }
  }
]

构建任务也可以通过未替换的标签引用现有任务:

[
  {
    "label": "Build Binary",
    "adapter": "CodeLLDB",
    "program": "path_to_program",
    "request": "launch",
    "build": "my build task" // 或 "my build task for $ZED_FILE"
  }
]

自动创建场景

给定一个 Zed 任务,Zed 可以为您自动创建场景。自动创建场景功能也支持我们基于编辑区(gutter)创建场景。 目前,自动创建场景功能支持 Rust、Go、Python、JavaScript 和 TypeScript。

断点

设置断点很简单,只需在编辑器行号旁的边栏点击即可。 断点还可以按需调整;右键点击边栏中的断点图标,选择需要的选项即可访问更多设置。 目前支持:

  • 为断点添加日志:每次命中该断点时输出一条日志。
  • 设置条件断点:只有条件满足时才会在断点处停下。条件语法取决于具体的 adapter。
  • 设置命中次数:只有命中次数达到指定数值后才会在断点处停下。
  • 禁用断点:断点仍显示在边栏中,但不会触发。

部分 debug adapter(如 CodeLLDB 和 JavaScript)还会验证断点能否被命中;无法命中的断点会在 UI 中更醒目地显示出来。

某个项目中启用的所有断点也会列在调试会话 UI 的 "Breakpoints" 项中。在这里你还可以管理异常断点(exception breakpoint),当发生指定类型的异常时,debug adapter 会停下。具体支持哪些异常类型取决于 debug adapter。

使用分屏

在开启多个分屏的情况下调试时,Zed 会只在其中一个面板显示当前调试行,其余面板保持原有布局。如果同一个文件在多个面板中打开,debugger 会选择该文件已是当前标签页的面板,而不会切换其他面板中的标签页。

debugger 选定某个面板后,整个会话期间都会继续使用它来处理后续断点。如果你把包含当前调试行的标签页拖到了其他分屏,debugger 也会跟随移动,改用新的面板。

这样能确保在跨文件单步调试时,debugger 不会打乱你的工作流。

设置

debugger 的设置在 settings.json 中统一放在 debugger 键下:

  • dock: 决定调试面板在 UI 中的位置。
  • stepping_granularity: 决定单步调试的粒度。
  • save_breakpoints: 是否在多次 Zed 会话之间保留断点。
  • button:是否在状态栏中显示调试按钮。
  • timeout:连接 TCP 调试适配器时的超时错误时间,以毫秒为单位。
  • log_dap_communications:是否记录活动调试适配器与 Zed 之间的消息。
  • format_dap_log_messages:将 DAP 消息添加到调试适配器日志时,是否对其进行格式化。

Dock

  • 描述:调试面板在 UI 中的位置。
  • 默认值:bottom
  • 设置项:debugger.dock

选项

  1. left - 调试面板将停靠在对 UI 的左侧。
  2. right - 调试面板将停靠在对 UI 的右侧。
  3. bottom - 调试面板将停靠在对 UI 的底部。
"debugger": {
  "dock": "bottom"
},

步进步长

  • 描述:调试器使用的步进步长
  • 默认值:line
  • 设置项:debugger.stepping_granularity

选项

  1. Statement - 单步执行应允许程序运行直到当前语句执行完毕。 语句的含义由适配器决定,且可能等同于一个行。 例如 for(int i = 0; i < 10; i++) 可能被视为包含 3 个语句:int i = 0i < 10i++
{
  "debugger": {
    "stepping_granularity": "statement"
  }
}
  1. Line - 单步执行应允许程序运行直到当前源代码行执行完毕。
{
  "debugger": {
    "stepping_granularity": "line"
  }
}
  1. Instruction - 单步执行应允许一条指令执行(例如一条 x86 指令)。
{
  "debugger": {
    "stepping_granularity": "instruction"
  }
}

保存断点

  • 描述:是否应在 Zed 会话之间保存断点。
  • 默认值:true
  • 设置项:debugger.save_breakpoints

可选值

boolean 类型

{
  "debugger": {
    "save_breakpoints": true
  }
}

工具栏按钮

  • 描述:是否需要在 Debugger 工具栏中显示该按钮。
  • 默认值:true
  • 设置项:debugger.button

可选值

boolean 类型

{
  "debugger": {
    "button": true
  }
}

超时时间

  • 描述:连接 TCP 调试适配器时的超时时长(毫秒)。
  • 默认值:2000
  • 设置项:debugger.timeout

可选值

integer 类型

{
  "debugger": {
    "timeout": 3000
  }
}

内联变量值

  • 描述:调试期间,是否启用编辑器 Inlay Hints 来显示代码中变量的值。
  • 默认值:true
  • 设置项:inlay_hints.show_value_hints

可选值

{
  "inlay_hints": {
    "show_value_hints": false
  }
}

也可以从编辑器工具栏的“编辑器控制”菜单中切换内联变量值提示的显示。

记录 DAP 通信

  • 描述:是否记录活跃调试适配器与 Zed 之间的消息。(用于 DAP 开发调试)
  • 默认值:false
  • 设置项:debugger.log_dap_communications

可选值

boolean 类型

{
  "debugger": {
    "log_dap_communications": true
  }
}

格式化 DAP 日志消息

  • 描述:将 DAP 消息写入调试适配器日志前,是否对其格式进行美化。(用于 DAP 开发调试)
  • 默认值:false
  • 设置项:debugger.format_dap_log_messages

可选值

boolean 类型

{
  "debugger": {
    "format_dap_log_messages": true
  }
}

自定义调试适配器

  • 说明:自定义程序路径和参数,覆盖 Zed 启动特定 debug adapter 的方式。
  • 默认值:取决于具体 adapter
  • 设置项:dap.$ADAPTER.binarydap.$ADAPTER.args

binaryargs 可以单独或一起配置。binary 应指向一个 debug adapter(如 lldb-dap),而不是 debugger(如 lldb 本身)。args 会覆盖 Zed 原本传给 adapter 的参数。

{
  "dap": {
    "CodeLLDB": {
      "binary": "/Users/name/bin/lldb-dap",
      "args": ["--wait-for-debugger"]
    }
  }
}

主题

Debugger 支持以下主题选项:

  • debugger.accent:用于强调断点及相关符号的颜色
  • editor.debugger_active_line.background:当前调试行的背景色

问题排查

如果使用 debugger 时遇到问题,请在 GitHub 上提交 issue,并尽量提供详细的上下文信息。你也可以利用以下功能收集更多问题线索:

  • 当 debug 面板中有正在运行的会话时,可以执行 {#action dev::CopyDebugAdapterArguments} 操作,把一段描述 Zed 如何初始化该会话的 JSON 复制到剪贴板。这在会话启动失败时尤其有用,提交 GitHub issue 时附上它是很好的补充信息。
  • 还可以使用 {#action dev::OpenDebugAdapterLogs} 操作,查看最近调试会话中 Zed 与 debug adapter 之间的全部通信记录。

评论 (0)