extension: Update DAP extension API (#32448)

- DAP schemas will be stored in `debug_adapters_schemas` subdirectory in
extension work dir.
- Added Debug Config integration and such.

Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2025-06-16 16:25:32 +02:00 committed by GitHub
parent 41e9f3148c
commit 8df6ce2aac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 620 additions and 47 deletions

View file

@ -20,8 +20,8 @@ pub use wit::{
make_file_executable,
zed::extension::context_server::ContextServerConfiguration,
zed::extension::dap::{
DebugAdapterBinary, DebugTaskDefinition, StartDebuggingRequestArguments,
StartDebuggingRequestArgumentsRequest, TcpArguments, TcpArgumentsTemplate,
DebugAdapterBinary, DebugRequest, DebugTaskDefinition, StartDebuggingRequestArguments,
StartDebuggingRequestArgumentsRequest, TaskTemplate, TcpArguments, TcpArgumentsTemplate,
resolve_tcp_template,
},
zed::extension::github::{
@ -204,8 +204,35 @@ pub trait Extension: Send + Sync {
Err("`get_dap_binary` not implemented".to_string())
}
fn dap_schema(&mut self) -> Result<serde_json::Value, String> {
Err("`dap_schema` not implemented".to_string())
fn dap_request_kind(
&mut self,
_adapter_name: String,
_config: serde_json::Value,
) -> Result<StartDebuggingRequestArgumentsRequest, String> {
Err("`dap_request_kind` not implemented".to_string())
}
fn dap_config_to_scenario(
&mut self,
_adapter_name: DebugConfig,
_config: &Worktree,
) -> Result<DebugScenario, String> {
Err("`dap_config_to_scenario` not implemented".to_string())
}
fn dap_locator_create_scenario(
&mut self,
_locator_name: String,
_build_task: TaskTemplate,
_resolved_label: String,
_debug_adapter_name: String,
) -> Option<DebugScenario> {
None
}
fn run_dap_locator(
&mut self,
_locator_name: String,
_build_task: TaskTemplate,
) -> Result<DebugRequest, String> {
Err("`run_dap_locator` not implemented".to_string())
}
}
@ -401,8 +428,39 @@ impl wit::Guest for Component {
extension().get_dap_binary(adapter_name, config, user_installed_path, worktree)
}
fn dap_schema() -> Result<String, String> {
extension().dap_schema().map(|schema| schema.to_string())
fn dap_request_kind(
adapter_name: String,
config: String,
) -> Result<StartDebuggingRequestArgumentsRequest, String> {
extension().dap_request_kind(
adapter_name,
serde_json::from_str(&config).map_err(|e| format!("Failed to parse config: {e}"))?,
)
}
fn dap_config_to_scenario(
config: DebugConfig,
worktree: &Worktree,
) -> Result<DebugScenario, String> {
extension().dap_config_to_scenario(config, worktree)
}
fn dap_locator_create_scenario(
locator_name: String,
build_task: TaskTemplate,
resolved_label: String,
debug_adapter_name: String,
) -> Option<DebugScenario> {
extension().dap_locator_create_scenario(
locator_name,
build_task,
resolved_label,
debug_adapter_name,
)
}
fn run_dap_locator(
locator_name: String,
build_task: TaskTemplate,
) -> Result<DebugRequest, String> {
extension().run_dap_locator(locator_name, build_task)
}
}

View file

@ -32,10 +32,55 @@ interface dap {
timeout: option<u64>,
}
record debug-task-definition {
/// Debug Config is the "highest-level" configuration for a debug session.
/// It comes from a new session modal UI; thus, it is essentially debug-adapter-agnostic.
/// It is expected of the extension to translate this generic configuration into something that can be debugged by the adapter (debug scenario).
record debug-config {
/// Name of the debug task
label: string,
/// The debug adapter to use
adapter: string,
request: debug-request,
stop-on-entry: option<bool>,
}
record task-template {
/// Human readable name of the task to display in the UI.
label: string,
/// Executable command to spawn.
command: string,
args: list<string>,
env: env-vars,
cwd: option<string>,
}
/// A task template with substituted task variables.
type resolved-task = task-template;
/// A task template for building a debug target.
type build-task-template = task-template;
variant build-task-definition {
by-name(string),
template(build-task-definition-template-payload )
}
record build-task-definition-template-payload {
locator-name: option<string>,
template: build-task-template
}
/// Debug Scenario is the user-facing configuration type (used in debug.json). It is still concerned with what to debug and not necessarily how to do it (except for any
/// debug-adapter-specific configuration options).
record debug-scenario {
/// Unsubstituted label for the task.DebugAdapterBinary
label: string,
/// Name of the Debug Adapter this configuration is intended for.
adapter: string,
/// An optional build step to be ran prior to starting a debug session. Build steps are used by Zed's locators to locate the executable to debug.
build: option<build-task-definition>,
/// JSON-encoded configuration for a given debug adapter.
config: string,
/// TCP connection parameters (if they were specified by user)
tcp-connection: option<tcp-arguments-template>,
}
@ -44,16 +89,34 @@ interface dap {
attach,
}
record debug-task-definition {
/// Unsubstituted label for the task.DebugAdapterBinary
label: string,
/// Name of the Debug Adapter this configuration is intended for.
adapter: string,
/// JSON-encoded configuration for a given debug adapter.
config: string,
/// TCP connection parameters (if they were specified by user)
tcp-connection: option<tcp-arguments-template>,
}
record start-debugging-request-arguments {
/// JSON-encoded configuration for a given debug adapter. It is specific to each debug adapter.
/// `configuration` will have it's Zed variable references substituted prior to being passed to the debug adapter.
configuration: string,
request: start-debugging-request-arguments-request,
}
/// The lowest-level representation of a debug session, which specifies:
/// - How to start a debug adapter process
/// - How to start a debug session with it (using DAP protocol)
/// for a given debug scenario.
record debug-adapter-binary {
command: option<string>,
arguments: list<string>,
envs: env-vars,
cwd: option<string>,
/// Zed will use TCP transport if `connection` is specified.
connection: option<tcp-arguments>,
request-args: start-debugging-request-arguments
}

View file

@ -11,7 +11,7 @@ world extension {
use common.{env-vars, range};
use context-server.{context-server-configuration};
use dap.{debug-adapter-binary, debug-task-definition, debug-request};
use dap.{attach-request, build-task-template, debug-config, debug-adapter-binary, debug-task-definition, debug-request, debug-scenario, launch-request, resolved-task, start-debugging-request-arguments-request};
use lsp.{completion, symbol};
use process.{command};
use slash-command.{slash-command, slash-command-argument-completion, slash-command-output};
@ -159,6 +159,9 @@ world extension {
/// Returns a configured debug adapter binary for a given debug task.
export get-dap-binary: func(adapter-name: string, config: debug-task-definition, user-installed-path: option<string>, worktree: borrow<worktree>) -> result<debug-adapter-binary, string>;
/// Get a debug adapter's configuration schema
export dap-schema: func() -> result<string, string>;
/// Returns the kind of a debug scenario (launch or attach).
export dap-request-kind: func(adapter-name: string, config: string) -> result<start-debugging-request-arguments-request, string>;
export dap-config-to-scenario: func(config: debug-config, worktree: borrow<worktree>) -> result<debug-scenario, string>;
export dap-locator-create-scenario: func(locator-name: string, build-config-template: build-task-template, resolved-label: string, debug-adapter-name: string) -> option<debug-scenario>;
export run-dap-locator: func(locator-name: string, config: resolved-task) -> result<debug-request, string>;
}