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