1use crate::{
2 CachedLspAdapter, File, Language, LanguageConfig, LanguageId, LanguageMatcher,
3 LanguageServerName, LspAdapter, PLAIN_TEXT, ToolchainLister,
4 language_settings::{
5 AllLanguageSettingsContent, LanguageSettingsContent, all_language_settings,
6 },
7 task_context::ContextProvider,
8 with_parser,
9};
10use anyhow::{Context as _, Result, anyhow};
11use collections::{FxHashMap, HashMap, HashSet, hash_map};
12
13use futures::{
14 Future,
15 channel::{mpsc, oneshot},
16};
17use globset::GlobSet;
18use gpui::{App, BackgroundExecutor, SharedString};
19use lsp::LanguageServerId;
20use parking_lot::{Mutex, RwLock};
21use postage::watch;
22use schemars::JsonSchema;
23use serde::{Deserialize, Serialize};
24use smallvec::SmallVec;
25use std::{
26 borrow::{Borrow, Cow},
27 cell::LazyCell,
28 ffi::OsStr,
29 ops::Not,
30 path::{Path, PathBuf},
31 sync::Arc,
32};
33use sum_tree::Bias;
34use text::{Point, Rope};
35use theme::Theme;
36use unicase::UniCase;
37use util::{ResultExt, maybe, post_inc};
38
39#[derive(
40 Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema,
41)]
42pub struct LanguageName(SharedString);
43
44impl LanguageName {
45 pub fn new(s: &str) -> Self {
46 Self(SharedString::new(s))
47 }
48
49 pub fn from_proto(s: String) -> Self {
50 Self(SharedString::from(s))
51 }
52 pub fn to_proto(self) -> String {
53 self.0.to_string()
54 }
55 pub fn lsp_id(&self) -> String {
56 match self.0.as_ref() {
57 "Plain Text" => "plaintext".to_string(),
58 language_name => language_name.to_lowercase(),
59 }
60 }
61}
62
63impl From<LanguageName> for SharedString {
64 fn from(value: LanguageName) -> Self {
65 value.0
66 }
67}
68
69impl AsRef<str> for LanguageName {
70 fn as_ref(&self) -> &str {
71 self.0.as_ref()
72 }
73}
74
75impl Borrow<str> for LanguageName {
76 fn borrow(&self) -> &str {
77 self.0.as_ref()
78 }
79}
80
81impl std::fmt::Display for LanguageName {
82 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
83 write!(f, "{}", self.0)
84 }
85}
86
87impl<'a> From<&'a str> for LanguageName {
88 fn from(str: &'a str) -> LanguageName {
89 LanguageName(SharedString::new(str))
90 }
91}
92
93impl From<LanguageName> for String {
94 fn from(value: LanguageName) -> Self {
95 let value: &str = &value.0;
96 Self::from(value)
97 }
98}
99
100pub struct LanguageRegistry {
101 state: RwLock<LanguageRegistryState>,
102 language_server_download_dir: Option<Arc<Path>>,
103 executor: BackgroundExecutor,
104 lsp_binary_status_tx: BinaryStatusSender,
105 dap_binary_status_tx: BinaryStatusSender,
106}
107
108struct LanguageRegistryState {
109 next_language_server_id: usize,
110 languages: Vec<Arc<Language>>,
111 language_settings: AllLanguageSettingsContent,
112 available_languages: Vec<AvailableLanguage>,
113 grammars: HashMap<Arc<str>, AvailableGrammar>,
114 lsp_adapters: HashMap<LanguageName, Vec<Arc<CachedLspAdapter>>>,
115 all_lsp_adapters: HashMap<LanguageServerName, Arc<CachedLspAdapter>>,
116 available_lsp_adapters:
117 HashMap<LanguageServerName, Arc<dyn Fn() -> Arc<CachedLspAdapter> + 'static + Send + Sync>>,
118 loading_languages: HashMap<LanguageId, Vec<oneshot::Sender<Result<Arc<Language>>>>>,
119 subscription: (watch::Sender<()>, watch::Receiver<()>),
120 theme: Option<Arc<Theme>>,
121 version: usize,
122 reload_count: usize,
123
124 #[cfg(any(test, feature = "test-support"))]
125 fake_server_entries: HashMap<LanguageServerName, FakeLanguageServerEntry>,
126}
127
128#[cfg(any(test, feature = "test-support"))]
129pub struct FakeLanguageServerEntry {
130 pub capabilities: lsp::ServerCapabilities,
131 pub initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,
132 pub tx: futures::channel::mpsc::UnboundedSender<lsp::FakeLanguageServer>,
133 pub _server: Option<lsp::FakeLanguageServer>,
134}
135
136#[derive(Clone, Debug, PartialEq, Eq)]
137pub enum BinaryStatus {
138 None,
139 CheckingForUpdate,
140 Downloading,
141 Failed { error: String },
142}
143
144#[derive(Clone)]
145pub struct AvailableLanguage {
146 id: LanguageId,
147 name: LanguageName,
148 grammar: Option<Arc<str>>,
149 matcher: LanguageMatcher,
150 hidden: bool,
151 load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
152 loaded: bool,
153}
154
155impl AvailableLanguage {
156 pub fn name(&self) -> LanguageName {
157 self.name.clone()
158 }
159
160 pub fn matcher(&self) -> &LanguageMatcher {
161 &self.matcher
162 }
163 pub fn hidden(&self) -> bool {
164 self.hidden
165 }
166}
167
168enum AvailableGrammar {
169 Native(tree_sitter::Language),
170 Loaded(#[allow(unused)] PathBuf, tree_sitter::Language),
171 Loading(
172 #[allow(unused)] PathBuf,
173 Vec<oneshot::Sender<Result<tree_sitter::Language, Arc<anyhow::Error>>>>,
174 ),
175 Unloaded(PathBuf),
176 LoadFailed(Arc<anyhow::Error>),
177}
178
179#[derive(Debug)]
180pub struct LanguageNotFound;
181
182impl std::fmt::Display for LanguageNotFound {
183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184 write!(f, "language not found")
185 }
186}
187
188pub const QUERY_FILENAME_PREFIXES: &[(
189 &str,
190 fn(&mut LanguageQueries) -> &mut Option<Cow<'static, str>>,
191)] = &[
192 ("highlights", |q| &mut q.highlights),
193 ("brackets", |q| &mut q.brackets),
194 ("outline", |q| &mut q.outline),
195 ("indents", |q| &mut q.indents),
196 ("embedding", |q| &mut q.embedding),
197 ("injections", |q| &mut q.injections),
198 ("overrides", |q| &mut q.overrides),
199 ("redactions", |q| &mut q.redactions),
200 ("runnables", |q| &mut q.runnables),
201 ("textobjects", |q| &mut q.text_objects),
202];
203
204/// Tree-sitter language queries for a given language.
205#[derive(Debug, Default)]
206pub struct LanguageQueries {
207 pub highlights: Option<Cow<'static, str>>,
208 pub brackets: Option<Cow<'static, str>>,
209 pub indents: Option<Cow<'static, str>>,
210 pub outline: Option<Cow<'static, str>>,
211 pub embedding: Option<Cow<'static, str>>,
212 pub injections: Option<Cow<'static, str>>,
213 pub overrides: Option<Cow<'static, str>>,
214 pub redactions: Option<Cow<'static, str>>,
215 pub runnables: Option<Cow<'static, str>>,
216 pub text_objects: Option<Cow<'static, str>>,
217}
218
219#[derive(Clone, Default)]
220struct BinaryStatusSender {
221 txs: Arc<Mutex<Vec<mpsc::UnboundedSender<(SharedString, BinaryStatus)>>>>,
222}
223
224pub struct LoadedLanguage {
225 pub config: LanguageConfig,
226 pub queries: LanguageQueries,
227 pub context_provider: Option<Arc<dyn ContextProvider>>,
228 pub toolchain_provider: Option<Arc<dyn ToolchainLister>>,
229}
230
231impl LanguageRegistry {
232 pub fn new(executor: BackgroundExecutor) -> Self {
233 let this = Self {
234 state: RwLock::new(LanguageRegistryState {
235 next_language_server_id: 0,
236 languages: Vec::new(),
237 available_languages: Vec::new(),
238 grammars: Default::default(),
239 language_settings: Default::default(),
240 loading_languages: Default::default(),
241 lsp_adapters: Default::default(),
242 all_lsp_adapters: Default::default(),
243 available_lsp_adapters: HashMap::default(),
244 subscription: watch::channel(),
245 theme: Default::default(),
246 version: 0,
247 reload_count: 0,
248
249 #[cfg(any(test, feature = "test-support"))]
250 fake_server_entries: Default::default(),
251 }),
252 language_server_download_dir: None,
253 lsp_binary_status_tx: Default::default(),
254 dap_binary_status_tx: Default::default(),
255 executor,
256 };
257 this.add(PLAIN_TEXT.clone());
258 this
259 }
260
261 #[cfg(any(test, feature = "test-support"))]
262 pub fn test(executor: BackgroundExecutor) -> Self {
263 let mut this = Self::new(executor);
264 this.language_server_download_dir = Some(Path::new("/the-download-dir").into());
265 this
266 }
267
268 /// Clears out all of the loaded languages and reload them from scratch.
269 pub fn reload(&self) {
270 self.state.write().reload();
271 }
272
273 /// Reorders the list of language servers for the given language.
274 ///
275 /// Uses the provided list of ordered [`CachedLspAdapters`] as the desired order.
276 ///
277 /// Any existing language servers not present in `ordered_lsp_adapters` will be
278 /// appended to the end.
279 pub fn reorder_language_servers(
280 &self,
281 language: &LanguageName,
282 ordered_lsp_adapters: Vec<Arc<CachedLspAdapter>>,
283 ) {
284 self.state
285 .write()
286 .reorder_language_servers(language, ordered_lsp_adapters);
287 }
288
289 /// Removes the specified languages and grammars from the registry.
290 pub fn remove_languages(
291 &self,
292 languages_to_remove: &[LanguageName],
293 grammars_to_remove: &[Arc<str>],
294 ) {
295 self.state
296 .write()
297 .remove_languages(languages_to_remove, grammars_to_remove)
298 }
299
300 pub fn remove_lsp_adapter(&self, language_name: &LanguageName, name: &LanguageServerName) {
301 let mut state = self.state.write();
302 if let Some(adapters) = state.lsp_adapters.get_mut(language_name) {
303 adapters.retain(|adapter| &adapter.name != name)
304 }
305 state.version += 1;
306 state.reload_count += 1;
307 *state.subscription.0.borrow_mut() = ();
308 }
309
310 #[cfg(any(feature = "test-support", test))]
311 pub fn register_test_language(&self, config: LanguageConfig) {
312 self.register_language(
313 config.name.clone(),
314 config.grammar.clone(),
315 config.matcher.clone(),
316 config.hidden,
317 Arc::new(move || {
318 Ok(LoadedLanguage {
319 config: config.clone(),
320 queries: Default::default(),
321 toolchain_provider: None,
322 context_provider: None,
323 })
324 }),
325 )
326 }
327
328 /// Registers an available language server adapter.
329 ///
330 /// The language server is registered under the language server name, but
331 /// not bound to a particular language.
332 ///
333 /// When a language wants to load this particular language server, it will
334 /// invoke the `load` function.
335 pub fn register_available_lsp_adapter(
336 &self,
337 name: LanguageServerName,
338 load: impl Fn() -> Arc<dyn LspAdapter> + 'static + Send + Sync,
339 ) {
340 self.state.write().available_lsp_adapters.insert(
341 name,
342 Arc::new(move || {
343 let lsp_adapter = load();
344 CachedLspAdapter::new(lsp_adapter)
345 }),
346 );
347 }
348
349 /// Loads the language server adapter for the language server with the given name.
350 pub fn load_available_lsp_adapter(
351 &self,
352 name: &LanguageServerName,
353 ) -> Option<Arc<CachedLspAdapter>> {
354 let state = self.state.read();
355 let load_lsp_adapter = state.available_lsp_adapters.get(name)?;
356
357 Some(load_lsp_adapter())
358 }
359
360 pub fn register_lsp_adapter(
361 &self,
362 language_name: LanguageName,
363 adapter: Arc<dyn LspAdapter>,
364 ) -> Arc<CachedLspAdapter> {
365 let cached = CachedLspAdapter::new(adapter);
366 let mut state = self.state.write();
367 state
368 .lsp_adapters
369 .entry(language_name)
370 .or_default()
371 .push(cached.clone());
372 state
373 .all_lsp_adapters
374 .insert(cached.name.clone(), cached.clone());
375
376 cached
377 }
378
379 pub fn get_or_register_lsp_adapter(
380 &self,
381 language_name: LanguageName,
382 server_name: LanguageServerName,
383 build_adapter: impl FnOnce() -> Arc<dyn LspAdapter> + 'static,
384 ) -> Arc<CachedLspAdapter> {
385 let registered = self
386 .state
387 .write()
388 .lsp_adapters
389 .entry(language_name.clone())
390 .or_default()
391 .iter()
392 .find(|cached_adapter| cached_adapter.name == server_name)
393 .cloned();
394
395 if let Some(found) = registered {
396 found
397 } else {
398 let adapter = build_adapter();
399 self.register_lsp_adapter(language_name, adapter)
400 }
401 }
402
403 /// Register a fake language server and adapter
404 /// The returned channel receives a new instance of the language server every time it is started
405 #[cfg(any(feature = "test-support", test))]
406 pub fn register_fake_lsp(
407 &self,
408 language_name: impl Into<LanguageName>,
409 mut adapter: crate::FakeLspAdapter,
410 ) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
411 let language_name = language_name.into();
412 let adapter_name = LanguageServerName(adapter.name.into());
413 let capabilities = adapter.capabilities.clone();
414 let initializer = adapter.initializer.take();
415 let adapter = CachedLspAdapter::new(Arc::new(adapter));
416 {
417 let mut state = self.state.write();
418 state
419 .lsp_adapters
420 .entry(language_name.clone())
421 .or_default()
422 .push(adapter.clone());
423 state.all_lsp_adapters.insert(adapter.name(), adapter);
424 }
425
426 self.register_fake_language_server(adapter_name, capabilities, initializer)
427 }
428
429 /// Register a fake lsp adapter (without the language server)
430 /// The returned channel receives a new instance of the language server every time it is started
431 #[cfg(any(feature = "test-support", test))]
432 pub fn register_fake_lsp_adapter(
433 &self,
434 language_name: impl Into<LanguageName>,
435 adapter: crate::FakeLspAdapter,
436 ) {
437 let language_name = language_name.into();
438 let mut state = self.state.write();
439 let cached_adapter = CachedLspAdapter::new(Arc::new(adapter));
440 state
441 .lsp_adapters
442 .entry(language_name.clone())
443 .or_default()
444 .push(cached_adapter.clone());
445 state
446 .all_lsp_adapters
447 .insert(cached_adapter.name(), cached_adapter);
448 }
449
450 /// Register a fake language server (without the adapter)
451 /// The returned channel receives a new instance of the language server every time it is started
452 #[cfg(any(feature = "test-support", test))]
453 pub fn register_fake_language_server(
454 &self,
455 lsp_name: LanguageServerName,
456 capabilities: lsp::ServerCapabilities,
457 initializer: Option<Box<dyn Fn(&mut lsp::FakeLanguageServer) + Send + Sync>>,
458 ) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
459 let (servers_tx, servers_rx) = futures::channel::mpsc::unbounded();
460 self.state.write().fake_server_entries.insert(
461 lsp_name,
462 FakeLanguageServerEntry {
463 tx: servers_tx,
464 capabilities,
465 initializer,
466 _server: None,
467 },
468 );
469 servers_rx
470 }
471
472 /// Adds a language to the registry, which can be loaded if needed.
473 pub fn register_language(
474 &self,
475 name: LanguageName,
476 grammar_name: Option<Arc<str>>,
477 matcher: LanguageMatcher,
478 hidden: bool,
479 load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
480 ) {
481 let state = &mut *self.state.write();
482
483 for existing_language in &mut state.available_languages {
484 if existing_language.name == name {
485 existing_language.grammar = grammar_name;
486 existing_language.matcher = matcher;
487 existing_language.load = load;
488 return;
489 }
490 }
491
492 state.available_languages.push(AvailableLanguage {
493 id: LanguageId::new(),
494 name,
495 grammar: grammar_name,
496 matcher,
497 load,
498 hidden,
499 loaded: false,
500 });
501 state.version += 1;
502 state.reload_count += 1;
503 *state.subscription.0.borrow_mut() = ();
504 }
505
506 /// Adds grammars to the registry. Language configurations reference a grammar by name. The
507 /// grammar controls how the source code is parsed.
508 pub fn register_native_grammars(
509 &self,
510 grammars: impl IntoIterator<Item = (impl Into<Arc<str>>, impl Into<tree_sitter::Language>)>,
511 ) {
512 self.state.write().grammars.extend(
513 grammars
514 .into_iter()
515 .map(|(name, grammar)| (name.into(), AvailableGrammar::Native(grammar.into()))),
516 );
517 }
518
519 /// Adds paths to WASM grammar files, which can be loaded if needed.
520 pub fn register_wasm_grammars(
521 &self,
522 grammars: impl IntoIterator<Item = (impl Into<Arc<str>>, PathBuf)>,
523 ) {
524 let mut state = self.state.write();
525 state.grammars.extend(
526 grammars
527 .into_iter()
528 .map(|(name, path)| (name.into(), AvailableGrammar::Unloaded(path))),
529 );
530 state.version += 1;
531 state.reload_count += 1;
532 *state.subscription.0.borrow_mut() = ();
533 }
534
535 pub fn language_settings(&self) -> AllLanguageSettingsContent {
536 self.state.read().language_settings.clone()
537 }
538
539 pub fn language_names(&self) -> Vec<String> {
540 let state = self.state.read();
541 let mut result = state
542 .available_languages
543 .iter()
544 .filter_map(|l| l.loaded.not().then_some(l.name.to_string()))
545 .chain(state.languages.iter().map(|l| l.config.name.to_string()))
546 .collect::<Vec<_>>();
547 result.sort_unstable_by_key(|language_name| language_name.to_lowercase());
548 result
549 }
550
551 pub fn grammar_names(&self) -> Vec<Arc<str>> {
552 let state = self.state.read();
553 let mut result = state.grammars.keys().cloned().collect::<Vec<_>>();
554 result.sort_unstable_by_key(|grammar_name| grammar_name.to_lowercase());
555 result
556 }
557
558 /// Add a pre-loaded language to the registry.
559 pub fn add(&self, language: Arc<Language>) {
560 let mut state = self.state.write();
561 state.available_languages.push(AvailableLanguage {
562 id: language.id,
563 name: language.name(),
564 grammar: language.config.grammar.clone(),
565 matcher: language.config.matcher.clone(),
566 hidden: language.config.hidden,
567 load: Arc::new(|| Err(anyhow!("already loaded"))),
568 loaded: true,
569 });
570 state.add(language);
571 }
572
573 pub fn subscribe(&self) -> watch::Receiver<()> {
574 self.state.read().subscription.1.clone()
575 }
576
577 /// Returns the number of times that the registry has been changed,
578 /// by adding languages or reloading.
579 pub fn version(&self) -> usize {
580 self.state.read().version
581 }
582
583 /// Returns the number of times that the registry has been reloaded.
584 pub fn reload_count(&self) -> usize {
585 self.state.read().reload_count
586 }
587
588 pub fn set_theme(&self, theme: Arc<Theme>) {
589 let mut state = self.state.write();
590 state.theme = Some(theme.clone());
591 for language in &state.languages {
592 language.set_theme(theme.syntax());
593 }
594 }
595
596 pub fn set_language_server_download_dir(&mut self, path: impl Into<Arc<Path>>) {
597 self.language_server_download_dir = Some(path.into());
598 }
599
600 pub fn language_for_name(
601 self: &Arc<Self>,
602 name: &str,
603 ) -> impl Future<Output = Result<Arc<Language>>> + use<> {
604 let name = UniCase::new(name);
605 let rx = self.get_or_load_language(|language_name, _| {
606 if UniCase::new(&language_name.0) == name {
607 1
608 } else {
609 0
610 }
611 });
612 async move { rx.await? }
613 }
614
615 pub fn language_for_name_or_extension(
616 self: &Arc<Self>,
617 string: &str,
618 ) -> impl Future<Output = Result<Arc<Language>>> {
619 let string = UniCase::new(string);
620 let rx = self.get_or_load_language(|name, config| {
621 if UniCase::new(&name.0) == string
622 || config
623 .path_suffixes
624 .iter()
625 .any(|suffix| UniCase::new(suffix) == string)
626 {
627 1
628 } else {
629 0
630 }
631 });
632 async move { rx.await? }
633 }
634
635 pub fn available_language_for_name(self: &Arc<Self>, name: &str) -> Option<AvailableLanguage> {
636 let state = self.state.read();
637 state
638 .available_languages
639 .iter()
640 .find(|l| l.name.0.as_ref() == name)
641 .cloned()
642 }
643
644 pub fn language_for_file(
645 self: &Arc<Self>,
646 file: &Arc<dyn File>,
647 content: Option<&Rope>,
648 cx: &App,
649 ) -> Option<AvailableLanguage> {
650 let user_file_types = all_language_settings(Some(file), cx);
651
652 self.language_for_file_internal(
653 &file.full_path(cx),
654 content,
655 Some(&user_file_types.file_types),
656 )
657 }
658
659 pub fn language_for_file_path<'a>(
660 self: &Arc<Self>,
661 path: &'a Path,
662 ) -> impl Future<Output = Result<Arc<Language>>> + 'a {
663 let available_language = self.language_for_file_internal(path, None, None);
664
665 let this = self.clone();
666 async move {
667 if let Some(language) = available_language {
668 this.load_language(&language).await?
669 } else {
670 Err(anyhow!(LanguageNotFound))
671 }
672 }
673 }
674
675 fn language_for_file_internal(
676 self: &Arc<Self>,
677 path: &Path,
678 content: Option<&Rope>,
679 user_file_types: Option<&FxHashMap<Arc<str>, GlobSet>>,
680 ) -> Option<AvailableLanguage> {
681 let filename = path.file_name().and_then(|name| name.to_str());
682 // `Path.extension()` returns None for files with a leading '.'
683 // and no other extension which is not the desired behavior here,
684 // as we want `.zshrc` to result in extension being `Some("zshrc")`
685 let extension = filename.and_then(|filename| filename.split('.').next_back());
686 let path_suffixes = [extension, filename, path.to_str()];
687 let path_suffixes_candidates = path_suffixes
688 .iter()
689 .filter_map(|suffix| suffix.map(globset::Candidate::new))
690 .collect::<SmallVec<[_; 3]>>();
691 let empty = GlobSet::empty();
692 let content = LazyCell::new(|| {
693 content.map(|content| {
694 let end = content.clip_point(Point::new(0, 256), Bias::Left);
695 let end = content.point_to_offset(end);
696 content.chunks_in_range(0..end).collect::<String>()
697 })
698 });
699 self.find_matching_language(move |language_name, config| {
700 let path_matches_default_suffix = || {
701 config
702 .path_suffixes
703 .iter()
704 .any(|suffix| path_suffixes.contains(&Some(suffix.as_str())))
705 };
706 let path_matches_custom_suffix = || {
707 let custom_suffixes = user_file_types
708 .and_then(|types| types.get(language_name.as_ref()))
709 .unwrap_or(&empty);
710 path_suffixes_candidates
711 .iter()
712 .any(|suffix| custom_suffixes.is_match_candidate(suffix))
713 };
714 let content_matches = || {
715 content
716 .as_ref()
717 .zip(config.first_line_pattern.as_ref())
718 .map_or(false, |(text, pattern)| pattern.is_match(&text))
719 };
720 if path_matches_custom_suffix() {
721 2
722 } else if path_matches_default_suffix() || content_matches() {
723 1
724 } else {
725 0
726 }
727 })
728 }
729
730 fn find_matching_language(
731 self: &Arc<Self>,
732 callback: impl Fn(&LanguageName, &LanguageMatcher) -> usize,
733 ) -> Option<AvailableLanguage> {
734 let state = self.state.read();
735 let available_language = state
736 .available_languages
737 .iter()
738 .filter_map(|language| {
739 let score = callback(&language.name, &language.matcher);
740 if score > 0 {
741 Some((language.clone(), score))
742 } else {
743 None
744 }
745 })
746 .max_by_key(|e| e.1)
747 .clone()
748 .map(|(available_language, _)| available_language);
749 drop(state);
750 available_language
751 }
752
753 pub fn load_language(
754 self: &Arc<Self>,
755 language: &AvailableLanguage,
756 ) -> oneshot::Receiver<Result<Arc<Language>>> {
757 let (tx, rx) = oneshot::channel();
758
759 let mut state = self.state.write();
760
761 // If the language is already loaded, resolve with it immediately.
762 for loaded_language in state.languages.iter() {
763 if loaded_language.id == language.id {
764 tx.send(Ok(loaded_language.clone())).unwrap();
765 return rx;
766 }
767 }
768
769 match state.loading_languages.entry(language.id) {
770 // If the language is already being loaded, then add this
771 // channel to a list that will be sent to when the load completes.
772 hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(tx),
773
774 // Otherwise, start loading the language.
775 hash_map::Entry::Vacant(entry) => {
776 let this = self.clone();
777
778 let id = language.id;
779 let name = language.name.clone();
780 let language_load = language.load.clone();
781
782 self.executor
783 .spawn(async move {
784 let language = async {
785 let loaded_language = (language_load)()?;
786 if let Some(grammar) = loaded_language.config.grammar.clone() {
787 let grammar = Some(this.get_or_load_grammar(grammar).await?);
788
789 Language::new_with_id(id, loaded_language.config, grammar)
790 .with_context_provider(loaded_language.context_provider)
791 .with_toolchain_lister(loaded_language.toolchain_provider)
792 .with_queries(loaded_language.queries)
793 } else {
794 Ok(Language::new_with_id(id, loaded_language.config, None)
795 .with_context_provider(loaded_language.context_provider)
796 .with_toolchain_lister(loaded_language.toolchain_provider))
797 }
798 }
799 .await;
800
801 match language {
802 Ok(language) => {
803 let language = Arc::new(language);
804 let mut state = this.state.write();
805
806 state.add(language.clone());
807 state.mark_language_loaded(id);
808 if let Some(mut txs) = state.loading_languages.remove(&id) {
809 for tx in txs.drain(..) {
810 let _ = tx.send(Ok(language.clone()));
811 }
812 }
813 }
814 Err(e) => {
815 log::error!("failed to load language {name}:\n{:?}", e);
816 let mut state = this.state.write();
817 state.mark_language_loaded(id);
818 if let Some(mut txs) = state.loading_languages.remove(&id) {
819 for tx in txs.drain(..) {
820 let _ = tx.send(Err(anyhow!(
821 "failed to load language {}: {}",
822 name,
823 e
824 )));
825 }
826 }
827 }
828 };
829 })
830 .detach();
831
832 entry.insert(vec![tx]);
833 }
834 }
835
836 drop(state);
837 rx
838 }
839
840 fn get_or_load_language(
841 self: &Arc<Self>,
842 callback: impl Fn(&LanguageName, &LanguageMatcher) -> usize,
843 ) -> oneshot::Receiver<Result<Arc<Language>>> {
844 let Some(language) = self.find_matching_language(callback) else {
845 let (tx, rx) = oneshot::channel();
846 let _ = tx.send(Err(anyhow!(LanguageNotFound)));
847 return rx;
848 };
849
850 self.load_language(&language)
851 }
852
853 fn get_or_load_grammar(
854 self: &Arc<Self>,
855 name: Arc<str>,
856 ) -> impl Future<Output = Result<tree_sitter::Language>> {
857 let (tx, rx) = oneshot::channel();
858 let mut state = self.state.write();
859
860 if let Some(grammar) = state.grammars.get_mut(name.as_ref()) {
861 match grammar {
862 AvailableGrammar::LoadFailed(error) => {
863 tx.send(Err(error.clone())).ok();
864 }
865 AvailableGrammar::Native(grammar) | AvailableGrammar::Loaded(_, grammar) => {
866 tx.send(Ok(grammar.clone())).ok();
867 }
868 AvailableGrammar::Loading(_, txs) => {
869 txs.push(tx);
870 }
871 AvailableGrammar::Unloaded(wasm_path) => {
872 let this = self.clone();
873 let wasm_path = wasm_path.clone();
874 *grammar = AvailableGrammar::Loading(wasm_path.clone(), vec![tx]);
875 self.executor
876 .spawn(async move {
877 let grammar_result = maybe!({
878 let wasm_bytes = std::fs::read(&wasm_path)?;
879 let grammar_name = wasm_path
880 .file_stem()
881 .and_then(OsStr::to_str)
882 .ok_or_else(|| anyhow!("invalid grammar filename"))?;
883 anyhow::Ok(with_parser(|parser| {
884 let mut store = parser.take_wasm_store().unwrap();
885 let grammar = store.load_language(grammar_name, &wasm_bytes);
886 parser.set_wasm_store(store).unwrap();
887 grammar
888 })?)
889 })
890 .map_err(Arc::new);
891
892 let value = match &grammar_result {
893 Ok(grammar) => AvailableGrammar::Loaded(wasm_path, grammar.clone()),
894 Err(error) => AvailableGrammar::LoadFailed(error.clone()),
895 };
896
897 let old_value = this.state.write().grammars.insert(name, value);
898 if let Some(AvailableGrammar::Loading(_, txs)) = old_value {
899 for tx in txs {
900 tx.send(grammar_result.clone()).ok();
901 }
902 }
903 })
904 .detach();
905 }
906 }
907 } else {
908 tx.send(Err(Arc::new(anyhow!("no such grammar {}", name))))
909 .ok();
910 }
911
912 async move { rx.await?.map_err(|e| anyhow!(e)) }
913 }
914
915 pub fn to_vec(&self) -> Vec<Arc<Language>> {
916 self.state.read().languages.to_vec()
917 }
918
919 pub fn lsp_adapters(&self, language_name: &LanguageName) -> Vec<Arc<CachedLspAdapter>> {
920 self.state
921 .read()
922 .lsp_adapters
923 .get(language_name)
924 .cloned()
925 .unwrap_or_default()
926 }
927
928 pub fn all_lsp_adapters(&self) -> Vec<Arc<CachedLspAdapter>> {
929 self.state
930 .read()
931 .all_lsp_adapters
932 .values()
933 .cloned()
934 .collect()
935 }
936
937 pub fn adapter_for_name(&self, name: &LanguageServerName) -> Option<Arc<CachedLspAdapter>> {
938 self.state.read().all_lsp_adapters.get(name).cloned()
939 }
940
941 pub fn update_lsp_status(&self, server_name: LanguageServerName, status: BinaryStatus) {
942 self.lsp_binary_status_tx.send(server_name.0, status);
943 }
944
945 pub fn update_dap_status(&self, server_name: LanguageServerName, status: BinaryStatus) {
946 self.dap_binary_status_tx.send(server_name.0, status);
947 }
948
949 pub fn next_language_server_id(&self) -> LanguageServerId {
950 self.state.write().next_language_server_id()
951 }
952
953 pub fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>> {
954 self.language_server_download_dir
955 .as_ref()
956 .map(|dir| Arc::from(dir.join(name.0.as_ref())))
957 }
958
959 #[cfg(any(test, feature = "test-support"))]
960 pub fn create_fake_language_server(
961 &self,
962 server_id: LanguageServerId,
963 name: &LanguageServerName,
964 binary: lsp::LanguageServerBinary,
965 cx: &mut gpui::AsyncApp,
966 ) -> Option<lsp::LanguageServer> {
967 use gpui::AppContext as _;
968
969 let mut state = self.state.write();
970 let fake_entry = state.fake_server_entries.get_mut(&name)?;
971 let (server, mut fake_server) = lsp::FakeLanguageServer::new(
972 server_id,
973 binary,
974 name.0.to_string(),
975 fake_entry.capabilities.clone(),
976 cx,
977 );
978 fake_entry._server = Some(fake_server.clone());
979
980 if let Some(initializer) = &fake_entry.initializer {
981 initializer(&mut fake_server);
982 }
983
984 let tx = fake_entry.tx.clone();
985 cx.background_spawn(async move {
986 if fake_server
987 .try_receive_notification::<lsp::notification::Initialized>()
988 .await
989 .is_some()
990 {
991 tx.unbounded_send(fake_server.clone()).ok();
992 }
993 })
994 .detach();
995
996 Some(server)
997 }
998
999 pub fn language_server_binary_statuses(
1000 &self,
1001 ) -> mpsc::UnboundedReceiver<(SharedString, BinaryStatus)> {
1002 self.lsp_binary_status_tx.subscribe()
1003 }
1004
1005 pub fn dap_server_binary_statuses(
1006 &self,
1007 ) -> mpsc::UnboundedReceiver<(SharedString, BinaryStatus)> {
1008 self.dap_binary_status_tx.subscribe()
1009 }
1010
1011 pub async fn delete_server_container(&self, name: LanguageServerName) {
1012 log::info!("deleting server container");
1013 let Some(dir) = self.language_server_download_dir(&name) else {
1014 return;
1015 };
1016
1017 smol::fs::remove_dir_all(dir)
1018 .await
1019 .context("server container removal")
1020 .log_err();
1021 }
1022}
1023
1024impl LanguageRegistryState {
1025 fn next_language_server_id(&mut self) -> LanguageServerId {
1026 LanguageServerId(post_inc(&mut self.next_language_server_id))
1027 }
1028
1029 fn add(&mut self, language: Arc<Language>) {
1030 if let Some(theme) = self.theme.as_ref() {
1031 language.set_theme(theme.syntax());
1032 }
1033 self.language_settings.languages.insert(
1034 language.name(),
1035 LanguageSettingsContent {
1036 tab_size: language.config.tab_size,
1037 hard_tabs: language.config.hard_tabs,
1038 soft_wrap: language.config.soft_wrap,
1039 auto_indent_on_paste: language.config.auto_indent_on_paste,
1040 ..Default::default()
1041 }
1042 .clone(),
1043 );
1044 self.languages.push(language);
1045 self.version += 1;
1046 *self.subscription.0.borrow_mut() = ();
1047 }
1048
1049 fn reload(&mut self) {
1050 self.languages.clear();
1051 self.version += 1;
1052 self.reload_count += 1;
1053 for language in &mut self.available_languages {
1054 language.loaded = false;
1055 }
1056 *self.subscription.0.borrow_mut() = ();
1057 }
1058
1059 /// Reorders the list of language servers for the given language.
1060 ///
1061 /// Uses the provided list of ordered [`CachedLspAdapters`] as the desired order.
1062 ///
1063 /// Any existing language servers not present in `ordered_lsp_adapters` will be
1064 /// appended to the end.
1065 fn reorder_language_servers(
1066 &mut self,
1067 language_name: &LanguageName,
1068 ordered_lsp_adapters: Vec<Arc<CachedLspAdapter>>,
1069 ) {
1070 let Some(lsp_adapters) = self.lsp_adapters.get_mut(language_name) else {
1071 return;
1072 };
1073
1074 let ordered_lsp_adapter_ids = ordered_lsp_adapters
1075 .iter()
1076 .map(|lsp_adapter| lsp_adapter.name.clone())
1077 .collect::<HashSet<_>>();
1078
1079 let mut new_lsp_adapters = ordered_lsp_adapters;
1080 for adapter in lsp_adapters.iter() {
1081 if !ordered_lsp_adapter_ids.contains(&adapter.name) {
1082 new_lsp_adapters.push(adapter.clone());
1083 }
1084 }
1085
1086 *lsp_adapters = new_lsp_adapters;
1087 }
1088
1089 fn remove_languages(
1090 &mut self,
1091 languages_to_remove: &[LanguageName],
1092 grammars_to_remove: &[Arc<str>],
1093 ) {
1094 if languages_to_remove.is_empty() && grammars_to_remove.is_empty() {
1095 return;
1096 }
1097
1098 self.languages
1099 .retain(|language| !languages_to_remove.contains(&language.name()));
1100 self.available_languages
1101 .retain(|language| !languages_to_remove.contains(&language.name));
1102 self.grammars
1103 .retain(|name, _| !grammars_to_remove.contains(name));
1104 self.version += 1;
1105 self.reload_count += 1;
1106 *self.subscription.0.borrow_mut() = ();
1107 }
1108
1109 /// Mark the given language as having been loaded, so that the
1110 /// language registry won't try to load it again.
1111 fn mark_language_loaded(&mut self, id: LanguageId) {
1112 for language in &mut self.available_languages {
1113 if language.id == id {
1114 language.loaded = true;
1115 break;
1116 }
1117 }
1118 }
1119}
1120
1121impl BinaryStatusSender {
1122 fn subscribe(&self) -> mpsc::UnboundedReceiver<(SharedString, BinaryStatus)> {
1123 let (tx, rx) = mpsc::unbounded();
1124 self.txs.lock().push(tx);
1125 rx
1126 }
1127
1128 fn send(&self, name: SharedString, status: BinaryStatus) {
1129 let mut txs = self.txs.lock();
1130 txs.retain(|tx| tx.unbounded_send((name.clone(), status.clone())).is_ok());
1131 }
1132}