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