registry.rs

  1use anyhow::Result;
  2use async_trait::async_trait;
  3use collections::FxHashMap;
  4use gpui::{App, Global, SharedString};
  5use parking_lot::RwLock;
  6use task::{DebugRequest, DebugScenario, SpawnInTerminal, TaskTemplate};
  7
  8use crate::{
  9    adapters::{DebugAdapter, DebugAdapterName},
 10    inline_value::InlineValueProvider,
 11};
 12use std::{collections::BTreeMap, sync::Arc};
 13
 14/// Given a user build configuration, locator creates a fill-in debug target ([DebugRequest]) on behalf of the user.
 15#[async_trait]
 16pub trait DapLocator: Send + Sync {
 17    fn name(&self) -> SharedString;
 18    /// Determines whether this locator can generate debug target for given task.
 19    fn create_scenario(
 20        &self,
 21        build_config: &TaskTemplate,
 22        resolved_label: &str,
 23        adapter: DebugAdapterName,
 24    ) -> Option<DebugScenario>;
 25
 26    async fn run(&self, build_config: SpawnInTerminal) -> Result<DebugRequest>;
 27}
 28
 29#[derive(Default)]
 30struct DapRegistryState {
 31    adapters: BTreeMap<DebugAdapterName, Arc<dyn DebugAdapter>>,
 32    locators: FxHashMap<SharedString, Arc<dyn DapLocator>>,
 33    inline_value_providers: FxHashMap<String, Arc<dyn InlineValueProvider>>,
 34}
 35
 36#[derive(Clone, Default)]
 37/// Stores available debug adapters.
 38pub struct DapRegistry(Arc<RwLock<DapRegistryState>>);
 39impl Global for DapRegistry {}
 40
 41impl DapRegistry {
 42    pub fn global(cx: &mut App) -> &mut Self {
 43        let ret = cx.default_global::<Self>();
 44
 45        #[cfg(any(test, feature = "test-support"))]
 46        if ret.adapter(crate::FakeAdapter::ADAPTER_NAME).is_none() {
 47            ret.add_adapter(Arc::new(crate::FakeAdapter::new()));
 48        }
 49
 50        ret
 51    }
 52
 53    pub fn add_adapter(&self, adapter: Arc<dyn DebugAdapter>) {
 54        let name = adapter.name();
 55        let _previous_value = self.0.write().adapters.insert(name, adapter);
 56        debug_assert!(
 57            _previous_value.is_none(),
 58            "Attempted to insert a new debug adapter when one is already registered"
 59        );
 60    }
 61
 62    pub fn add_locator(&self, locator: Arc<dyn DapLocator>) {
 63        let _previous_value = self.0.write().locators.insert(locator.name(), locator);
 64        debug_assert!(
 65            _previous_value.is_none(),
 66            "Attempted to insert a new debug locator when one is already registered"
 67        );
 68    }
 69
 70    pub fn add_inline_value_provider(
 71        &self,
 72        language: String,
 73        provider: Arc<dyn InlineValueProvider>,
 74    ) {
 75        let _previous_value = self
 76            .0
 77            .write()
 78            .inline_value_providers
 79            .insert(language, provider);
 80        debug_assert!(
 81            _previous_value.is_none(),
 82            "Attempted to insert a new inline value provider when one is already registered"
 83        );
 84    }
 85
 86    pub fn locators(&self) -> FxHashMap<SharedString, Arc<dyn DapLocator>> {
 87        self.0.read().locators.clone()
 88    }
 89
 90    pub fn adapter(&self, name: &str) -> Option<Arc<dyn DebugAdapter>> {
 91        self.0.read().adapters.get(name).cloned()
 92    }
 93
 94    pub fn inline_value_provider(&self, language: &str) -> Option<Arc<dyn InlineValueProvider>> {
 95        self.0.read().inline_value_providers.get(language).cloned()
 96    }
 97
 98    pub fn enumerate_adapters(&self) -> Vec<DebugAdapterName> {
 99        self.0.read().adapters.keys().cloned().collect()
100    }
101}