language_registry.rs

  1use crate::{
  2    CachedLspAdapter, Language, LanguageConfig, LanguageId, LanguageMatcher, LanguageServerName,
  3    LspAdapter, LspAdapterDelegate, PARSER, PLAIN_TEXT,
  4};
  5use anyhow::{anyhow, Context as _, Result};
  6use collections::{hash_map, HashMap};
  7use futures::{
  8    channel::{mpsc, oneshot},
  9    future::Shared,
 10    Future, FutureExt as _,
 11};
 12use gpui::{AppContext, BackgroundExecutor, Task};
 13use lsp::{LanguageServerBinary, LanguageServerId};
 14use parking_lot::{Mutex, RwLock};
 15use postage::watch;
 16use std::{
 17    borrow::Cow,
 18    ffi::OsStr,
 19    ops::Not,
 20    path::{Path, PathBuf},
 21    sync::Arc,
 22};
 23use sum_tree::Bias;
 24use text::{Point, Rope};
 25use theme::Theme;
 26use unicase::UniCase;
 27use util::{paths::PathExt, post_inc, ResultExt};
 28
 29pub struct LanguageRegistry {
 30    state: RwLock<LanguageRegistryState>,
 31    language_server_download_dir: Option<Arc<Path>>,
 32    login_shell_env_loaded: Shared<Task<()>>,
 33    #[allow(clippy::type_complexity)]
 34    lsp_binary_paths: Mutex<
 35        HashMap<LanguageServerName, Shared<Task<Result<LanguageServerBinary, Arc<anyhow::Error>>>>>,
 36    >,
 37    executor: Option<BackgroundExecutor>,
 38    lsp_binary_status_tx: LspBinaryStatusSender,
 39}
 40
 41struct LanguageRegistryState {
 42    next_language_server_id: usize,
 43    languages: Vec<Arc<Language>>,
 44    available_languages: Vec<AvailableLanguage>,
 45    grammars: HashMap<Arc<str>, AvailableGrammar>,
 46    lsp_adapters: HashMap<Arc<str>, Vec<Arc<CachedLspAdapter>>>,
 47    loading_languages: HashMap<LanguageId, Vec<oneshot::Sender<Result<Arc<Language>>>>>,
 48    subscription: (watch::Sender<()>, watch::Receiver<()>),
 49    theme: Option<Arc<Theme>>,
 50    version: usize,
 51    reload_count: usize,
 52
 53    #[cfg(any(test, feature = "test-support"))]
 54    fake_server_txs:
 55        HashMap<Arc<str>, Vec<futures::channel::mpsc::UnboundedSender<lsp::FakeLanguageServer>>>,
 56}
 57
 58#[derive(Clone, Debug, PartialEq, Eq)]
 59pub enum LanguageServerBinaryStatus {
 60    CheckingForUpdate,
 61    Downloading,
 62    Downloaded,
 63    Cached,
 64    Failed { error: String },
 65}
 66
 67pub struct PendingLanguageServer {
 68    pub server_id: LanguageServerId,
 69    pub task: Task<Result<lsp::LanguageServer>>,
 70    pub container_dir: Option<Arc<Path>>,
 71}
 72
 73#[derive(Clone)]
 74struct AvailableLanguage {
 75    id: LanguageId,
 76    name: Arc<str>,
 77    grammar: Option<Arc<str>>,
 78    matcher: LanguageMatcher,
 79    load: Arc<dyn Fn() -> Result<(LanguageConfig, LanguageQueries)> + 'static + Send + Sync>,
 80    loaded: bool,
 81}
 82
 83enum AvailableGrammar {
 84    Native(tree_sitter::Language),
 85    Loaded(#[allow(dead_code)] PathBuf, tree_sitter::Language),
 86    Loading(PathBuf, Vec<oneshot::Sender<Result<tree_sitter::Language>>>),
 87    Unloaded(PathBuf),
 88}
 89
 90pub const QUERY_FILENAME_PREFIXES: &[(
 91    &str,
 92    fn(&mut LanguageQueries) -> &mut Option<Cow<'static, str>>,
 93)] = &[
 94    ("highlights", |q| &mut q.highlights),
 95    ("brackets", |q| &mut q.brackets),
 96    ("outline", |q| &mut q.outline),
 97    ("indents", |q| &mut q.indents),
 98    ("embedding", |q| &mut q.embedding),
 99    ("injections", |q| &mut q.injections),
100    ("overrides", |q| &mut q.overrides),
101    ("redactions", |q| &mut q.redactions),
102];
103
104/// Tree-sitter language queries for a given language.
105#[derive(Debug, Default)]
106pub struct LanguageQueries {
107    pub highlights: Option<Cow<'static, str>>,
108    pub brackets: Option<Cow<'static, str>>,
109    pub indents: Option<Cow<'static, str>>,
110    pub outline: Option<Cow<'static, str>>,
111    pub embedding: Option<Cow<'static, str>>,
112    pub injections: Option<Cow<'static, str>>,
113    pub overrides: Option<Cow<'static, str>>,
114    pub redactions: Option<Cow<'static, str>>,
115}
116
117#[derive(Clone, Default)]
118struct LspBinaryStatusSender {
119    txs: Arc<Mutex<Vec<mpsc::UnboundedSender<(LanguageServerName, LanguageServerBinaryStatus)>>>>,
120}
121
122impl LanguageRegistry {
123    pub fn new(login_shell_env_loaded: Task<()>) -> Self {
124        Self {
125            state: RwLock::new(LanguageRegistryState {
126                next_language_server_id: 0,
127                languages: vec![PLAIN_TEXT.clone()],
128                available_languages: Default::default(),
129                grammars: Default::default(),
130                loading_languages: Default::default(),
131                lsp_adapters: Default::default(),
132                subscription: watch::channel(),
133                theme: Default::default(),
134                version: 0,
135                reload_count: 0,
136
137                #[cfg(any(test, feature = "test-support"))]
138                fake_server_txs: Default::default(),
139            }),
140            language_server_download_dir: None,
141            login_shell_env_loaded: login_shell_env_loaded.shared(),
142            lsp_binary_paths: Default::default(),
143            executor: None,
144            lsp_binary_status_tx: Default::default(),
145        }
146    }
147
148    #[cfg(any(test, feature = "test-support"))]
149    pub fn test() -> Self {
150        let mut this = Self::new(Task::ready(()));
151        this.language_server_download_dir = Some(Path::new("/the-download-dir").into());
152        this
153    }
154
155    pub fn set_executor(&mut self, executor: BackgroundExecutor) {
156        self.executor = Some(executor);
157    }
158
159    /// Clears out all of the loaded languages and reload them from scratch.
160    pub fn reload(&self) {
161        self.state.write().reload();
162    }
163
164    /// Removes the specified languages and grammars from the registry.
165    pub fn remove_languages(
166        &self,
167        languages_to_remove: &[Arc<str>],
168        grammars_to_remove: &[Arc<str>],
169    ) {
170        self.state
171            .write()
172            .remove_languages(languages_to_remove, grammars_to_remove)
173    }
174
175    pub fn remove_lsp_adapter(&self, language_name: &str, name: &LanguageServerName) {
176        let mut state = self.state.write();
177        if let Some(adapters) = state.lsp_adapters.get_mut(language_name) {
178            adapters.retain(|adapter| &adapter.name != 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            move || Ok((config.clone(), Default::default())),
192        )
193    }
194
195    pub fn register_lsp_adapter(&self, language_name: Arc<str>, adapter: Arc<dyn LspAdapter>) {
196        self.state
197            .write()
198            .lsp_adapters
199            .entry(language_name)
200            .or_default()
201            .push(CachedLspAdapter::new(adapter));
202    }
203
204    #[cfg(any(feature = "test-support", test))]
205    pub fn register_fake_lsp_adapter(
206        &self,
207        language_name: &str,
208        adapter: crate::FakeLspAdapter,
209    ) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
210        self.state
211            .write()
212            .lsp_adapters
213            .entry(language_name.into())
214            .or_default()
215            .push(CachedLspAdapter::new(Arc::new(adapter)));
216        self.fake_language_servers(language_name)
217    }
218
219    #[cfg(any(feature = "test-support", test))]
220    pub fn fake_language_servers(
221        &self,
222        language_name: &str,
223    ) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
224        let (servers_tx, servers_rx) = futures::channel::mpsc::unbounded();
225        self.state
226            .write()
227            .fake_server_txs
228            .entry(language_name.into())
229            .or_default()
230            .push(servers_tx);
231        servers_rx
232    }
233
234    /// Adds a language to the registry, which can be loaded if needed.
235    pub fn register_language(
236        &self,
237        name: Arc<str>,
238        grammar_name: Option<Arc<str>>,
239        matcher: LanguageMatcher,
240        load: impl Fn() -> Result<(LanguageConfig, LanguageQueries)> + 'static + Send + Sync,
241    ) {
242        let load = Arc::new(load);
243        let state = &mut *self.state.write();
244
245        for existing_language in &mut state.available_languages {
246            if existing_language.name == name {
247                existing_language.grammar = grammar_name;
248                existing_language.matcher = matcher;
249                existing_language.load = load;
250                return;
251            }
252        }
253
254        state.available_languages.push(AvailableLanguage {
255            id: LanguageId::new(),
256            name,
257            grammar: grammar_name,
258            matcher,
259            load,
260            loaded: false,
261        });
262        state.version += 1;
263        state.reload_count += 1;
264        *state.subscription.0.borrow_mut() = ();
265    }
266
267    /// Adds grammars to the registry. Language configurations reference a grammar by name. The
268    /// grammar controls how the source code is parsed.
269    pub fn register_native_grammars(
270        &self,
271        grammars: impl IntoIterator<Item = (impl Into<Arc<str>>, tree_sitter::Language)>,
272    ) {
273        self.state.write().grammars.extend(
274            grammars
275                .into_iter()
276                .map(|(name, grammar)| (name.into(), AvailableGrammar::Native(grammar))),
277        );
278    }
279
280    /// Adds paths to WASM grammar files, which can be loaded if needed.
281    pub fn register_wasm_grammars(
282        &self,
283        grammars: impl IntoIterator<Item = (impl Into<Arc<str>>, PathBuf)>,
284    ) {
285        let mut state = self.state.write();
286        state.grammars.extend(
287            grammars
288                .into_iter()
289                .map(|(name, path)| (name.into(), AvailableGrammar::Unloaded(path))),
290        );
291        state.version += 1;
292        state.reload_count += 1;
293        *state.subscription.0.borrow_mut() = ();
294    }
295
296    pub fn language_names(&self) -> Vec<String> {
297        let state = self.state.read();
298        let mut result = state
299            .available_languages
300            .iter()
301            .filter_map(|l| l.loaded.not().then_some(l.name.to_string()))
302            .chain(state.languages.iter().map(|l| l.config.name.to_string()))
303            .collect::<Vec<_>>();
304        result.sort_unstable_by_key(|language_name| language_name.to_lowercase());
305        result
306    }
307
308    pub fn grammar_names(&self) -> Vec<Arc<str>> {
309        let state = self.state.read();
310        let mut result = state.grammars.keys().cloned().collect::<Vec<_>>();
311        result.sort_unstable_by_key(|grammar_name| grammar_name.to_lowercase());
312        result
313    }
314
315    pub fn add(&self, language: Arc<Language>) {
316        self.state.write().add(language);
317    }
318
319    pub fn subscribe(&self) -> watch::Receiver<()> {
320        self.state.read().subscription.1.clone()
321    }
322
323    /// Returns the number of times that the registry has been changed,
324    /// by adding languages or reloading.
325    pub fn version(&self) -> usize {
326        self.state.read().version
327    }
328
329    /// Returns the number of times that the registry has been reloaded.
330    pub fn reload_count(&self) -> usize {
331        self.state.read().reload_count
332    }
333
334    pub fn set_theme(&self, theme: Arc<Theme>) {
335        let mut state = self.state.write();
336        state.theme = Some(theme.clone());
337        for language in &state.languages {
338            language.set_theme(theme.syntax());
339        }
340    }
341
342    pub fn set_language_server_download_dir(&mut self, path: impl Into<Arc<Path>>) {
343        self.language_server_download_dir = Some(path.into());
344    }
345
346    pub fn language_for_name(
347        self: &Arc<Self>,
348        name: &str,
349    ) -> impl Future<Output = Result<Arc<Language>>> {
350        let name = UniCase::new(name);
351        let rx = self.get_or_load_language(|language_name, _| UniCase::new(language_name) == name);
352        async move { rx.await? }
353    }
354
355    pub fn language_for_name_or_extension(
356        self: &Arc<Self>,
357        string: &str,
358    ) -> impl Future<Output = Result<Arc<Language>>> {
359        let string = UniCase::new(string);
360        let rx = self.get_or_load_language(|name, config| {
361            UniCase::new(name) == string
362                || config
363                    .path_suffixes
364                    .iter()
365                    .any(|suffix| UniCase::new(suffix) == string)
366        });
367        async move { rx.await? }
368    }
369
370    pub fn language_for_file(
371        self: &Arc<Self>,
372        path: &Path,
373        content: Option<&Rope>,
374    ) -> impl Future<Output = Result<Arc<Language>>> {
375        let filename = path.file_name().and_then(|name| name.to_str());
376        let extension = path.extension_or_hidden_file_name();
377        let path_suffixes = [extension, filename];
378        let rx = self.get_or_load_language(move |_, config| {
379            let path_matches = config
380                .path_suffixes
381                .iter()
382                .any(|suffix| path_suffixes.contains(&Some(suffix.as_str())));
383            let content_matches = content.zip(config.first_line_pattern.as_ref()).map_or(
384                false,
385                |(content, pattern)| {
386                    let end = content.clip_point(Point::new(0, 256), Bias::Left);
387                    let end = content.point_to_offset(end);
388                    let text = content.chunks_in_range(0..end).collect::<String>();
389                    pattern.is_match(&text)
390                },
391            );
392            path_matches || content_matches
393        });
394        async move { rx.await? }
395    }
396
397    fn get_or_load_language(
398        self: &Arc<Self>,
399        callback: impl Fn(&str, &LanguageMatcher) -> bool,
400    ) -> oneshot::Receiver<Result<Arc<Language>>> {
401        let (tx, rx) = oneshot::channel();
402
403        let mut state = self.state.write();
404        if let Some(language) = state
405            .languages
406            .iter()
407            .find(|language| callback(language.config.name.as_ref(), &language.config.matcher))
408        {
409            let _ = tx.send(Ok(language.clone()));
410        } else if let Some(executor) = self.executor.clone() {
411            if let Some(language) = state
412                .available_languages
413                .iter()
414                .rfind(|l| !l.loaded && callback(&l.name, &l.matcher))
415                .cloned()
416            {
417                match state.loading_languages.entry(language.id) {
418                    hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(tx),
419                    hash_map::Entry::Vacant(entry) => {
420                        let this = self.clone();
421                        executor
422                            .spawn(async move {
423                                let id = language.id;
424                                let name = language.name.clone();
425                                let language = async {
426                                    let (config, queries) = (language.load)()?;
427
428                                    let grammar = if let Some(grammar) = config.grammar.clone() {
429                                        Some(this.get_or_load_grammar(grammar).await?)
430                                    } else {
431                                        None
432                                    };
433
434                                    Language::new_with_id(id, config, grammar).with_queries(queries)
435                                }
436                                .await;
437
438                                match language {
439                                    Ok(language) => {
440                                        let language = Arc::new(language);
441                                        let mut state = this.state.write();
442
443                                        state.add(language.clone());
444                                        state.mark_language_loaded(id);
445                                        if let Some(mut txs) = state.loading_languages.remove(&id) {
446                                            for tx in txs.drain(..) {
447                                                let _ = tx.send(Ok(language.clone()));
448                                            }
449                                        }
450                                    }
451                                    Err(e) => {
452                                        log::error!("failed to load language {name}:\n{:?}", e);
453                                        let mut state = this.state.write();
454                                        state.mark_language_loaded(id);
455                                        if let Some(mut txs) = state.loading_languages.remove(&id) {
456                                            for tx in txs.drain(..) {
457                                                let _ = tx.send(Err(anyhow!(
458                                                    "failed to load language {}: {}",
459                                                    name,
460                                                    e
461                                                )));
462                                            }
463                                        }
464                                    }
465                                };
466                            })
467                            .detach();
468                        entry.insert(vec![tx]);
469                    }
470                }
471            } else {
472                let _ = tx.send(Err(anyhow!("language not found")));
473            }
474        } else {
475            let _ = tx.send(Err(anyhow!("executor does not exist")));
476        }
477
478        rx
479    }
480
481    fn get_or_load_grammar(
482        self: &Arc<Self>,
483        name: Arc<str>,
484    ) -> impl Future<Output = Result<tree_sitter::Language>> {
485        let (tx, rx) = oneshot::channel();
486        let mut state = self.state.write();
487
488        if let Some(grammar) = state.grammars.get_mut(name.as_ref()) {
489            match grammar {
490                AvailableGrammar::Native(grammar) | AvailableGrammar::Loaded(_, grammar) => {
491                    tx.send(Ok(grammar.clone())).ok();
492                }
493                AvailableGrammar::Loading(_, txs) => {
494                    txs.push(tx);
495                }
496                AvailableGrammar::Unloaded(wasm_path) => {
497                    if let Some(executor) = &self.executor {
498                        let this = self.clone();
499                        executor
500                            .spawn({
501                                let wasm_path = wasm_path.clone();
502                                async move {
503                                    let wasm_bytes = std::fs::read(&wasm_path)?;
504                                    let grammar_name = wasm_path
505                                        .file_stem()
506                                        .and_then(OsStr::to_str)
507                                        .ok_or_else(|| anyhow!("invalid grammar filename"))?;
508                                    let grammar = PARSER.with(|parser| {
509                                        let mut parser = parser.borrow_mut();
510                                        let mut store = parser.take_wasm_store().unwrap();
511                                        let grammar =
512                                            store.load_language(&grammar_name, &wasm_bytes);
513                                        parser.set_wasm_store(store).unwrap();
514                                        grammar
515                                    })?;
516
517                                    if let Some(AvailableGrammar::Loading(_, txs)) =
518                                        this.state.write().grammars.insert(
519                                            name,
520                                            AvailableGrammar::Loaded(wasm_path, grammar.clone()),
521                                        )
522                                    {
523                                        for tx in txs {
524                                            tx.send(Ok(grammar.clone())).ok();
525                                        }
526                                    }
527
528                                    anyhow::Ok(())
529                                }
530                            })
531                            .detach();
532                        *grammar = AvailableGrammar::Loading(wasm_path.clone(), vec![tx]);
533                    }
534                }
535            }
536        } else {
537            tx.send(Err(anyhow!("no such grammar {}", name))).ok();
538        }
539
540        async move { rx.await? }
541    }
542
543    pub fn to_vec(&self) -> Vec<Arc<Language>> {
544        self.state.read().languages.iter().cloned().collect()
545    }
546
547    pub fn lsp_adapters(&self, language: &Arc<Language>) -> Vec<Arc<CachedLspAdapter>> {
548        self.state
549            .read()
550            .lsp_adapters
551            .get(&language.config.name)
552            .cloned()
553            .unwrap_or_default()
554    }
555
556    pub fn update_lsp_status(
557        &self,
558        server_name: LanguageServerName,
559        status: LanguageServerBinaryStatus,
560    ) {
561        self.lsp_binary_status_tx.send(server_name, status);
562    }
563
564    pub fn create_pending_language_server(
565        self: &Arc<Self>,
566        stderr_capture: Arc<Mutex<Option<String>>>,
567        language: Arc<Language>,
568        adapter: Arc<CachedLspAdapter>,
569        root_path: Arc<Path>,
570        delegate: Arc<dyn LspAdapterDelegate>,
571        cx: &mut AppContext,
572    ) -> Option<PendingLanguageServer> {
573        let server_id = self.state.write().next_language_server_id();
574        log::info!(
575            "starting language server {:?}, path: {root_path:?}, id: {server_id}",
576            adapter.name.0
577        );
578
579        let download_dir = self
580            .language_server_download_dir
581            .clone()
582            .ok_or_else(|| anyhow!("language server download directory has not been assigned before starting server"))
583            .log_err()?;
584        let language = language.clone();
585        let container_dir: Arc<Path> = Arc::from(download_dir.join(adapter.name.0.as_ref()));
586        let root_path = root_path.clone();
587        let login_shell_env_loaded = self.login_shell_env_loaded.clone();
588        let this = Arc::downgrade(self);
589
590        let task = cx.spawn({
591            let container_dir = container_dir.clone();
592            move |mut cx| async move {
593                // If we want to install a binary globally, we need to wait for
594                // the login shell to be set on our process.
595                login_shell_env_loaded.await;
596
597                let binary = adapter
598                    .clone()
599                    .get_language_server_command(
600                        language.clone(),
601                        container_dir,
602                        delegate.clone(),
603                        &mut cx,
604                    )
605                    .await?;
606
607                if let Some(task) = adapter.will_start_server(&delegate, &mut cx) {
608                    task.await?;
609                }
610
611                #[cfg(any(test, feature = "test-support"))]
612                if true {
613                    let capabilities = adapter
614                        .as_fake()
615                        .map(|fake_adapter| fake_adapter.capabilities.clone())
616                        .unwrap_or_default();
617
618                    let (server, mut fake_server) = lsp::FakeLanguageServer::new(
619                        binary,
620                        adapter.name.0.to_string(),
621                        capabilities,
622                        cx.clone(),
623                    );
624
625                    if let Some(fake_adapter) = adapter.as_fake() {
626                        if let Some(initializer) = &fake_adapter.initializer {
627                            initializer(&mut fake_server);
628                        }
629                    }
630
631                    cx.background_executor()
632                        .spawn(async move {
633                            if fake_server
634                                .try_receive_notification::<lsp::notification::Initialized>()
635                                .await
636                                .is_some()
637                            {
638                                if let Some(this) = this.upgrade() {
639                                    if let Some(txs) = this
640                                        .state
641                                        .write()
642                                        .fake_server_txs
643                                        .get_mut(language.name().as_ref())
644                                    {
645                                        for tx in txs {
646                                            tx.unbounded_send(fake_server.clone()).ok();
647                                        }
648                                    }
649                                }
650                            }
651                        })
652                        .detach();
653
654                    return Ok(server);
655                }
656
657                drop(this);
658                lsp::LanguageServer::new(
659                    stderr_capture,
660                    server_id,
661                    binary,
662                    &root_path,
663                    adapter.code_action_kinds(),
664                    cx,
665                )
666            }
667        });
668
669        Some(PendingLanguageServer {
670            server_id,
671            task,
672            container_dir: Some(container_dir),
673        })
674    }
675
676    pub fn language_server_binary_statuses(
677        &self,
678    ) -> mpsc::UnboundedReceiver<(LanguageServerName, LanguageServerBinaryStatus)> {
679        self.lsp_binary_status_tx.subscribe()
680    }
681
682    pub fn delete_server_container(
683        &self,
684        adapter: Arc<CachedLspAdapter>,
685        cx: &mut AppContext,
686    ) -> Task<()> {
687        log::info!("deleting server container");
688
689        let mut lock = self.lsp_binary_paths.lock();
690        lock.remove(&adapter.name);
691
692        let download_dir = self
693            .language_server_download_dir
694            .clone()
695            .expect("language server download directory has not been assigned before deleting server container");
696
697        cx.spawn(|_| async move {
698            let container_dir = download_dir.join(adapter.name.0.as_ref());
699            smol::fs::remove_dir_all(container_dir)
700                .await
701                .context("server container removal")
702                .log_err();
703        })
704    }
705
706    pub fn next_language_server_id(&self) -> LanguageServerId {
707        self.state.write().next_language_server_id()
708    }
709}
710
711#[cfg(any(test, feature = "test-support"))]
712impl Default for LanguageRegistry {
713    fn default() -> Self {
714        Self::test()
715    }
716}
717
718impl LanguageRegistryState {
719    fn next_language_server_id(&mut self) -> LanguageServerId {
720        LanguageServerId(post_inc(&mut self.next_language_server_id))
721    }
722
723    fn add(&mut self, language: Arc<Language>) {
724        if let Some(theme) = self.theme.as_ref() {
725            language.set_theme(theme.syntax());
726        }
727        self.languages.push(language);
728        self.version += 1;
729        *self.subscription.0.borrow_mut() = ();
730    }
731
732    fn reload(&mut self) {
733        self.languages.clear();
734        self.version += 1;
735        self.reload_count += 1;
736        for language in &mut self.available_languages {
737            language.loaded = false;
738        }
739        *self.subscription.0.borrow_mut() = ();
740    }
741
742    fn remove_languages(
743        &mut self,
744        languages_to_remove: &[Arc<str>],
745        grammars_to_remove: &[Arc<str>],
746    ) {
747        if languages_to_remove.is_empty() && grammars_to_remove.is_empty() {
748            return;
749        }
750
751        self.languages
752            .retain(|language| !languages_to_remove.contains(&language.name()));
753        self.available_languages
754            .retain(|language| !languages_to_remove.contains(&language.name));
755        self.grammars
756            .retain(|name, _| !grammars_to_remove.contains(&name));
757        self.version += 1;
758        self.reload_count += 1;
759        *self.subscription.0.borrow_mut() = ();
760    }
761
762    /// Mark the given language as having been loaded, so that the
763    /// language registry won't try to load it again.
764    fn mark_language_loaded(&mut self, id: LanguageId) {
765        for language in &mut self.available_languages {
766            if language.id == id {
767                language.loaded = true;
768                break;
769            }
770        }
771    }
772}
773
774impl LspBinaryStatusSender {
775    fn subscribe(
776        &self,
777    ) -> mpsc::UnboundedReceiver<(LanguageServerName, LanguageServerBinaryStatus)> {
778        let (tx, rx) = mpsc::unbounded();
779        self.txs.lock().push(tx);
780        rx
781    }
782
783    fn send(&self, name: LanguageServerName, status: LanguageServerBinaryStatus) {
784        let mut txs = self.txs.lock();
785        txs.retain(|tx| tx.unbounded_send((name.clone(), status.clone())).is_ok());
786    }
787}