debugger: Filter test executables by metadata profile in Cargo locator (#33126)
Closes #33114 Release Notes: - debugger: Ensure Cargo locator only targets relevant executables.
This commit is contained in:
parent
b7bfdd3383
commit
1d74fdc59f
1 changed files with 37 additions and 6 deletions
|
@ -4,9 +4,11 @@ use dap::{DapLocator, DebugRequest, adapters::DebugAdapterName};
|
||||||
use gpui::SharedString;
|
use gpui::SharedString;
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
use smol::{
|
use smol::{
|
||||||
|
Timer,
|
||||||
io::AsyncReadExt,
|
io::AsyncReadExt,
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
};
|
};
|
||||||
|
use std::time::Duration;
|
||||||
use task::{BuildTaskDefinition, DebugScenario, ShellBuilder, SpawnInTerminal, TaskTemplate};
|
use task::{BuildTaskDefinition, DebugScenario, ShellBuilder, SpawnInTerminal, TaskTemplate};
|
||||||
|
|
||||||
pub(crate) struct CargoLocator;
|
pub(crate) struct CargoLocator;
|
||||||
|
@ -25,14 +27,29 @@ async fn find_best_executable(executables: &[String], test_name: &str) -> Option
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let mut test_lines = String::default();
|
let mut test_lines = String::default();
|
||||||
|
let exec_result = smol::future::race(
|
||||||
|
async {
|
||||||
if let Some(mut stdout) = child.stdout.take() {
|
if let Some(mut stdout) = child.stdout.take() {
|
||||||
stdout.read_to_string(&mut test_lines).await.ok();
|
stdout.read_to_string(&mut test_lines).await?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
async {
|
||||||
|
Timer::after(Duration::from_secs(3)).await;
|
||||||
|
anyhow::bail!("Timed out waiting for executable stdout")
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(err) = exec_result.await {
|
||||||
|
log::warn!("Failed to list tests for {executable}: {err}");
|
||||||
|
} else {
|
||||||
for line in test_lines.lines() {
|
for line in test_lines.lines() {
|
||||||
if line.contains(&test_name) {
|
if line.contains(&test_name) {
|
||||||
return Some(executable.clone());
|
return Some(executable.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let _ = child.kill();
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -126,10 +143,28 @@ impl DapLocator for CargoLocator {
|
||||||
let status = child.status().await?;
|
let status = child.status().await?;
|
||||||
anyhow::ensure!(status.success(), "Cargo command failed");
|
anyhow::ensure!(status.success(), "Cargo command failed");
|
||||||
|
|
||||||
|
let is_test = build_config
|
||||||
|
.args
|
||||||
|
.first()
|
||||||
|
.map_or(false, |arg| arg == "test" || arg == "t");
|
||||||
|
|
||||||
let executables = output
|
let executables = output
|
||||||
.lines()
|
.lines()
|
||||||
.filter(|line| !line.trim().is_empty())
|
.filter(|line| !line.trim().is_empty())
|
||||||
.filter_map(|line| serde_json::from_str(line).ok())
|
.filter_map(|line| serde_json::from_str(line).ok())
|
||||||
|
.filter(|json: &Value| {
|
||||||
|
let is_test_binary = json
|
||||||
|
.get("profile")
|
||||||
|
.and_then(|profile| profile.get("test"))
|
||||||
|
.and_then(Value::as_bool)
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if is_test {
|
||||||
|
is_test_binary
|
||||||
|
} else {
|
||||||
|
!is_test_binary
|
||||||
|
}
|
||||||
|
})
|
||||||
.filter_map(|json: Value| {
|
.filter_map(|json: Value| {
|
||||||
json.get("executable")
|
json.get("executable")
|
||||||
.and_then(Value::as_str)
|
.and_then(Value::as_str)
|
||||||
|
@ -140,10 +175,6 @@ impl DapLocator for CargoLocator {
|
||||||
!executables.is_empty(),
|
!executables.is_empty(),
|
||||||
"Couldn't get executable in cargo locator"
|
"Couldn't get executable in cargo locator"
|
||||||
);
|
);
|
||||||
let is_test = build_config
|
|
||||||
.args
|
|
||||||
.first()
|
|
||||||
.map_or(false, |arg| arg == "test" || arg == "t");
|
|
||||||
|
|
||||||
let mut test_name = None;
|
let mut test_name = None;
|
||||||
if is_test {
|
if is_test {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue