diff --git a/Cargo.lock b/Cargo.lock index 62c65bc5a5..0cea2e3ecc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4980,6 +4980,7 @@ dependencies = [ "clap", "client", "collections", + "debug_adapter_extension", "dirs 4.0.0", "dotenv", "env_logger 0.11.8", @@ -12883,6 +12884,7 @@ dependencies = [ "clock", "dap", "dap_adapters", + "debug_adapter_extension", "env_logger 0.11.8", "extension", "extension_host", @@ -19631,6 +19633,7 @@ dependencies = [ "dap", "dap_adapters", "db", + "debug_adapter_extension", "debugger_tools", "debugger_ui", "diagnostics", diff --git a/crates/dap/src/adapters.rs b/crates/dap/src/adapters.rs index 009ddea125..30c7fe7160 100644 --- a/crates/dap/src/adapters.rs +++ b/crates/dap/src/adapters.rs @@ -32,15 +32,17 @@ pub enum DapStatus { Failed { error: String }, } -#[async_trait(?Send)] -pub trait DapDelegate { +#[async_trait] +pub trait DapDelegate: Send + Sync + 'static { fn worktree_id(&self) -> WorktreeId; + fn worktree_root_path(&self) -> &Path; fn http_client(&self) -> Arc; fn node_runtime(&self) -> NodeRuntime; fn toolchain_store(&self) -> Arc; fn fs(&self) -> Arc; fn output_to_console(&self, msg: String); - fn which(&self, command: &OsStr) -> Option; + async fn which(&self, command: &OsStr) -> Option; + async fn read_text_file(&self, path: PathBuf) -> Result; async fn shell_env(&self) -> collections::HashMap; } @@ -413,7 +415,7 @@ pub trait DebugAdapter: 'static + Send + Sync { async fn get_binary( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, config: &DebugTaskDefinition, user_installed_path: Option, cx: &mut AsyncApp, @@ -472,7 +474,7 @@ impl DebugAdapter for FakeAdapter { async fn get_binary( &self, - _: &dyn DapDelegate, + _: &Arc, config: &DebugTaskDefinition, _: Option, _: &mut AsyncApp, diff --git a/crates/dap_adapters/src/codelldb.rs b/crates/dap_adapters/src/codelldb.rs index ae1ac94ae5..88501cc57c 100644 --- a/crates/dap_adapters/src/codelldb.rs +++ b/crates/dap_adapters/src/codelldb.rs @@ -61,7 +61,7 @@ impl CodeLldbDebugAdapter { async fn fetch_latest_adapter_version( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, ) -> Result { let release = latest_github_release("vadimcn/codelldb", true, false, delegate.http_client()).await?; @@ -111,7 +111,7 @@ impl DebugAdapter for CodeLldbDebugAdapter { async fn get_binary( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, config: &DebugTaskDefinition, user_installed_path: Option, _: &mut AsyncApp, @@ -129,7 +129,7 @@ impl DebugAdapter for CodeLldbDebugAdapter { self.name(), version.clone(), adapters::DownloadedFileType::Vsix, - delegate, + delegate.as_ref(), ) .await?; let version_path = diff --git a/crates/dap_adapters/src/gdb.rs b/crates/dap_adapters/src/gdb.rs index 1d1f8a9523..803f9a8e90 100644 --- a/crates/dap_adapters/src/gdb.rs +++ b/crates/dap_adapters/src/gdb.rs @@ -65,7 +65,7 @@ impl DebugAdapter for GdbDebugAdapter { async fn get_binary( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, config: &DebugTaskDefinition, user_installed_path: Option, _: &mut AsyncApp, @@ -76,6 +76,7 @@ impl DebugAdapter for GdbDebugAdapter { let gdb_path = delegate .which(OsStr::new("gdb")) + .await .and_then(|p| p.to_str().map(|s| s.to_string())) .ok_or(anyhow!("Could not find gdb in path")); diff --git a/crates/dap_adapters/src/go.rs b/crates/dap_adapters/src/go.rs index 5cc132acd9..bd2802f17c 100644 --- a/crates/dap_adapters/src/go.rs +++ b/crates/dap_adapters/src/go.rs @@ -50,13 +50,14 @@ impl DebugAdapter for GoDebugAdapter { async fn get_binary( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, config: &DebugTaskDefinition, _user_installed_path: Option, _cx: &mut AsyncApp, ) -> Result { let delve_path = delegate .which(OsStr::new("dlv")) + .await .and_then(|p| p.to_str().map(|p| p.to_string())) .ok_or(anyhow!("Dlv not found in path"))?; diff --git a/crates/dap_adapters/src/javascript.rs b/crates/dap_adapters/src/javascript.rs index bed414b735..93783b7def 100644 --- a/crates/dap_adapters/src/javascript.rs +++ b/crates/dap_adapters/src/javascript.rs @@ -56,7 +56,7 @@ impl JsDebugAdapter { async fn fetch_latest_adapter_version( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, ) -> Result { let release = latest_github_release( &format!("{}/{}", "microsoft", Self::ADAPTER_NPM_NAME), @@ -82,7 +82,7 @@ impl JsDebugAdapter { async fn get_installed_binary( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, config: &DebugTaskDefinition, user_installed_path: Option, _: &mut AsyncApp, @@ -139,7 +139,7 @@ impl DebugAdapter for JsDebugAdapter { async fn get_binary( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, config: &DebugTaskDefinition, user_installed_path: Option, cx: &mut AsyncApp, @@ -151,7 +151,7 @@ impl DebugAdapter for JsDebugAdapter { self.name(), version, adapters::DownloadedFileType::GzipTar, - delegate, + delegate.as_ref(), ) .await?; } diff --git a/crates/dap_adapters/src/php.rs b/crates/dap_adapters/src/php.rs index 7eef069333..7788a1f9c1 100644 --- a/crates/dap_adapters/src/php.rs +++ b/crates/dap_adapters/src/php.rs @@ -40,7 +40,7 @@ impl PhpDebugAdapter { async fn fetch_latest_adapter_version( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, ) -> Result { let release = latest_github_release( &format!("{}/{}", "xdebug", Self::ADAPTER_PACKAGE_NAME), @@ -66,7 +66,7 @@ impl PhpDebugAdapter { async fn get_installed_binary( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, config: &DebugTaskDefinition, user_installed_path: Option, _: &mut AsyncApp, @@ -126,7 +126,7 @@ impl DebugAdapter for PhpDebugAdapter { async fn get_binary( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, config: &DebugTaskDefinition, user_installed_path: Option, cx: &mut AsyncApp, @@ -138,7 +138,7 @@ impl DebugAdapter for PhpDebugAdapter { self.name(), version, adapters::DownloadedFileType::Vsix, - delegate, + delegate.as_ref(), ) .await?; } diff --git a/crates/dap_adapters/src/python.rs b/crates/dap_adapters/src/python.rs index 1ea50527bd..7df0eefc47 100644 --- a/crates/dap_adapters/src/python.rs +++ b/crates/dap_adapters/src/python.rs @@ -52,26 +52,26 @@ impl PythonDebugAdapter { } async fn fetch_latest_adapter_version( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, ) -> Result { let github_repo = GithubRepo { repo_name: Self::ADAPTER_PACKAGE_NAME.into(), repo_owner: "microsoft".into(), }; - adapters::fetch_latest_adapter_version_from_github(github_repo, delegate).await + adapters::fetch_latest_adapter_version_from_github(github_repo, delegate.as_ref()).await } async fn install_binary( &self, version: AdapterVersion, - delegate: &dyn DapDelegate, + delegate: &Arc, ) -> Result<()> { let version_path = adapters::download_adapter_from_github( self.name(), version, adapters::DownloadedFileType::Zip, - delegate, + delegate.as_ref(), ) .await?; @@ -93,7 +93,7 @@ impl PythonDebugAdapter { async fn get_installed_binary( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, config: &DebugTaskDefinition, user_installed_path: Option, cx: &mut AsyncApp, @@ -128,14 +128,18 @@ impl PythonDebugAdapter { let python_path = if let Some(toolchain) = toolchain { Some(toolchain.path.to_string()) } else { - BINARY_NAMES - .iter() - .filter_map(|cmd| { - delegate - .which(OsStr::new(cmd)) - .map(|path| path.to_string_lossy().to_string()) - }) - .find(|_| true) + let mut name = None; + + for cmd in BINARY_NAMES { + name = delegate + .which(OsStr::new(cmd)) + .await + .map(|path| path.to_string_lossy().to_string()); + if name.is_some() { + break; + } + } + name }; Ok(DebugAdapterBinary { @@ -172,7 +176,7 @@ impl DebugAdapter for PythonDebugAdapter { async fn get_binary( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, config: &DebugTaskDefinition, user_installed_path: Option, cx: &mut AsyncApp, diff --git a/crates/dap_adapters/src/ruby.rs b/crates/dap_adapters/src/ruby.rs index 8483b0bdb8..62263b50e2 100644 --- a/crates/dap_adapters/src/ruby.rs +++ b/crates/dap_adapters/src/ruby.rs @@ -8,7 +8,7 @@ use dap::{ }; use gpui::{AsyncApp, SharedString}; use language::LanguageName; -use std::path::PathBuf; +use std::{path::PathBuf, sync::Arc}; use util::command::new_smol_command; use crate::ToDap; @@ -32,7 +32,7 @@ impl DebugAdapter for RubyDebugAdapter { async fn get_binary( &self, - delegate: &dyn DapDelegate, + delegate: &Arc, definition: &DebugTaskDefinition, _user_installed_path: Option, _cx: &mut AsyncApp, @@ -40,7 +40,7 @@ impl DebugAdapter for RubyDebugAdapter { let adapter_path = paths::debug_adapters_dir().join(self.name().as_ref()); let mut rdbg_path = adapter_path.join("rdbg"); if !delegate.fs().is_file(&rdbg_path).await { - match delegate.which("rdbg".as_ref()) { + match delegate.which("rdbg".as_ref()).await { Some(path) => rdbg_path = path, None => { delegate.output_to_console( @@ -76,7 +76,7 @@ impl DebugAdapter for RubyDebugAdapter { format!("--port={}", port), format!("--host={}", host), ]; - if delegate.which(launch.program.as_ref()).is_some() { + if delegate.which(launch.program.as_ref()).await.is_some() { arguments.push("--command".to_string()) } arguments.push(launch.program); diff --git a/crates/debug_adapter_extension/src/extension_dap_adapter.rs b/crates/debug_adapter_extension/src/extension_dap_adapter.rs index c9930697e0..38c09c012f 100644 --- a/crates/debug_adapter_extension/src/extension_dap_adapter.rs +++ b/crates/debug_adapter_extension/src/extension_dap_adapter.rs @@ -5,7 +5,7 @@ use async_trait::async_trait; use dap::adapters::{ DapDelegate, DebugAdapter, DebugAdapterBinary, DebugAdapterName, DebugTaskDefinition, }; -use extension::Extension; +use extension::{Extension, WorktreeDelegate}; use gpui::AsyncApp; pub(crate) struct ExtensionDapAdapter { @@ -25,6 +25,35 @@ impl ExtensionDapAdapter { } } +/// An adapter that allows an [`dap::adapters::DapDelegate`] to be used as a [`WorktreeDelegate`]. +struct WorktreeDelegateAdapter(pub Arc); + +#[async_trait] +impl WorktreeDelegate for WorktreeDelegateAdapter { + fn id(&self) -> u64 { + self.0.worktree_id().to_proto() + } + + fn root_path(&self) -> String { + self.0.worktree_root_path().to_string_lossy().to_string() + } + + async fn read_text_file(&self, path: PathBuf) -> Result { + self.0.read_text_file(path).await + } + + async fn which(&self, binary_name: String) -> Option { + self.0 + .which(binary_name.as_ref()) + .await + .map(|path| path.to_string_lossy().to_string()) + } + + async fn shell_env(&self) -> Vec<(String, String)> { + self.0.shell_env().await.into_iter().collect() + } +} + #[async_trait(?Send)] impl DebugAdapter for ExtensionDapAdapter { fn name(&self) -> DebugAdapterName { @@ -33,7 +62,7 @@ impl DebugAdapter for ExtensionDapAdapter { async fn get_binary( &self, - _: &dyn DapDelegate, + delegate: &Arc, config: &DebugTaskDefinition, user_installed_path: Option, _cx: &mut AsyncApp, @@ -43,6 +72,7 @@ impl DebugAdapter for ExtensionDapAdapter { self.debug_adapter_name.clone(), config.clone(), user_installed_path, + Arc::new(WorktreeDelegateAdapter(delegate.clone())), ) .await } diff --git a/crates/eval/Cargo.toml b/crates/eval/Cargo.toml index 2cd7290788..0a5779a66a 100644 --- a/crates/eval/Cargo.toml +++ b/crates/eval/Cargo.toml @@ -30,6 +30,7 @@ chrono.workspace = true clap.workspace = true client.workspace = true collections.workspace = true +debug_adapter_extension.workspace = true dirs.workspace = true dotenv.workspace = true env_logger.workspace = true diff --git a/crates/eval/src/eval.rs b/crates/eval/src/eval.rs index 789349116d..79d03ce23a 100644 --- a/crates/eval/src/eval.rs +++ b/crates/eval/src/eval.rs @@ -422,6 +422,7 @@ pub fn init(cx: &mut App) -> Arc { let extension_host_proxy = ExtensionHostProxy::global(cx); language::init(cx); + debug_adapter_extension::init(extension_host_proxy.clone(), cx); language_extension::init(extension_host_proxy.clone(), languages.clone()); language_model::init(client.clone(), cx); language_models::init(user_store.clone(), client.clone(), fs.clone(), cx); diff --git a/crates/extension/src/extension.rs b/crates/extension/src/extension.rs index 868acda7ae..f93571dce6 100644 --- a/crates/extension/src/extension.rs +++ b/crates/extension/src/extension.rs @@ -141,6 +141,7 @@ pub trait Extension: Send + Sync + 'static { dap_name: Arc, config: DebugTaskDefinition, user_installed_path: Option, + worktree: Arc, ) -> Result; } diff --git a/crates/extension/src/extension_manifest.rs b/crates/extension/src/extension_manifest.rs index 6ddaee98ba..1b2f3084aa 100644 --- a/crates/extension/src/extension_manifest.rs +++ b/crates/extension/src/extension_manifest.rs @@ -87,6 +87,8 @@ pub struct ExtensionManifest { pub snippets: Option, #[serde(default)] pub capabilities: Vec, + #[serde(default)] + pub debug_adapters: Vec>, } impl ExtensionManifest { @@ -274,6 +276,7 @@ fn manifest_from_old_manifest( indexed_docs_providers: BTreeMap::default(), snippets: None, capabilities: Vec::new(), + debug_adapters: vec![], } } @@ -301,6 +304,7 @@ mod tests { indexed_docs_providers: BTreeMap::default(), snippets: None, capabilities: vec![], + debug_adapters: Default::default(), } } diff --git a/crates/extension_api/src/extension_api.rs b/crates/extension_api/src/extension_api.rs index e6280baab6..be44952114 100644 --- a/crates/extension_api/src/extension_api.rs +++ b/crates/extension_api/src/extension_api.rs @@ -19,6 +19,10 @@ pub use wit::{ KeyValueStore, LanguageServerInstallationStatus, Project, Range, Worktree, download_file, make_file_executable, zed::extension::context_server::ContextServerConfiguration, + zed::extension::dap::{ + DebugAdapterBinary, DebugRequest, DebugTaskDefinition, StartDebuggingRequestArguments, + StartDebuggingRequestArgumentsRequest, TcpArguments, TcpArgumentsTemplate, + }, zed::extension::github::{ GithubRelease, GithubReleaseAsset, GithubReleaseOptions, github_release_by_tag_name, latest_github_release, @@ -194,6 +198,7 @@ pub trait Extension: Send + Sync { _adapter_name: String, _config: DebugTaskDefinition, _user_provided_path: Option, + _worktree: &Worktree, ) -> Result { Err("`get_dap_binary` not implemented".to_string()) } @@ -386,8 +391,9 @@ impl wit::Guest for Component { adapter_name: String, config: DebugTaskDefinition, user_installed_path: Option, - ) -> Result { - extension().get_dap_binary(adapter_name, config, user_installed_path) + worktree: &Worktree, + ) -> Result { + extension().get_dap_binary(adapter_name, config, user_installed_path, worktree) } } diff --git a/crates/extension_api/wit/since_v0.6.0/extension.wit b/crates/extension_api/wit/since_v0.6.0/extension.wit index b1e9558926..f0fd6f2705 100644 --- a/crates/extension_api/wit/since_v0.6.0/extension.wit +++ b/crates/extension_api/wit/since_v0.6.0/extension.wit @@ -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}; + use dap.{debug-adapter-binary, debug-task-definition, debug-request}; use lsp.{completion, symbol}; use process.{command}; use slash-command.{slash-command, slash-command-argument-completion, slash-command-output}; @@ -157,5 +157,5 @@ world extension { export index-docs: func(provider-name: string, package-name: string, database: borrow) -> 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) -> result; + export get-dap-binary: func(adapter-name: string, config: debug-task-definition, user-installed-path: option, worktree: borrow) -> result; } diff --git a/crates/extension_host/src/extension_host.rs b/crates/extension_host/src/extension_host.rs index fb96c9bec2..d09694af6a 100644 --- a/crates/extension_host/src/extension_host.rs +++ b/crates/extension_host/src/extension_host.rs @@ -14,9 +14,10 @@ use collections::{BTreeMap, BTreeSet, HashMap, HashSet, btree_map}; pub use extension::ExtensionManifest; use extension::extension_builder::{CompileExtensionOptions, ExtensionBuilder}; use extension::{ - ExtensionContextServerProxy, ExtensionEvents, ExtensionGrammarProxy, ExtensionHostProxy, - ExtensionIndexedDocsProviderProxy, ExtensionLanguageProxy, ExtensionLanguageServerProxy, - ExtensionSlashCommandProxy, ExtensionSnippetProxy, ExtensionThemeProxy, + ExtensionContextServerProxy, ExtensionDebugAdapterProviderProxy, ExtensionEvents, + ExtensionGrammarProxy, ExtensionHostProxy, ExtensionIndexedDocsProviderProxy, + ExtensionLanguageProxy, ExtensionLanguageServerProxy, ExtensionSlashCommandProxy, + ExtensionSnippetProxy, ExtensionThemeProxy, }; use fs::{Fs, RemoveOptions}; use futures::{ @@ -1328,6 +1329,11 @@ impl ExtensionStore { this.proxy .register_indexed_docs_provider(extension.clone(), provider_id.clone()); } + + for debug_adapter in &manifest.debug_adapters { + this.proxy + .register_debug_adapter(extension.clone(), debug_adapter.clone()); + } } this.wasm_extensions.extend(wasm_extensions); diff --git a/crates/extension_host/src/extension_store_test.rs b/crates/extension_host/src/extension_store_test.rs index fa6b9bd5c4..c7332b3893 100644 --- a/crates/extension_host/src/extension_store_test.rs +++ b/crates/extension_host/src/extension_store_test.rs @@ -164,6 +164,7 @@ async fn test_extension_store(cx: &mut TestAppContext) { indexed_docs_providers: BTreeMap::default(), snippets: None, capabilities: Vec::new(), + debug_adapters: Default::default(), }), dev: false, }, @@ -193,6 +194,7 @@ async fn test_extension_store(cx: &mut TestAppContext) { indexed_docs_providers: BTreeMap::default(), snippets: None, capabilities: Vec::new(), + debug_adapters: Default::default(), }), dev: false, }, @@ -367,6 +369,7 @@ async fn test_extension_store(cx: &mut TestAppContext) { indexed_docs_providers: BTreeMap::default(), snippets: None, capabilities: Vec::new(), + debug_adapters: Default::default(), }), dev: false, }, diff --git a/crates/extension_host/src/wasm_host.rs b/crates/extension_host/src/wasm_host.rs index 2727609be1..9a9a5a400e 100644 --- a/crates/extension_host/src/wasm_host.rs +++ b/crates/extension_host/src/wasm_host.rs @@ -379,11 +379,13 @@ impl extension::Extension for WasmExtension { dap_name: Arc, config: DebugTaskDefinition, user_installed_path: Option, + worktree: Arc, ) -> Result { self.call(|extension, store| { async move { + let resource = store.data_mut().table().push(worktree)?; let dap_binary = extension - .call_get_dap_binary(store, dap_name, config, user_installed_path) + .call_get_dap_binary(store, dap_name, config, user_installed_path, resource) .await? .map_err(|err| anyhow!("{err:?}"))?; let dap_binary = dap_binary.try_into()?; diff --git a/crates/extension_host/src/wasm_host/wit.rs b/crates/extension_host/src/wasm_host/wit.rs index dbe773d5e9..cc719ba6d8 100644 --- a/crates/extension_host/src/wasm_host/wit.rs +++ b/crates/extension_host/src/wasm_host/wit.rs @@ -903,6 +903,7 @@ impl Extension { adapter_name: Arc, task: DebugTaskDefinition, user_installed_path: Option, + resource: Resource>, ) -> Result> { match self { Extension::V0_6_0(ext) => { @@ -912,6 +913,7 @@ impl Extension { &adapter_name, &task.try_into()?, user_installed_path.as_ref().and_then(|p| p.to_str()), + resource, ) .await? .map_err(|e| anyhow!("{e:?}"))?; diff --git a/crates/language/src/toolchain.rs b/crates/language/src/toolchain.rs index 2937879429..fb738edb88 100644 --- a/crates/language/src/toolchain.rs +++ b/crates/language/src/toolchain.rs @@ -51,7 +51,7 @@ pub trait ToolchainLister: Send + Sync { } #[async_trait(?Send)] -pub trait LanguageToolchainStore { +pub trait LanguageToolchainStore: Send + Sync + 'static { async fn active_toolchain( self: Arc, worktree_id: WorktreeId, diff --git a/crates/project/src/debugger/dap_store.rs b/crates/project/src/debugger/dap_store.rs index 848e13a293..6ddcfbd05e 100644 --- a/crates/project/src/debugger/dap_store.rs +++ b/crates/project/src/debugger/dap_store.rs @@ -10,13 +10,15 @@ use crate::{ terminals::{SshCommand, wrap_for_ssh}, worktree_store::WorktreeStore, }; -use anyhow::{Result, anyhow}; +use anyhow::{Context as _, Result, anyhow}; use async_trait::async_trait; use collections::HashMap; use dap::{ Capabilities, CompletionItem, CompletionsArguments, DapRegistry, DebugRequest, EvaluateArguments, EvaluateArgumentsContext, EvaluateResponse, Source, StackFrameId, - adapters::{DebugAdapterBinary, DebugAdapterName, DebugTaskDefinition, TcpArguments}, + adapters::{ + DapDelegate, DebugAdapterBinary, DebugAdapterName, DebugTaskDefinition, TcpArguments, + }, client::SessionId, inline_value::VariableLookupKind, messages::Message, @@ -488,14 +490,14 @@ impl DapStore { worktree: &Entity, console: UnboundedSender, cx: &mut App, - ) -> DapAdapterDelegate { + ) -> Arc { let Some(local_store) = self.as_local() else { unimplemented!("Starting session on remote side"); }; - DapAdapterDelegate::new( + Arc::new(DapAdapterDelegate::new( local_store.fs.clone(), - worktree.read(cx).id(), + worktree.read(cx).snapshot(), console, local_store.node_runtime.clone(), local_store.http_client.clone(), @@ -503,7 +505,7 @@ impl DapStore { local_store.environment.update(cx, |env, cx| { env.get_worktree_environment(worktree.clone(), cx) }), - ) + )) } pub fn evaluate( @@ -811,7 +813,7 @@ impl DapStore { pub struct DapAdapterDelegate { fs: Arc, console: mpsc::UnboundedSender, - worktree_id: WorktreeId, + worktree: worktree::Snapshot, node_runtime: NodeRuntime, http_client: Arc, toolchain_store: Arc, @@ -821,7 +823,7 @@ pub struct DapAdapterDelegate { impl DapAdapterDelegate { pub fn new( fs: Arc, - worktree_id: WorktreeId, + worktree: worktree::Snapshot, status: mpsc::UnboundedSender, node_runtime: NodeRuntime, http_client: Arc, @@ -831,7 +833,7 @@ impl DapAdapterDelegate { Self { fs, console: status, - worktree_id, + worktree, http_client, node_runtime, toolchain_store, @@ -840,12 +842,15 @@ impl DapAdapterDelegate { } } -#[async_trait(?Send)] +#[async_trait] impl dap::adapters::DapDelegate for DapAdapterDelegate { fn worktree_id(&self) -> WorktreeId { - self.worktree_id + self.worktree.id() } + fn worktree_root_path(&self) -> &Path { + &self.worktree.abs_path() + } fn http_client(&self) -> Arc { self.http_client.clone() } @@ -862,7 +867,7 @@ impl dap::adapters::DapDelegate for DapAdapterDelegate { self.console.unbounded_send(msg).ok(); } - fn which(&self, command: &OsStr) -> Option { + async fn which(&self, command: &OsStr) -> Option { which::which(command).ok() } @@ -874,4 +879,16 @@ impl dap::adapters::DapDelegate for DapAdapterDelegate { fn toolchain_store(&self) -> Arc { self.toolchain_store.clone() } + async fn read_text_file(&self, path: PathBuf) -> Result { + let entry = self + .worktree + .entry_for_path(&path) + .with_context(|| format!("no worktree entry for path {path:?}"))?; + let abs_path = self + .worktree + .absolutize(&entry.path) + .with_context(|| format!("cannot absolutize path {path:?}"))?; + + self.fs.load(&abs_path).await + } } diff --git a/crates/remote_server/Cargo.toml b/crates/remote_server/Cargo.toml index f3c85afb28..c0ec39c067 100644 --- a/crates/remote_server/Cargo.toml +++ b/crates/remote_server/Cargo.toml @@ -30,6 +30,7 @@ chrono.workspace = true clap.workspace = true client.workspace = true dap_adapters.workspace = true +debug_adapter_extension.workspace = true env_logger.workspace = true extension.workspace = true extension_host.workspace = true diff --git a/crates/remote_server/src/headless_project.rs b/crates/remote_server/src/headless_project.rs index 08ac6fc70b..9d5836f468 100644 --- a/crates/remote_server/src/headless_project.rs +++ b/crates/remote_server/src/headless_project.rs @@ -76,6 +76,7 @@ impl HeadlessProject { }: HeadlessAppState, cx: &mut Context, ) -> Self { + debug_adapter_extension::init(proxy.clone(), cx); language_extension::init(proxy.clone(), languages.clone()); languages::init(languages.clone(), node_runtime.clone(), cx); diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 4b924876da..31920f1969 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -45,6 +45,7 @@ dap_adapters.workspace = true debugger_ui.workspace = true debugger_tools.workspace = true db.workspace = true +debug_adapter_extension.workspace = true diagnostics.workspace = true editor.workspace = true env_logger.workspace = true diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 7970c072d1..183c69358e 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -419,6 +419,7 @@ fn main() { .detach(); let node_runtime = NodeRuntime::new(client.http_client(), Some(shell_env_loaded_rx), rx); + debug_adapter_extension::init(extension_host_proxy.clone(), cx); language::init(cx); language_extension::init(extension_host_proxy.clone(), languages.clone()); languages::init(languages.clone(), node_runtime.clone(), cx);