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