Implement basic support for VS Code debug configurations (#29160)

- [x] Basic implementation
- [x] Match common VSC debug extension names to Zed debug adapters
- [ ] ~~`preLaunchTask` support~~ descoped for this PR

Release Notes:

- N/A
This commit is contained in:
Cole Miller 2025-04-22 10:24:09 -04:00 committed by GitHub
parent 36d02de784
commit 207fb04969
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 269 additions and 46 deletions

View file

@ -4,6 +4,7 @@ mod debug_format;
mod serde_helpers;
pub mod static_source;
mod task_template;
mod vscode_debug_format;
mod vscode_format;
use collections::{HashMap, HashSet, hash_map};
@ -22,6 +23,7 @@ pub use task_template::{
DebugArgs, DebugArgsRequest, HideStrategy, RevealStrategy, TaskModal, TaskTemplate,
TaskTemplates, TaskType,
};
pub use vscode_debug_format::VsCodeDebugTaskFile;
pub use vscode_format::VsCodeTaskFile;
pub use zed_actions::RevealTarget;
@ -522,3 +524,50 @@ impl ShellBuilder {
}
}
}
type VsCodeEnvVariable = String;
type ZedEnvVariable = String;
struct EnvVariableReplacer {
variables: HashMap<VsCodeEnvVariable, ZedEnvVariable>,
}
impl EnvVariableReplacer {
fn new(variables: HashMap<VsCodeEnvVariable, ZedEnvVariable>) -> Self {
Self { variables }
}
// Replaces occurrences of VsCode-specific environment variables with Zed equivalents.
fn replace(&self, input: &str) -> String {
shellexpand::env_with_context_no_errors(&input, |var: &str| {
// Colons denote a default value in case the variable is not set. We want to preserve that default, as otherwise shellexpand will substitute it for us.
let colon_position = var.find(':').unwrap_or(var.len());
let (left, right) = var.split_at(colon_position);
if left == "env" && !right.is_empty() {
let variable_name = &right[1..];
return Some(format!("${{{variable_name}}}"));
}
let (variable_name, default) = (left, right);
let append_previous_default = |ret: &mut String| {
if !default.is_empty() {
ret.push_str(default);
}
};
if let Some(substitution) = self.variables.get(variable_name) {
// Got a VSCode->Zed hit, perform a substitution
let mut name = format!("${{{substitution}");
append_previous_default(&mut name);
name.push('}');
return Some(name);
}
// This is an unknown variable.
// We should not error out, as they may come from user environment (e.g. $PATH). That means that the variable substitution might not be perfect.
// If there's a default, we need to return the string verbatim as otherwise shellexpand will apply that default for us.
if !default.is_empty() {
return Some(format!("${{{var}}}"));
}
// Else we can just return None and that variable will be left as is.
None
})
.into_owned()
}
}