调试器
Zed 使用 调试适配器协议 (DAP) 在多种编程语言中提供调试功能。DAP 是一种标准化协议,定义了调试器、编辑器和 IDE 之间如何通信。它允许 Zed 支持各种调试器,而无需实现特定于语言的调试逻辑。Zed 实现协议的客户端,而各种调试适配器实现服务器端。
此协议以一致的方式在不同的编程语言和运行时环境中实现设置断点、单步执行代码、检查变量等功能。
支持的语言
要调试用特定语言编写的代码,Zed 需要为该语言找到一个调试适配器。有些调试适配器由 Zed 提供,无需额外设置,有些则由语言扩展提供。目前支持以下语言的调试适配器:
- C(内置)
- C++(内置)
- Go(内置)
- JavaScript(内置)
- PHP(内置)
- Python(内置)
- Ruby(由扩展提供)
- Rust(内置)
- Swift(由扩展提供)
- TypeScript(内置)
如果您的语言未列出,您可以通过添加调试适配器来做出贡献。请查看我们的调试器扩展文档以获取更多信息。
请按照这些链接获取特定于语言和适配器的信息和示例,或者继续阅读以了解 Zed 适用于所有适配器的一般调试功能。
入门
对于大多数语言,最快的入门方法是运行 debugger: start (f4|f4)。这将打开新进程模式,其中显示当前项目的预配置调试任务的上下文列表。调试任务是从测试、入口点(如 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 加载调试配置,并在新进程模式中显示它们。
全局调试配置
如果您在多个项目中使用相同的启动配置文件,您可以将它们存储在用户配置中一次。从命令面板调用 zed: open debug tasks 以打开全局 debug.json 文件;Zed 会在您的用户 settings.json 旁边创建它,并使其与调试器 UI 同步。该文件位于
- 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(和底层的调试适配器)通常在获取调试信息方面做得更好,因为它控制着整个程序的生命周期,相比之下,附加到现有进程时则不然。运行单元测试或应用程序的调试版本是启动的好用例。
与启动相比,附加到现有进程可能看起来逊色,但这远非事实;在某些情况下,您无法承担重新启动程序的代价,例如,因为错误在生产环境或其他情况下无法重现。
配置
Zed 要求所有调试任务都有 adapter 和 label 字段。此外,Zed 将使用 build 字段在调试器启动之前运行任何必要的设置步骤(见下文),并且可以接受 tcp_connection 字段以连接到现有进程。
所有其他字段均由调试适配器提供,并且可以包含任务变量。大多数适配器支持 request、program 和 cwd
[
{
// The label for the debug configuration and used to identify the debug session inside the debug panel & new process modal
"label": "Example Start debugger config",
// The debug adapter that Zed should use to debug the program
"adapter": "Example adapter name",
// Request:
// - launch: Zed will launch the program if specified, or show a debug terminal with the right configuration
// - attach: Zed will attach to a running program to debug it, or when the process_id is not specified, will show a process picker (only supported for node currently)
"request": "launch",
// The program to debug. This field supports path resolution with ~ or . symbols.
"program": "path_to_program",
// cwd: defaults to the current working directory of your project ($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" // Or "my build task for $ZED_FILE"
}
]
自动场景创建
给定一个 Zed 任务,Zed 可以自动为您创建一个场景。自动场景创建还支持我们从装订线创建场景。Rust、Go、Python、JavaScript 和 TypeScript 目前支持自动场景创建。
断点
要设置断点,只需单击编辑器装订线中行号旁边。断点可以根据您的需要进行调整;要访问给定断点的附加选项,请右键单击装订线中的断点图标并选择所需选项。目前,您可以
- 向断点添加日志,每次命中该断点时,它都会输出一条日志消息。
- 使断点成为条件断点,只有当条件满足时才会停止在断点处。条件的语法因适配器而异。
- 向断点添加命中计数,只有在命中一定次数后才会停止在断点处。
- 禁用断点,这将阻止其被命中,同时使其在装订线中可见。
某些调试适配器(例如 CodeLLDB 和 JavaScript)还会验证您的断点是否可命中;无法命中的断点会在 UI 中更突出地显示。
给定项目启用的所有断点也列在调试会话 UI 中的“断点”项中。在 UI 的“断点”项中,您还可以管理异常断点。当发生给定类型的异常时,调试适配器将停止。支持的异常类型取决于调试适配器。
设置
调试器的设置在 settings.json 的 debugger 键下分组
dock:确定调试面板在 UI 中的位置。stepping_granularity:确定步进粒度。save_breakpoints:断点是否应在 Zed 会话之间重用。button:是否在状态栏中显示调试按钮。timeout:连接到 TCP 调试适配器时超时错误的毫秒数。log_dap_communications:是否记录活动调试适配器和 Zed 之间的消息。format_dap_log_messages:在将 DAP 消息添加到调试适配器记录器时是否格式化 DAP 消息。
停靠
- 描述:调试面板在 UI 中的位置。
- 默认值:
bottom - 设置:debugger.dock
选项
left- 调试面板将停靠在 UI 的左侧。right- 调试面板将停靠在 UI 的右侧。bottom- 调试面板将停靠在 UI 的底部。
"debugger": {
"dock": "bottom"
},
步进粒度
- 描述:调试器将使用的步进粒度
- 默认值:
line - 设置:
debugger.stepping_granularity
选项
- 语句 - 步进应允许程序运行,直到当前语句执行完毕。语句的含义由适配器确定,可能被视为等同于一行。例如,“for(int i = 0; i < 10; i++)”可以被认为有 3 个语句:“int i = 0”、“i < 10”和“i++”。
{
"debugger": {
"stepping_granularity": "statement"
}
}
- 行 - 步进应允许程序运行,直到当前源代码行执行完毕。
{
"debugger": {
"stepping_granularity": "line"
}
}
- 指令 - 步进应允许执行一条指令(例如,一条 x86 指令)。
{
"debugger": {
"stepping_granularity": "instruction"
}
}
保存断点
- 描述:断点是否应在 Zed 会话之间保存。
- 默认值:
true - 设置:
debugger.save_breakpoints
选项
boolean 值
{
"debugger": {
"save_breakpoints": true
}
}
按钮
- 描述:是否在调试器工具栏中显示按钮。
- 默认值:
true - 设置:
debugger.show_button
选项
boolean 值
{
"debugger": {
"show_button": true
}
}
超时
- 描述:连接到 TCP 调试适配器时,直到超时错误的毫秒数。
- 默认值:
2000 - 设置:
debugger.timeout
选项
integer 值
{
"debugger": {
"timeout": 3000
}
}
内联值
- 描述:是否启用编辑器嵌入式提示,以在调试会话期间显示代码中变量的值。
- 默认值:
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 消息。(用于 DAP 开发)
- 默认值:false
- 设置:debugger.format_dap_log_messages
选项
boolean 值
{
"debugger": {
"format_dap_log_messages": true
}
}
自定义调试适配器
- 描述:自定义程序路径和参数,以覆盖 Zed 启动特定调试适配器的方式。
- 默认值:特定于适配器
- 设置:
dap.$ADAPTER.binary和dap.$ADAPTER.args
您可以传递 binary、args,或两者。binary 应该是指向调试适配器(如 lldb-dap)的路径,而不是调试器(如 lldb 本身)。args 设置会覆盖 Zed 否则会传递给适配器的任何参数。
{
"dap": {
"CodeLLDB": {
"binary": "/Users/name/bin/lldb-dap",
"args": ["--wait-for-debugger"]
}
}
}
主题
调试器支持以下主题选项
debugger.accent:用于突出断点和与断点相关的符号的颜色editor.debugger_active_line.background:活动调试行的背景颜色
故障排除
如果您在使用调试器时遇到问题,请打开一个 GitHub 问题,并提供尽可能多的上下文。您还可以使用一些功能来收集有关问题的更多信息
- 当您在调试面板中运行会话时,可以运行
dev: copy debug adapter arguments操作,将描述 Zed 如何初始化会话的 JSON blob 复制到剪贴板。当会话启动失败时,这尤其有用,并且如果您打开 GitHub 问题,这是一个很好的上下文。 - 您还可以使用
dev: open debug adapter logs操作来查看 Zed 与调试适配器在最近调试会话期间所有通信的跟踪。