language_extension.rs

 1mod extension_lsp_adapter;
 2
 3use std::sync::{Arc, OnceLock};
 4use std::{path::PathBuf, sync::RwLock};
 5
 6use anyhow::Result;
 7use collections::FxHashMap;
 8use extension::{ExtensionGrammarProxy, ExtensionHostProxy, ExtensionLanguageProxy};
 9use gpui::{App, Entity};
10use language::{LanguageMatcher, LanguageName, LanguageRegistry, LoadedLanguage};
11use lsp::{LanguageServerId, LanguageServerName};
12use project::LspStore;
13
14#[derive(Clone)]
15pub enum LspAccess {
16    ViaLspStore(Entity<LspStore>),
17    ViaWorkspaces(Arc<dyn Fn(&mut App) -> Result<Vec<Entity<LspStore>>> + Send + Sync + 'static>),
18    Noop,
19}
20
21pub fn init(
22    lsp_access: LspAccess,
23    extension_host_proxy: Arc<ExtensionHostProxy>,
24    language_registry: Arc<LanguageRegistry>,
25) {
26    let language_server_registry_proxy = LanguageServerRegistryProxy {
27        language_registry,
28        language_server_ids: Default::default(),
29        lsp_access,
30    };
31    extension_host_proxy.register_grammar_proxy(language_server_registry_proxy.clone());
32    extension_host_proxy.register_language_proxy(language_server_registry_proxy.clone());
33    extension_host_proxy.register_language_server_proxy(language_server_registry_proxy);
34}
35
36#[derive(Clone)]
37struct LanguageServerRegistryProxy {
38    language_registry: Arc<LanguageRegistry>,
39    // extensions can only spawn one language server currently
40    language_server_ids:
41        Arc<RwLock<FxHashMap<LanguageServerName, Arc<OnceLock<LanguageServerId>>>>>,
42    lsp_access: LspAccess,
43}
44
45impl ExtensionGrammarProxy for LanguageServerRegistryProxy {
46    fn register_grammars(&self, grammars: Vec<(Arc<str>, PathBuf)>) {
47        self.language_registry.register_wasm_grammars(grammars)
48    }
49}
50
51impl ExtensionLanguageProxy for LanguageServerRegistryProxy {
52    fn register_language(
53        &self,
54        language: LanguageName,
55        grammar: Option<Arc<str>>,
56        matcher: LanguageMatcher,
57        hidden: bool,
58        load: Arc<dyn Fn() -> Result<LoadedLanguage> + Send + Sync + 'static>,
59    ) {
60        self.language_registry
61            .register_language(language, grammar, matcher, hidden, None, load);
62    }
63
64    fn remove_languages(
65        &self,
66        languages_to_remove: &[LanguageName],
67        grammars_to_remove: &[Arc<str>],
68    ) {
69        self.language_registry
70            .remove_languages(languages_to_remove, grammars_to_remove);
71    }
72}