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