Debugger: Add pretty printers for Cargo-located tasks (#27979)

Piotr Osiewicz created

Closes #ISSUE

Release Notes:

- N/A

Change summary

crates/project/src/debugger/dap_store.rs              |  9 ++
crates/project/src/debugger/locator_store/cargo.rs    | 36 ++++++++++++
crates/project/src/debugger/locator_store/locators.rs |  2 
3 files changed, 43 insertions(+), 4 deletions(-)

Detailed changes

crates/project/src/debugger/dap_store.rs 🔗

@@ -358,7 +358,14 @@ impl DapStore {
 
         let task = cx.spawn(async move |this, cx| {
             if config.locator.is_some() {
-                locator_store.resolve_debug_config(&mut config).await?;
+                config = cx
+                    .background_spawn(async move {
+                        locator_store
+                            .resolve_debug_config(&mut config)
+                            .await
+                            .map(|_| config)
+                    })
+                    .await?;
             }
 
             let start_client_task = this.update(cx, |this, cx| {

crates/project/src/debugger/locator_store/cargo.rs 🔗

@@ -2,13 +2,14 @@ use super::DapLocator;
 use anyhow::{Result, anyhow};
 use async_trait::async_trait;
 use dap::DebugAdapterConfig;
-use serde_json::Value;
+use serde_json::{Value, json};
 use smol::{
     io::AsyncReadExt,
     process::{Command, Stdio},
 };
+use util::maybe;
 
-pub(super) struct CargoLocator {}
+pub(super) struct CargoLocator;
 
 #[async_trait]
 impl DapLocator for CargoLocator {
@@ -79,6 +80,37 @@ impl DapLocator for CargoLocator {
             }
         }
 
+        if debug_config.adapter == "LLDB" && debug_config.initialize_args.is_none() {
+            // Find Rust pretty-printers in current toolchain's sysroot
+            let cwd = launch_config.cwd.clone();
+            debug_config.initialize_args = maybe!(async move {
+                let cwd = cwd?;
+
+                let output = Command::new("rustc")
+                    .arg("--print")
+                    .arg("sysroot")
+                    .current_dir(cwd)
+                    .output()
+                    .await
+                    .ok()?;
+
+                if !output.status.success() {
+                    return None;
+                }
+
+                let sysroot_path = String::from_utf8(output.stdout).ok()?;
+                let sysroot_path = sysroot_path.trim_end();
+                let first_command = format!(
+                    r#"command script import "{sysroot_path}/lib/rustlib/etc/lldb_lookup.py"#
+                );
+                let second_command =
+                    format!(r#"command source -s 0 '{sysroot_path}/lib/rustlib/etc/lldb_commands"#);
+
+                Some(json!({"initCommands": [first_command, second_command]}))
+            })
+            .await;
+        }
+
         launch_config.args.clear();
         if let Some(test_name) = test_name {
             launch_config.args.push(test_name);

crates/project/src/debugger/locator_store/locators.rs 🔗

@@ -3,6 +3,6 @@ use async_trait::async_trait;
 use dap::DebugAdapterConfig;
 
 #[async_trait]
-pub(super) trait DapLocator {
+pub(super) trait DapLocator: Send + Sync {
     async fn run_locator(&self, debug_config: &mut DebugAdapterConfig) -> Result<()>;
 }