1use std::borrow::Cow;
2
3use anyhow::{Result, bail};
4use async_trait::async_trait;
5use dap::{DapLocator, DebugRequest, adapters::DebugAdapterName};
6use gpui::SharedString;
7
8use task::{DebugScenario, SpawnInTerminal, TaskTemplate, VariableName};
9
10pub(crate) struct NodeLocator;
11
12const TYPESCRIPT_RUNNER_VARIABLE: VariableName =
13 VariableName::Custom(Cow::Borrowed("TYPESCRIPT_RUNNER"));
14
15#[async_trait]
16impl DapLocator for NodeLocator {
17 fn name(&self) -> SharedString {
18 SharedString::new_static("Node")
19 }
20
21 /// Determines whether this locator can generate debug target for given task.
22 async fn create_scenario(
23 &self,
24 build_config: &TaskTemplate,
25 resolved_label: &str,
26 adapter: &DebugAdapterName,
27 ) -> Option<DebugScenario> {
28 if adapter.0.as_ref() != "JavaScript" {
29 return None;
30 }
31 if build_config.command != TYPESCRIPT_RUNNER_VARIABLE.template_value()
32 && build_config.command != "npm"
33 && build_config.command != "pnpm"
34 && build_config.command != "yarn"
35 {
36 return None;
37 }
38
39 let config = serde_json::json!({
40 "request": "launch",
41 "type": "pwa-node",
42 "args": build_config.args.clone(),
43 "cwd": build_config.cwd.clone(),
44 "runtimeExecutable": build_config.command.clone(),
45 "env": build_config.env.clone(),
46 "runtimeArgs": ["--inspect-brk"],
47 "console": "integratedTerminal",
48 });
49
50 Some(DebugScenario {
51 adapter: adapter.0.clone(),
52 label: resolved_label.to_string().into(),
53 build: None,
54 config,
55 tcp_connection: None,
56 })
57 }
58
59 async fn run(&self, _: SpawnInTerminal) -> Result<DebugRequest> {
60 bail!("JavaScript locator should not require DapLocator::run to be ran");
61 }
62}