debugger: Run debug scenarios from package.json (#32958)

Release Notes:

- New session modal for a debugger will now show tasks from package.json
as debuggable scenarios

---------

Co-authored-by: Remco Smits <djsmits12@gmail.com>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
This commit is contained in:
Piotr Osiewicz 2025-06-18 20:04:25 +02:00 committed by GitHub
parent 73fee01c85
commit 99215f7660
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 83 additions and 25 deletions

View file

@ -5,12 +5,14 @@ use async_trait::async_trait;
use collections::HashMap;
use dap::DapRegistry;
use futures::StreamExt;
use gpui::{App, AsyncApp};
use gpui::{App, AsyncApp, Task};
use http_client::github::{GitHubLspBinaryVersion, latest_github_release};
use language::{LanguageRegistry, LanguageToolchainStore, LspAdapter, LspAdapterDelegate};
use language::{
ContextProvider, LanguageRegistry, LanguageToolchainStore, LspAdapter, LspAdapterDelegate,
};
use lsp::{LanguageServerBinary, LanguageServerName};
use node_runtime::NodeRuntime;
use project::{ContextProviderWithTasks, Fs, lsp_store::language_server_settings};
use project::{Fs, lsp_store::language_server_settings};
use serde_json::{Value, json};
use settings::{KeymapFile, SettingsJsonSchemaParams, SettingsStore};
use smol::{
@ -36,25 +38,77 @@ const SERVER_PATH: &str =
const TSCONFIG_SCHEMA: &str = include_str!("json/schemas/tsconfig.json");
const PACKAGE_JSON_SCHEMA: &str = include_str!("json/schemas/package.json");
pub(super) fn json_task_context() -> ContextProviderWithTasks {
ContextProviderWithTasks::new(TaskTemplates(vec![
TaskTemplate {
label: "package script $ZED_CUSTOM_script".to_owned(),
command: "npm --prefix $ZED_DIRNAME run".to_owned(),
args: vec![VariableName::Custom("script".into()).template_value()],
tags: vec!["package-script".into()],
..TaskTemplate::default()
},
TaskTemplate {
label: "composer script $ZED_CUSTOM_script".to_owned(),
command: "composer -d $ZED_DIRNAME".to_owned(),
args: vec![VariableName::Custom("script".into()).template_value()],
tags: vec!["composer-script".into()],
..TaskTemplate::default()
},
]))
}
pub(crate) struct JsonTaskProvider;
impl ContextProvider for JsonTaskProvider {
fn associated_tasks(
&self,
_: Arc<dyn Fs>,
file: Option<Arc<dyn language::File>>,
cx: &App,
) -> gpui::Task<Option<TaskTemplates>> {
let Some(file) = project::File::from_dyn(file.as_ref())
.filter(|file| file.path.file_name() == Some("package.json".as_ref()))
.cloned()
else {
return Task::ready(None);
};
cx.spawn(async move |cx| {
let contents = file
.worktree
.update(cx, |this, cx| this.load_file(&file.path, cx))
.ok()?
.await
.ok()?;
let as_json = serde_json_lenient::Value::from_str(&contents.text).ok()?;
let gutter_tasks = [
TaskTemplate {
label: "package script $ZED_CUSTOM_script".to_owned(),
command: "npm".to_owned(),
args: vec![
"--prefix".into(),
"$ZED_DIRNAME".into(),
"run".into(),
VariableName::Custom("script".into()).template_value(),
],
tags: vec!["package-script".into()],
..TaskTemplate::default()
},
TaskTemplate {
label: "composer script $ZED_CUSTOM_script".to_owned(),
command: "composer".to_owned(),
args: vec![
"-d".into(),
"$ZED_DIRNAME".into(),
VariableName::Custom("script".into()).template_value(),
],
tags: vec!["composer-script".into()],
..TaskTemplate::default()
},
];
let tasks = as_json
.get("scripts")?
.as_object()?
.keys()
.map(|key| TaskTemplate {
label: format!("run {key}"),
command: "npm".to_owned(),
args: vec![
"--prefix".into(),
"$ZED_DIRNAME".into(),
"run".into(),
key.into(),
],
..TaskTemplate::default()
})
.chain(gutter_tasks)
.collect();
Some(TaskTemplates(tasks))
})
}
}
fn server_binary_arguments(server_path: &Path) -> Vec<OsString> {
vec![server_path.into(), "--stdio".into()]
}