@@ -42,61 +42,63 @@ pub fn init(cx: &mut App) {
}
#[cfg(test)]
-struct MockDelegate {
- worktree_root: PathBuf,
-}
+mod test_mocks {
+ use super::*;
-#[cfg(test)]
-impl MockDelegate {
- fn new() -> Arc<dyn adapters::DapDelegate> {
- Arc::new(Self {
- worktree_root: PathBuf::from("/tmp/test"),
- })
+ pub(crate) struct MockDelegate {
+ worktree_root: PathBuf,
}
-}
-#[cfg(test)]
-#[async_trait::async_trait]
-impl adapters::DapDelegate for MockDelegate {
- fn worktree_id(&self) -> settings::WorktreeId {
- settings::WorktreeId::from_usize(0)
+ impl MockDelegate {
+ pub(crate) fn new() -> Arc<dyn adapters::DapDelegate> {
+ Arc::new(Self {
+ worktree_root: PathBuf::from("/tmp/test"),
+ })
+ }
}
- fn worktree_root_path(&self) -> &std::path::Path {
- &self.worktree_root
- }
+ #[async_trait::async_trait]
+ impl adapters::DapDelegate for MockDelegate {
+ fn worktree_id(&self) -> settings::WorktreeId {
+ settings::WorktreeId::from_usize(0)
+ }
- fn http_client(&self) -> Arc<dyn http_client::HttpClient> {
- unimplemented!("Not needed for tests")
- }
+ fn worktree_root_path(&self) -> &std::path::Path {
+ &self.worktree_root
+ }
- fn node_runtime(&self) -> node_runtime::NodeRuntime {
- unimplemented!("Not needed for tests")
- }
+ fn http_client(&self) -> Arc<dyn http_client::HttpClient> {
+ unimplemented!("Not needed for tests")
+ }
- fn toolchain_store(&self) -> Arc<dyn language::LanguageToolchainStore> {
- unimplemented!("Not needed for tests")
- }
+ fn node_runtime(&self) -> node_runtime::NodeRuntime {
+ unimplemented!("Not needed for tests")
+ }
- fn fs(&self) -> Arc<dyn fs::Fs> {
- unimplemented!("Not needed for tests")
- }
+ fn toolchain_store(&self) -> Arc<dyn language::LanguageToolchainStore> {
+ unimplemented!("Not needed for tests")
+ }
- fn output_to_console(&self, _msg: String) {}
+ fn fs(&self) -> Arc<dyn fs::Fs> {
+ unimplemented!("Not needed for tests")
+ }
- async fn which(&self, _command: &std::ffi::OsStr) -> Option<PathBuf> {
- None
- }
+ fn output_to_console(&self, _msg: String) {}
- async fn read_text_file(&self, _path: &util::rel_path::RelPath) -> Result<String> {
- Ok(String::new())
- }
+ async fn which(&self, _command: &std::ffi::OsStr) -> Option<PathBuf> {
+ None
+ }
- async fn shell_env(&self) -> collections::HashMap<String, String> {
- collections::HashMap::default()
- }
+ async fn read_text_file(&self, _path: &util::rel_path::RelPath) -> Result<String> {
+ Ok(String::new())
+ }
- fn is_headless(&self) -> bool {
- false
+ async fn shell_env(&self) -> collections::HashMap<String, String> {
+ collections::HashMap::default()
+ }
+
+ fn is_headless(&self) -> bool {
+ false
+ }
}
}
@@ -824,29 +824,58 @@ impl DebugAdapter for PythonDebugAdapter {
.await;
}
- let base_path = config
- .config
- .get("cwd")
- .and_then(|cwd| {
- RelPath::new(
- cwd.as_str()
- .map(Path::new)?
- .strip_prefix(delegate.worktree_root_path())
- .ok()?,
- PathStyle::local(),
- )
- .ok()
+ let base_paths = ["cwd", "program", "module"]
+ .into_iter()
+ .filter_map(|key| {
+ config.config.get(key).and_then(|cwd| {
+ RelPath::new(
+ cwd.as_str()
+ .map(Path::new)?
+ .strip_prefix(delegate.worktree_root_path())
+ .ok()?,
+ PathStyle::local(),
+ )
+ .ok()
+ })
})
- .unwrap_or_else(|| RelPath::empty().into());
- let toolchain = delegate
- .toolchain_store()
- .active_toolchain(
- delegate.worktree_id(),
- base_path.into_arc(),
- language::LanguageName::new(Self::LANGUAGE_NAME),
- cx,
+ .chain(
+ // While Debugpy's wiki saids absolute paths are required, but it actually supports relative paths when cwd is passed in.
+ // (Which should always be the case because Zed defaults to the cwd worktree root)
+ // So we want to check that these relative paths find toolchains as well. Otherwise, they won't be checked
+ // because the strip prefix in the iteration above will return an error
+ config
+ .config
+ .get("cwd")
+ .map(|_| {
+ ["program", "module"].into_iter().filter_map(|key| {
+ config.config.get(key).and_then(|value| {
+ let path = Path::new(value.as_str()?);
+ RelPath::new(path, PathStyle::local()).ok()
+ })
+ })
+ })
+ .into_iter()
+ .flatten(),
)
- .await;
+ .chain([RelPath::empty().into()]);
+
+ let mut toolchain = None;
+
+ for base_path in base_paths {
+ if let Some(found_toolchain) = delegate
+ .toolchain_store()
+ .active_toolchain(
+ delegate.worktree_id(),
+ base_path.into_arc(),
+ language::LanguageName::new(Self::LANGUAGE_NAME),
+ cx,
+ )
+ .await
+ {
+ toolchain = Some(found_toolchain);
+ break;
+ }
+ }
self.fetch_debugpy_whl(toolchain.clone(), delegate)
.await
@@ -914,7 +943,7 @@ mod tests {
let result = adapter
.get_installed_binary(
- &MockDelegate::new(),
+ &test_mocks::MockDelegate::new(),
&task_def,
None,
None,
@@ -955,7 +984,7 @@ mod tests {
let result_host = adapter
.get_installed_binary(
- &MockDelegate::new(),
+ &test_mocks::MockDelegate::new(),
&task_def_host,
None,
None,