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