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