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