Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T02:58:06.111Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

language_registry.rs

957 lines · 34.6 KB · rust
1use crate::available_languages::AvailableLanguage;
2use crate::{
3    CachedLspAdapter, File, Language, LanguageConfig, LanguageId, LanguageMatcher,
4    LanguageServerName, LspAdapter, ManifestName, PLAIN_TEXT, ToolchainLister,
5    available_languages::AvailableLanguages, language_settings::all_language_settings,
6    task_context::ContextProvider, with_parser,
7};
8use anyhow::{Context as _, Result, anyhow};
9use collections::{FxHashMap, HashMap, HashSet, hash_map};
10pub use language_core::{
11    BinaryStatus, LanguageName, LanguageQueries, LanguageServerStatusUpdate,
12    QUERY_FILENAME_PREFIXES, ServerHealth,
13};
14use settings::{AllLanguageSettingsContent, LanguageSettingsContent};
15
16use futures::{
17    Future,
18    channel::{mpsc, oneshot},
19};
20use globset::GlobSet;
21use gpui::{App, BackgroundExecutor};
22use lsp::LanguageServerId;
23use parking_lot::{Mutex, RwLock};
24use postage::watch;
25
26use std::{
27    ffi::OsStr,
28    path::{Path, PathBuf},
29    sync::Arc,
30};
31use text::Rope;
32use theme::Theme;
33
34use util::{maybe, post_inc};
35
36pub struct LanguageRegistry {
37    state: RwLock<LanguageRegistryState>,
38    language_server_download_dir: Option<Arc<Path>>,
39    executor: BackgroundExecutor,
40    lsp_binary_status_tx: ServerStatusSender,
41}
42
43struct LanguageRegistryState {
44    next_language_server_id: usize,
45    languages: Vec<Arc<Language>>,
46    language_settings: AllLanguageSettingsContent,
47    available_languages: AvailableLanguages,
48    grammars: HashMap<Arc<str>, AvailableGrammar>,
49    lsp_adapters: HashMap<LanguageName, Vec<Arc<CachedLspAdapter>>>,
50    all_lsp_adapters: HashMap<LanguageServerName, Arc<CachedLspAdapter>>,
51    available_lsp_adapters:
52        HashMap<LanguageServerName, Arc<dyn Fn() -> Arc<CachedLspAdapter> + 'static + Send + Sync>>,
53    loading_languages: HashMap<LanguageId, Vec<oneshot::Sender<Result<Arc<Language>>>>>,
54    subscription: (watch::Sender<()>, watch::Receiver<()>),
55    theme: Option<Arc<Theme>>,
56    version: usize,
57    reload_count: usize,
58
59    #[cfg(any(test, feature = "test-support"))]
60    fake_server_entries: HashMap<LanguageServerName, FakeLanguageServerEntry>,
61}
62
63#[cfg(any(test, feature = "test-support"))]
64pub struct FakeLanguageServerEntry {
65    pub capabilities: lsp::ServerCapabilities,
66    pub initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,
67    pub tx: futures::channel::mpsc::UnboundedSender<lsp::FakeLanguageServer>,
68    pub _server: Option<lsp::FakeLanguageServer>,
69}
70
71enum AvailableGrammar {
72    Native(tree_sitter::Language),
73    Loaded(#[allow(unused)] PathBuf, tree_sitter::Language),
74    Loading(
75        #[allow(unused)] PathBuf,
76        Vec<oneshot::Sender<Result<tree_sitter::Language, Arc<anyhow::Error>>>>,
77    ),
78    Unloaded(PathBuf),
79    LoadFailed(Arc<anyhow::Error>),
80}
81
82#[derive(Debug)]
83pub struct LanguageNotFound;
84
85impl std::fmt::Display for LanguageNotFound {
86    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87        write!(f, "language not found")
88    }
89}
90
91#[derive(Clone, Default)]
92struct ServerStatusSender {
93    txs: Arc<Mutex<Vec<mpsc::UnboundedSender<(LanguageServerName, BinaryStatus)>>>>,
94}
95
96pub struct LoadedLanguage {
97    pub config: LanguageConfig,
98    pub queries: LanguageQueries,
99    pub context_provider: Option<Arc<dyn ContextProvider>>,
100    pub toolchain_provider: Option<Arc<dyn ToolchainLister>>,
101    pub manifest_name: Option<ManifestName>,
102}
103
104impl LanguageRegistry {
105    pub fn new(executor: BackgroundExecutor) -> Self {
106        let this = Self {
107            state: RwLock::new(LanguageRegistryState {
108                next_language_server_id: 0,
109                languages: Vec::new(),
110                available_languages: AvailableLanguages::default(),
111                grammars: Default::default(),
112                language_settings: Default::default(),
113                loading_languages: Default::default(),
114                lsp_adapters: Default::default(),
115                all_lsp_adapters: Default::default(),
116                available_lsp_adapters: HashMap::default(),
117                subscription: watch::channel(),
118                theme: Default::default(),
119                version: 0,
120                reload_count: 0,
121
122                #[cfg(any(test, feature = "test-support"))]
123                fake_server_entries: Default::default(),
124            }),
125            language_server_download_dir: None,
126            lsp_binary_status_tx: Default::default(),
127            executor,
128        };
129        this.add(PLAIN_TEXT.clone());
130        this
131    }
132
133    #[cfg(any(test, feature = "test-support"))]
134    pub fn test(executor: BackgroundExecutor) -> Self {
135        let mut this = Self::new(executor);
136        this.language_server_download_dir = Some(Path::new("/the-download-dir").into());
137        this
138    }
139
140    /// Clears out all of the loaded languages and reload them from scratch.
141    pub fn reload(&self) {
142        self.state.write().reload();
143    }
144
145    /// Reorders the list of language servers for the given language.
146    ///
147    /// Uses the provided list of ordered [`CachedLspAdapters`] as the desired order.
148    ///
149    /// Any existing language servers not present in `ordered_lsp_adapters` will be
150    /// appended to the end.
151    pub fn reorder_language_servers(
152        &self,
153        language: &LanguageName,
154        ordered_lsp_adapters: Vec<Arc<CachedLspAdapter>>,
155    ) {
156        self.state
157            .write()
158            .reorder_language_servers(language, ordered_lsp_adapters);
159    }
160
161    /// Removes the specified languages and grammars from the registry.
162    pub fn remove_languages(
163        &self,
164        languages_to_remove: &[LanguageName],
165        grammars_to_remove: &[Arc<str>],
166    ) {
167        self.state
168            .write()
169            .remove_languages(languages_to_remove, grammars_to_remove)
170    }
171
172    pub fn remove_lsp_adapter(&self, language_name: &LanguageName, name: &LanguageServerName) {
173        let mut state = self.state.write();
174        if let Some(adapters) = state.lsp_adapters.get_mut(language_name) {
175            adapters.retain(|adapter| &adapter.name != name)
176        }
177        state.all_lsp_adapters.remove(name);
178        state.available_lsp_adapters.remove(name);
179
180        state.version += 1;
181        state.reload_count += 1;
182        *state.subscription.0.borrow_mut() = ();
183    }
184
185    #[cfg(any(feature = "test-support", test))]
186    pub fn register_test_language(&self, config: LanguageConfig) {
187        self.register_language(
188            config.name.clone(),
189            config.grammar.clone(),
190            config.matcher.clone(),
191            config.hidden,
192            None,
193            Arc::new(move || {
194                Ok(LoadedLanguage {
195                    config: config.clone(),
196                    queries: Default::default(),
197                    toolchain_provider: None,
198                    context_provider: None,
199                    manifest_name: None,
200                })
201            }),
202        )
203    }
204
205    /// Registers an available language server adapter.
206    ///
207    /// The language server is registered under the language server name, but
208    /// not bound to a particular language.
209    ///
210    /// When a language wants to load this particular language server, it will
211    /// invoke the `load` function.
212    pub fn register_available_lsp_adapter(
213        &self,
214        name: LanguageServerName,
215        adapter: Arc<dyn LspAdapter>,
216    ) {
217        let mut state = self.state.write();
218
219        if adapter.is_extension()
220            && let Some(existing_adapter) = state.all_lsp_adapters.get(&name)
221            && !existing_adapter.adapter.is_extension()
222        {
223            log::warn!(
224                "not registering extension-provided language server {name:?}, since a builtin language server exists with that name",
225            );
226            return;
227        }
228
229        state.available_lsp_adapters.insert(
230            name,
231            Arc::new(move || CachedLspAdapter::new(adapter.clone())),
232        );
233    }
234
235    /// Loads the language server adapter for the language server with the given name.
236    pub fn load_available_lsp_adapter(
237        &self,
238        name: &LanguageServerName,
239    ) -> Option<Arc<CachedLspAdapter>> {
240        let state = self.state.read();
241        let load_lsp_adapter = state.available_lsp_adapters.get(name)?;
242
243        Some(load_lsp_adapter())
244    }
245
246    /// Checks if a language server adapter with the given name is available to be loaded.
247    pub fn is_lsp_adapter_available(&self, name: &LanguageServerName) -> bool {
248        let state = self.state.read();
249        state.available_lsp_adapters.contains_key(name)
250    }
251
252    /// Returns the names of all available LSP adapters (registered via `register_available_lsp_adapter`).
253    /// These are adapters that are not bound to a specific language but can be enabled via settings.
254    pub fn available_lsp_adapter_names(&self) -> Vec<LanguageServerName> {
255        self.state
256            .read()
257            .available_lsp_adapters
258            .keys()
259            .cloned()
260            .collect()
261    }
262
263    pub fn register_lsp_adapter(&self, language_name: LanguageName, adapter: Arc<dyn LspAdapter>) {
264        let mut state = self.state.write();
265
266        if adapter.is_extension()
267            && let Some(existing_adapter) = state.all_lsp_adapters.get(&adapter.name())
268            && !existing_adapter.adapter.is_extension()
269        {
270            log::warn!(
271                "not registering extension-provided language server {:?} for language {language_name:?}, since a builtin language server exists with that name",
272                adapter.name(),
273            );
274            return;
275        }
276
277        let cached = CachedLspAdapter::new(adapter);
278        state
279            .lsp_adapters
280            .entry(language_name)
281            .or_default()
282            .push(cached.clone());
283        state
284            .all_lsp_adapters
285            .insert(cached.name.clone(), cached.clone());
286        state.version += 1;
287        *state.subscription.0.borrow_mut() = ();
288    }
289
290    /// Register a fake language server and adapter
291    /// The returned channel receives a new instance of the language server every time it is started
292    #[cfg(any(feature = "test-support", test))]
293    pub fn register_fake_lsp(
294        &self,
295        language_name: impl Into<LanguageName>,
296        mut adapter: crate::FakeLspAdapter,
297    ) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
298        let adapter_name = LanguageServerName(adapter.name.into());
299        let capabilities = adapter.capabilities.clone();
300        let initializer = adapter.initializer.take();
301        self.register_fake_lsp_adapter(language_name, adapter);
302        self.register_fake_lsp_server(adapter_name, capabilities, initializer)
303    }
304
305    /// Register a fake lsp adapter (without the language server)
306    #[cfg(any(feature = "test-support", test))]
307    pub fn register_fake_lsp_adapter(
308        &self,
309        language_name: impl Into<LanguageName>,
310        adapter: crate::FakeLspAdapter,
311    ) {
312        let language_name = language_name.into();
313        let mut state = self.state.write();
314        let cached_adapter = CachedLspAdapter::new(Arc::new(adapter));
315        state
316            .lsp_adapters
317            .entry(language_name)
318            .or_default()
319            .push(cached_adapter.clone());
320        state
321            .all_lsp_adapters
322            .insert(cached_adapter.name(), cached_adapter);
323        state.version += 1;
324        *state.subscription.0.borrow_mut() = ();
325    }
326
327    /// Register a fake language server (without the adapter)
328    /// The returned channel receives a new instance of the language server every time it is started
329    #[cfg(any(feature = "test-support", test))]
330    pub fn register_fake_lsp_server(
331        &self,
332        lsp_name: LanguageServerName,
333        capabilities: lsp::ServerCapabilities,
334        initializer: Option<Box<dyn Fn(&mut lsp::FakeLanguageServer) + Send + Sync>>,
335    ) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
336        let (servers_tx, servers_rx) = futures::channel::mpsc::unbounded();
337        self.state.write().fake_server_entries.insert(
338            lsp_name,
339            FakeLanguageServerEntry {
340                tx: servers_tx,
341                capabilities,
342                initializer,
343                _server: None,
344            },
345        );
346        servers_rx
347    }
348
349    #[cfg(any(feature = "test-support", test))]
350    pub fn register_fake_available_lsp_adapter(
351        &self,
352        name: impl Into<LanguageServerName>,
353        adapter: crate::FakeLspAdapter,
354    ) {
355        let name = name.into();
356        let adapter = Arc::new(adapter);
357        let mut state = self.state.write();
358        state.available_lsp_adapters.insert(
359            name,
360            Arc::new(move || CachedLspAdapter::new(adapter.clone())),
361        );
362    }
363
364    #[cfg(any(feature = "test-support", test))]
365    pub fn has_fake_lsp_server(&self, lsp_name: &LanguageServerName) -> bool {
366        self.state.read().fake_server_entries.contains_key(lsp_name)
367    }
368
369    /// Adds a language to the registry, which can be loaded if needed.
370    pub fn register_language(
371        &self,
372        name: LanguageName,
373        grammar_name: Option<Arc<str>>,
374        matcher: Arc<LanguageMatcher>,
375        hidden: bool,
376        manifest_name: Option<ManifestName>,
377        load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
378    ) {
379        let state = &mut *self.state.write();
380
381        let was_added = state.available_languages.register(
382            name,
383            grammar_name,
384            matcher,
385            hidden,
386            manifest_name,
387            load,
388        );
389        if !was_added {
390            return;
391        }
392
393        state.version += 1;
394        state.reload_count += 1;
395        *state.subscription.0.borrow_mut() = ();
396    }
397
398    /// Adds grammars to the registry. Language configurations reference a grammar by name. The
399    /// grammar controls how the source code is parsed.
400    pub fn register_native_grammars(
401        &self,
402        grammars: impl IntoIterator<Item = (impl Into<Arc<str>>, impl Into<tree_sitter::Language>)>,
403    ) {
404        self.state.write().grammars.extend(
405            grammars
406                .into_iter()
407                .map(|(name, grammar)| (name.into(), AvailableGrammar::Native(grammar.into()))),
408        );
409    }
410
411    /// Adds paths to WASM grammar files, which can be loaded if needed.
412    pub fn register_wasm_grammars(&self, grammars: Vec<(Arc<str>, PathBuf)>) {
413        if grammars.is_empty() {
414            return;
415        }
416
417        let mut state = self.state.write();
418        state.grammars.extend(
419            grammars
420                .into_iter()
421                .map(|(name, path)| (name, AvailableGrammar::Unloaded(path))),
422        );
423        state.version += 1;
424        state.reload_count += 1;
425        *state.subscription.0.borrow_mut() = ();
426    }
427
428    pub fn language_settings(&self) -> AllLanguageSettingsContent {
429        self.state.read().language_settings.clone()
430    }
431
432    pub fn language_names(&self) -> Vec<LanguageName> {
433        let state = self.state.read();
434        let mut result = state.available_languages.unloaded_language_names();
435        result.extend(
436            state
437                .languages
438                .iter()
439                .map(|language| language.config.name.clone()),
440        );
441        result.sort_unstable_by_key(|language_name| language_name.as_ref().to_lowercase());
442        result
443    }
444
445    pub fn grammar_names(&self) -> Vec<Arc<str>> {
446        let state = self.state.read();
447        let mut result = state.grammars.keys().cloned().collect::<Vec<_>>();
448        result.sort_unstable_by_key(|grammar_name| grammar_name.to_lowercase());
449        result
450    }
451
452    /// Add a pre-loaded language to the registry.
453    pub fn add(&self, language: Arc<Language>) {
454        let mut state = self.state.write();
455        state.available_languages.add(AvailableLanguage {
456            id: language.id,
457            name: language.name(),
458            grammar: language.config.grammar.clone(),
459            matcher: language.config.matcher.clone(),
460            hidden: language.config.hidden,
461            manifest_name: None,
462            load: Arc::new(|| Err(anyhow!("already loaded"))),
463            loaded: true,
464        });
465        state.add(language);
466    }
467
468    pub fn subscribe(&self) -> watch::Receiver<()> {
469        self.state.read().subscription.1.clone()
470    }
471
472    /// Returns the number of times that the registry has been changed,
473    /// by adding languages or reloading.
474    pub fn version(&self) -> usize {
475        self.state.read().version
476    }
477
478    /// Returns the number of times that the registry has been reloaded.
479    pub fn reload_count(&self) -> usize {
480        self.state.read().reload_count
481    }
482
483    pub fn set_theme(&self, theme: Arc<Theme>) {
484        let mut state = self.state.write();
485        state.theme = Some(theme.clone());
486        for language in &state.languages {
487            language.set_theme(theme.syntax());
488        }
489    }
490
491    pub fn set_language_server_download_dir(&mut self, path: impl Into<Arc<Path>>) {
492        self.language_server_download_dir = Some(path.into());
493    }
494
495    pub fn language_for_name(
496        self: &Arc<Self>,
497        name: &str,
498    ) -> impl Future<Output = Result<Arc<Language>>> + use<> {
499        let language_id = self.state.read().available_languages.find_by_name(name);
500        let rx = self.get_or_load_language(language_id);
501        async move { rx.await? }
502    }
503
504    #[cfg(any(test, feature = "test-support"))]
505    pub fn language_name_for_id(&self, id: LanguageId) -> Option<LanguageName> {
506        self.state.read().available_languages.name_for_id(id)
507    }
508
509    pub fn language_name_for_extension(self: &Arc<Self>, extension: &str) -> Option<LanguageName> {
510        self.state
511            .try_read()
512            .and_then(|state| state.available_languages.find_name_by_extension(extension))
513    }
514
515    pub fn language_for_name_or_extension(
516        self: &Arc<Self>,
517        string: &str,
518    ) -> impl Future<Output = Result<Arc<Language>>> {
519        let language_id = self
520            .state
521            .read()
522            .available_languages
523            .find_by_name_or_extension(string);
524        let rx = self.get_or_load_language(language_id);
525        async move { rx.await? }
526    }
527
528    pub fn available_language_for_name(self: &Arc<Self>, name: &str) -> Option<AvailableLanguage> {
529        let state = self.state.read();
530        state.available_languages.find_by_exact_name(name)
531    }
532
533    /// Look up a language by its modeline name (vim filetype or emacs mode).
534    ///
535    /// This performs a case-insensitive match against:
536    /// 1. Explicit modeline aliases defined in the language config
537    /// 2. The language's grammar name
538    /// 3. The language name itself
539    pub fn available_language_for_modeline_name(
540        self: &Arc<Self>,
541        modeline_name: &str,
542    ) -> Option<AvailableLanguage> {
543        self.state
544            .read()
545            .available_languages
546            .find_by_modeline_name(modeline_name)
547    }
548
549    pub fn language_for_file(
550        self: &Arc<Self>,
551        file: &Arc<dyn File>,
552        content: Option<&Rope>,
553        cx: &App,
554    ) -> Option<LanguageId> {
555        let user_file_types = all_language_settings(Some(file), cx);
556
557        self.language_for_file_internal(
558            &file.full_path(cx),
559            content,
560            Some(&user_file_types.file_types),
561        )
562    }
563
564    pub fn language_for_file_path(self: &Arc<Self>, path: &Path) -> Option<LanguageId> {
565        self.language_for_file_internal(path, None, None)
566    }
567
568    #[ztracing::instrument(skip_all)]
569    pub fn load_language_for_file_path<'a>(
570        self: &Arc<Self>,
571        path: &'a Path,
572    ) -> impl Future<Output = Result<Arc<Language>>> + 'a {
573        let language = self.language_for_file_path(path);
574
575        let this = self.clone();
576        async move {
577            if let Some(language_id) = language {
578                this.load_language(language_id).await?
579            } else {
580                Err(anyhow!(LanguageNotFound))
581            }
582        }
583    }
584
585    fn language_for_file_internal(
586        self: &Arc<Self>,
587        path: &Path,
588        content: Option<&Rope>,
589        user_file_types: Option<&FxHashMap<Arc<str>, (GlobSet, Vec<String>)>>,
590    ) -> Option<LanguageId> {
591        self.state
592            .read()
593            .available_languages
594            .find_for_file(path, content, user_file_types)
595    }
596
597    #[ztracing::instrument(skip_all)]
598    pub fn load_language(
599        self: &Arc<Self>,
600        language_id: LanguageId,
601    ) -> oneshot::Receiver<Result<Arc<Language>>> {
602        let (tx, rx) = oneshot::channel();
603
604        let mut state = self.state.write();
605
606        // If the language is already loaded, resolve with it immediately.
607        for loaded_language in state.languages.iter() {
608            if loaded_language.id == language_id {
609                tx.send(Ok(loaded_language.clone())).unwrap();
610                return rx;
611            }
612        }
613
614        let Some(available_language) = state.available_languages.get_language(language_id) else {
615            tx.send(Err(anyhow!(LanguageNotFound))).ok();
616            return rx;
617        };
618
619        let (language_name, language_load) = (
620            available_language.name.clone(),
621            available_language.load.clone(),
622        );
623
624        match state.loading_languages.entry(language_id) {
625            // If the language is already being loaded, then add this
626            // channel to a list that will be sent to when the load completes.
627            hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(tx),
628
629            // Otherwise, start loading the language.
630            hash_map::Entry::Vacant(entry) => {
631                let this = self.clone();
632
633                self.executor
634                    .spawn(async move {
635                        let language = async {
636                            let loaded_language = (language_load)()?;
637                            if let Some(grammar) = loaded_language.config.grammar.clone() {
638                                let grammar = Some(this.get_or_load_grammar(grammar).await?);
639
640                                Language::new_with_id(language_id, loaded_language.config, grammar)
641                                    .with_context_provider(loaded_language.context_provider)
642                                    .with_toolchain_lister(loaded_language.toolchain_provider)
643                                    .with_manifest(loaded_language.manifest_name)
644                                    .with_queries(loaded_language.queries)
645                            } else {
646                                Ok(
647                                    Language::new_with_id(
648                                        language_id,
649                                        loaded_language.config,
650                                        None,
651                                    )
652                                    .with_context_provider(loaded_language.context_provider)
653                                    .with_manifest(loaded_language.manifest_name)
654                                    .with_toolchain_lister(loaded_language.toolchain_provider),
655                                )
656                            }
657                        }
658                        .await;
659
660                        match language {
661                            Ok(language) => {
662                                let language = Arc::new(language);
663                                let mut state = this.state.write();
664
665                                state.add(language.clone());
666                                state.mark_language_loaded(language_id);
667                                if let Some(mut txs) = state.loading_languages.remove(&language_id)
668                                {
669                                    for tx in txs.drain(..) {
670                                        let _ = tx.send(Ok(language.clone()));
671                                    }
672                                }
673                            }
674                            Err(e) => {
675                                log::error!("failed to load language {language_name}:\n{e:?}");
676                                let mut state = this.state.write();
677                                state.mark_language_loaded(language_id);
678                                if let Some(mut txs) = state.loading_languages.remove(&language_id)
679                                {
680                                    for tx in txs.drain(..) {
681                                        let _ = tx.send(Err(anyhow!(
682                                            "failed to load language {language_name}: {e}",
683                                        )));
684                                    }
685                                }
686                            }
687                        };
688                    })
689                    .detach();
690
691                entry.insert(vec![tx]);
692            }
693        }
694
695        drop(state);
696        rx
697    }
698
699    #[ztracing::instrument(skip_all)]
700    fn get_or_load_language(
701        self: &Arc<Self>,
702        language_id: Option<LanguageId>,
703    ) -> oneshot::Receiver<Result<Arc<Language>>> {
704        let Some(language_id) = language_id else {
705            let (tx, rx) = oneshot::channel();
706            let _ = tx.send(Err(anyhow!(LanguageNotFound)));
707            return rx;
708        };
709
710        self.load_language(language_id)
711    }
712
713    fn get_or_load_grammar(
714        self: &Arc<Self>,
715        name: Arc<str>,
716    ) -> impl Future<Output = Result<tree_sitter::Language>> {
717        let span = ztracing::debug_span!("get_or_load_grammar", name = &*name.clone());
718        let _enter = span.enter();
719        let (tx, rx) = oneshot::channel();
720        let mut state = self.state.write();
721
722        if let Some(grammar) = state.grammars.get_mut(name.as_ref()) {
723            match grammar {
724                AvailableGrammar::LoadFailed(error) => {
725                    tx.send(Err(error.clone())).ok();
726                }
727                AvailableGrammar::Native(grammar) | AvailableGrammar::Loaded(_, grammar) => {
728                    tx.send(Ok(grammar.clone())).ok();
729                }
730                AvailableGrammar::Loading(_, txs) => {
731                    txs.push(tx);
732                }
733                AvailableGrammar::Unloaded(wasm_path) => {
734                    log::trace!("start loading grammar {name:?}");
735                    let this = self.clone();
736                    let wasm_path = wasm_path.clone();
737                    *grammar = AvailableGrammar::Loading(wasm_path.clone(), vec![tx]);
738                    self.executor
739                        .spawn(async move {
740                            let grammar_result = maybe!({
741                                let wasm_bytes = std::fs::read(&wasm_path)?;
742                                let grammar_name = wasm_path
743                                    .file_stem()
744                                    .and_then(OsStr::to_str)
745                                    .context("invalid grammar filename")?;
746                                anyhow::Ok(with_parser(|parser| {
747                                    let mut store = parser.take_wasm_store().unwrap();
748                                    let grammar = store.load_language(grammar_name, &wasm_bytes);
749                                    parser.set_wasm_store(store).unwrap();
750                                    grammar
751                                })?)
752                            })
753                            .map_err(Arc::new);
754
755                            let value = match &grammar_result {
756                                Ok(grammar) => AvailableGrammar::Loaded(wasm_path, grammar.clone()),
757                                Err(error) => AvailableGrammar::LoadFailed(error.clone()),
758                            };
759
760                            log::trace!("finish loading grammar {name:?}");
761                            let old_value = this.state.write().grammars.insert(name, value);
762                            if let Some(AvailableGrammar::Loading(_, txs)) = old_value {
763                                for tx in txs {
764                                    tx.send(grammar_result.clone()).ok();
765                                }
766                            }
767                        })
768                        .detach();
769                }
770            }
771        } else {
772            tx.send(Err(Arc::new(anyhow!("no such grammar {name}"))))
773                .ok();
774        }
775
776        async move { rx.await?.map_err(|e| anyhow!(e)) }
777    }
778
779    pub fn to_vec(&self) -> Vec<Arc<Language>> {
780        self.state.read().languages.to_vec()
781    }
782
783    pub fn lsp_adapters(&self, language_name: &LanguageName) -> Vec<Arc<CachedLspAdapter>> {
784        self.state
785            .read()
786            .lsp_adapters
787            .get(language_name)
788            .cloned()
789            .unwrap_or_default()
790    }
791
792    pub fn all_lsp_adapters(&self) -> Vec<Arc<CachedLspAdapter>> {
793        self.state
794            .read()
795            .all_lsp_adapters
796            .values()
797            .cloned()
798            .collect()
799    }
800
801    pub fn adapter_for_name(&self, name: &LanguageServerName) -> Option<Arc<CachedLspAdapter>> {
802        self.state.read().all_lsp_adapters.get(name).cloned()
803    }
804
805    pub fn update_lsp_binary_status(&self, server_name: LanguageServerName, status: BinaryStatus) {
806        self.lsp_binary_status_tx.send(server_name, status);
807    }
808
809    pub fn next_language_server_id(&self) -> LanguageServerId {
810        self.state.write().next_language_server_id()
811    }
812
813    pub fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>> {
814        self.language_server_download_dir
815            .as_ref()
816            .map(|dir| Arc::from(dir.join(name.0.as_ref())))
817    }
818
819    #[cfg(any(test, feature = "test-support"))]
820    pub fn create_fake_language_server(
821        &self,
822        server_id: LanguageServerId,
823        name: &LanguageServerName,
824        binary: lsp::LanguageServerBinary,
825        cx: &mut gpui::AsyncApp,
826    ) -> Option<lsp::LanguageServer> {
827        let mut state = self.state.write();
828        let fake_entry = state.fake_server_entries.get_mut(name)?;
829
830        let (server, mut fake_server) = lsp::FakeLanguageServer::new(
831            server_id,
832            binary,
833            name.0.to_string(),
834            fake_entry.capabilities.clone(),
835            cx,
836        );
837        fake_entry._server = Some(fake_server.clone());
838
839        if let Some(initializer) = &fake_entry.initializer {
840            initializer(&mut fake_server);
841        }
842
843        // Emit synchronously so tests can reliably observe server creation even if the LSP startup
844        // task hasn't progressed to initialization yet.
845        fake_entry.tx.unbounded_send(fake_server).ok();
846
847        Some(server)
848    }
849
850    pub fn language_server_binary_statuses(
851        &self,
852    ) -> mpsc::UnboundedReceiver<(LanguageServerName, BinaryStatus)> {
853        self.lsp_binary_status_tx.subscribe()
854    }
855}
856
857impl LanguageRegistryState {
858    fn next_language_server_id(&mut self) -> LanguageServerId {
859        LanguageServerId(post_inc(&mut self.next_language_server_id))
860    }
861
862    fn add(&mut self, language: Arc<Language>) {
863        if let Some(theme) = self.theme.as_ref() {
864            language.set_theme(theme.syntax());
865        }
866        self.language_settings.languages.0.insert(
867            language.name().0.to_string(),
868            LanguageSettingsContent {
869                tab_size: language.config.tab_size,
870                hard_tabs: language.config.hard_tabs,
871                soft_wrap: language.config.soft_wrap.map(crate::to_settings_soft_wrap),
872                auto_indent_on_paste: language.config.auto_indent_on_paste,
873                ..Default::default()
874            },
875        );
876        self.languages.push(language);
877        self.version += 1;
878        *self.subscription.0.borrow_mut() = ();
879    }
880
881    fn reload(&mut self) {
882        self.languages.clear();
883        self.version += 1;
884        self.reload_count += 1;
885        self.available_languages.mark_all_unloaded();
886        *self.subscription.0.borrow_mut() = ();
887    }
888
889    /// Reorders the list of language servers for the given language.
890    ///
891    /// Uses the provided list of ordered [`CachedLspAdapters`] as the desired order.
892    ///
893    /// Any existing language servers not present in `ordered_lsp_adapters` will be
894    /// appended to the end.
895    fn reorder_language_servers(
896        &mut self,
897        language_name: &LanguageName,
898        ordered_lsp_adapters: Vec<Arc<CachedLspAdapter>>,
899    ) {
900        let Some(lsp_adapters) = self.lsp_adapters.get_mut(language_name) else {
901            return;
902        };
903
904        let ordered_lsp_adapter_ids = ordered_lsp_adapters
905            .iter()
906            .map(|lsp_adapter| lsp_adapter.name.clone())
907            .collect::<HashSet<_>>();
908
909        let mut new_lsp_adapters = ordered_lsp_adapters;
910        for adapter in lsp_adapters.iter() {
911            if !ordered_lsp_adapter_ids.contains(&adapter.name) {
912                new_lsp_adapters.push(adapter.clone());
913            }
914        }
915
916        *lsp_adapters = new_lsp_adapters;
917    }
918
919    fn remove_languages(
920        &mut self,
921        languages_to_remove: &[LanguageName],
922        grammars_to_remove: &[Arc<str>],
923    ) {
924        if languages_to_remove.is_empty() && grammars_to_remove.is_empty() {
925            return;
926        }
927
928        self.languages
929            .retain(|language| !languages_to_remove.contains(&language.name()));
930        self.available_languages.remove(languages_to_remove);
931        self.grammars
932            .retain(|name, _| !grammars_to_remove.contains(name));
933        self.version += 1;
934        self.reload_count += 1;
935        *self.subscription.0.borrow_mut() = ();
936    }
937
938    /// Mark the given language as having been loaded, so that the
939    /// language registry won't try to load it again.
940    fn mark_language_loaded(&mut self, id: LanguageId) {
941        self.available_languages.mark_loaded(id);
942    }
943}
944
945impl ServerStatusSender {
946    fn subscribe(&self) -> mpsc::UnboundedReceiver<(LanguageServerName, BinaryStatus)> {
947        let (tx, rx) = mpsc::unbounded();
948        self.txs.lock().push(tx);
949        rx
950    }
951
952    fn send(&self, name: LanguageServerName, status: BinaryStatus) {
953        let mut txs = self.txs.lock();
954        txs.retain(|tx| tx.unbounded_send((name.clone(), status.clone())).is_ok());
955    }
956}
957
Served at tenant.openagents/omega Member data and write actions are omitted.