调试器扩展
定义调试器扩展
给定的扩展可以提供一个或多个 DAP 服务器。每个 DAP 服务器都必须在 extension.toml 中注册
[debug_adapters.my-debug-adapter]
# Optional relative path to the JSON schema for the debug adapter configuration schema. Defaults to `debug_adapter_schemas/$DEBUG_ADAPTER_NAME_ID.json`.
# Note that while this field is optional, a schema is mandatory.
schema_path = "relative/path/to/schema.json"
然后,在扩展的 Rust 代码中,实现扩展上的 get_dap_binary 方法
#![allow(unused)] fn main() { impl zed::Extension for MyExtension { fn get_dap_binary( &mut self, adapter_name: String, config: DebugTaskDefinition, user_provided_debug_adapter_path: Option<String>, worktree: &Worktree, ) -> Result<DebugAdapterBinary, String>; } }
此方法应返回启动调试适配器协议服务器的命令,以及其正常运行所需的任何参数或环境变量。
如果您需要从外部源(如 GitHub Releases 或 npm)下载 DAP 服务器,也可以在此函数中完成。请务必仅定期检查更新,因为每当用户使用您的调试适配器启动新的调试会话时,都会调用此函数。
您还必须实现 dap_request_kind。此函数用于确定给定的调试场景是启动一个新的调试对象还是附加到现有对象。我们还使用它来确定给定的调试场景是否需要运行一个定位器。
#![allow(unused)] fn main() { impl zed::Extension for MyExtension { fn dap_request_kind( &mut self, _adapter_name: String, _config: Value, ) -> Result<StartDebuggingRequestArgumentsRequest, String>; } }
这两个函数足以在基于 debug.json 的用户工作流中暴露您的调试适配器,但您应该强烈考虑也实现 dap_config_to_scenario。
#![allow(unused)] fn main() { impl zed::Extension for MyExtension { fn dap_config_to_scenario( &mut self, _adapter_name: DebugConfig, ) -> Result<DebugScenario, String>; } }
当用户通过新的进程模式 UI 启动会话时,会使用 dap_config_to_scenario。从高层次看,它接收一个通用调试配置(不特定于任何调试适配器),并尝试将其转换为您的适配器的具体调试场景。换句话说,它应该回答这个问题:“给定一个程序、一个参数列表、当前工作目录和环境变量,启动这个调试适配器的配置会是什么样子?”。
定义调试定位器
Zed 提供了一种使用调试定位器自动创建调试场景的方法。定位器定位调试目标并找出如何为其启动调试会话。借助定位器,我们可以自动将现有用户任务(例如 cargo run)转换为调试场景(例如 cargo build,然后使用 target/debug/my_program 作为要调试的程序启动调试器)。
您的扩展可以定义自己的调试定位器,即使它不暴露调试适配器。当您的扩展已经暴露语言任务时,我们强烈建议这样做,因为它允许用户启动调试会话,而无需手动配置调试适配器。
定位器可以(但不一定)与其使用的调试适配器无关。它们只负责定位调试目标并找出如何为其启动调试会话。这允许更灵活和可扩展的调试体验。
您的扩展可以定义一个或多个调试定位器。每个调试定位器都必须在 extension.toml 中注册
[debug_locators.my-debug-locator]
定位器有两个组件。首先,每个定位器在每个可用任务上运行,以确定任何可用定位器是否可以为给定任务提供调试场景。这是通过调用 dap_locator_create_scenario 完成的。
#![allow(unused)] fn main() { impl zed::Extension for MyExtension { fn dap_locator_create_scenario( &mut self, _locator_name: String, _build_task: TaskTemplate, _resolved_label: String, _debug_adapter_name: String, ) -> Option<DebugScenario>; } }
当某个场景定义了给定用户任务的调试对应物时,此函数应返回 Some 调试场景。请注意,DebugScenario 可以包含一个构建任务。如果存在,我们将在构建任务成功完成后执行 run_dap_locator。
#![allow(unused)] fn main() { impl zed::Extension for MyExtension { fn run_dap_locator( &mut self, _locator_name: String, _build_task: TaskTemplate, ) -> Result<DebugRequest, String>; } }
如果无法确定性地确定构建目标,run_dap_locator 会很有用。某些构建系统可能会生成其名称事先未知的工件。但请注意,您不需要进行两阶段解析;如果您可以通过 dap_locator_create_scenario 确定完整的调试配置,则可以省略返回的 DebugScenario 上的 build 属性。另请注意,您的定位器将被调用,其中包含它不太可能接受的任务;因此,您应该努力在执行任何昂贵操作之前尽早返回 None。
可用扩展
在 Zed 网站上查看所有已暴露为扩展的 DAP 服务器。
我们建议查看它们的存储库,以了解它们通常是如何创建和组织的。
测试
要测试您的新调试适配器协议服务器扩展,您可以将其安装为开发扩展。