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