Skip to repository content957 lines · 34.6 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T02:58:06.111Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
language_registry.rs
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