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