debugger: Add extensions support (#30625)
Closes #ISSUE Release Notes: - N/A --------- Co-authored-by: Anthony <anthony@zed.dev>
This commit is contained in:
parent
6fc9036063
commit
9826b7b5c1
21 changed files with 402 additions and 13 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -4134,6 +4134,18 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "debug_adapter_extension"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"async-trait",
|
||||||
|
"dap",
|
||||||
|
"extension",
|
||||||
|
"gpui",
|
||||||
|
"workspace-hack",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "debugger_tools"
|
name = "debugger_tools"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -5039,6 +5051,7 @@ dependencies = [
|
||||||
"async-tar",
|
"async-tar",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"collections",
|
"collections",
|
||||||
|
"dap",
|
||||||
"fs",
|
"fs",
|
||||||
"futures 0.3.31",
|
"futures 0.3.31",
|
||||||
"gpui",
|
"gpui",
|
||||||
|
@ -5051,6 +5064,7 @@ dependencies = [
|
||||||
"semantic_version",
|
"semantic_version",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"task",
|
||||||
"toml 0.8.20",
|
"toml 0.8.20",
|
||||||
"util",
|
"util",
|
||||||
"wasm-encoder 0.221.3",
|
"wasm-encoder 0.221.3",
|
||||||
|
@ -5094,6 +5108,7 @@ dependencies = [
|
||||||
"client",
|
"client",
|
||||||
"collections",
|
"collections",
|
||||||
"ctor",
|
"ctor",
|
||||||
|
"dap",
|
||||||
"env_logger 0.11.8",
|
"env_logger 0.11.8",
|
||||||
"extension",
|
"extension",
|
||||||
"fs",
|
"fs",
|
||||||
|
@ -18018,7 +18033,6 @@ dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"anstream",
|
"anstream",
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"async-compression",
|
|
||||||
"async-std",
|
"async-std",
|
||||||
"async-tungstenite",
|
"async-tungstenite",
|
||||||
"aws-config",
|
"aws-config",
|
||||||
|
|
|
@ -37,6 +37,7 @@ members = [
|
||||||
"crates/dap",
|
"crates/dap",
|
||||||
"crates/dap_adapters",
|
"crates/dap_adapters",
|
||||||
"crates/db",
|
"crates/db",
|
||||||
|
"crates/debug_adapter_extension",
|
||||||
"crates/debugger_tools",
|
"crates/debugger_tools",
|
||||||
"crates/debugger_ui",
|
"crates/debugger_ui",
|
||||||
"crates/deepseek",
|
"crates/deepseek",
|
||||||
|
@ -243,6 +244,7 @@ credentials_provider = { path = "crates/credentials_provider" }
|
||||||
dap = { path = "crates/dap" }
|
dap = { path = "crates/dap" }
|
||||||
dap_adapters = { path = "crates/dap_adapters" }
|
dap_adapters = { path = "crates/dap_adapters" }
|
||||||
db = { path = "crates/db" }
|
db = { path = "crates/db" }
|
||||||
|
debug_adapter_extension = { path = "crates/debug_adapter_extension" }
|
||||||
debugger_tools = { path = "crates/debugger_tools" }
|
debugger_tools = { path = "crates/debugger_tools" }
|
||||||
debugger_ui = { path = "crates/debugger_ui" }
|
debugger_ui = { path = "crates/debugger_ui" }
|
||||||
deepseek = { path = "crates/deepseek" }
|
deepseek = { path = "crates/deepseek" }
|
||||||
|
|
|
@ -4,7 +4,7 @@ use async_compression::futures::bufread::GzipDecoder;
|
||||||
use async_tar::Archive;
|
use async_tar::Archive;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use dap_types::{StartDebuggingRequestArguments, StartDebuggingRequestArgumentsRequest};
|
pub use dap_types::{StartDebuggingRequestArguments, StartDebuggingRequestArgumentsRequest};
|
||||||
use futures::io::BufReader;
|
use futures::io::BufReader;
|
||||||
use gpui::{AsyncApp, SharedString};
|
use gpui::{AsyncApp, SharedString};
|
||||||
pub use http_client::{HttpClient, github::latest_github_release};
|
pub use http_client::{HttpClient, github::latest_github_release};
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub struct InlineValueLocation {
|
||||||
/// during debugging sessions. Implementors must also handle variable scoping
|
/// during debugging sessions. Implementors must also handle variable scoping
|
||||||
/// themselves by traversing the syntax tree upwards to determine whether a
|
/// themselves by traversing the syntax tree upwards to determine whether a
|
||||||
/// variable is local or global.
|
/// variable is local or global.
|
||||||
pub trait InlineValueProvider {
|
pub trait InlineValueProvider: 'static + Send + Sync {
|
||||||
/// Provides a list of inline value locations based on the given node and source code.
|
/// Provides a list of inline value locations based on the given node and source code.
|
||||||
///
|
///
|
||||||
/// # Parameters
|
/// # Parameters
|
||||||
|
|
20
crates/debug_adapter_extension/Cargo.toml
Normal file
20
crates/debug_adapter_extension/Cargo.toml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
[package]
|
||||||
|
name = "debug_adapter_extension"
|
||||||
|
version = "0.1.0"
|
||||||
|
license = "GPL-3.0-or-later"
|
||||||
|
publish.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow.workspace = true
|
||||||
|
async-trait.workspace = true
|
||||||
|
dap.workspace = true
|
||||||
|
extension.workspace = true
|
||||||
|
gpui.workspace = true
|
||||||
|
workspace-hack = { version = "0.1", path = "../../tooling/workspace-hack" }
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "src/debug_adapter_extension.rs"
|
1
crates/debug_adapter_extension/LICENSE-GPL
Symbolic link
1
crates/debug_adapter_extension/LICENSE-GPL
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../LICENSE-GPL
|
|
@ -0,0 +1,40 @@
|
||||||
|
mod extension_dap_adapter;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use dap::DapRegistry;
|
||||||
|
use extension::{ExtensionDebugAdapterProviderProxy, ExtensionHostProxy};
|
||||||
|
use extension_dap_adapter::ExtensionDapAdapter;
|
||||||
|
use gpui::App;
|
||||||
|
|
||||||
|
pub fn init(extension_host_proxy: Arc<ExtensionHostProxy>, cx: &mut App) {
|
||||||
|
let language_server_registry_proxy = DebugAdapterRegistryProxy::new(cx);
|
||||||
|
extension_host_proxy.register_debug_adapter_proxy(language_server_registry_proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct DebugAdapterRegistryProxy {
|
||||||
|
debug_adapter_registry: DapRegistry,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DebugAdapterRegistryProxy {
|
||||||
|
fn new(cx: &mut App) -> Self {
|
||||||
|
Self {
|
||||||
|
debug_adapter_registry: DapRegistry::global(cx).clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtensionDebugAdapterProviderProxy for DebugAdapterRegistryProxy {
|
||||||
|
fn register_debug_adapter(
|
||||||
|
&self,
|
||||||
|
extension: Arc<dyn extension::Extension>,
|
||||||
|
debug_adapter_name: Arc<str>,
|
||||||
|
) {
|
||||||
|
self.debug_adapter_registry
|
||||||
|
.add_adapter(Arc::new(ExtensionDapAdapter::new(
|
||||||
|
extension,
|
||||||
|
debug_adapter_name,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
49
crates/debug_adapter_extension/src/extension_dap_adapter.rs
Normal file
49
crates/debug_adapter_extension/src/extension_dap_adapter.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
use std::{path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use dap::adapters::{
|
||||||
|
DapDelegate, DebugAdapter, DebugAdapterBinary, DebugAdapterName, DebugTaskDefinition,
|
||||||
|
};
|
||||||
|
use extension::Extension;
|
||||||
|
use gpui::AsyncApp;
|
||||||
|
|
||||||
|
pub(crate) struct ExtensionDapAdapter {
|
||||||
|
extension: Arc<dyn Extension>,
|
||||||
|
debug_adapter_name: Arc<str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtensionDapAdapter {
|
||||||
|
pub(crate) fn new(
|
||||||
|
extension: Arc<dyn extension::Extension>,
|
||||||
|
debug_adapter_name: Arc<str>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
extension,
|
||||||
|
debug_adapter_name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait(?Send)]
|
||||||
|
impl DebugAdapter for ExtensionDapAdapter {
|
||||||
|
fn name(&self) -> DebugAdapterName {
|
||||||
|
self.debug_adapter_name.as_ref().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_binary(
|
||||||
|
&self,
|
||||||
|
_: &dyn DapDelegate,
|
||||||
|
config: &DebugTaskDefinition,
|
||||||
|
user_installed_path: Option<PathBuf>,
|
||||||
|
_cx: &mut AsyncApp,
|
||||||
|
) -> Result<DebugAdapterBinary> {
|
||||||
|
self.extension
|
||||||
|
.get_dap_binary(
|
||||||
|
self.debug_adapter_name.clone(),
|
||||||
|
config.clone(),
|
||||||
|
user_installed_path,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ async-compression.workspace = true
|
||||||
async-tar.workspace = true
|
async-tar.workspace = true
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
collections.workspace = true
|
collections.workspace = true
|
||||||
|
dap.workspace = true
|
||||||
fs.workspace = true
|
fs.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
|
@ -29,6 +30,7 @@ parking_lot.workspace = true
|
||||||
semantic_version.workspace = true
|
semantic_version.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
|
task.workspace = true
|
||||||
toml.workspace = true
|
toml.workspace = true
|
||||||
util.workspace = true
|
util.workspace = true
|
||||||
wasm-encoder.workspace = true
|
wasm-encoder.workspace = true
|
||||||
|
|
|
@ -135,6 +135,13 @@ pub trait Extension: Send + Sync + 'static {
|
||||||
package_name: Arc<str>,
|
package_name: Arc<str>,
|
||||||
kv_store: Arc<dyn KeyValueStoreDelegate>,
|
kv_store: Arc<dyn KeyValueStoreDelegate>,
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
|
|
||||||
|
async fn get_dap_binary(
|
||||||
|
&self,
|
||||||
|
dap_name: Arc<str>,
|
||||||
|
config: DebugTaskDefinition,
|
||||||
|
user_installed_path: Option<PathBuf>,
|
||||||
|
) -> Result<DebugAdapterBinary>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_wasm_extension_version(
|
pub fn parse_wasm_extension_version(
|
||||||
|
|
|
@ -29,6 +29,7 @@ pub struct ExtensionHostProxy {
|
||||||
slash_command_proxy: RwLock<Option<Arc<dyn ExtensionSlashCommandProxy>>>,
|
slash_command_proxy: RwLock<Option<Arc<dyn ExtensionSlashCommandProxy>>>,
|
||||||
context_server_proxy: RwLock<Option<Arc<dyn ExtensionContextServerProxy>>>,
|
context_server_proxy: RwLock<Option<Arc<dyn ExtensionContextServerProxy>>>,
|
||||||
indexed_docs_provider_proxy: RwLock<Option<Arc<dyn ExtensionIndexedDocsProviderProxy>>>,
|
indexed_docs_provider_proxy: RwLock<Option<Arc<dyn ExtensionIndexedDocsProviderProxy>>>,
|
||||||
|
debug_adapter_provider_proxy: RwLock<Option<Arc<dyn ExtensionDebugAdapterProviderProxy>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtensionHostProxy {
|
impl ExtensionHostProxy {
|
||||||
|
@ -54,6 +55,7 @@ impl ExtensionHostProxy {
|
||||||
slash_command_proxy: RwLock::default(),
|
slash_command_proxy: RwLock::default(),
|
||||||
context_server_proxy: RwLock::default(),
|
context_server_proxy: RwLock::default(),
|
||||||
indexed_docs_provider_proxy: RwLock::default(),
|
indexed_docs_provider_proxy: RwLock::default(),
|
||||||
|
debug_adapter_provider_proxy: RwLock::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +95,11 @@ impl ExtensionHostProxy {
|
||||||
.write()
|
.write()
|
||||||
.replace(Arc::new(proxy));
|
.replace(Arc::new(proxy));
|
||||||
}
|
}
|
||||||
|
pub fn register_debug_adapter_proxy(&self, proxy: impl ExtensionDebugAdapterProviderProxy) {
|
||||||
|
self.debug_adapter_provider_proxy
|
||||||
|
.write()
|
||||||
|
.replace(Arc::new(proxy));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ExtensionThemeProxy: Send + Sync + 'static {
|
pub trait ExtensionThemeProxy: Send + Sync + 'static {
|
||||||
|
@ -402,3 +409,17 @@ impl ExtensionIndexedDocsProviderProxy for ExtensionHostProxy {
|
||||||
proxy.register_indexed_docs_provider(extension, provider_id)
|
proxy.register_indexed_docs_provider(extension, provider_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ExtensionDebugAdapterProviderProxy: Send + Sync + 'static {
|
||||||
|
fn register_debug_adapter(&self, extension: Arc<dyn Extension>, debug_adapter_name: Arc<str>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtensionDebugAdapterProviderProxy for ExtensionHostProxy {
|
||||||
|
fn register_debug_adapter(&self, extension: Arc<dyn Extension>, debug_adapter_name: Arc<str>) {
|
||||||
|
let Some(proxy) = self.debug_adapter_provider_proxy.read().clone() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
proxy.register_debug_adapter(extension, debug_adapter_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
mod context_server;
|
mod context_server;
|
||||||
|
mod dap;
|
||||||
mod lsp;
|
mod lsp;
|
||||||
mod slash_command;
|
mod slash_command;
|
||||||
|
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
pub use context_server::*;
|
pub use context_server::*;
|
||||||
|
pub use dap::*;
|
||||||
pub use lsp::*;
|
pub use lsp::*;
|
||||||
pub use slash_command::*;
|
pub use slash_command::*;
|
||||||
|
|
||||||
|
|
5
crates/extension/src/types/dap.rs
Normal file
5
crates/extension/src/types/dap.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
pub use dap::{
|
||||||
|
StartDebuggingRequestArguments, StartDebuggingRequestArgumentsRequest,
|
||||||
|
adapters::{DebugAdapterBinary, DebugTaskDefinition, TcpArguments},
|
||||||
|
};
|
||||||
|
pub use task::{AttachRequest, DebugRequest, LaunchRequest, TcpArgumentsTemplate};
|
|
@ -187,6 +187,16 @@ pub trait Extension: Send + Sync {
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
Err("`index_docs` not implemented".to_string())
|
Err("`index_docs` not implemented".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the debug adapter binary for the specified adapter name and configuration.
|
||||||
|
fn get_dap_binary(
|
||||||
|
&mut self,
|
||||||
|
_adapter_name: String,
|
||||||
|
_config: DebugTaskDefinition,
|
||||||
|
_user_provided_path: Option<String>,
|
||||||
|
) -> Result<DebugAdapterBinary, String> {
|
||||||
|
Err("`get_dap_binary` not implemented".to_string())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers the provided type as a Zed extension.
|
/// Registers the provided type as a Zed extension.
|
||||||
|
@ -371,6 +381,14 @@ impl wit::Guest for Component {
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
extension().index_docs(provider, package, database)
|
extension().index_docs(provider, package, database)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_dap_binary(
|
||||||
|
adapter_name: String,
|
||||||
|
config: DebugTaskDefinition,
|
||||||
|
user_installed_path: Option<String>,
|
||||||
|
) -> Result<DebugAdapterBinary, String> {
|
||||||
|
extension().get_dap_binary(adapter_name, config, user_installed_path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The ID of a language server.
|
/// The ID of a language server.
|
||||||
|
|
56
crates/extension_api/wit/since_v0.6.0/dap.wit
Normal file
56
crates/extension_api/wit/since_v0.6.0/dap.wit
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
interface dap {
|
||||||
|
use common.{env-vars};
|
||||||
|
record launch-request {
|
||||||
|
program: string,
|
||||||
|
cwd: option<string>,
|
||||||
|
args: list<string>,
|
||||||
|
envs: env-vars,
|
||||||
|
}
|
||||||
|
|
||||||
|
record attach-request {
|
||||||
|
process-id: option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
variant debug-request {
|
||||||
|
launch(launch-request),
|
||||||
|
attach(attach-request)
|
||||||
|
}
|
||||||
|
|
||||||
|
record tcp-arguments {
|
||||||
|
port: u16,
|
||||||
|
host: u32,
|
||||||
|
timeout: option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
record tcp-arguments-template {
|
||||||
|
port: option<u16>,
|
||||||
|
host: option<u32>,
|
||||||
|
timeout: option<u64>,
|
||||||
|
}
|
||||||
|
record debug-task-definition {
|
||||||
|
label: string,
|
||||||
|
adapter: string,
|
||||||
|
request: debug-request,
|
||||||
|
initialize-args: option<string>,
|
||||||
|
stop-on-entry: option<bool>,
|
||||||
|
tcp-connection: option<tcp-arguments-template>,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum start-debugging-request-arguments-request {
|
||||||
|
launch,
|
||||||
|
attach,
|
||||||
|
}
|
||||||
|
record start-debugging-request-arguments {
|
||||||
|
configuration: string,
|
||||||
|
request: start-debugging-request-arguments-request,
|
||||||
|
|
||||||
|
}
|
||||||
|
record debug-adapter-binary {
|
||||||
|
command: string,
|
||||||
|
arguments: list<string>,
|
||||||
|
envs: env-vars,
|
||||||
|
cwd: option<string>,
|
||||||
|
connection: option<tcp-arguments>,
|
||||||
|
request-args: start-debugging-request-arguments
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package zed:extension;
|
||||||
|
|
||||||
world extension {
|
world extension {
|
||||||
import context-server;
|
import context-server;
|
||||||
|
import dap;
|
||||||
import github;
|
import github;
|
||||||
import http-client;
|
import http-client;
|
||||||
import platform;
|
import platform;
|
||||||
|
@ -10,6 +11,7 @@ world extension {
|
||||||
|
|
||||||
use common.{env-vars, range};
|
use common.{env-vars, range};
|
||||||
use context-server.{context-server-configuration};
|
use context-server.{context-server-configuration};
|
||||||
|
use dap.{debug-adapter-binary, debug-task-definition};
|
||||||
use lsp.{completion, symbol};
|
use lsp.{completion, symbol};
|
||||||
use process.{command};
|
use process.{command};
|
||||||
use slash-command.{slash-command, slash-command-argument-completion, slash-command-output};
|
use slash-command.{slash-command, slash-command-argument-completion, slash-command-output};
|
||||||
|
@ -153,4 +155,7 @@ world extension {
|
||||||
|
|
||||||
/// Indexes the docs for the specified package.
|
/// Indexes the docs for the specified package.
|
||||||
export index-docs: func(provider-name: string, package-name: string, database: borrow<key-value-store>) -> result<_, string>;
|
export index-docs: func(provider-name: string, package-name: string, database: borrow<key-value-store>) -> result<_, string>;
|
||||||
|
|
||||||
|
/// 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>) -> result<debug-adapter-binary, string>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ async-tar.workspace = true
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
client.workspace = true
|
client.workspace = true
|
||||||
collections.workspace = true
|
collections.workspace = true
|
||||||
|
dap.workspace = true
|
||||||
extension.workspace = true
|
extension.workspace = true
|
||||||
fs.workspace = true
|
fs.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
|
|
|
@ -4,9 +4,9 @@ use crate::ExtensionManifest;
|
||||||
use anyhow::{Context as _, Result, anyhow, bail};
|
use anyhow::{Context as _, Result, anyhow, bail};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use extension::{
|
use extension::{
|
||||||
CodeLabel, Command, Completion, ContextServerConfiguration, ExtensionHostProxy,
|
CodeLabel, Command, Completion, ContextServerConfiguration, DebugAdapterBinary,
|
||||||
KeyValueStoreDelegate, ProjectDelegate, SlashCommand, SlashCommandArgumentCompletion,
|
DebugTaskDefinition, ExtensionHostProxy, KeyValueStoreDelegate, ProjectDelegate, SlashCommand,
|
||||||
SlashCommandOutput, Symbol, WorktreeDelegate,
|
SlashCommandArgumentCompletion, SlashCommandOutput, Symbol, WorktreeDelegate,
|
||||||
};
|
};
|
||||||
use fs::{Fs, normalize_path};
|
use fs::{Fs, normalize_path};
|
||||||
use futures::future::LocalBoxFuture;
|
use futures::future::LocalBoxFuture;
|
||||||
|
@ -374,6 +374,25 @@ impl extension::Extension for WasmExtension {
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
async fn get_dap_binary(
|
||||||
|
&self,
|
||||||
|
dap_name: Arc<str>,
|
||||||
|
config: DebugTaskDefinition,
|
||||||
|
user_installed_path: Option<PathBuf>,
|
||||||
|
) -> Result<DebugAdapterBinary> {
|
||||||
|
self.call(|extension, store| {
|
||||||
|
async move {
|
||||||
|
let dap_binary = extension
|
||||||
|
.call_get_dap_binary(store, dap_name, config, user_installed_path)
|
||||||
|
.await?
|
||||||
|
.map_err(|err| anyhow!("{err:?}"))?;
|
||||||
|
let dap_binary = dap_binary.try_into()?;
|
||||||
|
Ok(dap_binary)
|
||||||
|
}
|
||||||
|
.boxed()
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WasmState {
|
pub struct WasmState {
|
||||||
|
|
|
@ -7,16 +7,16 @@ mod since_v0_3_0;
|
||||||
mod since_v0_4_0;
|
mod since_v0_4_0;
|
||||||
mod since_v0_5_0;
|
mod since_v0_5_0;
|
||||||
mod since_v0_6_0;
|
mod since_v0_6_0;
|
||||||
use extension::{KeyValueStoreDelegate, WorktreeDelegate};
|
use extension::{DebugTaskDefinition, KeyValueStoreDelegate, WorktreeDelegate};
|
||||||
use language::LanguageName;
|
use language::LanguageName;
|
||||||
use lsp::LanguageServerName;
|
use lsp::LanguageServerName;
|
||||||
use release_channel::ReleaseChannel;
|
use release_channel::ReleaseChannel;
|
||||||
use since_v0_6_0 as latest;
|
|
||||||
|
|
||||||
use super::{WasmState, wasm_engine};
|
use super::{WasmState, wasm_engine};
|
||||||
use anyhow::{Context as _, Result, anyhow};
|
use anyhow::{Context as _, Result, anyhow};
|
||||||
use semantic_version::SemanticVersion;
|
use semantic_version::SemanticVersion;
|
||||||
use std::{ops::RangeInclusive, sync::Arc};
|
use since_v0_6_0 as latest;
|
||||||
|
use std::{ops::RangeInclusive, path::PathBuf, sync::Arc};
|
||||||
use wasmtime::{
|
use wasmtime::{
|
||||||
Store,
|
Store,
|
||||||
component::{Component, Linker, Resource},
|
component::{Component, Linker, Resource},
|
||||||
|
@ -25,7 +25,7 @@ use wasmtime::{
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub use latest::CodeLabelSpanLiteral;
|
pub use latest::CodeLabelSpanLiteral;
|
||||||
pub use latest::{
|
pub use latest::{
|
||||||
CodeLabel, CodeLabelSpan, Command, ExtensionProject, Range, SlashCommand,
|
CodeLabel, CodeLabelSpan, Command, DebugAdapterBinary, ExtensionProject, Range, SlashCommand,
|
||||||
zed::extension::context_server::ContextServerConfiguration,
|
zed::extension::context_server::ContextServerConfiguration,
|
||||||
zed::extension::lsp::{
|
zed::extension::lsp::{
|
||||||
Completion, CompletionKind, CompletionLabelDetails, InsertTextFormat, Symbol, SymbolKind,
|
Completion, CompletionKind, CompletionLabelDetails, InsertTextFormat, Symbol, SymbolKind,
|
||||||
|
@ -897,6 +897,30 @@ impl Extension {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub async fn call_get_dap_binary(
|
||||||
|
&self,
|
||||||
|
store: &mut Store<WasmState>,
|
||||||
|
adapter_name: Arc<str>,
|
||||||
|
task: DebugTaskDefinition,
|
||||||
|
user_installed_path: Option<PathBuf>,
|
||||||
|
) -> Result<Result<DebugAdapterBinary, String>> {
|
||||||
|
match self {
|
||||||
|
Extension::V0_6_0(ext) => {
|
||||||
|
let dap_binary = ext
|
||||||
|
.call_get_dap_binary(
|
||||||
|
store,
|
||||||
|
&adapter_name,
|
||||||
|
&task.try_into()?,
|
||||||
|
user_installed_path.as_ref().and_then(|p| p.to_str()),
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.map_err(|e| anyhow!("{e:?}"))?;
|
||||||
|
|
||||||
|
Ok(Ok(dap_binary))
|
||||||
|
}
|
||||||
|
_ => Err(anyhow!("`get_dap_binary` not available prior to v0.6.0")),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ToWasmtimeResult<T> {
|
trait ToWasmtimeResult<T> {
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
use crate::wasm_host::wit::since_v0_6_0::slash_command::SlashCommandOutputSection;
|
use crate::wasm_host::wit::since_v0_6_0::{
|
||||||
|
dap::{
|
||||||
|
AttachRequest, DebugRequest, LaunchRequest, StartDebuggingRequestArguments,
|
||||||
|
StartDebuggingRequestArgumentsRequest, TcpArguments, TcpArgumentsTemplate,
|
||||||
|
},
|
||||||
|
slash_command::SlashCommandOutputSection,
|
||||||
|
};
|
||||||
use crate::wasm_host::wit::{CompletionKind, CompletionLabelDetails, InsertTextFormat, SymbolKind};
|
use crate::wasm_host::wit::{CompletionKind, CompletionLabelDetails, InsertTextFormat, SymbolKind};
|
||||||
use crate::wasm_host::{WasmState, wit::ToWasmtimeResult};
|
use crate::wasm_host::{WasmState, wit::ToWasmtimeResult};
|
||||||
use ::http_client::{AsyncBody, HttpRequestExt};
|
use ::http_client::{AsyncBody, HttpRequestExt};
|
||||||
|
@ -17,6 +23,7 @@ use project::project_settings::ProjectSettings;
|
||||||
use semantic_version::SemanticVersion;
|
use semantic_version::SemanticVersion;
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
|
net::Ipv4Addr,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{Arc, OnceLock},
|
sync::{Arc, OnceLock},
|
||||||
};
|
};
|
||||||
|
@ -72,6 +79,101 @@ impl From<Command> for extension::Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<extension::LaunchRequest> for LaunchRequest {
|
||||||
|
fn from(value: extension::LaunchRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
program: value.program,
|
||||||
|
cwd: value.cwd.map(|path| path.to_string_lossy().into_owned()),
|
||||||
|
envs: value.env.into_iter().collect(),
|
||||||
|
args: value.args,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<StartDebuggingRequestArgumentsRequest>
|
||||||
|
for extension::StartDebuggingRequestArgumentsRequest
|
||||||
|
{
|
||||||
|
fn from(value: StartDebuggingRequestArgumentsRequest) -> Self {
|
||||||
|
match value {
|
||||||
|
StartDebuggingRequestArgumentsRequest::Launch => Self::Launch,
|
||||||
|
StartDebuggingRequestArgumentsRequest::Attach => Self::Attach,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl TryFrom<StartDebuggingRequestArguments> for extension::StartDebuggingRequestArguments {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: StartDebuggingRequestArguments) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
configuration: serde_json::from_str(&value.configuration)?,
|
||||||
|
request: value.request.into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<TcpArguments> for extension::TcpArguments {
|
||||||
|
fn from(value: TcpArguments) -> Self {
|
||||||
|
Self {
|
||||||
|
host: value.host.into(),
|
||||||
|
port: value.port,
|
||||||
|
timeout: value.timeout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<extension::TcpArgumentsTemplate> for TcpArgumentsTemplate {
|
||||||
|
fn from(value: extension::TcpArgumentsTemplate) -> Self {
|
||||||
|
Self {
|
||||||
|
host: value.host.map(Ipv4Addr::to_bits),
|
||||||
|
port: value.port,
|
||||||
|
timeout: value.timeout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<extension::AttachRequest> for AttachRequest {
|
||||||
|
fn from(value: extension::AttachRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
process_id: value.process_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<extension::DebugRequest> for DebugRequest {
|
||||||
|
fn from(value: extension::DebugRequest) -> Self {
|
||||||
|
match value {
|
||||||
|
extension::DebugRequest::Launch(launch_request) => Self::Launch(launch_request.into()),
|
||||||
|
extension::DebugRequest::Attach(attach_request) => Self::Attach(attach_request.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<extension::DebugTaskDefinition> for DebugTaskDefinition {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
fn try_from(value: extension::DebugTaskDefinition) -> Result<Self, Self::Error> {
|
||||||
|
let initialize_args = value.initialize_args.map(|s| s.to_string());
|
||||||
|
Ok(Self {
|
||||||
|
label: value.label.to_string(),
|
||||||
|
adapter: value.adapter.to_string(),
|
||||||
|
request: value.request.into(),
|
||||||
|
initialize_args,
|
||||||
|
stop_on_entry: value.stop_on_entry,
|
||||||
|
tcp_connection: value.tcp_connection.map(Into::into),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<DebugAdapterBinary> for extension::DebugAdapterBinary {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
fn try_from(value: DebugAdapterBinary) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
command: value.command,
|
||||||
|
arguments: value.arguments,
|
||||||
|
envs: value.envs.into_iter().collect(),
|
||||||
|
cwd: value.cwd.map(|s| s.into()),
|
||||||
|
connection: value.connection.map(Into::into),
|
||||||
|
request_args: value.request_args.try_into()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<CodeLabel> for extension::CodeLabel {
|
impl From<CodeLabel> for extension::CodeLabel {
|
||||||
fn from(value: CodeLabel) -> Self {
|
fn from(value: CodeLabel) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -627,6 +729,9 @@ impl slash_command::Host for WasmState {}
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl context_server::Host for WasmState {}
|
impl context_server::Host for WasmState {}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl dap::Host for WasmState {}
|
||||||
|
|
||||||
impl ExtensionImports for WasmState {
|
impl ExtensionImports for WasmState {
|
||||||
async fn get_settings(
|
async fn get_settings(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -19,7 +19,6 @@ ahash = { version = "0.8", features = ["serde"] }
|
||||||
aho-corasick = { version = "1" }
|
aho-corasick = { version = "1" }
|
||||||
anstream = { version = "0.6" }
|
anstream = { version = "0.6" }
|
||||||
arrayvec = { version = "0.7", features = ["serde"] }
|
arrayvec = { version = "0.7", features = ["serde"] }
|
||||||
async-compression = { version = "0.4", default-features = false, features = ["deflate", "deflate64", "futures-io", "gzip"] }
|
|
||||||
async-std = { version = "1", features = ["attributes", "unstable"] }
|
async-std = { version = "1", features = ["attributes", "unstable"] }
|
||||||
async-tungstenite = { version = "0.29", features = ["tokio-rustls-manual-roots"] }
|
async-tungstenite = { version = "0.29", features = ["tokio-rustls-manual-roots"] }
|
||||||
aws-config = { version = "1", features = ["behavior-version-latest"] }
|
aws-config = { version = "1", features = ["behavior-version-latest"] }
|
||||||
|
@ -136,7 +135,6 @@ ahash = { version = "0.8", features = ["serde"] }
|
||||||
aho-corasick = { version = "1" }
|
aho-corasick = { version = "1" }
|
||||||
anstream = { version = "0.6" }
|
anstream = { version = "0.6" }
|
||||||
arrayvec = { version = "0.7", features = ["serde"] }
|
arrayvec = { version = "0.7", features = ["serde"] }
|
||||||
async-compression = { version = "0.4", default-features = false, features = ["deflate", "deflate64", "futures-io", "gzip"] }
|
|
||||||
async-std = { version = "1", features = ["attributes", "unstable"] }
|
async-std = { version = "1", features = ["attributes", "unstable"] }
|
||||||
async-tungstenite = { version = "0.29", features = ["tokio-rustls-manual-roots"] }
|
async-tungstenite = { version = "0.29", features = ["tokio-rustls-manual-roots"] }
|
||||||
aws-config = { version = "1", features = ["behavior-version-latest"] }
|
aws-config = { version = "1", features = ["behavior-version-latest"] }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue