language.rs

   1mod buffer;
   2mod diagnostic_set;
   3mod highlight_map;
   4mod outline;
   5pub mod proto;
   6mod syntax_map;
   7
   8#[cfg(test)]
   9mod buffer_tests;
  10
  11use anyhow::{anyhow, Context, Result};
  12use async_trait::async_trait;
  13use client::http::HttpClient;
  14use collections::HashMap;
  15use futures::{
  16    future::{BoxFuture, Shared},
  17    FutureExt, TryFutureExt,
  18};
  19use gpui::{MutableAppContext, Task};
  20use highlight_map::HighlightMap;
  21use lazy_static::lazy_static;
  22use parking_lot::{Mutex, RwLock};
  23use postage::watch;
  24use regex::Regex;
  25use serde::{de, Deserialize, Deserializer};
  26use serde_json::Value;
  27use std::{
  28    any::Any,
  29    cell::RefCell,
  30    fmt::Debug,
  31    hash::Hash,
  32    mem,
  33    ops::Range,
  34    path::{Path, PathBuf},
  35    str,
  36    sync::{
  37        atomic::{AtomicUsize, Ordering::SeqCst},
  38        Arc,
  39    },
  40};
  41use syntax_map::SyntaxSnapshot;
  42use theme::{SyntaxTheme, Theme};
  43use tree_sitter::{self, Query};
  44use util::ResultExt;
  45
  46#[cfg(any(test, feature = "test-support"))]
  47use futures::channel::mpsc;
  48
  49pub use buffer::Operation;
  50pub use buffer::*;
  51pub use diagnostic_set::DiagnosticEntry;
  52pub use outline::{Outline, OutlineItem};
  53pub use tree_sitter::{Parser, Tree};
  54
  55thread_local! {
  56    static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
  57}
  58
  59lazy_static! {
  60    pub static ref NEXT_GRAMMAR_ID: AtomicUsize = Default::default();
  61    pub static ref PLAIN_TEXT: Arc<Language> = Arc::new(Language::new(
  62        LanguageConfig {
  63            name: "Plain Text".into(),
  64            ..Default::default()
  65        },
  66        None,
  67    ));
  68}
  69
  70pub trait ToLspPosition {
  71    fn to_lsp_position(self) -> lsp::Position;
  72}
  73
  74#[derive(Clone, Debug, PartialEq, Eq, Hash)]
  75pub struct LanguageServerName(pub Arc<str>);
  76
  77/// Represents a Language Server, with certain cached sync properties.
  78/// Uses [`LspAdapter`] under the hood, but calls all 'static' methods
  79/// once at startup, and caches the results.
  80pub struct CachedLspAdapter {
  81    pub name: LanguageServerName,
  82    pub server_args: Vec<String>,
  83    pub initialization_options: Option<Value>,
  84    pub disk_based_diagnostic_sources: Vec<String>,
  85    pub disk_based_diagnostics_progress_token: Option<String>,
  86    pub language_ids: HashMap<String, String>,
  87    pub adapter: Box<dyn LspAdapter>,
  88}
  89
  90impl CachedLspAdapter {
  91    pub async fn new<T: LspAdapter>(adapter: T) -> Arc<Self> {
  92        let adapter = Box::new(adapter);
  93        let name = adapter.name().await;
  94        let server_args = adapter.server_args().await;
  95        let initialization_options = adapter.initialization_options().await;
  96        let disk_based_diagnostic_sources = adapter.disk_based_diagnostic_sources().await;
  97        let disk_based_diagnostics_progress_token =
  98            adapter.disk_based_diagnostics_progress_token().await;
  99        let language_ids = adapter.language_ids().await;
 100
 101        Arc::new(CachedLspAdapter {
 102            name,
 103            server_args,
 104            initialization_options,
 105            disk_based_diagnostic_sources,
 106            disk_based_diagnostics_progress_token,
 107            language_ids,
 108            adapter,
 109        })
 110    }
 111
 112    pub async fn fetch_latest_server_version(
 113        &self,
 114        http: Arc<dyn HttpClient>,
 115    ) -> Result<Box<dyn 'static + Send + Any>> {
 116        self.adapter.fetch_latest_server_version(http).await
 117    }
 118
 119    pub async fn fetch_server_binary(
 120        &self,
 121        version: Box<dyn 'static + Send + Any>,
 122        http: Arc<dyn HttpClient>,
 123        container_dir: PathBuf,
 124    ) -> Result<PathBuf> {
 125        self.adapter
 126            .fetch_server_binary(version, http, container_dir)
 127            .await
 128    }
 129
 130    pub async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
 131        self.adapter.cached_server_binary(container_dir).await
 132    }
 133
 134    pub async fn process_diagnostics(&self, params: &mut lsp::PublishDiagnosticsParams) {
 135        self.adapter.process_diagnostics(params).await
 136    }
 137
 138    pub async fn process_completion(&self, completion_item: &mut lsp::CompletionItem) {
 139        self.adapter.process_completion(completion_item).await
 140    }
 141
 142    pub async fn label_for_completion(
 143        &self,
 144        completion_item: &lsp::CompletionItem,
 145        language: &Arc<Language>,
 146    ) -> Option<CodeLabel> {
 147        self.adapter
 148            .label_for_completion(completion_item, language)
 149            .await
 150    }
 151
 152    pub async fn label_for_symbol(
 153        &self,
 154        name: &str,
 155        kind: lsp::SymbolKind,
 156        language: &Arc<Language>,
 157    ) -> Option<CodeLabel> {
 158        self.adapter.label_for_symbol(name, kind, language).await
 159    }
 160}
 161
 162#[async_trait]
 163pub trait LspAdapter: 'static + Send + Sync {
 164    async fn name(&self) -> LanguageServerName;
 165
 166    async fn fetch_latest_server_version(
 167        &self,
 168        http: Arc<dyn HttpClient>,
 169    ) -> Result<Box<dyn 'static + Send + Any>>;
 170
 171    async fn fetch_server_binary(
 172        &self,
 173        version: Box<dyn 'static + Send + Any>,
 174        http: Arc<dyn HttpClient>,
 175        container_dir: PathBuf,
 176    ) -> Result<PathBuf>;
 177
 178    async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf>;
 179
 180    async fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
 181
 182    async fn process_completion(&self, _: &mut lsp::CompletionItem) {}
 183
 184    async fn label_for_completion(
 185        &self,
 186        _: &lsp::CompletionItem,
 187        _: &Arc<Language>,
 188    ) -> Option<CodeLabel> {
 189        None
 190    }
 191
 192    async fn label_for_symbol(
 193        &self,
 194        _: &str,
 195        _: lsp::SymbolKind,
 196        _: &Arc<Language>,
 197    ) -> Option<CodeLabel> {
 198        None
 199    }
 200
 201    async fn server_args(&self) -> Vec<String> {
 202        Vec::new()
 203    }
 204
 205    async fn initialization_options(&self) -> Option<Value> {
 206        None
 207    }
 208
 209    async fn disk_based_diagnostic_sources(&self) -> Vec<String> {
 210        Default::default()
 211    }
 212
 213    async fn disk_based_diagnostics_progress_token(&self) -> Option<String> {
 214        None
 215    }
 216
 217    async fn language_ids(&self) -> HashMap<String, String> {
 218        Default::default()
 219    }
 220}
 221
 222#[derive(Clone, Debug, PartialEq, Eq)]
 223pub struct CodeLabel {
 224    pub text: String,
 225    pub runs: Vec<(Range<usize>, HighlightId)>,
 226    pub filter_range: Range<usize>,
 227}
 228
 229#[derive(Deserialize)]
 230pub struct LanguageConfig {
 231    pub name: Arc<str>,
 232    pub path_suffixes: Vec<String>,
 233    pub brackets: Vec<BracketPair>,
 234    #[serde(default = "auto_indent_using_last_non_empty_line_default")]
 235    pub auto_indent_using_last_non_empty_line: bool,
 236    #[serde(default, deserialize_with = "deserialize_regex")]
 237    pub increase_indent_pattern: Option<Regex>,
 238    #[serde(default, deserialize_with = "deserialize_regex")]
 239    pub decrease_indent_pattern: Option<Regex>,
 240    #[serde(default)]
 241    pub autoclose_before: String,
 242    #[serde(default)]
 243    pub line_comment: Option<Arc<str>>,
 244    #[serde(default)]
 245    pub block_comment: Option<(Arc<str>, Arc<str>)>,
 246    #[serde(default)]
 247    pub overrides: HashMap<String, LanguageConfigOverride>,
 248}
 249
 250#[derive(Clone)]
 251pub struct LanguageScope {
 252    language: Arc<Language>,
 253    override_id: Option<u32>,
 254}
 255
 256#[derive(Deserialize, Default, Debug)]
 257pub struct LanguageConfigOverride {
 258    #[serde(default)]
 259    pub line_comment: Override<Arc<str>>,
 260    #[serde(default)]
 261    pub block_comment: Override<(Arc<str>, Arc<str>)>,
 262    #[serde(default)]
 263    pub brackets: Override<Vec<BracketPair>>,
 264}
 265
 266#[derive(Deserialize, Debug)]
 267#[serde(untagged)]
 268pub enum Override<T> {
 269    Remove { remove: bool },
 270    Set(T),
 271}
 272
 273impl<T> Default for Override<T> {
 274    fn default() -> Self {
 275        Override::Remove { remove: false }
 276    }
 277}
 278
 279impl<T> Override<T> {
 280    fn as_option<'a>(this: Option<&'a Self>, original: Option<&'a T>) -> Option<&'a T> {
 281        match this {
 282            Some(Self::Set(value)) => Some(value),
 283            Some(Self::Remove { remove: true }) => None,
 284            Some(Self::Remove { remove: false }) | None => original,
 285        }
 286    }
 287}
 288
 289impl Default for LanguageConfig {
 290    fn default() -> Self {
 291        Self {
 292            name: "".into(),
 293            path_suffixes: Default::default(),
 294            brackets: Default::default(),
 295            auto_indent_using_last_non_empty_line: auto_indent_using_last_non_empty_line_default(),
 296            increase_indent_pattern: Default::default(),
 297            decrease_indent_pattern: Default::default(),
 298            autoclose_before: Default::default(),
 299            line_comment: Default::default(),
 300            block_comment: Default::default(),
 301            overrides: Default::default(),
 302        }
 303    }
 304}
 305
 306fn auto_indent_using_last_non_empty_line_default() -> bool {
 307    true
 308}
 309
 310fn deserialize_regex<'de, D: Deserializer<'de>>(d: D) -> Result<Option<Regex>, D::Error> {
 311    let source = Option::<String>::deserialize(d)?;
 312    if let Some(source) = source {
 313        Ok(Some(regex::Regex::new(&source).map_err(de::Error::custom)?))
 314    } else {
 315        Ok(None)
 316    }
 317}
 318
 319#[cfg(any(test, feature = "test-support"))]
 320pub struct FakeLspAdapter {
 321    pub name: &'static str,
 322    pub capabilities: lsp::ServerCapabilities,
 323    pub initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,
 324    pub disk_based_diagnostics_progress_token: Option<String>,
 325    pub disk_based_diagnostics_sources: Vec<String>,
 326}
 327
 328#[derive(Clone, Debug, Default, Deserialize)]
 329pub struct BracketPair {
 330    pub start: String,
 331    pub end: String,
 332    pub close: bool,
 333    pub newline: bool,
 334}
 335
 336pub struct Language {
 337    pub(crate) config: LanguageConfig,
 338    pub(crate) grammar: Option<Arc<Grammar>>,
 339    pub(crate) adapter: Option<Arc<CachedLspAdapter>>,
 340
 341    #[cfg(any(test, feature = "test-support"))]
 342    fake_adapter: Option<(
 343        mpsc::UnboundedSender<lsp::FakeLanguageServer>,
 344        Arc<FakeLspAdapter>,
 345    )>,
 346}
 347
 348pub struct Grammar {
 349    id: usize,
 350    pub(crate) ts_language: tree_sitter::Language,
 351    pub(crate) error_query: Query,
 352    pub(crate) highlights_query: Option<Query>,
 353    pub(crate) brackets_config: Option<BracketConfig>,
 354    pub(crate) indents_config: Option<IndentConfig>,
 355    pub(crate) outline_config: Option<OutlineConfig>,
 356    pub(crate) injection_config: Option<InjectionConfig>,
 357    pub(crate) override_config: Option<OverrideConfig>,
 358    pub(crate) highlight_map: Mutex<HighlightMap>,
 359}
 360
 361struct IndentConfig {
 362    query: Query,
 363    indent_capture_ix: u32,
 364    start_capture_ix: Option<u32>,
 365    end_capture_ix: Option<u32>,
 366    outdent_capture_ix: Option<u32>,
 367}
 368
 369struct OutlineConfig {
 370    query: Query,
 371    item_capture_ix: u32,
 372    name_capture_ix: u32,
 373    context_capture_ix: Option<u32>,
 374}
 375
 376struct InjectionConfig {
 377    query: Query,
 378    content_capture_ix: u32,
 379    language_capture_ix: Option<u32>,
 380    patterns: Vec<InjectionPatternConfig>,
 381}
 382
 383struct OverrideConfig {
 384    query: Query,
 385    values: HashMap<u32, LanguageConfigOverride>,
 386}
 387
 388#[derive(Default, Clone)]
 389struct InjectionPatternConfig {
 390    language: Option<Box<str>>,
 391    combined: bool,
 392}
 393
 394struct BracketConfig {
 395    query: Query,
 396    open_capture_ix: u32,
 397    close_capture_ix: u32,
 398}
 399
 400#[derive(Clone)]
 401pub enum LanguageServerBinaryStatus {
 402    CheckingForUpdate,
 403    Downloading,
 404    Downloaded,
 405    Cached,
 406    Failed { error: String },
 407}
 408
 409pub struct LanguageRegistry {
 410    languages: RwLock<Vec<Arc<Language>>>,
 411    language_server_download_dir: Option<Arc<Path>>,
 412    lsp_binary_statuses_tx: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
 413    lsp_binary_statuses_rx: async_broadcast::Receiver<(Arc<Language>, LanguageServerBinaryStatus)>,
 414    login_shell_env_loaded: Shared<Task<()>>,
 415    #[allow(clippy::type_complexity)]
 416    lsp_binary_paths: Mutex<
 417        HashMap<
 418            LanguageServerName,
 419            Shared<BoxFuture<'static, Result<PathBuf, Arc<anyhow::Error>>>>,
 420        >,
 421    >,
 422    subscription: RwLock<(watch::Sender<()>, watch::Receiver<()>)>,
 423    theme: RwLock<Option<Arc<Theme>>>,
 424}
 425
 426impl LanguageRegistry {
 427    pub fn new(login_shell_env_loaded: Task<()>) -> Self {
 428        let (lsp_binary_statuses_tx, lsp_binary_statuses_rx) = async_broadcast::broadcast(16);
 429        Self {
 430            language_server_download_dir: None,
 431            languages: Default::default(),
 432            lsp_binary_statuses_tx,
 433            lsp_binary_statuses_rx,
 434            login_shell_env_loaded: login_shell_env_loaded.shared(),
 435            lsp_binary_paths: Default::default(),
 436            subscription: RwLock::new(watch::channel()),
 437            theme: Default::default(),
 438        }
 439    }
 440
 441    #[cfg(any(test, feature = "test-support"))]
 442    pub fn test() -> Self {
 443        Self::new(Task::ready(()))
 444    }
 445
 446    pub fn add(&self, language: Arc<Language>) {
 447        if let Some(theme) = self.theme.read().clone() {
 448            language.set_theme(&theme.editor.syntax);
 449        }
 450        self.languages.write().push(language);
 451        *self.subscription.write().0.borrow_mut() = ();
 452    }
 453
 454    pub fn subscribe(&self) -> watch::Receiver<()> {
 455        self.subscription.read().1.clone()
 456    }
 457
 458    pub fn set_theme(&self, theme: Arc<Theme>) {
 459        *self.theme.write() = Some(theme.clone());
 460        for language in self.languages.read().iter() {
 461            language.set_theme(&theme.editor.syntax);
 462        }
 463    }
 464
 465    pub fn set_language_server_download_dir(&mut self, path: impl Into<Arc<Path>>) {
 466        self.language_server_download_dir = Some(path.into());
 467    }
 468
 469    pub fn get_language(&self, name: &str) -> Option<Arc<Language>> {
 470        self.languages
 471            .read()
 472            .iter()
 473            .find(|language| language.name().to_lowercase() == name.to_lowercase())
 474            .cloned()
 475    }
 476
 477    pub fn to_vec(&self) -> Vec<Arc<Language>> {
 478        self.languages.read().iter().cloned().collect()
 479    }
 480
 481    pub fn language_names(&self) -> Vec<String> {
 482        self.languages
 483            .read()
 484            .iter()
 485            .map(|language| language.name().to_string())
 486            .collect()
 487    }
 488
 489    pub fn select_language(&self, path: impl AsRef<Path>) -> Option<Arc<Language>> {
 490        let path = path.as_ref();
 491        let filename = path.file_name().and_then(|name| name.to_str());
 492        let extension = path.extension().and_then(|name| name.to_str());
 493        let path_suffixes = [extension, filename];
 494        self.languages
 495            .read()
 496            .iter()
 497            .find(|language| {
 498                language
 499                    .config
 500                    .path_suffixes
 501                    .iter()
 502                    .any(|suffix| path_suffixes.contains(&Some(suffix.as_str())))
 503            })
 504            .cloned()
 505    }
 506
 507    pub fn start_language_server(
 508        self: &Arc<Self>,
 509        server_id: usize,
 510        language: Arc<Language>,
 511        root_path: Arc<Path>,
 512        http_client: Arc<dyn HttpClient>,
 513        cx: &mut MutableAppContext,
 514    ) -> Option<Task<Result<lsp::LanguageServer>>> {
 515        #[cfg(any(test, feature = "test-support"))]
 516        if language.fake_adapter.is_some() {
 517            let language = language;
 518            return Some(cx.spawn(|cx| async move {
 519                let (servers_tx, fake_adapter) = language.fake_adapter.as_ref().unwrap();
 520                let (server, mut fake_server) = lsp::LanguageServer::fake(
 521                    fake_adapter.name.to_string(),
 522                    fake_adapter.capabilities.clone(),
 523                    cx.clone(),
 524                );
 525
 526                if let Some(initializer) = &fake_adapter.initializer {
 527                    initializer(&mut fake_server);
 528                }
 529
 530                let servers_tx = servers_tx.clone();
 531                cx.background()
 532                    .spawn(async move {
 533                        if fake_server
 534                            .try_receive_notification::<lsp::notification::Initialized>()
 535                            .await
 536                            .is_some()
 537                        {
 538                            servers_tx.unbounded_send(fake_server).ok();
 539                        }
 540                    })
 541                    .detach();
 542                Ok(server)
 543            }));
 544        }
 545
 546        let download_dir = self
 547            .language_server_download_dir
 548            .clone()
 549            .ok_or_else(|| anyhow!("language server download directory has not been assigned"))
 550            .log_err()?;
 551
 552        let this = self.clone();
 553        let adapter = language.adapter.clone()?;
 554        let lsp_binary_statuses = self.lsp_binary_statuses_tx.clone();
 555        let login_shell_env_loaded = self.login_shell_env_loaded.clone();
 556        Some(cx.spawn(|cx| async move {
 557            login_shell_env_loaded.await;
 558            let server_binary_path = this
 559                .lsp_binary_paths
 560                .lock()
 561                .entry(adapter.name.clone())
 562                .or_insert_with(|| {
 563                    get_server_binary_path(
 564                        adapter.clone(),
 565                        language.clone(),
 566                        http_client,
 567                        download_dir,
 568                        lsp_binary_statuses,
 569                    )
 570                    .map_err(Arc::new)
 571                    .boxed()
 572                    .shared()
 573                })
 574                .clone()
 575                .map_err(|e| anyhow!(e));
 576
 577            let server_binary_path = server_binary_path.await?;
 578            let server_args = &adapter.server_args;
 579            let server = lsp::LanguageServer::new(
 580                server_id,
 581                &server_binary_path,
 582                server_args,
 583                &root_path,
 584                cx,
 585            )?;
 586            Ok(server)
 587        }))
 588    }
 589
 590    pub fn language_server_binary_statuses(
 591        &self,
 592    ) -> async_broadcast::Receiver<(Arc<Language>, LanguageServerBinaryStatus)> {
 593        self.lsp_binary_statuses_rx.clone()
 594    }
 595}
 596
 597#[cfg(any(test, feature = "test-support"))]
 598impl Default for LanguageRegistry {
 599    fn default() -> Self {
 600        Self::test()
 601    }
 602}
 603
 604async fn get_server_binary_path(
 605    adapter: Arc<CachedLspAdapter>,
 606    language: Arc<Language>,
 607    http_client: Arc<dyn HttpClient>,
 608    download_dir: Arc<Path>,
 609    statuses: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
 610) -> Result<PathBuf> {
 611    let container_dir = download_dir.join(adapter.name.0.as_ref());
 612    if !container_dir.exists() {
 613        smol::fs::create_dir_all(&container_dir)
 614            .await
 615            .context("failed to create container directory")?;
 616    }
 617
 618    let path = fetch_latest_server_binary_path(
 619        adapter.clone(),
 620        language.clone(),
 621        http_client,
 622        &container_dir,
 623        statuses.clone(),
 624    )
 625    .await;
 626    if let Err(error) = path.as_ref() {
 627        if let Some(cached_path) = adapter.cached_server_binary(container_dir).await {
 628            statuses
 629                .broadcast((language.clone(), LanguageServerBinaryStatus::Cached))
 630                .await?;
 631            return Ok(cached_path);
 632        } else {
 633            statuses
 634                .broadcast((
 635                    language.clone(),
 636                    LanguageServerBinaryStatus::Failed {
 637                        error: format!("{:?}", error),
 638                    },
 639                ))
 640                .await?;
 641        }
 642    }
 643    path
 644}
 645
 646async fn fetch_latest_server_binary_path(
 647    adapter: Arc<CachedLspAdapter>,
 648    language: Arc<Language>,
 649    http_client: Arc<dyn HttpClient>,
 650    container_dir: &Path,
 651    lsp_binary_statuses_tx: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
 652) -> Result<PathBuf> {
 653    let container_dir: Arc<Path> = container_dir.into();
 654    lsp_binary_statuses_tx
 655        .broadcast((
 656            language.clone(),
 657            LanguageServerBinaryStatus::CheckingForUpdate,
 658        ))
 659        .await?;
 660    let version_info = adapter
 661        .fetch_latest_server_version(http_client.clone())
 662        .await?;
 663    lsp_binary_statuses_tx
 664        .broadcast((language.clone(), LanguageServerBinaryStatus::Downloading))
 665        .await?;
 666    let path = adapter
 667        .fetch_server_binary(version_info, http_client, container_dir.to_path_buf())
 668        .await?;
 669    lsp_binary_statuses_tx
 670        .broadcast((language.clone(), LanguageServerBinaryStatus::Downloaded))
 671        .await?;
 672    Ok(path)
 673}
 674
 675impl Language {
 676    pub fn new(config: LanguageConfig, ts_language: Option<tree_sitter::Language>) -> Self {
 677        Self {
 678            config,
 679            grammar: ts_language.map(|ts_language| {
 680                Arc::new(Grammar {
 681                    id: NEXT_GRAMMAR_ID.fetch_add(1, SeqCst),
 682                    highlights_query: None,
 683                    brackets_config: None,
 684                    outline_config: None,
 685                    indents_config: None,
 686                    injection_config: None,
 687                    override_config: None,
 688                    error_query: Query::new(ts_language, "(ERROR) @error").unwrap(),
 689                    ts_language,
 690                    highlight_map: Default::default(),
 691                })
 692            }),
 693            adapter: None,
 694
 695            #[cfg(any(test, feature = "test-support"))]
 696            fake_adapter: None,
 697        }
 698    }
 699
 700    pub fn lsp_adapter(&self) -> Option<Arc<CachedLspAdapter>> {
 701        self.adapter.clone()
 702    }
 703
 704    pub fn id(&self) -> Option<usize> {
 705        self.grammar.as_ref().map(|g| g.id)
 706    }
 707
 708    pub fn with_highlights_query(mut self, source: &str) -> Result<Self> {
 709        let grammar = self.grammar_mut();
 710        grammar.highlights_query = Some(Query::new(grammar.ts_language, source)?);
 711        Ok(self)
 712    }
 713
 714    pub fn with_brackets_query(mut self, source: &str) -> Result<Self> {
 715        let grammar = self.grammar_mut();
 716        let query = Query::new(grammar.ts_language, source)?;
 717        let mut open_capture_ix = None;
 718        let mut close_capture_ix = None;
 719        get_capture_indices(
 720            &query,
 721            &mut [
 722                ("open", &mut open_capture_ix),
 723                ("close", &mut close_capture_ix),
 724            ],
 725        );
 726        if let Some((open_capture_ix, close_capture_ix)) = open_capture_ix.zip(close_capture_ix) {
 727            grammar.brackets_config = Some(BracketConfig {
 728                query,
 729                open_capture_ix,
 730                close_capture_ix,
 731            });
 732        }
 733        Ok(self)
 734    }
 735
 736    pub fn with_indents_query(mut self, source: &str) -> Result<Self> {
 737        let grammar = self.grammar_mut();
 738        let query = Query::new(grammar.ts_language, source)?;
 739        let mut indent_capture_ix = None;
 740        let mut start_capture_ix = None;
 741        let mut end_capture_ix = None;
 742        let mut outdent_capture_ix = None;
 743        get_capture_indices(
 744            &query,
 745            &mut [
 746                ("indent", &mut indent_capture_ix),
 747                ("start", &mut start_capture_ix),
 748                ("end", &mut end_capture_ix),
 749                ("outdent", &mut outdent_capture_ix),
 750            ],
 751        );
 752        if let Some(indent_capture_ix) = indent_capture_ix {
 753            grammar.indents_config = Some(IndentConfig {
 754                query,
 755                indent_capture_ix,
 756                start_capture_ix,
 757                end_capture_ix,
 758                outdent_capture_ix,
 759            });
 760        }
 761        Ok(self)
 762    }
 763
 764    pub fn with_outline_query(mut self, source: &str) -> Result<Self> {
 765        let grammar = self.grammar_mut();
 766        let query = Query::new(grammar.ts_language, source)?;
 767        let mut item_capture_ix = None;
 768        let mut name_capture_ix = None;
 769        let mut context_capture_ix = None;
 770        get_capture_indices(
 771            &query,
 772            &mut [
 773                ("item", &mut item_capture_ix),
 774                ("name", &mut name_capture_ix),
 775                ("context", &mut context_capture_ix),
 776            ],
 777        );
 778        if let Some((item_capture_ix, name_capture_ix)) = item_capture_ix.zip(name_capture_ix) {
 779            grammar.outline_config = Some(OutlineConfig {
 780                query,
 781                item_capture_ix,
 782                name_capture_ix,
 783                context_capture_ix,
 784            });
 785        }
 786        Ok(self)
 787    }
 788
 789    pub fn with_injection_query(mut self, source: &str) -> Result<Self> {
 790        let grammar = self.grammar_mut();
 791        let query = Query::new(grammar.ts_language, source)?;
 792        let mut language_capture_ix = None;
 793        let mut content_capture_ix = None;
 794        get_capture_indices(
 795            &query,
 796            &mut [
 797                ("language", &mut language_capture_ix),
 798                ("content", &mut content_capture_ix),
 799            ],
 800        );
 801        let patterns = (0..query.pattern_count())
 802            .map(|ix| {
 803                let mut config = InjectionPatternConfig::default();
 804                for setting in query.property_settings(ix) {
 805                    match setting.key.as_ref() {
 806                        "language" => {
 807                            config.language = setting.value.clone();
 808                        }
 809                        "combined" => {
 810                            config.combined = true;
 811                        }
 812                        _ => {}
 813                    }
 814                }
 815                config
 816            })
 817            .collect();
 818        if let Some(content_capture_ix) = content_capture_ix {
 819            grammar.injection_config = Some(InjectionConfig {
 820                query,
 821                language_capture_ix,
 822                content_capture_ix,
 823                patterns,
 824            });
 825        }
 826        Ok(self)
 827    }
 828
 829    pub fn with_override_query(mut self, source: &str) -> Result<Self> {
 830        let query = Query::new(self.grammar_mut().ts_language, source)?;
 831
 832        let mut values = HashMap::default();
 833        for (ix, name) in query.capture_names().iter().enumerate() {
 834            if !name.starts_with('_') {
 835                let value = self.config.overrides.remove(name).ok_or_else(|| {
 836                    anyhow!(
 837                        "language {:?} has override in query but not in config: {name:?}",
 838                        self.config.name
 839                    )
 840                })?;
 841                values.insert(ix as u32, value);
 842            }
 843        }
 844
 845        if !self.config.overrides.is_empty() {
 846            let keys = self.config.overrides.keys().collect::<Vec<_>>();
 847            Err(anyhow!(
 848                "language {:?} has overrides in config not in query: {keys:?}",
 849                self.config.name
 850            ))?;
 851        }
 852
 853        self.grammar_mut().override_config = Some(OverrideConfig { query, values });
 854        Ok(self)
 855    }
 856
 857    fn grammar_mut(&mut self) -> &mut Grammar {
 858        Arc::get_mut(self.grammar.as_mut().unwrap()).unwrap()
 859    }
 860
 861    pub fn with_lsp_adapter(mut self, lsp_adapter: Arc<CachedLspAdapter>) -> Self {
 862        self.adapter = Some(lsp_adapter);
 863        self
 864    }
 865
 866    #[cfg(any(test, feature = "test-support"))]
 867    pub async fn set_fake_lsp_adapter(
 868        &mut self,
 869        fake_lsp_adapter: Arc<FakeLspAdapter>,
 870    ) -> mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
 871        let (servers_tx, servers_rx) = mpsc::unbounded();
 872        self.fake_adapter = Some((servers_tx, fake_lsp_adapter.clone()));
 873        let adapter = CachedLspAdapter::new(fake_lsp_adapter).await;
 874        self.adapter = Some(adapter);
 875        servers_rx
 876    }
 877
 878    pub fn name(&self) -> Arc<str> {
 879        self.config.name.clone()
 880    }
 881
 882    pub async fn disk_based_diagnostic_sources(&self) -> &[String] {
 883        match self.adapter.as_ref() {
 884            Some(adapter) => &adapter.disk_based_diagnostic_sources,
 885            None => &[],
 886        }
 887    }
 888
 889    pub async fn disk_based_diagnostics_progress_token(&self) -> Option<&str> {
 890        if let Some(adapter) = self.adapter.as_ref() {
 891            adapter.disk_based_diagnostics_progress_token.as_deref()
 892        } else {
 893            None
 894        }
 895    }
 896
 897    pub async fn process_diagnostics(&self, diagnostics: &mut lsp::PublishDiagnosticsParams) {
 898        if let Some(processor) = self.adapter.as_ref() {
 899            processor.process_diagnostics(diagnostics).await;
 900        }
 901    }
 902
 903    pub async fn process_completion(self: &Arc<Self>, completion: &mut lsp::CompletionItem) {
 904        if let Some(adapter) = self.adapter.as_ref() {
 905            adapter.process_completion(completion).await;
 906        }
 907    }
 908
 909    pub async fn label_for_completion(
 910        self: &Arc<Self>,
 911        completion: &lsp::CompletionItem,
 912    ) -> Option<CodeLabel> {
 913        self.adapter
 914            .as_ref()?
 915            .label_for_completion(completion, self)
 916            .await
 917    }
 918
 919    pub async fn label_for_symbol(
 920        self: &Arc<Self>,
 921        name: &str,
 922        kind: lsp::SymbolKind,
 923    ) -> Option<CodeLabel> {
 924        self.adapter
 925            .as_ref()?
 926            .label_for_symbol(name, kind, self)
 927            .await
 928    }
 929
 930    pub fn highlight_text<'a>(
 931        self: &'a Arc<Self>,
 932        text: &'a Rope,
 933        range: Range<usize>,
 934    ) -> Vec<(Range<usize>, HighlightId)> {
 935        let mut result = Vec::new();
 936        if let Some(grammar) = &self.grammar {
 937            let tree = grammar.parse_text(text, None);
 938            let captures =
 939                SyntaxSnapshot::single_tree_captures(range.clone(), text, &tree, self, |grammar| {
 940                    grammar.highlights_query.as_ref()
 941                });
 942            let highlight_maps = vec![grammar.highlight_map()];
 943            let mut offset = 0;
 944            for chunk in BufferChunks::new(text, range, Some((captures, highlight_maps)), vec![]) {
 945                let end_offset = offset + chunk.text.len();
 946                if let Some(highlight_id) = chunk.syntax_highlight_id {
 947                    if !highlight_id.is_default() {
 948                        result.push((offset..end_offset, highlight_id));
 949                    }
 950                }
 951                offset = end_offset;
 952            }
 953        }
 954        result
 955    }
 956
 957    pub fn path_suffixes(&self) -> &[String] {
 958        &self.config.path_suffixes
 959    }
 960
 961    pub fn should_autoclose_before(&self, c: char) -> bool {
 962        c.is_whitespace() || self.config.autoclose_before.contains(c)
 963    }
 964
 965    pub fn set_theme(&self, theme: &SyntaxTheme) {
 966        if let Some(grammar) = self.grammar.as_ref() {
 967            if let Some(highlights_query) = &grammar.highlights_query {
 968                *grammar.highlight_map.lock() =
 969                    HighlightMap::new(highlights_query.capture_names(), theme);
 970            }
 971        }
 972    }
 973
 974    pub fn grammar(&self) -> Option<&Arc<Grammar>> {
 975        self.grammar.as_ref()
 976    }
 977}
 978
 979impl LanguageScope {
 980    pub fn line_comment_prefix(&self) -> Option<&Arc<str>> {
 981        Override::as_option(
 982            self.config_override().map(|o| &o.line_comment),
 983            self.language.config.line_comment.as_ref(),
 984        )
 985    }
 986
 987    pub fn block_comment_delimiters(&self) -> Option<(&Arc<str>, &Arc<str>)> {
 988        Override::as_option(
 989            self.config_override().map(|o| &o.block_comment),
 990            self.language.config.block_comment.as_ref(),
 991        )
 992        .map(|e| (&e.0, &e.1))
 993    }
 994
 995    pub fn brackets(&self) -> &[BracketPair] {
 996        Override::as_option(
 997            self.config_override().map(|o| &o.brackets),
 998            Some(&self.language.config.brackets),
 999        )
1000        .map_or(&[], Vec::as_slice)
1001    }
1002
1003    pub fn should_autoclose_before(&self, c: char) -> bool {
1004        c.is_whitespace() || self.language.config.autoclose_before.contains(c)
1005    }
1006
1007    fn config_override(&self) -> Option<&LanguageConfigOverride> {
1008        let id = self.override_id?;
1009        let grammar = self.language.grammar.as_ref()?;
1010        let override_config = grammar.override_config.as_ref()?;
1011        override_config.values.get(&id)
1012    }
1013}
1014
1015impl Hash for Language {
1016    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1017        self.id().hash(state)
1018    }
1019}
1020
1021impl PartialEq for Language {
1022    fn eq(&self, other: &Self) -> bool {
1023        self.id().eq(&other.id())
1024    }
1025}
1026
1027impl Eq for Language {}
1028
1029impl Debug for Language {
1030    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1031        f.debug_struct("Language")
1032            .field("name", &self.config.name)
1033            .finish()
1034    }
1035}
1036
1037impl Grammar {
1038    pub fn id(&self) -> usize {
1039        self.id
1040    }
1041
1042    fn parse_text(&self, text: &Rope, old_tree: Option<Tree>) -> Tree {
1043        PARSER.with(|parser| {
1044            let mut parser = parser.borrow_mut();
1045            parser
1046                .set_language(self.ts_language)
1047                .expect("incompatible grammar");
1048            let mut chunks = text.chunks_in_range(0..text.len());
1049            parser
1050                .parse_with(
1051                    &mut move |offset, _| {
1052                        chunks.seek(offset);
1053                        chunks.next().unwrap_or("").as_bytes()
1054                    },
1055                    old_tree.as_ref(),
1056                )
1057                .unwrap()
1058        })
1059    }
1060
1061    pub fn highlight_map(&self) -> HighlightMap {
1062        self.highlight_map.lock().clone()
1063    }
1064
1065    pub fn highlight_id_for_name(&self, name: &str) -> Option<HighlightId> {
1066        let capture_id = self
1067            .highlights_query
1068            .as_ref()?
1069            .capture_index_for_name(name)?;
1070        Some(self.highlight_map.lock().get(capture_id))
1071    }
1072}
1073
1074impl CodeLabel {
1075    pub fn plain(text: String, filter_text: Option<&str>) -> Self {
1076        let mut result = Self {
1077            runs: Vec::new(),
1078            filter_range: 0..text.len(),
1079            text,
1080        };
1081        if let Some(filter_text) = filter_text {
1082            if let Some(ix) = result.text.find(filter_text) {
1083                result.filter_range = ix..ix + filter_text.len();
1084            }
1085        }
1086        result
1087    }
1088}
1089
1090#[cfg(any(test, feature = "test-support"))]
1091impl Default for FakeLspAdapter {
1092    fn default() -> Self {
1093        Self {
1094            name: "the-fake-language-server",
1095            capabilities: lsp::LanguageServer::full_capabilities(),
1096            initializer: None,
1097            disk_based_diagnostics_progress_token: None,
1098            disk_based_diagnostics_sources: Vec::new(),
1099        }
1100    }
1101}
1102
1103#[cfg(any(test, feature = "test-support"))]
1104#[async_trait]
1105impl LspAdapter for Arc<FakeLspAdapter> {
1106    async fn name(&self) -> LanguageServerName {
1107        LanguageServerName(self.name.into())
1108    }
1109
1110    async fn fetch_latest_server_version(
1111        &self,
1112        _: Arc<dyn HttpClient>,
1113    ) -> Result<Box<dyn 'static + Send + Any>> {
1114        unreachable!();
1115    }
1116
1117    async fn fetch_server_binary(
1118        &self,
1119        _: Box<dyn 'static + Send + Any>,
1120        _: Arc<dyn HttpClient>,
1121        _: PathBuf,
1122    ) -> Result<PathBuf> {
1123        unreachable!();
1124    }
1125
1126    async fn cached_server_binary(&self, _: PathBuf) -> Option<PathBuf> {
1127        unreachable!();
1128    }
1129
1130    async fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
1131
1132    async fn disk_based_diagnostic_sources(&self) -> Vec<String> {
1133        self.disk_based_diagnostics_sources.clone()
1134    }
1135
1136    async fn disk_based_diagnostics_progress_token(&self) -> Option<String> {
1137        self.disk_based_diagnostics_progress_token.clone()
1138    }
1139}
1140
1141fn get_capture_indices(query: &Query, captures: &mut [(&str, &mut Option<u32>)]) {
1142    for (ix, name) in query.capture_names().iter().enumerate() {
1143        for (capture_name, index) in captures.iter_mut() {
1144            if capture_name == name {
1145                **index = Some(ix as u32);
1146                break;
1147            }
1148        }
1149    }
1150}
1151
1152pub fn point_to_lsp(point: PointUtf16) -> lsp::Position {
1153    lsp::Position::new(point.row, point.column)
1154}
1155
1156pub fn point_from_lsp(point: lsp::Position) -> Unclipped<PointUtf16> {
1157    Unclipped(PointUtf16::new(point.line, point.character))
1158}
1159
1160pub fn range_to_lsp(range: Range<PointUtf16>) -> lsp::Range {
1161    lsp::Range {
1162        start: point_to_lsp(range.start),
1163        end: point_to_lsp(range.end),
1164    }
1165}
1166
1167pub fn range_from_lsp(range: lsp::Range) -> Range<Unclipped<PointUtf16>> {
1168    let mut start = point_from_lsp(range.start);
1169    let mut end = point_from_lsp(range.end);
1170    if start > end {
1171        mem::swap(&mut start, &mut end);
1172    }
1173    start..end
1174}