extension_registration_hooks.rs

  1use std::{path::PathBuf, sync::Arc};
  2
  3use anyhow::Result;
  4use assistant_slash_command::SlashCommandRegistry;
  5use context_servers::ContextServerFactoryRegistry;
  6use extension_host::{extension_lsp_adapter::ExtensionLspAdapter, wasm_host};
  7use fs::Fs;
  8use gpui::{AppContext, BackgroundExecutor, Task};
  9use indexed_docs::{IndexedDocsRegistry, ProviderId};
 10use language::{LanguageRegistry, LanguageServerBinaryStatus, LoadedLanguage};
 11use snippet_provider::SnippetRegistry;
 12use theme::{ThemeRegistry, ThemeSettings};
 13use ui::SharedString;
 14
 15use crate::extension_context_server::ExtensionContextServer;
 16use crate::{extension_indexed_docs_provider, extension_slash_command::ExtensionSlashCommand};
 17
 18pub struct ConcreteExtensionRegistrationHooks {
 19    slash_command_registry: Arc<SlashCommandRegistry>,
 20    theme_registry: Arc<ThemeRegistry>,
 21    indexed_docs_registry: Arc<IndexedDocsRegistry>,
 22    snippet_registry: Arc<SnippetRegistry>,
 23    language_registry: Arc<LanguageRegistry>,
 24    context_server_factory_registry: Arc<ContextServerFactoryRegistry>,
 25    executor: BackgroundExecutor,
 26}
 27
 28impl ConcreteExtensionRegistrationHooks {
 29    pub fn new(
 30        theme_registry: Arc<ThemeRegistry>,
 31        slash_command_registry: Arc<SlashCommandRegistry>,
 32        indexed_docs_registry: Arc<IndexedDocsRegistry>,
 33        snippet_registry: Arc<SnippetRegistry>,
 34        language_registry: Arc<LanguageRegistry>,
 35        context_server_factory_registry: Arc<ContextServerFactoryRegistry>,
 36        cx: &AppContext,
 37    ) -> Arc<dyn extension_host::ExtensionRegistrationHooks> {
 38        Arc::new(Self {
 39            theme_registry,
 40            slash_command_registry,
 41            indexed_docs_registry,
 42            snippet_registry,
 43            language_registry,
 44            context_server_factory_registry,
 45            executor: cx.background_executor().clone(),
 46        })
 47    }
 48}
 49
 50impl extension_host::ExtensionRegistrationHooks for ConcreteExtensionRegistrationHooks {
 51    fn remove_user_themes(&self, themes: Vec<SharedString>) {
 52        self.theme_registry.remove_user_themes(&themes);
 53    }
 54
 55    fn load_user_theme(&self, theme_path: PathBuf, fs: Arc<dyn fs::Fs>) -> Task<Result<()>> {
 56        let theme_registry = self.theme_registry.clone();
 57        self.executor
 58            .spawn(async move { theme_registry.load_user_theme(&theme_path, fs).await })
 59    }
 60
 61    fn register_slash_command(
 62        &self,
 63        command: wasm_host::SlashCommand,
 64        extension: wasm_host::WasmExtension,
 65        host: Arc<wasm_host::WasmHost>,
 66    ) {
 67        self.slash_command_registry.register_command(
 68            ExtensionSlashCommand {
 69                command,
 70                extension,
 71                host,
 72            },
 73            false,
 74        )
 75    }
 76
 77    fn register_context_server(
 78        &self,
 79        id: Arc<str>,
 80        extension: wasm_host::WasmExtension,
 81        host: Arc<wasm_host::WasmHost>,
 82    ) {
 83        self.context_server_factory_registry
 84            .register_server_factory(
 85                id.clone(),
 86                Arc::new({
 87                    move |cx| {
 88                        let id = id.clone();
 89                        let extension = extension.clone();
 90                        let host = host.clone();
 91                        cx.spawn(|_cx| async move {
 92                            let context_server =
 93                                ExtensionContextServer::new(extension, host, id).await?;
 94
 95                            anyhow::Ok(Arc::new(context_server) as _)
 96                        })
 97                    }
 98                }),
 99            );
100    }
101
102    fn register_docs_provider(
103        &self,
104        extension: wasm_host::WasmExtension,
105        host: Arc<wasm_host::WasmHost>,
106        provider_id: Arc<str>,
107    ) {
108        self.indexed_docs_registry.register_provider(Box::new(
109            extension_indexed_docs_provider::ExtensionIndexedDocsProvider {
110                extension,
111                host,
112                id: ProviderId(provider_id),
113            },
114        ));
115    }
116
117    fn register_snippets(&self, path: &PathBuf, snippet_contents: &str) -> Result<()> {
118        self.snippet_registry
119            .register_snippets(path, snippet_contents)
120    }
121
122    fn update_lsp_status(
123        &self,
124        server_name: lsp::LanguageServerName,
125        status: LanguageServerBinaryStatus,
126    ) {
127        self.language_registry
128            .update_lsp_status(server_name, status);
129    }
130
131    fn register_lsp_adapter(
132        &self,
133        language_name: language::LanguageName,
134        adapter: ExtensionLspAdapter,
135    ) {
136        self.language_registry
137            .register_lsp_adapter(language_name, Arc::new(adapter));
138    }
139
140    fn remove_lsp_adapter(
141        &self,
142        language_name: &language::LanguageName,
143        server_name: &lsp::LanguageServerName,
144    ) {
145        self.language_registry
146            .remove_lsp_adapter(language_name, server_name);
147    }
148
149    fn remove_languages(
150        &self,
151        languages_to_remove: &[language::LanguageName],
152        grammars_to_remove: &[Arc<str>],
153    ) {
154        self.language_registry
155            .remove_languages(&languages_to_remove, &grammars_to_remove);
156    }
157
158    fn register_wasm_grammars(&self, grammars: Vec<(Arc<str>, PathBuf)>) {
159        self.language_registry.register_wasm_grammars(grammars)
160    }
161
162    fn register_language(
163        &self,
164        language: language::LanguageName,
165        grammar: Option<Arc<str>>,
166        matcher: language::LanguageMatcher,
167        load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
168    ) {
169        self.language_registry
170            .register_language(language, grammar, matcher, load)
171    }
172
173    fn reload_current_theme(&self, cx: &mut AppContext) {
174        ThemeSettings::reload_current_theme(cx)
175    }
176
177    fn list_theme_names(&self, path: PathBuf, fs: Arc<dyn Fs>) -> Task<Result<Vec<String>>> {
178        self.executor.spawn(async move {
179            let themes = theme::read_user_theme(&path, fs).await?;
180            Ok(themes.themes.into_iter().map(|theme| theme.name).collect())
181        })
182    }
183}