registry.rs

 1use anyhow::Result;
 2use async_trait::async_trait;
 3use collections::FxHashMap;
 4use gpui::{App, Global, SharedString};
 5use language::LanguageName;
 6use parking_lot::RwLock;
 7use task::{DebugRequest, DebugScenario, SpawnInTerminal, TaskTemplate};
 8
 9use crate::adapters::{DebugAdapter, DebugAdapterName};
10use std::{borrow::Cow, collections::BTreeMap, sync::Arc};
11
12/// Given a user build configuration, locator creates a fill-in debug target ([DebugScenario]) on behalf of the user.
13#[async_trait]
14pub trait DapLocator: Send + Sync {
15    fn name(&self) -> SharedString;
16    /// Determines whether this locator can generate debug target for given task.
17    async fn create_scenario(
18        &self,
19        build_config: &TaskTemplate,
20        resolved_label: &str,
21        adapter: &DebugAdapterName,
22    ) -> Option<DebugScenario>;
23
24    async fn run(&self, build_config: SpawnInTerminal) -> Result<DebugRequest>;
25}
26
27#[derive(Default)]
28struct DapRegistryState {
29    adapters: BTreeMap<DebugAdapterName, Arc<dyn DebugAdapter>>,
30    locators: FxHashMap<SharedString, Arc<dyn DapLocator>>,
31}
32
33#[derive(Clone, Default)]
34/// Stores available debug adapters.
35pub struct DapRegistry(Arc<RwLock<DapRegistryState>>);
36impl Global for DapRegistry {}
37
38impl DapRegistry {
39    pub fn global(cx: &mut App) -> &mut Self {
40        cx.default_global::<Self>()
41    }
42
43    pub fn add_adapter(&self, adapter: Arc<dyn DebugAdapter>) {
44        let name = adapter.name();
45        let _previous_value = self.0.write().adapters.insert(name, adapter);
46    }
47    pub fn add_locator(&self, locator: Arc<dyn DapLocator>) {
48        self.0.write().locators.insert(locator.name(), locator);
49    }
50
51    pub fn remove_adapter(&self, name: &str) {
52        self.0.write().adapters.remove(name);
53    }
54
55    pub fn remove_locator(&self, locator: &str) {
56        self.0.write().locators.remove(locator);
57    }
58
59    pub fn adapter_language(&self, adapter_name: &str) -> Option<LanguageName> {
60        self.adapter(adapter_name)
61            .and_then(|adapter| adapter.adapter_language_name())
62    }
63
64    pub async fn adapter_schemas(&self) -> Vec<(SharedString, Cow<'static, serde_json::Value>)> {
65        self.0
66            .read()
67            .adapters
68            .iter()
69            .map(|(name, adapter)| (name.0.clone(), adapter.dap_schema()))
70            .collect()
71    }
72
73    pub fn locators(&self) -> FxHashMap<SharedString, Arc<dyn DapLocator>> {
74        self.0.read().locators.clone()
75    }
76
77    pub fn adapter(&self, name: &str) -> Option<Arc<dyn DebugAdapter>> {
78        self.0.read().adapters.get(name).cloned()
79    }
80
81    pub fn enumerate_adapters(&self) -> Vec<DebugAdapterName> {
82        self.0.read().adapters.keys().cloned().collect()
83    }
84}