1mod buffer;
2mod diagnostic_set;
3mod highlight_map;
4pub mod language_settings;
5pub mod markdown;
6mod outline;
7pub mod proto;
8mod syntax_map;
9
10#[cfg(test)]
11mod buffer_tests;
12
13use anyhow::{anyhow, Context, Result};
14use async_trait::async_trait;
15use collections::{HashMap, HashSet};
16use futures::{
17 channel::{mpsc, oneshot},
18 future::{BoxFuture, Shared},
19 FutureExt, TryFutureExt as _,
20};
21use gpui::{executor::Background, AppContext, AsyncAppContext, Task};
22pub use highlight_map::HighlightMap;
23use lazy_static::lazy_static;
24use lsp::{CodeActionKind, LanguageServerBinary};
25use parking_lot::{Mutex, RwLock};
26use postage::watch;
27use regex::Regex;
28use serde::{de, Deserialize, Deserializer};
29use serde_json::Value;
30use std::{
31 any::Any,
32 borrow::Cow,
33 cell::RefCell,
34 fmt::Debug,
35 hash::Hash,
36 mem,
37 ops::{Not, Range},
38 path::{Path, PathBuf},
39 str,
40 sync::{
41 atomic::{AtomicU64, AtomicUsize, Ordering::SeqCst},
42 Arc,
43 },
44};
45use syntax_map::SyntaxSnapshot;
46use theme::{SyntaxTheme, Theme};
47use tree_sitter::{self, Query};
48use unicase::UniCase;
49use util::{http::HttpClient, paths::PathExt};
50use util::{post_inc, ResultExt, TryFutureExt as _, UnwrapFuture};
51
52pub use buffer::Operation;
53pub use buffer::*;
54pub use diagnostic_set::DiagnosticEntry;
55pub use lsp::LanguageServerId;
56pub use outline::{Outline, OutlineItem};
57pub use syntax_map::{OwnedSyntaxLayerInfo, SyntaxLayerInfo};
58pub use text::LineEnding;
59pub use tree_sitter::{Parser, Tree};
60
61pub fn init(cx: &mut AppContext) {
62 language_settings::init(cx);
63}
64
65#[derive(Clone, Default)]
66struct LspBinaryStatusSender {
67 txs: Arc<Mutex<Vec<mpsc::UnboundedSender<(Arc<Language>, LanguageServerBinaryStatus)>>>>,
68}
69
70impl LspBinaryStatusSender {
71 fn subscribe(&self) -> mpsc::UnboundedReceiver<(Arc<Language>, LanguageServerBinaryStatus)> {
72 let (tx, rx) = mpsc::unbounded();
73 self.txs.lock().push(tx);
74 rx
75 }
76
77 fn send(&self, language: Arc<Language>, status: LanguageServerBinaryStatus) {
78 let mut txs = self.txs.lock();
79 txs.retain(|tx| {
80 tx.unbounded_send((language.clone(), status.clone()))
81 .is_ok()
82 });
83 }
84}
85
86thread_local! {
87 static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
88}
89
90lazy_static! {
91 pub static ref NEXT_GRAMMAR_ID: AtomicUsize = Default::default();
92 pub static ref PLAIN_TEXT: Arc<Language> = Arc::new(Language::new(
93 LanguageConfig {
94 name: "Plain Text".into(),
95 ..Default::default()
96 },
97 None,
98 ));
99}
100
101pub trait ToLspPosition {
102 fn to_lsp_position(self) -> lsp::Position;
103}
104
105#[derive(Clone, Debug, PartialEq, Eq, Hash)]
106pub struct LanguageServerName(pub Arc<str>);
107
108/// Represents a Language Server, with certain cached sync properties.
109/// Uses [`LspAdapter`] under the hood, but calls all 'static' methods
110/// once at startup, and caches the results.
111pub struct CachedLspAdapter {
112 pub name: LanguageServerName,
113 pub short_name: &'static str,
114 pub disk_based_diagnostic_sources: Vec<String>,
115 pub disk_based_diagnostics_progress_token: Option<String>,
116 pub language_ids: HashMap<String, String>,
117 pub adapter: Arc<dyn LspAdapter>,
118 pub reinstall_attempt_count: AtomicU64,
119}
120
121impl CachedLspAdapter {
122 pub async fn new(adapter: Arc<dyn LspAdapter>) -> Arc<Self> {
123 let name = adapter.name().await;
124 let short_name = adapter.short_name();
125 let disk_based_diagnostic_sources = adapter.disk_based_diagnostic_sources().await;
126 let disk_based_diagnostics_progress_token =
127 adapter.disk_based_diagnostics_progress_token().await;
128 let language_ids = adapter.language_ids().await;
129
130 Arc::new(CachedLspAdapter {
131 name,
132 short_name,
133 disk_based_diagnostic_sources,
134 disk_based_diagnostics_progress_token,
135 language_ids,
136 adapter,
137 reinstall_attempt_count: AtomicU64::new(0),
138 })
139 }
140
141 pub async fn fetch_latest_server_version(
142 &self,
143 delegate: &dyn LspAdapterDelegate,
144 ) -> Result<Box<dyn 'static + Send + Any>> {
145 self.adapter.fetch_latest_server_version(delegate).await
146 }
147
148 pub fn will_fetch_server(
149 &self,
150 delegate: &Arc<dyn LspAdapterDelegate>,
151 cx: &mut AsyncAppContext,
152 ) -> Option<Task<Result<()>>> {
153 self.adapter.will_fetch_server(delegate, cx)
154 }
155
156 pub fn will_start_server(
157 &self,
158 delegate: &Arc<dyn LspAdapterDelegate>,
159 cx: &mut AsyncAppContext,
160 ) -> Option<Task<Result<()>>> {
161 self.adapter.will_start_server(delegate, cx)
162 }
163
164 pub async fn fetch_server_binary(
165 &self,
166 version: Box<dyn 'static + Send + Any>,
167 container_dir: PathBuf,
168 delegate: &dyn LspAdapterDelegate,
169 ) -> Result<LanguageServerBinary> {
170 self.adapter
171 .fetch_server_binary(version, container_dir, delegate)
172 .await
173 }
174
175 pub async fn cached_server_binary(
176 &self,
177 container_dir: PathBuf,
178 delegate: &dyn LspAdapterDelegate,
179 ) -> Option<LanguageServerBinary> {
180 self.adapter
181 .cached_server_binary(container_dir, delegate)
182 .await
183 }
184
185 pub fn can_be_reinstalled(&self) -> bool {
186 self.adapter.can_be_reinstalled()
187 }
188
189 pub async fn installation_test_binary(
190 &self,
191 container_dir: PathBuf,
192 ) -> Option<LanguageServerBinary> {
193 self.adapter.installation_test_binary(container_dir).await
194 }
195
196 pub fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
197 self.adapter.code_action_kinds()
198 }
199
200 pub fn workspace_configuration(&self, cx: &mut AppContext) -> BoxFuture<'static, Value> {
201 self.adapter.workspace_configuration(cx)
202 }
203
204 pub fn process_diagnostics(&self, params: &mut lsp::PublishDiagnosticsParams) {
205 self.adapter.process_diagnostics(params)
206 }
207
208 pub async fn process_completion(&self, completion_item: &mut lsp::CompletionItem) {
209 self.adapter.process_completion(completion_item).await
210 }
211
212 pub async fn label_for_completion(
213 &self,
214 completion_item: &lsp::CompletionItem,
215 language: &Arc<Language>,
216 ) -> Option<CodeLabel> {
217 self.adapter
218 .label_for_completion(completion_item, language)
219 .await
220 }
221
222 pub async fn label_for_symbol(
223 &self,
224 name: &str,
225 kind: lsp::SymbolKind,
226 language: &Arc<Language>,
227 ) -> Option<CodeLabel> {
228 self.adapter.label_for_symbol(name, kind, language).await
229 }
230
231 pub fn prettier_plugins(&self) -> &[&'static str] {
232 self.adapter.prettier_plugins()
233 }
234}
235
236pub trait LspAdapterDelegate: Send + Sync {
237 fn show_notification(&self, message: &str, cx: &mut AppContext);
238 fn http_client(&self) -> Arc<dyn HttpClient>;
239}
240
241#[async_trait]
242pub trait LspAdapter: 'static + Send + Sync {
243 async fn name(&self) -> LanguageServerName;
244
245 fn short_name(&self) -> &'static str;
246
247 async fn fetch_latest_server_version(
248 &self,
249 delegate: &dyn LspAdapterDelegate,
250 ) -> Result<Box<dyn 'static + Send + Any>>;
251
252 fn will_fetch_server(
253 &self,
254 _: &Arc<dyn LspAdapterDelegate>,
255 _: &mut AsyncAppContext,
256 ) -> Option<Task<Result<()>>> {
257 None
258 }
259
260 fn will_start_server(
261 &self,
262 _: &Arc<dyn LspAdapterDelegate>,
263 _: &mut AsyncAppContext,
264 ) -> Option<Task<Result<()>>> {
265 None
266 }
267
268 async fn fetch_server_binary(
269 &self,
270 version: Box<dyn 'static + Send + Any>,
271 container_dir: PathBuf,
272 delegate: &dyn LspAdapterDelegate,
273 ) -> Result<LanguageServerBinary>;
274
275 async fn cached_server_binary(
276 &self,
277 container_dir: PathBuf,
278 delegate: &dyn LspAdapterDelegate,
279 ) -> Option<LanguageServerBinary>;
280
281 fn can_be_reinstalled(&self) -> bool {
282 true
283 }
284
285 async fn installation_test_binary(
286 &self,
287 container_dir: PathBuf,
288 ) -> Option<LanguageServerBinary>;
289
290 fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
291
292 async fn process_completion(&self, _: &mut lsp::CompletionItem) {}
293
294 async fn label_for_completion(
295 &self,
296 _: &lsp::CompletionItem,
297 _: &Arc<Language>,
298 ) -> Option<CodeLabel> {
299 None
300 }
301
302 async fn label_for_symbol(
303 &self,
304 _: &str,
305 _: lsp::SymbolKind,
306 _: &Arc<Language>,
307 ) -> Option<CodeLabel> {
308 None
309 }
310
311 async fn initialization_options(&self) -> Option<Value> {
312 None
313 }
314
315 fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> {
316 futures::future::ready(serde_json::json!({})).boxed()
317 }
318
319 fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
320 Some(vec![
321 CodeActionKind::EMPTY,
322 CodeActionKind::QUICKFIX,
323 CodeActionKind::REFACTOR,
324 CodeActionKind::REFACTOR_EXTRACT,
325 CodeActionKind::SOURCE,
326 ])
327 }
328
329 async fn disk_based_diagnostic_sources(&self) -> Vec<String> {
330 Default::default()
331 }
332
333 async fn disk_based_diagnostics_progress_token(&self) -> Option<String> {
334 None
335 }
336
337 async fn language_ids(&self) -> HashMap<String, String> {
338 Default::default()
339 }
340
341 fn prettier_plugins(&self) -> &[&'static str] {
342 &[]
343 }
344}
345
346#[derive(Clone, Debug, PartialEq, Eq)]
347pub struct CodeLabel {
348 pub text: String,
349 pub runs: Vec<(Range<usize>, HighlightId)>,
350 pub filter_range: Range<usize>,
351}
352
353#[derive(Clone, Deserialize)]
354pub struct LanguageConfig {
355 pub name: Arc<str>,
356 pub path_suffixes: Vec<String>,
357 pub brackets: BracketPairConfig,
358 #[serde(default, deserialize_with = "deserialize_regex")]
359 pub first_line_pattern: Option<Regex>,
360 #[serde(default = "auto_indent_using_last_non_empty_line_default")]
361 pub auto_indent_using_last_non_empty_line: bool,
362 #[serde(default, deserialize_with = "deserialize_regex")]
363 pub increase_indent_pattern: Option<Regex>,
364 #[serde(default, deserialize_with = "deserialize_regex")]
365 pub decrease_indent_pattern: Option<Regex>,
366 #[serde(default)]
367 pub autoclose_before: String,
368 #[serde(default)]
369 pub line_comment: Option<Arc<str>>,
370 #[serde(default)]
371 pub collapsed_placeholder: String,
372 #[serde(default)]
373 pub block_comment: Option<(Arc<str>, Arc<str>)>,
374 #[serde(default)]
375 pub scope_opt_in_language_servers: Vec<String>,
376 #[serde(default)]
377 pub overrides: HashMap<String, LanguageConfigOverride>,
378 #[serde(default)]
379 pub word_characters: HashSet<char>,
380 #[serde(default)]
381 pub prettier_parser_name: Option<String>,
382}
383
384#[derive(Debug, Default)]
385pub struct LanguageQueries {
386 pub highlights: Option<Cow<'static, str>>,
387 pub brackets: Option<Cow<'static, str>>,
388 pub indents: Option<Cow<'static, str>>,
389 pub outline: Option<Cow<'static, str>>,
390 pub embedding: Option<Cow<'static, str>>,
391 pub injections: Option<Cow<'static, str>>,
392 pub overrides: Option<Cow<'static, str>>,
393}
394
395#[derive(Clone, Debug)]
396pub struct LanguageScope {
397 language: Arc<Language>,
398 override_id: Option<u32>,
399}
400
401#[derive(Clone, Deserialize, Default, Debug)]
402pub struct LanguageConfigOverride {
403 #[serde(default)]
404 pub line_comment: Override<Arc<str>>,
405 #[serde(default)]
406 pub block_comment: Override<(Arc<str>, Arc<str>)>,
407 #[serde(skip_deserializing)]
408 pub disabled_bracket_ixs: Vec<u16>,
409 #[serde(default)]
410 pub word_characters: Override<HashSet<char>>,
411 #[serde(default)]
412 pub opt_into_language_servers: Vec<String>,
413}
414
415#[derive(Clone, Deserialize, Debug)]
416#[serde(untagged)]
417pub enum Override<T> {
418 Remove { remove: bool },
419 Set(T),
420}
421
422impl<T> Default for Override<T> {
423 fn default() -> Self {
424 Override::Remove { remove: false }
425 }
426}
427
428impl<T> Override<T> {
429 fn as_option<'a>(this: Option<&'a Self>, original: Option<&'a T>) -> Option<&'a T> {
430 match this {
431 Some(Self::Set(value)) => Some(value),
432 Some(Self::Remove { remove: true }) => None,
433 Some(Self::Remove { remove: false }) | None => original,
434 }
435 }
436}
437
438impl Default for LanguageConfig {
439 fn default() -> Self {
440 Self {
441 name: "".into(),
442 path_suffixes: Default::default(),
443 brackets: Default::default(),
444 auto_indent_using_last_non_empty_line: auto_indent_using_last_non_empty_line_default(),
445 first_line_pattern: Default::default(),
446 increase_indent_pattern: Default::default(),
447 decrease_indent_pattern: Default::default(),
448 autoclose_before: Default::default(),
449 line_comment: Default::default(),
450 block_comment: Default::default(),
451 scope_opt_in_language_servers: Default::default(),
452 overrides: Default::default(),
453 collapsed_placeholder: Default::default(),
454 word_characters: Default::default(),
455 prettier_parser_name: None,
456 }
457 }
458}
459
460fn auto_indent_using_last_non_empty_line_default() -> bool {
461 true
462}
463
464fn deserialize_regex<'de, D: Deserializer<'de>>(d: D) -> Result<Option<Regex>, D::Error> {
465 let source = Option::<String>::deserialize(d)?;
466 if let Some(source) = source {
467 Ok(Some(regex::Regex::new(&source).map_err(de::Error::custom)?))
468 } else {
469 Ok(None)
470 }
471}
472
473#[cfg(any(test, feature = "test-support"))]
474pub struct FakeLspAdapter {
475 pub name: &'static str,
476 pub initialization_options: Option<Value>,
477 pub capabilities: lsp::ServerCapabilities,
478 pub initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,
479 pub disk_based_diagnostics_progress_token: Option<String>,
480 pub disk_based_diagnostics_sources: Vec<String>,
481 pub prettier_plugins: Vec<&'static str>,
482}
483
484#[derive(Clone, Debug, Default)]
485pub struct BracketPairConfig {
486 pub pairs: Vec<BracketPair>,
487 pub disabled_scopes_by_bracket_ix: Vec<Vec<String>>,
488}
489
490impl<'de> Deserialize<'de> for BracketPairConfig {
491 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
492 where
493 D: Deserializer<'de>,
494 {
495 #[derive(Deserialize)]
496 pub struct Entry {
497 #[serde(flatten)]
498 pub bracket_pair: BracketPair,
499 #[serde(default)]
500 pub not_in: Vec<String>,
501 }
502
503 let result = Vec::<Entry>::deserialize(deserializer)?;
504 let mut brackets = Vec::with_capacity(result.len());
505 let mut disabled_scopes_by_bracket_ix = Vec::with_capacity(result.len());
506 for entry in result {
507 brackets.push(entry.bracket_pair);
508 disabled_scopes_by_bracket_ix.push(entry.not_in);
509 }
510
511 Ok(BracketPairConfig {
512 pairs: brackets,
513 disabled_scopes_by_bracket_ix,
514 })
515 }
516}
517
518#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
519pub struct BracketPair {
520 pub start: String,
521 pub end: String,
522 pub close: bool,
523 pub newline: bool,
524}
525
526pub struct Language {
527 pub(crate) config: LanguageConfig,
528 pub(crate) grammar: Option<Arc<Grammar>>,
529 pub(crate) adapters: Vec<Arc<CachedLspAdapter>>,
530
531 #[cfg(any(test, feature = "test-support"))]
532 fake_adapter: Option<(
533 mpsc::UnboundedSender<lsp::FakeLanguageServer>,
534 Arc<FakeLspAdapter>,
535 )>,
536}
537
538pub struct Grammar {
539 id: usize,
540 pub ts_language: tree_sitter::Language,
541 pub(crate) error_query: Query,
542 pub(crate) highlights_query: Option<Query>,
543 pub(crate) brackets_config: Option<BracketConfig>,
544 pub(crate) indents_config: Option<IndentConfig>,
545 pub outline_config: Option<OutlineConfig>,
546 pub embedding_config: Option<EmbeddingConfig>,
547 pub(crate) injection_config: Option<InjectionConfig>,
548 pub(crate) override_config: Option<OverrideConfig>,
549 pub(crate) highlight_map: Mutex<HighlightMap>,
550}
551
552struct IndentConfig {
553 query: Query,
554 indent_capture_ix: u32,
555 start_capture_ix: Option<u32>,
556 end_capture_ix: Option<u32>,
557 outdent_capture_ix: Option<u32>,
558}
559
560pub struct OutlineConfig {
561 pub query: Query,
562 pub item_capture_ix: u32,
563 pub name_capture_ix: u32,
564 pub context_capture_ix: Option<u32>,
565 pub extra_context_capture_ix: Option<u32>,
566}
567
568#[derive(Debug)]
569pub struct EmbeddingConfig {
570 pub query: Query,
571 pub item_capture_ix: u32,
572 pub name_capture_ix: Option<u32>,
573 pub context_capture_ix: Option<u32>,
574 pub collapse_capture_ix: Option<u32>,
575 pub keep_capture_ix: Option<u32>,
576}
577
578struct InjectionConfig {
579 query: Query,
580 content_capture_ix: u32,
581 language_capture_ix: Option<u32>,
582 patterns: Vec<InjectionPatternConfig>,
583}
584
585struct OverrideConfig {
586 query: Query,
587 values: HashMap<u32, (String, LanguageConfigOverride)>,
588}
589
590#[derive(Default, Clone)]
591struct InjectionPatternConfig {
592 language: Option<Box<str>>,
593 combined: bool,
594}
595
596struct BracketConfig {
597 query: Query,
598 open_capture_ix: u32,
599 close_capture_ix: u32,
600}
601
602#[derive(Clone)]
603pub enum LanguageServerBinaryStatus {
604 CheckingForUpdate,
605 Downloading,
606 Downloaded,
607 Cached,
608 Failed { error: String },
609}
610
611type AvailableLanguageId = usize;
612
613#[derive(Clone)]
614struct AvailableLanguage {
615 id: AvailableLanguageId,
616 path: &'static str,
617 config: LanguageConfig,
618 grammar: tree_sitter::Language,
619 lsp_adapters: Vec<Arc<dyn LspAdapter>>,
620 get_queries: fn(&str) -> LanguageQueries,
621 loaded: bool,
622}
623
624pub struct LanguageRegistry {
625 state: RwLock<LanguageRegistryState>,
626 language_server_download_dir: Option<Arc<Path>>,
627 login_shell_env_loaded: Shared<Task<()>>,
628 #[allow(clippy::type_complexity)]
629 lsp_binary_paths: Mutex<
630 HashMap<LanguageServerName, Shared<Task<Result<LanguageServerBinary, Arc<anyhow::Error>>>>>,
631 >,
632 executor: Option<Arc<Background>>,
633 lsp_binary_status_tx: LspBinaryStatusSender,
634}
635
636struct LanguageRegistryState {
637 next_language_server_id: usize,
638 languages: Vec<Arc<Language>>,
639 available_languages: Vec<AvailableLanguage>,
640 next_available_language_id: AvailableLanguageId,
641 loading_languages: HashMap<AvailableLanguageId, Vec<oneshot::Sender<Result<Arc<Language>>>>>,
642 subscription: (watch::Sender<()>, watch::Receiver<()>),
643 theme: Option<Arc<Theme>>,
644 version: usize,
645 reload_count: usize,
646}
647
648pub struct PendingLanguageServer {
649 pub server_id: LanguageServerId,
650 pub task: Task<Result<lsp::LanguageServer>>,
651 pub container_dir: Option<Arc<Path>>,
652}
653
654impl LanguageRegistry {
655 pub fn new(login_shell_env_loaded: Task<()>) -> Self {
656 Self {
657 state: RwLock::new(LanguageRegistryState {
658 next_language_server_id: 0,
659 languages: vec![PLAIN_TEXT.clone()],
660 available_languages: Default::default(),
661 next_available_language_id: 0,
662 loading_languages: Default::default(),
663 subscription: watch::channel(),
664 theme: Default::default(),
665 version: 0,
666 reload_count: 0,
667 }),
668 language_server_download_dir: None,
669 login_shell_env_loaded: login_shell_env_loaded.shared(),
670 lsp_binary_paths: Default::default(),
671 executor: None,
672 lsp_binary_status_tx: Default::default(),
673 }
674 }
675
676 #[cfg(any(test, feature = "test-support"))]
677 pub fn test() -> Self {
678 Self::new(Task::ready(()))
679 }
680
681 pub fn set_executor(&mut self, executor: Arc<Background>) {
682 self.executor = Some(executor);
683 }
684
685 /// Clear out all of the loaded languages and reload them from scratch.
686 ///
687 /// This is useful in development, when queries have changed.
688 #[cfg(debug_assertions)]
689 pub fn reload(&self) {
690 self.state.write().reload();
691 }
692
693 pub fn register(
694 &self,
695 path: &'static str,
696 config: LanguageConfig,
697 grammar: tree_sitter::Language,
698 lsp_adapters: Vec<Arc<dyn LspAdapter>>,
699 get_queries: fn(&str) -> LanguageQueries,
700 ) {
701 let state = &mut *self.state.write();
702 state.available_languages.push(AvailableLanguage {
703 id: post_inc(&mut state.next_available_language_id),
704 path,
705 config,
706 grammar,
707 lsp_adapters,
708 get_queries,
709 loaded: false,
710 });
711 }
712
713 pub fn language_names(&self) -> Vec<String> {
714 let state = self.state.read();
715 let mut result = state
716 .available_languages
717 .iter()
718 .filter_map(|l| l.loaded.not().then_some(l.config.name.to_string()))
719 .chain(state.languages.iter().map(|l| l.config.name.to_string()))
720 .collect::<Vec<_>>();
721 result.sort_unstable_by_key(|language_name| language_name.to_lowercase());
722 result
723 }
724
725 pub fn add(&self, language: Arc<Language>) {
726 self.state.write().add(language);
727 }
728
729 pub fn subscribe(&self) -> watch::Receiver<()> {
730 self.state.read().subscription.1.clone()
731 }
732
733 /// The number of times that the registry has been changed,
734 /// by adding languages or reloading.
735 pub fn version(&self) -> usize {
736 self.state.read().version
737 }
738
739 /// The number of times that the registry has been reloaded.
740 pub fn reload_count(&self) -> usize {
741 self.state.read().reload_count
742 }
743
744 pub fn set_theme(&self, theme: Arc<Theme>) {
745 let mut state = self.state.write();
746 state.theme = Some(theme.clone());
747 for language in &state.languages {
748 language.set_theme(&theme.editor.syntax);
749 }
750 }
751
752 pub fn set_language_server_download_dir(&mut self, path: impl Into<Arc<Path>>) {
753 self.language_server_download_dir = Some(path.into());
754 }
755
756 pub fn language_for_name(
757 self: &Arc<Self>,
758 name: &str,
759 ) -> UnwrapFuture<oneshot::Receiver<Result<Arc<Language>>>> {
760 let name = UniCase::new(name);
761 self.get_or_load_language(|config| UniCase::new(config.name.as_ref()) == name)
762 }
763
764 pub fn language_for_name_or_extension(
765 self: &Arc<Self>,
766 string: &str,
767 ) -> UnwrapFuture<oneshot::Receiver<Result<Arc<Language>>>> {
768 let string = UniCase::new(string);
769 self.get_or_load_language(|config| {
770 UniCase::new(config.name.as_ref()) == string
771 || config
772 .path_suffixes
773 .iter()
774 .any(|suffix| UniCase::new(suffix) == string)
775 })
776 }
777
778 pub fn language_for_file(
779 self: &Arc<Self>,
780 path: impl AsRef<Path>,
781 content: Option<&Rope>,
782 ) -> UnwrapFuture<oneshot::Receiver<Result<Arc<Language>>>> {
783 let path = path.as_ref();
784 let filename = path.file_name().and_then(|name| name.to_str());
785 let extension = path.extension_or_hidden_file_name();
786 let path_suffixes = [extension, filename];
787 self.get_or_load_language(|config| {
788 let path_matches = config
789 .path_suffixes
790 .iter()
791 .any(|suffix| path_suffixes.contains(&Some(suffix.as_str())));
792 let content_matches = content.zip(config.first_line_pattern.as_ref()).map_or(
793 false,
794 |(content, pattern)| {
795 let end = content.clip_point(Point::new(0, 256), Bias::Left);
796 let end = content.point_to_offset(end);
797 let text = content.chunks_in_range(0..end).collect::<String>();
798 pattern.is_match(&text)
799 },
800 );
801 path_matches || content_matches
802 })
803 }
804
805 fn get_or_load_language(
806 self: &Arc<Self>,
807 callback: impl Fn(&LanguageConfig) -> bool,
808 ) -> UnwrapFuture<oneshot::Receiver<Result<Arc<Language>>>> {
809 let (tx, rx) = oneshot::channel();
810
811 let mut state = self.state.write();
812 if let Some(language) = state
813 .languages
814 .iter()
815 .find(|language| callback(&language.config))
816 {
817 let _ = tx.send(Ok(language.clone()));
818 } else if let Some(executor) = self.executor.clone() {
819 if let Some(language) = state
820 .available_languages
821 .iter()
822 .find(|l| !l.loaded && callback(&l.config))
823 .cloned()
824 {
825 let txs = state
826 .loading_languages
827 .entry(language.id)
828 .or_insert_with(|| {
829 let this = self.clone();
830 executor
831 .spawn(async move {
832 let id = language.id;
833 let queries = (language.get_queries)(&language.path);
834 let language =
835 Language::new(language.config, Some(language.grammar))
836 .with_lsp_adapters(language.lsp_adapters)
837 .await;
838 let name = language.name();
839 match language.with_queries(queries) {
840 Ok(language) => {
841 let language = Arc::new(language);
842 let mut state = this.state.write();
843
844 state.add(language.clone());
845 state.mark_language_loaded(id);
846 if let Some(mut txs) = state.loading_languages.remove(&id) {
847 for tx in txs.drain(..) {
848 let _ = tx.send(Ok(language.clone()));
849 }
850 }
851 }
852 Err(e) => {
853 log::error!("failed to load language {name}:\n{:?}", e);
854 let mut state = this.state.write();
855 state.mark_language_loaded(id);
856 if let Some(mut txs) = state.loading_languages.remove(&id) {
857 for tx in txs.drain(..) {
858 let _ = tx.send(Err(anyhow!(
859 "failed to load language {}: {}",
860 name,
861 e
862 )));
863 }
864 }
865 }
866 };
867 })
868 .detach();
869
870 Vec::new()
871 });
872 txs.push(tx);
873 } else {
874 let _ = tx.send(Err(anyhow!("language not found")));
875 }
876 } else {
877 let _ = tx.send(Err(anyhow!("executor does not exist")));
878 }
879
880 rx.unwrap()
881 }
882
883 pub fn to_vec(&self) -> Vec<Arc<Language>> {
884 self.state.read().languages.iter().cloned().collect()
885 }
886
887 pub fn create_pending_language_server(
888 self: &Arc<Self>,
889 stderr_capture: Arc<Mutex<Option<String>>>,
890 language: Arc<Language>,
891 adapter: Arc<CachedLspAdapter>,
892 root_path: Arc<Path>,
893 delegate: Arc<dyn LspAdapterDelegate>,
894 cx: &mut AppContext,
895 ) -> Option<PendingLanguageServer> {
896 let server_id = self.state.write().next_language_server_id();
897 log::info!(
898 "starting language server {:?}, path: {root_path:?}, id: {server_id}",
899 adapter.name.0
900 );
901
902 #[cfg(any(test, feature = "test-support"))]
903 if language.fake_adapter.is_some() {
904 let task = cx.spawn(|cx| async move {
905 let (servers_tx, fake_adapter) = language.fake_adapter.as_ref().unwrap();
906 let (server, mut fake_server) = lsp::LanguageServer::fake(
907 fake_adapter.name.to_string(),
908 fake_adapter.capabilities.clone(),
909 cx.clone(),
910 );
911
912 if let Some(initializer) = &fake_adapter.initializer {
913 initializer(&mut fake_server);
914 }
915
916 let servers_tx = servers_tx.clone();
917 cx.background()
918 .spawn(async move {
919 if fake_server
920 .try_receive_notification::<lsp::notification::Initialized>()
921 .await
922 .is_some()
923 {
924 servers_tx.unbounded_send(fake_server).ok();
925 }
926 })
927 .detach();
928
929 Ok(server)
930 });
931
932 return Some(PendingLanguageServer {
933 server_id,
934 task,
935 container_dir: None,
936 });
937 }
938
939 let download_dir = self
940 .language_server_download_dir
941 .clone()
942 .ok_or_else(|| anyhow!("language server download directory has not been assigned before starting server"))
943 .log_err()?;
944 let this = self.clone();
945 let language = language.clone();
946 let container_dir: Arc<Path> = Arc::from(download_dir.join(adapter.name.0.as_ref()));
947 let root_path = root_path.clone();
948 let adapter = adapter.clone();
949 let login_shell_env_loaded = self.login_shell_env_loaded.clone();
950 let lsp_binary_statuses = self.lsp_binary_status_tx.clone();
951
952 let task = {
953 let container_dir = container_dir.clone();
954 cx.spawn(|mut cx| async move {
955 login_shell_env_loaded.await;
956
957 let mut lock = this.lsp_binary_paths.lock();
958 let entry = lock
959 .entry(adapter.name.clone())
960 .or_insert_with(|| {
961 cx.spawn(|cx| {
962 get_binary(
963 adapter.clone(),
964 language.clone(),
965 delegate.clone(),
966 container_dir,
967 lsp_binary_statuses,
968 cx,
969 )
970 .map_err(Arc::new)
971 })
972 .shared()
973 })
974 .clone();
975 drop(lock);
976
977 let binary = match entry.clone().await {
978 Ok(binary) => binary,
979 Err(err) => anyhow::bail!("{err}"),
980 };
981
982 if let Some(task) = adapter.will_start_server(&delegate, &mut cx) {
983 task.await?;
984 }
985
986 lsp::LanguageServer::new(
987 stderr_capture,
988 server_id,
989 binary,
990 &root_path,
991 adapter.code_action_kinds(),
992 cx,
993 )
994 })
995 };
996
997 Some(PendingLanguageServer {
998 server_id,
999 task,
1000 container_dir: Some(container_dir),
1001 })
1002 }
1003
1004 pub fn language_server_binary_statuses(
1005 &self,
1006 ) -> mpsc::UnboundedReceiver<(Arc<Language>, LanguageServerBinaryStatus)> {
1007 self.lsp_binary_status_tx.subscribe()
1008 }
1009
1010 pub fn delete_server_container(
1011 &self,
1012 adapter: Arc<CachedLspAdapter>,
1013 cx: &mut AppContext,
1014 ) -> Task<()> {
1015 log::info!("deleting server container");
1016
1017 let mut lock = self.lsp_binary_paths.lock();
1018 lock.remove(&adapter.name);
1019
1020 let download_dir = self
1021 .language_server_download_dir
1022 .clone()
1023 .expect("language server download directory has not been assigned before deleting server container");
1024
1025 cx.spawn(|_| async move {
1026 let container_dir = download_dir.join(adapter.name.0.as_ref());
1027 smol::fs::remove_dir_all(container_dir)
1028 .await
1029 .context("server container removal")
1030 .log_err();
1031 })
1032 }
1033
1034 pub fn next_language_server_id(&self) -> LanguageServerId {
1035 self.state.write().next_language_server_id()
1036 }
1037}
1038
1039impl LanguageRegistryState {
1040 fn next_language_server_id(&mut self) -> LanguageServerId {
1041 LanguageServerId(post_inc(&mut self.next_language_server_id))
1042 }
1043
1044 fn add(&mut self, language: Arc<Language>) {
1045 if let Some(theme) = self.theme.as_ref() {
1046 language.set_theme(&theme.editor.syntax);
1047 }
1048 self.languages.push(language);
1049 self.version += 1;
1050 *self.subscription.0.borrow_mut() = ();
1051 }
1052
1053 #[cfg(debug_assertions)]
1054 fn reload(&mut self) {
1055 self.languages.clear();
1056 self.version += 1;
1057 self.reload_count += 1;
1058 for language in &mut self.available_languages {
1059 language.loaded = false;
1060 }
1061 *self.subscription.0.borrow_mut() = ();
1062 }
1063
1064 /// Mark the given language a having been loaded, so that the
1065 /// language registry won't try to load it again.
1066 fn mark_language_loaded(&mut self, id: AvailableLanguageId) {
1067 for language in &mut self.available_languages {
1068 if language.id == id {
1069 language.loaded = true;
1070 break;
1071 }
1072 }
1073 }
1074}
1075
1076#[cfg(any(test, feature = "test-support"))]
1077impl Default for LanguageRegistry {
1078 fn default() -> Self {
1079 Self::test()
1080 }
1081}
1082
1083async fn get_binary(
1084 adapter: Arc<CachedLspAdapter>,
1085 language: Arc<Language>,
1086 delegate: Arc<dyn LspAdapterDelegate>,
1087 container_dir: Arc<Path>,
1088 statuses: LspBinaryStatusSender,
1089 mut cx: AsyncAppContext,
1090) -> Result<LanguageServerBinary> {
1091 if !container_dir.exists() {
1092 smol::fs::create_dir_all(&container_dir)
1093 .await
1094 .context("failed to create container directory")?;
1095 }
1096
1097 if let Some(task) = adapter.will_fetch_server(&delegate, &mut cx) {
1098 task.await?;
1099 }
1100
1101 let binary = fetch_latest_binary(
1102 adapter.clone(),
1103 language.clone(),
1104 delegate.as_ref(),
1105 &container_dir,
1106 statuses.clone(),
1107 )
1108 .await;
1109
1110 if let Err(error) = binary.as_ref() {
1111 if let Some(binary) = adapter
1112 .cached_server_binary(container_dir.to_path_buf(), delegate.as_ref())
1113 .await
1114 {
1115 statuses.send(language.clone(), LanguageServerBinaryStatus::Cached);
1116 return Ok(binary);
1117 } else {
1118 statuses.send(
1119 language.clone(),
1120 LanguageServerBinaryStatus::Failed {
1121 error: format!("{:?}", error),
1122 },
1123 );
1124 }
1125 }
1126
1127 binary
1128}
1129
1130async fn fetch_latest_binary(
1131 adapter: Arc<CachedLspAdapter>,
1132 language: Arc<Language>,
1133 delegate: &dyn LspAdapterDelegate,
1134 container_dir: &Path,
1135 lsp_binary_statuses_tx: LspBinaryStatusSender,
1136) -> Result<LanguageServerBinary> {
1137 let container_dir: Arc<Path> = container_dir.into();
1138 lsp_binary_statuses_tx.send(
1139 language.clone(),
1140 LanguageServerBinaryStatus::CheckingForUpdate,
1141 );
1142
1143 let version_info = adapter.fetch_latest_server_version(delegate).await?;
1144 lsp_binary_statuses_tx.send(language.clone(), LanguageServerBinaryStatus::Downloading);
1145
1146 let binary = adapter
1147 .fetch_server_binary(version_info, container_dir.to_path_buf(), delegate)
1148 .await?;
1149 lsp_binary_statuses_tx.send(language.clone(), LanguageServerBinaryStatus::Downloaded);
1150
1151 Ok(binary)
1152}
1153
1154impl Language {
1155 pub fn new(config: LanguageConfig, ts_language: Option<tree_sitter::Language>) -> Self {
1156 Self {
1157 config,
1158 grammar: ts_language.map(|ts_language| {
1159 Arc::new(Grammar {
1160 id: NEXT_GRAMMAR_ID.fetch_add(1, SeqCst),
1161 highlights_query: None,
1162 brackets_config: None,
1163 outline_config: None,
1164 embedding_config: None,
1165 indents_config: None,
1166 injection_config: None,
1167 override_config: None,
1168 error_query: Query::new(ts_language, "(ERROR) @error").unwrap(),
1169 ts_language,
1170 highlight_map: Default::default(),
1171 })
1172 }),
1173 adapters: Vec::new(),
1174
1175 #[cfg(any(test, feature = "test-support"))]
1176 fake_adapter: None,
1177 }
1178 }
1179
1180 pub fn lsp_adapters(&self) -> &[Arc<CachedLspAdapter>] {
1181 &self.adapters
1182 }
1183
1184 pub fn id(&self) -> Option<usize> {
1185 self.grammar.as_ref().map(|g| g.id)
1186 }
1187
1188 pub fn with_queries(mut self, queries: LanguageQueries) -> Result<Self> {
1189 if let Some(query) = queries.highlights {
1190 self = self
1191 .with_highlights_query(query.as_ref())
1192 .context("Error loading highlights query")?;
1193 }
1194 if let Some(query) = queries.brackets {
1195 self = self
1196 .with_brackets_query(query.as_ref())
1197 .context("Error loading brackets query")?;
1198 }
1199 if let Some(query) = queries.indents {
1200 self = self
1201 .with_indents_query(query.as_ref())
1202 .context("Error loading indents query")?;
1203 }
1204 if let Some(query) = queries.outline {
1205 self = self
1206 .with_outline_query(query.as_ref())
1207 .context("Error loading outline query")?;
1208 }
1209 if let Some(query) = queries.embedding {
1210 self = self
1211 .with_embedding_query(query.as_ref())
1212 .context("Error loading embedding query")?;
1213 }
1214 if let Some(query) = queries.injections {
1215 self = self
1216 .with_injection_query(query.as_ref())
1217 .context("Error loading injection query")?;
1218 }
1219 if let Some(query) = queries.overrides {
1220 self = self
1221 .with_override_query(query.as_ref())
1222 .context("Error loading override query")?;
1223 }
1224 Ok(self)
1225 }
1226
1227 pub fn with_highlights_query(mut self, source: &str) -> Result<Self> {
1228 let grammar = self.grammar_mut();
1229 grammar.highlights_query = Some(Query::new(grammar.ts_language, source)?);
1230 Ok(self)
1231 }
1232
1233 pub fn with_outline_query(mut self, source: &str) -> Result<Self> {
1234 let grammar = self.grammar_mut();
1235 let query = Query::new(grammar.ts_language, source)?;
1236 let mut item_capture_ix = None;
1237 let mut name_capture_ix = None;
1238 let mut context_capture_ix = None;
1239 let mut extra_context_capture_ix = None;
1240 get_capture_indices(
1241 &query,
1242 &mut [
1243 ("item", &mut item_capture_ix),
1244 ("name", &mut name_capture_ix),
1245 ("context", &mut context_capture_ix),
1246 ("context.extra", &mut extra_context_capture_ix),
1247 ],
1248 );
1249 if let Some((item_capture_ix, name_capture_ix)) = item_capture_ix.zip(name_capture_ix) {
1250 grammar.outline_config = Some(OutlineConfig {
1251 query,
1252 item_capture_ix,
1253 name_capture_ix,
1254 context_capture_ix,
1255 extra_context_capture_ix,
1256 });
1257 }
1258 Ok(self)
1259 }
1260
1261 pub fn with_embedding_query(mut self, source: &str) -> Result<Self> {
1262 let grammar = self.grammar_mut();
1263 let query = Query::new(grammar.ts_language, source)?;
1264 let mut item_capture_ix = None;
1265 let mut name_capture_ix = None;
1266 let mut context_capture_ix = None;
1267 let mut collapse_capture_ix = None;
1268 let mut keep_capture_ix = None;
1269 get_capture_indices(
1270 &query,
1271 &mut [
1272 ("item", &mut item_capture_ix),
1273 ("name", &mut name_capture_ix),
1274 ("context", &mut context_capture_ix),
1275 ("keep", &mut keep_capture_ix),
1276 ("collapse", &mut collapse_capture_ix),
1277 ],
1278 );
1279 if let Some(item_capture_ix) = item_capture_ix {
1280 grammar.embedding_config = Some(EmbeddingConfig {
1281 query,
1282 item_capture_ix,
1283 name_capture_ix,
1284 context_capture_ix,
1285 collapse_capture_ix,
1286 keep_capture_ix,
1287 });
1288 }
1289 Ok(self)
1290 }
1291
1292 pub fn with_brackets_query(mut self, source: &str) -> Result<Self> {
1293 let grammar = self.grammar_mut();
1294 let query = Query::new(grammar.ts_language, source)?;
1295 let mut open_capture_ix = None;
1296 let mut close_capture_ix = None;
1297 get_capture_indices(
1298 &query,
1299 &mut [
1300 ("open", &mut open_capture_ix),
1301 ("close", &mut close_capture_ix),
1302 ],
1303 );
1304 if let Some((open_capture_ix, close_capture_ix)) = open_capture_ix.zip(close_capture_ix) {
1305 grammar.brackets_config = Some(BracketConfig {
1306 query,
1307 open_capture_ix,
1308 close_capture_ix,
1309 });
1310 }
1311 Ok(self)
1312 }
1313
1314 pub fn with_indents_query(mut self, source: &str) -> Result<Self> {
1315 let grammar = self.grammar_mut();
1316 let query = Query::new(grammar.ts_language, source)?;
1317 let mut indent_capture_ix = None;
1318 let mut start_capture_ix = None;
1319 let mut end_capture_ix = None;
1320 let mut outdent_capture_ix = None;
1321 get_capture_indices(
1322 &query,
1323 &mut [
1324 ("indent", &mut indent_capture_ix),
1325 ("start", &mut start_capture_ix),
1326 ("end", &mut end_capture_ix),
1327 ("outdent", &mut outdent_capture_ix),
1328 ],
1329 );
1330 if let Some(indent_capture_ix) = indent_capture_ix {
1331 grammar.indents_config = Some(IndentConfig {
1332 query,
1333 indent_capture_ix,
1334 start_capture_ix,
1335 end_capture_ix,
1336 outdent_capture_ix,
1337 });
1338 }
1339 Ok(self)
1340 }
1341
1342 pub fn with_injection_query(mut self, source: &str) -> Result<Self> {
1343 let grammar = self.grammar_mut();
1344 let query = Query::new(grammar.ts_language, source)?;
1345 let mut language_capture_ix = None;
1346 let mut content_capture_ix = None;
1347 get_capture_indices(
1348 &query,
1349 &mut [
1350 ("language", &mut language_capture_ix),
1351 ("content", &mut content_capture_ix),
1352 ],
1353 );
1354 let patterns = (0..query.pattern_count())
1355 .map(|ix| {
1356 let mut config = InjectionPatternConfig::default();
1357 for setting in query.property_settings(ix) {
1358 match setting.key.as_ref() {
1359 "language" => {
1360 config.language = setting.value.clone();
1361 }
1362 "combined" => {
1363 config.combined = true;
1364 }
1365 _ => {}
1366 }
1367 }
1368 config
1369 })
1370 .collect();
1371 if let Some(content_capture_ix) = content_capture_ix {
1372 grammar.injection_config = Some(InjectionConfig {
1373 query,
1374 language_capture_ix,
1375 content_capture_ix,
1376 patterns,
1377 });
1378 }
1379 Ok(self)
1380 }
1381
1382 pub fn with_override_query(mut self, source: &str) -> anyhow::Result<Self> {
1383 let query = Query::new(self.grammar_mut().ts_language, source)?;
1384
1385 let mut override_configs_by_id = HashMap::default();
1386 for (ix, name) in query.capture_names().iter().enumerate() {
1387 if !name.starts_with('_') {
1388 let value = self.config.overrides.remove(name).unwrap_or_default();
1389 for server_name in &value.opt_into_language_servers {
1390 if !self
1391 .config
1392 .scope_opt_in_language_servers
1393 .contains(server_name)
1394 {
1395 util::debug_panic!("Server {server_name:?} has been opted-in by scope {name:?} but has not been marked as an opt-in server");
1396 }
1397 }
1398
1399 override_configs_by_id.insert(ix as u32, (name.clone(), value));
1400 }
1401 }
1402
1403 if !self.config.overrides.is_empty() {
1404 let keys = self.config.overrides.keys().collect::<Vec<_>>();
1405 Err(anyhow!(
1406 "language {:?} has overrides in config not in query: {keys:?}",
1407 self.config.name
1408 ))?;
1409 }
1410
1411 for disabled_scope_name in self
1412 .config
1413 .brackets
1414 .disabled_scopes_by_bracket_ix
1415 .iter()
1416 .flatten()
1417 {
1418 if !override_configs_by_id
1419 .values()
1420 .any(|(scope_name, _)| scope_name == disabled_scope_name)
1421 {
1422 Err(anyhow!(
1423 "language {:?} has overrides in config not in query: {disabled_scope_name:?}",
1424 self.config.name
1425 ))?;
1426 }
1427 }
1428
1429 for (name, override_config) in override_configs_by_id.values_mut() {
1430 override_config.disabled_bracket_ixs = self
1431 .config
1432 .brackets
1433 .disabled_scopes_by_bracket_ix
1434 .iter()
1435 .enumerate()
1436 .filter_map(|(ix, disabled_scope_names)| {
1437 if disabled_scope_names.contains(name) {
1438 Some(ix as u16)
1439 } else {
1440 None
1441 }
1442 })
1443 .collect();
1444 }
1445
1446 self.config.brackets.disabled_scopes_by_bracket_ix.clear();
1447 self.grammar_mut().override_config = Some(OverrideConfig {
1448 query,
1449 values: override_configs_by_id,
1450 });
1451 Ok(self)
1452 }
1453
1454 fn grammar_mut(&mut self) -> &mut Grammar {
1455 Arc::get_mut(self.grammar.as_mut().unwrap()).unwrap()
1456 }
1457
1458 pub async fn with_lsp_adapters(mut self, lsp_adapters: Vec<Arc<dyn LspAdapter>>) -> Self {
1459 for adapter in lsp_adapters {
1460 self.adapters.push(CachedLspAdapter::new(adapter).await);
1461 }
1462 self
1463 }
1464
1465 #[cfg(any(test, feature = "test-support"))]
1466 pub async fn set_fake_lsp_adapter(
1467 &mut self,
1468 fake_lsp_adapter: Arc<FakeLspAdapter>,
1469 ) -> mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
1470 let (servers_tx, servers_rx) = mpsc::unbounded();
1471 self.fake_adapter = Some((servers_tx, fake_lsp_adapter.clone()));
1472 let adapter = CachedLspAdapter::new(Arc::new(fake_lsp_adapter)).await;
1473 self.adapters = vec![adapter];
1474 servers_rx
1475 }
1476
1477 pub fn name(&self) -> Arc<str> {
1478 self.config.name.clone()
1479 }
1480
1481 pub async fn disk_based_diagnostic_sources(&self) -> &[String] {
1482 match self.adapters.first().as_ref() {
1483 Some(adapter) => &adapter.disk_based_diagnostic_sources,
1484 None => &[],
1485 }
1486 }
1487
1488 pub async fn disk_based_diagnostics_progress_token(&self) -> Option<&str> {
1489 for adapter in &self.adapters {
1490 let token = adapter.disk_based_diagnostics_progress_token.as_deref();
1491 if token.is_some() {
1492 return token;
1493 }
1494 }
1495
1496 None
1497 }
1498
1499 pub async fn process_completion(self: &Arc<Self>, completion: &mut lsp::CompletionItem) {
1500 for adapter in &self.adapters {
1501 adapter.process_completion(completion).await;
1502 }
1503 }
1504
1505 pub async fn label_for_completion(
1506 self: &Arc<Self>,
1507 completion: &lsp::CompletionItem,
1508 ) -> Option<CodeLabel> {
1509 self.adapters
1510 .first()
1511 .as_ref()?
1512 .label_for_completion(completion, self)
1513 .await
1514 }
1515
1516 pub async fn label_for_symbol(
1517 self: &Arc<Self>,
1518 name: &str,
1519 kind: lsp::SymbolKind,
1520 ) -> Option<CodeLabel> {
1521 self.adapters
1522 .first()
1523 .as_ref()?
1524 .label_for_symbol(name, kind, self)
1525 .await
1526 }
1527
1528 pub fn highlight_text<'a>(
1529 self: &'a Arc<Self>,
1530 text: &'a Rope,
1531 range: Range<usize>,
1532 ) -> Vec<(Range<usize>, HighlightId)> {
1533 let mut result = Vec::new();
1534 if let Some(grammar) = &self.grammar {
1535 let tree = grammar.parse_text(text, None);
1536 let captures =
1537 SyntaxSnapshot::single_tree_captures(range.clone(), text, &tree, self, |grammar| {
1538 grammar.highlights_query.as_ref()
1539 });
1540 let highlight_maps = vec![grammar.highlight_map()];
1541 let mut offset = 0;
1542 for chunk in BufferChunks::new(text, range, Some((captures, highlight_maps)), vec![]) {
1543 let end_offset = offset + chunk.text.len();
1544 if let Some(highlight_id) = chunk.syntax_highlight_id {
1545 if !highlight_id.is_default() {
1546 result.push((offset..end_offset, highlight_id));
1547 }
1548 }
1549 offset = end_offset;
1550 }
1551 }
1552 result
1553 }
1554
1555 pub fn path_suffixes(&self) -> &[String] {
1556 &self.config.path_suffixes
1557 }
1558
1559 pub fn should_autoclose_before(&self, c: char) -> bool {
1560 c.is_whitespace() || self.config.autoclose_before.contains(c)
1561 }
1562
1563 pub fn set_theme(&self, theme: &SyntaxTheme) {
1564 if let Some(grammar) = self.grammar.as_ref() {
1565 if let Some(highlights_query) = &grammar.highlights_query {
1566 *grammar.highlight_map.lock() =
1567 HighlightMap::new(highlights_query.capture_names(), theme);
1568 }
1569 }
1570 }
1571
1572 pub fn grammar(&self) -> Option<&Arc<Grammar>> {
1573 self.grammar.as_ref()
1574 }
1575
1576 pub fn default_scope(self: &Arc<Self>) -> LanguageScope {
1577 LanguageScope {
1578 language: self.clone(),
1579 override_id: None,
1580 }
1581 }
1582
1583 pub fn prettier_parser_name(&self) -> Option<&str> {
1584 self.config.prettier_parser_name.as_deref()
1585 }
1586}
1587
1588impl LanguageScope {
1589 pub fn collapsed_placeholder(&self) -> &str {
1590 self.language.config.collapsed_placeholder.as_ref()
1591 }
1592
1593 pub fn line_comment_prefix(&self) -> Option<&Arc<str>> {
1594 Override::as_option(
1595 self.config_override().map(|o| &o.line_comment),
1596 self.language.config.line_comment.as_ref(),
1597 )
1598 }
1599
1600 pub fn block_comment_delimiters(&self) -> Option<(&Arc<str>, &Arc<str>)> {
1601 Override::as_option(
1602 self.config_override().map(|o| &o.block_comment),
1603 self.language.config.block_comment.as_ref(),
1604 )
1605 .map(|e| (&e.0, &e.1))
1606 }
1607
1608 pub fn word_characters(&self) -> Option<&HashSet<char>> {
1609 Override::as_option(
1610 self.config_override().map(|o| &o.word_characters),
1611 Some(&self.language.config.word_characters),
1612 )
1613 }
1614
1615 pub fn brackets(&self) -> impl Iterator<Item = (&BracketPair, bool)> {
1616 let mut disabled_ids = self
1617 .config_override()
1618 .map_or(&[] as _, |o| o.disabled_bracket_ixs.as_slice());
1619 self.language
1620 .config
1621 .brackets
1622 .pairs
1623 .iter()
1624 .enumerate()
1625 .map(move |(ix, bracket)| {
1626 let mut is_enabled = true;
1627 if let Some(next_disabled_ix) = disabled_ids.first() {
1628 if ix == *next_disabled_ix as usize {
1629 disabled_ids = &disabled_ids[1..];
1630 is_enabled = false;
1631 }
1632 }
1633 (bracket, is_enabled)
1634 })
1635 }
1636
1637 pub fn should_autoclose_before(&self, c: char) -> bool {
1638 c.is_whitespace() || self.language.config.autoclose_before.contains(c)
1639 }
1640
1641 pub fn language_allowed(&self, name: &LanguageServerName) -> bool {
1642 let config = &self.language.config;
1643 let opt_in_servers = &config.scope_opt_in_language_servers;
1644 if opt_in_servers.iter().any(|o| *o == *name.0) {
1645 if let Some(over) = self.config_override() {
1646 over.opt_into_language_servers.iter().any(|o| *o == *name.0)
1647 } else {
1648 false
1649 }
1650 } else {
1651 true
1652 }
1653 }
1654
1655 fn config_override(&self) -> Option<&LanguageConfigOverride> {
1656 let id = self.override_id?;
1657 let grammar = self.language.grammar.as_ref()?;
1658 let override_config = grammar.override_config.as_ref()?;
1659 override_config.values.get(&id).map(|e| &e.1)
1660 }
1661}
1662
1663impl Hash for Language {
1664 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1665 self.id().hash(state)
1666 }
1667}
1668
1669impl PartialEq for Language {
1670 fn eq(&self, other: &Self) -> bool {
1671 self.id().eq(&other.id())
1672 }
1673}
1674
1675impl Eq for Language {}
1676
1677impl Debug for Language {
1678 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1679 f.debug_struct("Language")
1680 .field("name", &self.config.name)
1681 .finish()
1682 }
1683}
1684
1685impl Grammar {
1686 pub fn id(&self) -> usize {
1687 self.id
1688 }
1689
1690 fn parse_text(&self, text: &Rope, old_tree: Option<Tree>) -> Tree {
1691 PARSER.with(|parser| {
1692 let mut parser = parser.borrow_mut();
1693 parser
1694 .set_language(self.ts_language)
1695 .expect("incompatible grammar");
1696 let mut chunks = text.chunks_in_range(0..text.len());
1697 parser
1698 .parse_with(
1699 &mut move |offset, _| {
1700 chunks.seek(offset);
1701 chunks.next().unwrap_or("").as_bytes()
1702 },
1703 old_tree.as_ref(),
1704 )
1705 .unwrap()
1706 })
1707 }
1708
1709 pub fn highlight_map(&self) -> HighlightMap {
1710 self.highlight_map.lock().clone()
1711 }
1712
1713 pub fn highlight_id_for_name(&self, name: &str) -> Option<HighlightId> {
1714 let capture_id = self
1715 .highlights_query
1716 .as_ref()?
1717 .capture_index_for_name(name)?;
1718 Some(self.highlight_map.lock().get(capture_id))
1719 }
1720}
1721
1722impl CodeLabel {
1723 pub fn plain(text: String, filter_text: Option<&str>) -> Self {
1724 let mut result = Self {
1725 runs: Vec::new(),
1726 filter_range: 0..text.len(),
1727 text,
1728 };
1729 if let Some(filter_text) = filter_text {
1730 if let Some(ix) = result.text.find(filter_text) {
1731 result.filter_range = ix..ix + filter_text.len();
1732 }
1733 }
1734 result
1735 }
1736}
1737
1738#[cfg(any(test, feature = "test-support"))]
1739impl Default for FakeLspAdapter {
1740 fn default() -> Self {
1741 Self {
1742 name: "the-fake-language-server",
1743 capabilities: lsp::LanguageServer::full_capabilities(),
1744 initializer: None,
1745 disk_based_diagnostics_progress_token: None,
1746 initialization_options: None,
1747 disk_based_diagnostics_sources: Vec::new(),
1748 prettier_plugins: Vec::new(),
1749 }
1750 }
1751}
1752
1753#[cfg(any(test, feature = "test-support"))]
1754#[async_trait]
1755impl LspAdapter for Arc<FakeLspAdapter> {
1756 async fn name(&self) -> LanguageServerName {
1757 LanguageServerName(self.name.into())
1758 }
1759
1760 fn short_name(&self) -> &'static str {
1761 "FakeLspAdapter"
1762 }
1763
1764 async fn fetch_latest_server_version(
1765 &self,
1766 _: &dyn LspAdapterDelegate,
1767 ) -> Result<Box<dyn 'static + Send + Any>> {
1768 unreachable!();
1769 }
1770
1771 async fn fetch_server_binary(
1772 &self,
1773 _: Box<dyn 'static + Send + Any>,
1774 _: PathBuf,
1775 _: &dyn LspAdapterDelegate,
1776 ) -> Result<LanguageServerBinary> {
1777 unreachable!();
1778 }
1779
1780 async fn cached_server_binary(
1781 &self,
1782 _: PathBuf,
1783 _: &dyn LspAdapterDelegate,
1784 ) -> Option<LanguageServerBinary> {
1785 unreachable!();
1786 }
1787
1788 async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
1789 unreachable!();
1790 }
1791
1792 fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
1793
1794 async fn disk_based_diagnostic_sources(&self) -> Vec<String> {
1795 self.disk_based_diagnostics_sources.clone()
1796 }
1797
1798 async fn disk_based_diagnostics_progress_token(&self) -> Option<String> {
1799 self.disk_based_diagnostics_progress_token.clone()
1800 }
1801
1802 async fn initialization_options(&self) -> Option<Value> {
1803 self.initialization_options.clone()
1804 }
1805
1806 fn prettier_plugins(&self) -> &[&'static str] {
1807 &self.prettier_plugins
1808 }
1809}
1810
1811fn get_capture_indices(query: &Query, captures: &mut [(&str, &mut Option<u32>)]) {
1812 for (ix, name) in query.capture_names().iter().enumerate() {
1813 for (capture_name, index) in captures.iter_mut() {
1814 if capture_name == name {
1815 **index = Some(ix as u32);
1816 break;
1817 }
1818 }
1819 }
1820}
1821
1822pub fn point_to_lsp(point: PointUtf16) -> lsp::Position {
1823 lsp::Position::new(point.row, point.column)
1824}
1825
1826pub fn point_from_lsp(point: lsp::Position) -> Unclipped<PointUtf16> {
1827 Unclipped(PointUtf16::new(point.line, point.character))
1828}
1829
1830pub fn range_to_lsp(range: Range<PointUtf16>) -> lsp::Range {
1831 lsp::Range {
1832 start: point_to_lsp(range.start),
1833 end: point_to_lsp(range.end),
1834 }
1835}
1836
1837pub fn range_from_lsp(range: lsp::Range) -> Range<Unclipped<PointUtf16>> {
1838 let mut start = point_from_lsp(range.start);
1839 let mut end = point_from_lsp(range.end);
1840 if start > end {
1841 mem::swap(&mut start, &mut end);
1842 }
1843 start..end
1844}
1845
1846#[cfg(test)]
1847mod tests {
1848 use super::*;
1849 use gpui::TestAppContext;
1850
1851 #[gpui::test(iterations = 10)]
1852 async fn test_first_line_pattern(cx: &mut TestAppContext) {
1853 let mut languages = LanguageRegistry::test();
1854 languages.set_executor(cx.background());
1855 let languages = Arc::new(languages);
1856 languages.register(
1857 "/javascript",
1858 LanguageConfig {
1859 name: "JavaScript".into(),
1860 path_suffixes: vec!["js".into()],
1861 first_line_pattern: Some(Regex::new(r"\bnode\b").unwrap()),
1862 ..Default::default()
1863 },
1864 tree_sitter_typescript::language_tsx(),
1865 vec![],
1866 |_| Default::default(),
1867 );
1868
1869 languages
1870 .language_for_file("the/script", None)
1871 .await
1872 .unwrap_err();
1873 languages
1874 .language_for_file("the/script", Some(&"nothing".into()))
1875 .await
1876 .unwrap_err();
1877 assert_eq!(
1878 languages
1879 .language_for_file("the/script", Some(&"#!/bin/env node".into()))
1880 .await
1881 .unwrap()
1882 .name()
1883 .as_ref(),
1884 "JavaScript"
1885 );
1886 }
1887
1888 #[gpui::test(iterations = 10)]
1889 async fn test_language_loading(cx: &mut TestAppContext) {
1890 let mut languages = LanguageRegistry::test();
1891 languages.set_executor(cx.background());
1892 let languages = Arc::new(languages);
1893 languages.register(
1894 "/JSON",
1895 LanguageConfig {
1896 name: "JSON".into(),
1897 path_suffixes: vec!["json".into()],
1898 ..Default::default()
1899 },
1900 tree_sitter_json::language(),
1901 vec![],
1902 |_| Default::default(),
1903 );
1904 languages.register(
1905 "/rust",
1906 LanguageConfig {
1907 name: "Rust".into(),
1908 path_suffixes: vec!["rs".into()],
1909 ..Default::default()
1910 },
1911 tree_sitter_rust::language(),
1912 vec![],
1913 |_| Default::default(),
1914 );
1915 assert_eq!(
1916 languages.language_names(),
1917 &[
1918 "JSON".to_string(),
1919 "Plain Text".to_string(),
1920 "Rust".to_string(),
1921 ]
1922 );
1923
1924 let rust1 = languages.language_for_name("Rust");
1925 let rust2 = languages.language_for_name("Rust");
1926
1927 // Ensure language is still listed even if it's being loaded.
1928 assert_eq!(
1929 languages.language_names(),
1930 &[
1931 "JSON".to_string(),
1932 "Plain Text".to_string(),
1933 "Rust".to_string(),
1934 ]
1935 );
1936
1937 let (rust1, rust2) = futures::join!(rust1, rust2);
1938 assert!(Arc::ptr_eq(&rust1.unwrap(), &rust2.unwrap()));
1939
1940 // Ensure language is still listed even after loading it.
1941 assert_eq!(
1942 languages.language_names(),
1943 &[
1944 "JSON".to_string(),
1945 "Plain Text".to_string(),
1946 "Rust".to_string(),
1947 ]
1948 );
1949
1950 // Loading an unknown language returns an error.
1951 assert!(languages.language_for_name("Unknown").await.is_err());
1952 }
1953}