1use std::sync::Arc;
2
3use anyhow::Result;
4use collections::HashMap;
5use gpui::{AppContext, AsyncAppContext, Global, Model, ReadGlobal, Task};
6use parking_lot::RwLock;
7use project::Project;
8
9use crate::ContextServer;
10
11pub type ContextServerFactory = Arc<
12 dyn Fn(Model<Project>, &AsyncAppContext) -> Task<Result<Arc<dyn ContextServer>>>
13 + Send
14 + Sync
15 + 'static,
16>;
17
18#[derive(Default)]
19struct GlobalContextServerFactoryRegistry(Arc<ContextServerFactoryRegistry>);
20
21impl Global for GlobalContextServerFactoryRegistry {}
22
23#[derive(Default)]
24struct ContextServerFactoryRegistryState {
25 context_servers: HashMap<Arc<str>, ContextServerFactory>,
26}
27
28#[derive(Default)]
29pub struct ContextServerFactoryRegistry {
30 state: RwLock<ContextServerFactoryRegistryState>,
31}
32
33impl ContextServerFactoryRegistry {
34 /// Returns the global [`ContextServerFactoryRegistry`].
35 pub fn global(cx: &AppContext) -> Arc<Self> {
36 GlobalContextServerFactoryRegistry::global(cx).0.clone()
37 }
38
39 /// Returns the global [`ContextServerFactoryRegistry`].
40 ///
41 /// Inserts a default [`ContextServerFactoryRegistry`] if one does not yet exist.
42 pub fn default_global(cx: &mut AppContext) -> Arc<Self> {
43 cx.default_global::<GlobalContextServerFactoryRegistry>()
44 .0
45 .clone()
46 }
47
48 pub fn new() -> Arc<Self> {
49 Arc::new(Self {
50 state: RwLock::new(ContextServerFactoryRegistryState {
51 context_servers: HashMap::default(),
52 }),
53 })
54 }
55
56 pub fn context_server_factories(&self) -> Vec<(Arc<str>, ContextServerFactory)> {
57 self.state
58 .read()
59 .context_servers
60 .iter()
61 .map(|(id, factory)| (id.clone(), factory.clone()))
62 .collect()
63 }
64
65 /// Registers the provided [`ContextServerFactory`].
66 pub fn register_server_factory(&self, id: Arc<str>, factory: ContextServerFactory) {
67 let mut state = self.state.write();
68 state.context_servers.insert(id, factory);
69 }
70
71 /// Unregisters the [`ContextServerFactory`] for the server with the given ID.
72 pub fn unregister_server_factory_by_id(&self, server_id: &str) {
73 let mut state = self.state.write();
74 state.context_servers.remove(server_id);
75 }
76}