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) highlights_query: Option<Query>,
 352    pub(crate) brackets_config: Option<BracketConfig>,
 353    pub(crate) indents_config: Option<IndentConfig>,
 354    pub(crate) outline_config: Option<OutlineConfig>,
 355    pub(crate) injection_config: Option<InjectionConfig>,
 356    pub(crate) override_config: Option<OverrideConfig>,
 357    pub(crate) highlight_map: Mutex<HighlightMap>,
 358}
 359
 360struct IndentConfig {
 361    query: Query,
 362    indent_capture_ix: u32,
 363    start_capture_ix: Option<u32>,
 364    end_capture_ix: Option<u32>,
 365    outdent_capture_ix: Option<u32>,
 366}
 367
 368struct OutlineConfig {
 369    query: Query,
 370    item_capture_ix: u32,
 371    name_capture_ix: u32,
 372    context_capture_ix: Option<u32>,
 373}
 374
 375struct InjectionConfig {
 376    query: Query,
 377    content_capture_ix: u32,
 378    language_capture_ix: Option<u32>,
 379    patterns: Vec<InjectionPatternConfig>,
 380}
 381
 382struct OverrideConfig {
 383    query: Query,
 384    values: HashMap<u32, LanguageConfigOverride>,
 385}
 386
 387#[derive(Default, Clone)]
 388struct InjectionPatternConfig {
 389    language: Option<Box<str>>,
 390    combined: bool,
 391}
 392
 393struct BracketConfig {
 394    query: Query,
 395    open_capture_ix: u32,
 396    close_capture_ix: u32,
 397}
 398
 399#[derive(Clone)]
 400pub enum LanguageServerBinaryStatus {
 401    CheckingForUpdate,
 402    Downloading,
 403    Downloaded,
 404    Cached,
 405    Failed { error: String },
 406}
 407
 408pub struct LanguageRegistry {
 409    languages: RwLock<Vec<Arc<Language>>>,
 410    language_server_download_dir: Option<Arc<Path>>,
 411    lsp_binary_statuses_tx: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
 412    lsp_binary_statuses_rx: async_broadcast::Receiver<(Arc<Language>, LanguageServerBinaryStatus)>,
 413    login_shell_env_loaded: Shared<Task<()>>,
 414    #[allow(clippy::type_complexity)]
 415    lsp_binary_paths: Mutex<
 416        HashMap<
 417            LanguageServerName,
 418            Shared<BoxFuture<'static, Result<PathBuf, Arc<anyhow::Error>>>>,
 419        >,
 420    >,
 421    subscription: RwLock<(watch::Sender<()>, watch::Receiver<()>)>,
 422    theme: RwLock<Option<Arc<Theme>>>,
 423}
 424
 425impl LanguageRegistry {
 426    pub fn new(login_shell_env_loaded: Task<()>) -> Self {
 427        let (lsp_binary_statuses_tx, lsp_binary_statuses_rx) = async_broadcast::broadcast(16);
 428        Self {
 429            language_server_download_dir: None,
 430            languages: Default::default(),
 431            lsp_binary_statuses_tx,
 432            lsp_binary_statuses_rx,
 433            login_shell_env_loaded: login_shell_env_loaded.shared(),
 434            lsp_binary_paths: Default::default(),
 435            subscription: RwLock::new(watch::channel()),
 436            theme: Default::default(),
 437        }
 438    }
 439
 440    #[cfg(any(test, feature = "test-support"))]
 441    pub fn test() -> Self {
 442        Self::new(Task::ready(()))
 443    }
 444
 445    pub fn add(&self, language: Arc<Language>) {
 446        if let Some(theme) = self.theme.read().clone() {
 447            language.set_theme(&theme.editor.syntax);
 448        }
 449        self.languages.write().push(language);
 450        *self.subscription.write().0.borrow_mut() = ();
 451    }
 452
 453    pub fn subscribe(&self) -> watch::Receiver<()> {
 454        self.subscription.read().1.clone()
 455    }
 456
 457    pub fn set_theme(&self, theme: Arc<Theme>) {
 458        *self.theme.write() = Some(theme.clone());
 459        for language in self.languages.read().iter() {
 460            language.set_theme(&theme.editor.syntax);
 461        }
 462    }
 463
 464    pub fn set_language_server_download_dir(&mut self, path: impl Into<Arc<Path>>) {
 465        self.language_server_download_dir = Some(path.into());
 466    }
 467
 468    pub fn get_language(&self, name: &str) -> Option<Arc<Language>> {
 469        self.languages
 470            .read()
 471            .iter()
 472            .find(|language| language.name().to_lowercase() == name.to_lowercase())
 473            .cloned()
 474    }
 475
 476    pub fn to_vec(&self) -> Vec<Arc<Language>> {
 477        self.languages.read().iter().cloned().collect()
 478    }
 479
 480    pub fn language_names(&self) -> Vec<String> {
 481        self.languages
 482            .read()
 483            .iter()
 484            .map(|language| language.name().to_string())
 485            .collect()
 486    }
 487
 488    pub fn select_language(&self, path: impl AsRef<Path>) -> Option<Arc<Language>> {
 489        let path = path.as_ref();
 490        let filename = path.file_name().and_then(|name| name.to_str());
 491        let extension = path.extension().and_then(|name| name.to_str());
 492        let path_suffixes = [extension, filename];
 493        self.languages
 494            .read()
 495            .iter()
 496            .find(|language| {
 497                language
 498                    .config
 499                    .path_suffixes
 500                    .iter()
 501                    .any(|suffix| path_suffixes.contains(&Some(suffix.as_str())))
 502            })
 503            .cloned()
 504    }
 505
 506    pub fn start_language_server(
 507        self: &Arc<Self>,
 508        server_id: usize,
 509        language: Arc<Language>,
 510        root_path: Arc<Path>,
 511        http_client: Arc<dyn HttpClient>,
 512        cx: &mut MutableAppContext,
 513    ) -> Option<Task<Result<lsp::LanguageServer>>> {
 514        #[cfg(any(test, feature = "test-support"))]
 515        if language.fake_adapter.is_some() {
 516            let language = language;
 517            return Some(cx.spawn(|cx| async move {
 518                let (servers_tx, fake_adapter) = language.fake_adapter.as_ref().unwrap();
 519                let (server, mut fake_server) = lsp::LanguageServer::fake(
 520                    fake_adapter.name.to_string(),
 521                    fake_adapter.capabilities.clone(),
 522                    cx.clone(),
 523                );
 524
 525                if let Some(initializer) = &fake_adapter.initializer {
 526                    initializer(&mut fake_server);
 527                }
 528
 529                let servers_tx = servers_tx.clone();
 530                cx.background()
 531                    .spawn(async move {
 532                        if fake_server
 533                            .try_receive_notification::<lsp::notification::Initialized>()
 534                            .await
 535                            .is_some()
 536                        {
 537                            servers_tx.unbounded_send(fake_server).ok();
 538                        }
 539                    })
 540                    .detach();
 541                Ok(server)
 542            }));
 543        }
 544
 545        let download_dir = self
 546            .language_server_download_dir
 547            .clone()
 548            .ok_or_else(|| anyhow!("language server download directory has not been assigned"))
 549            .log_err()?;
 550
 551        let this = self.clone();
 552        let adapter = language.adapter.clone()?;
 553        let lsp_binary_statuses = self.lsp_binary_statuses_tx.clone();
 554        let login_shell_env_loaded = self.login_shell_env_loaded.clone();
 555        Some(cx.spawn(|cx| async move {
 556            login_shell_env_loaded.await;
 557            let server_binary_path = this
 558                .lsp_binary_paths
 559                .lock()
 560                .entry(adapter.name.clone())
 561                .or_insert_with(|| {
 562                    get_server_binary_path(
 563                        adapter.clone(),
 564                        language.clone(),
 565                        http_client,
 566                        download_dir,
 567                        lsp_binary_statuses,
 568                    )
 569                    .map_err(Arc::new)
 570                    .boxed()
 571                    .shared()
 572                })
 573                .clone()
 574                .map_err(|e| anyhow!(e));
 575
 576            let server_binary_path = server_binary_path.await?;
 577            let server_args = &adapter.server_args;
 578            let server = lsp::LanguageServer::new(
 579                server_id,
 580                &server_binary_path,
 581                server_args,
 582                &root_path,
 583                cx,
 584            )?;
 585            Ok(server)
 586        }))
 587    }
 588
 589    pub fn language_server_binary_statuses(
 590        &self,
 591    ) -> async_broadcast::Receiver<(Arc<Language>, LanguageServerBinaryStatus)> {
 592        self.lsp_binary_statuses_rx.clone()
 593    }
 594}
 595
 596#[cfg(any(test, feature = "test-support"))]
 597impl Default for LanguageRegistry {
 598    fn default() -> Self {
 599        Self::test()
 600    }
 601}
 602
 603async fn get_server_binary_path(
 604    adapter: Arc<CachedLspAdapter>,
 605    language: Arc<Language>,
 606    http_client: Arc<dyn HttpClient>,
 607    download_dir: Arc<Path>,
 608    statuses: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
 609) -> Result<PathBuf> {
 610    let container_dir = download_dir.join(adapter.name.0.as_ref());
 611    if !container_dir.exists() {
 612        smol::fs::create_dir_all(&container_dir)
 613            .await
 614            .context("failed to create container directory")?;
 615    }
 616
 617    let path = fetch_latest_server_binary_path(
 618        adapter.clone(),
 619        language.clone(),
 620        http_client,
 621        &container_dir,
 622        statuses.clone(),
 623    )
 624    .await;
 625    if let Err(error) = path.as_ref() {
 626        if let Some(cached_path) = adapter.cached_server_binary(container_dir).await {
 627            statuses
 628                .broadcast((language.clone(), LanguageServerBinaryStatus::Cached))
 629                .await?;
 630            return Ok(cached_path);
 631        } else {
 632            statuses
 633                .broadcast((
 634                    language.clone(),
 635                    LanguageServerBinaryStatus::Failed {
 636                        error: format!("{:?}", error),
 637                    },
 638                ))
 639                .await?;
 640        }
 641    }
 642    path
 643}
 644
 645async fn fetch_latest_server_binary_path(
 646    adapter: Arc<CachedLspAdapter>,
 647    language: Arc<Language>,
 648    http_client: Arc<dyn HttpClient>,
 649    container_dir: &Path,
 650    lsp_binary_statuses_tx: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
 651) -> Result<PathBuf> {
 652    let container_dir: Arc<Path> = container_dir.into();
 653    lsp_binary_statuses_tx
 654        .broadcast((
 655            language.clone(),
 656            LanguageServerBinaryStatus::CheckingForUpdate,
 657        ))
 658        .await?;
 659    let version_info = adapter
 660        .fetch_latest_server_version(http_client.clone())
 661        .await?;
 662    lsp_binary_statuses_tx
 663        .broadcast((language.clone(), LanguageServerBinaryStatus::Downloading))
 664        .await?;
 665    let path = adapter
 666        .fetch_server_binary(version_info, http_client, container_dir.to_path_buf())
 667        .await?;
 668    lsp_binary_statuses_tx
 669        .broadcast((language.clone(), LanguageServerBinaryStatus::Downloaded))
 670        .await?;
 671    Ok(path)
 672}
 673
 674impl Language {
 675    pub fn new(config: LanguageConfig, ts_language: Option<tree_sitter::Language>) -> Self {
 676        Self {
 677            config,
 678            grammar: ts_language.map(|ts_language| {
 679                Arc::new(Grammar {
 680                    id: NEXT_GRAMMAR_ID.fetch_add(1, SeqCst),
 681                    highlights_query: None,
 682                    brackets_config: None,
 683                    outline_config: None,
 684                    indents_config: None,
 685                    injection_config: None,
 686                    override_config: None,
 687                    ts_language,
 688                    highlight_map: Default::default(),
 689                })
 690            }),
 691            adapter: None,
 692
 693            #[cfg(any(test, feature = "test-support"))]
 694            fake_adapter: None,
 695        }
 696    }
 697
 698    pub fn lsp_adapter(&self) -> Option<Arc<CachedLspAdapter>> {
 699        self.adapter.clone()
 700    }
 701
 702    pub fn id(&self) -> Option<usize> {
 703        self.grammar.as_ref().map(|g| g.id)
 704    }
 705
 706    pub fn with_highlights_query(mut self, source: &str) -> Result<Self> {
 707        let grammar = self.grammar_mut();
 708        grammar.highlights_query = Some(Query::new(grammar.ts_language, source)?);
 709        Ok(self)
 710    }
 711
 712    pub fn with_brackets_query(mut self, source: &str) -> Result<Self> {
 713        let grammar = self.grammar_mut();
 714        let query = Query::new(grammar.ts_language, source)?;
 715        let mut open_capture_ix = None;
 716        let mut close_capture_ix = None;
 717        get_capture_indices(
 718            &query,
 719            &mut [
 720                ("open", &mut open_capture_ix),
 721                ("close", &mut close_capture_ix),
 722            ],
 723        );
 724        if let Some((open_capture_ix, close_capture_ix)) = open_capture_ix.zip(close_capture_ix) {
 725            grammar.brackets_config = Some(BracketConfig {
 726                query,
 727                open_capture_ix,
 728                close_capture_ix,
 729            });
 730        }
 731        Ok(self)
 732    }
 733
 734    pub fn with_indents_query(mut self, source: &str) -> Result<Self> {
 735        let grammar = self.grammar_mut();
 736        let query = Query::new(grammar.ts_language, source)?;
 737        let mut indent_capture_ix = None;
 738        let mut start_capture_ix = None;
 739        let mut end_capture_ix = None;
 740        let mut outdent_capture_ix = None;
 741        get_capture_indices(
 742            &query,
 743            &mut [
 744                ("indent", &mut indent_capture_ix),
 745                ("start", &mut start_capture_ix),
 746                ("end", &mut end_capture_ix),
 747                ("outdent", &mut outdent_capture_ix),
 748            ],
 749        );
 750        if let Some(indent_capture_ix) = indent_capture_ix {
 751            grammar.indents_config = Some(IndentConfig {
 752                query,
 753                indent_capture_ix,
 754                start_capture_ix,
 755                end_capture_ix,
 756                outdent_capture_ix,
 757            });
 758        }
 759        Ok(self)
 760    }
 761
 762    pub fn with_outline_query(mut self, source: &str) -> Result<Self> {
 763        let grammar = self.grammar_mut();
 764        let query = Query::new(grammar.ts_language, source)?;
 765        let mut item_capture_ix = None;
 766        let mut name_capture_ix = None;
 767        let mut context_capture_ix = None;
 768        get_capture_indices(
 769            &query,
 770            &mut [
 771                ("item", &mut item_capture_ix),
 772                ("name", &mut name_capture_ix),
 773                ("context", &mut context_capture_ix),
 774            ],
 775        );
 776        if let Some((item_capture_ix, name_capture_ix)) = item_capture_ix.zip(name_capture_ix) {
 777            grammar.outline_config = Some(OutlineConfig {
 778                query,
 779                item_capture_ix,
 780                name_capture_ix,
 781                context_capture_ix,
 782            });
 783        }
 784        Ok(self)
 785    }
 786
 787    pub fn with_injection_query(mut self, source: &str) -> Result<Self> {
 788        let grammar = self.grammar_mut();
 789        let query = Query::new(grammar.ts_language, source)?;
 790        let mut language_capture_ix = None;
 791        let mut content_capture_ix = None;
 792        get_capture_indices(
 793            &query,
 794            &mut [
 795                ("language", &mut language_capture_ix),
 796                ("content", &mut content_capture_ix),
 797            ],
 798        );
 799        let patterns = (0..query.pattern_count())
 800            .map(|ix| {
 801                let mut config = InjectionPatternConfig::default();
 802                for setting in query.property_settings(ix) {
 803                    match setting.key.as_ref() {
 804                        "language" => {
 805                            config.language = setting.value.clone();
 806                        }
 807                        "combined" => {
 808                            config.combined = true;
 809                        }
 810                        _ => {}
 811                    }
 812                }
 813                config
 814            })
 815            .collect();
 816        if let Some(content_capture_ix) = content_capture_ix {
 817            grammar.injection_config = Some(InjectionConfig {
 818                query,
 819                language_capture_ix,
 820                content_capture_ix,
 821                patterns,
 822            });
 823        }
 824        Ok(self)
 825    }
 826
 827    pub fn with_override_query(mut self, source: &str) -> Result<Self> {
 828        let query = Query::new(self.grammar_mut().ts_language, source)?;
 829
 830        let mut values = HashMap::default();
 831        for (ix, name) in query.capture_names().iter().enumerate() {
 832            if !name.starts_with('_') {
 833                let value = self.config.overrides.remove(name).ok_or_else(|| {
 834                    anyhow!(
 835                        "language {:?} has override in query but not in config: {name:?}",
 836                        self.config.name
 837                    )
 838                })?;
 839                values.insert(ix as u32, value);
 840            }
 841        }
 842
 843        if !self.config.overrides.is_empty() {
 844            let keys = self.config.overrides.keys().collect::<Vec<_>>();
 845            Err(anyhow!(
 846                "language {:?} has overrides in config not in query: {keys:?}",
 847                self.config.name
 848            ))?;
 849        }
 850
 851        self.grammar_mut().override_config = Some(OverrideConfig { query, values });
 852        Ok(self)
 853    }
 854
 855    fn grammar_mut(&mut self) -> &mut Grammar {
 856        Arc::get_mut(self.grammar.as_mut().unwrap()).unwrap()
 857    }
 858
 859    pub fn with_lsp_adapter(mut self, lsp_adapter: Arc<CachedLspAdapter>) -> Self {
 860        self.adapter = Some(lsp_adapter);
 861        self
 862    }
 863
 864    #[cfg(any(test, feature = "test-support"))]
 865    pub async fn set_fake_lsp_adapter(
 866        &mut self,
 867        fake_lsp_adapter: Arc<FakeLspAdapter>,
 868    ) -> mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
 869        let (servers_tx, servers_rx) = mpsc::unbounded();
 870        self.fake_adapter = Some((servers_tx, fake_lsp_adapter.clone()));
 871        let adapter = CachedLspAdapter::new(fake_lsp_adapter).await;
 872        self.adapter = Some(adapter);
 873        servers_rx
 874    }
 875
 876    pub fn name(&self) -> Arc<str> {
 877        self.config.name.clone()
 878    }
 879
 880    pub async fn disk_based_diagnostic_sources(&self) -> &[String] {
 881        match self.adapter.as_ref() {
 882            Some(adapter) => &adapter.disk_based_diagnostic_sources,
 883            None => &[],
 884        }
 885    }
 886
 887    pub async fn disk_based_diagnostics_progress_token(&self) -> Option<&str> {
 888        if let Some(adapter) = self.adapter.as_ref() {
 889            adapter.disk_based_diagnostics_progress_token.as_deref()
 890        } else {
 891            None
 892        }
 893    }
 894
 895    pub async fn process_diagnostics(&self, diagnostics: &mut lsp::PublishDiagnosticsParams) {
 896        if let Some(processor) = self.adapter.as_ref() {
 897            processor.process_diagnostics(diagnostics).await;
 898        }
 899    }
 900
 901    pub async fn process_completion(self: &Arc<Self>, completion: &mut lsp::CompletionItem) {
 902        if let Some(adapter) = self.adapter.as_ref() {
 903            adapter.process_completion(completion).await;
 904        }
 905    }
 906
 907    pub async fn label_for_completion(
 908        self: &Arc<Self>,
 909        completion: &lsp::CompletionItem,
 910    ) -> Option<CodeLabel> {
 911        self.adapter
 912            .as_ref()?
 913            .label_for_completion(completion, self)
 914            .await
 915    }
 916
 917    pub async fn label_for_symbol(
 918        self: &Arc<Self>,
 919        name: &str,
 920        kind: lsp::SymbolKind,
 921    ) -> Option<CodeLabel> {
 922        self.adapter
 923            .as_ref()?
 924            .label_for_symbol(name, kind, self)
 925            .await
 926    }
 927
 928    pub fn highlight_text<'a>(
 929        self: &'a Arc<Self>,
 930        text: &'a Rope,
 931        range: Range<usize>,
 932    ) -> Vec<(Range<usize>, HighlightId)> {
 933        let mut result = Vec::new();
 934        if let Some(grammar) = &self.grammar {
 935            let tree = grammar.parse_text(text, None);
 936            let captures =
 937                SyntaxSnapshot::single_tree_captures(range.clone(), text, &tree, self, |grammar| {
 938                    grammar.highlights_query.as_ref()
 939                });
 940            let highlight_maps = vec![grammar.highlight_map()];
 941            let mut offset = 0;
 942            for chunk in BufferChunks::new(text, range, Some((captures, highlight_maps)), vec![]) {
 943                let end_offset = offset + chunk.text.len();
 944                if let Some(highlight_id) = chunk.syntax_highlight_id {
 945                    if !highlight_id.is_default() {
 946                        result.push((offset..end_offset, highlight_id));
 947                    }
 948                }
 949                offset = end_offset;
 950            }
 951        }
 952        result
 953    }
 954
 955    pub fn path_suffixes(&self) -> &[String] {
 956        &self.config.path_suffixes
 957    }
 958
 959    pub fn should_autoclose_before(&self, c: char) -> bool {
 960        c.is_whitespace() || self.config.autoclose_before.contains(c)
 961    }
 962
 963    pub fn set_theme(&self, theme: &SyntaxTheme) {
 964        if let Some(grammar) = self.grammar.as_ref() {
 965            if let Some(highlights_query) = &grammar.highlights_query {
 966                *grammar.highlight_map.lock() =
 967                    HighlightMap::new(highlights_query.capture_names(), theme);
 968            }
 969        }
 970    }
 971
 972    pub fn grammar(&self) -> Option<&Arc<Grammar>> {
 973        self.grammar.as_ref()
 974    }
 975}
 976
 977impl LanguageScope {
 978    pub fn line_comment_prefix(&self) -> Option<&Arc<str>> {
 979        Override::as_option(
 980            self.config_override().map(|o| &o.line_comment),
 981            self.language.config.line_comment.as_ref(),
 982        )
 983    }
 984
 985    pub fn block_comment_delimiters(&self) -> Option<(&Arc<str>, &Arc<str>)> {
 986        Override::as_option(
 987            self.config_override().map(|o| &o.block_comment),
 988            self.language.config.block_comment.as_ref(),
 989        )
 990        .map(|e| (&e.0, &e.1))
 991    }
 992
 993    pub fn brackets(&self) -> &[BracketPair] {
 994        Override::as_option(
 995            self.config_override().map(|o| &o.brackets),
 996            Some(&self.language.config.brackets),
 997        )
 998        .map_or(&[], Vec::as_slice)
 999    }
1000
1001    pub fn should_autoclose_before(&self, c: char) -> bool {
1002        c.is_whitespace() || self.language.config.autoclose_before.contains(c)
1003    }
1004
1005    fn config_override(&self) -> Option<&LanguageConfigOverride> {
1006        let id = self.override_id?;
1007        let grammar = self.language.grammar.as_ref()?;
1008        let override_config = grammar.override_config.as_ref()?;
1009        override_config.values.get(&id)
1010    }
1011}
1012
1013impl Hash for Language {
1014    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1015        self.id().hash(state)
1016    }
1017}
1018
1019impl PartialEq for Language {
1020    fn eq(&self, other: &Self) -> bool {
1021        self.id().eq(&other.id())
1022    }
1023}
1024
1025impl Eq for Language {}
1026
1027impl Debug for Language {
1028    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1029        f.debug_struct("Language")
1030            .field("name", &self.config.name)
1031            .finish()
1032    }
1033}
1034
1035impl Grammar {
1036    pub fn id(&self) -> usize {
1037        self.id
1038    }
1039
1040    fn parse_text(&self, text: &Rope, old_tree: Option<Tree>) -> Tree {
1041        PARSER.with(|parser| {
1042            let mut parser = parser.borrow_mut();
1043            parser
1044                .set_language(self.ts_language)
1045                .expect("incompatible grammar");
1046            let mut chunks = text.chunks_in_range(0..text.len());
1047            parser
1048                .parse_with(
1049                    &mut move |offset, _| {
1050                        chunks.seek(offset);
1051                        chunks.next().unwrap_or("").as_bytes()
1052                    },
1053                    old_tree.as_ref(),
1054                )
1055                .unwrap()
1056        })
1057    }
1058
1059    pub fn highlight_map(&self) -> HighlightMap {
1060        self.highlight_map.lock().clone()
1061    }
1062
1063    pub fn highlight_id_for_name(&self, name: &str) -> Option<HighlightId> {
1064        let capture_id = self
1065            .highlights_query
1066            .as_ref()?
1067            .capture_index_for_name(name)?;
1068        Some(self.highlight_map.lock().get(capture_id))
1069    }
1070}
1071
1072impl CodeLabel {
1073    pub fn plain(text: String, filter_text: Option<&str>) -> Self {
1074        let mut result = Self {
1075            runs: Vec::new(),
1076            filter_range: 0..text.len(),
1077            text,
1078        };
1079        if let Some(filter_text) = filter_text {
1080            if let Some(ix) = result.text.find(filter_text) {
1081                result.filter_range = ix..ix + filter_text.len();
1082            }
1083        }
1084        result
1085    }
1086}
1087
1088#[cfg(any(test, feature = "test-support"))]
1089impl Default for FakeLspAdapter {
1090    fn default() -> Self {
1091        Self {
1092            name: "the-fake-language-server",
1093            capabilities: lsp::LanguageServer::full_capabilities(),
1094            initializer: None,
1095            disk_based_diagnostics_progress_token: None,
1096            disk_based_diagnostics_sources: Vec::new(),
1097        }
1098    }
1099}
1100
1101#[cfg(any(test, feature = "test-support"))]
1102#[async_trait]
1103impl LspAdapter for Arc<FakeLspAdapter> {
1104    async fn name(&self) -> LanguageServerName {
1105        LanguageServerName(self.name.into())
1106    }
1107
1108    async fn fetch_latest_server_version(
1109        &self,
1110        _: Arc<dyn HttpClient>,
1111    ) -> Result<Box<dyn 'static + Send + Any>> {
1112        unreachable!();
1113    }
1114
1115    async fn fetch_server_binary(
1116        &self,
1117        _: Box<dyn 'static + Send + Any>,
1118        _: Arc<dyn HttpClient>,
1119        _: PathBuf,
1120    ) -> Result<PathBuf> {
1121        unreachable!();
1122    }
1123
1124    async fn cached_server_binary(&self, _: PathBuf) -> Option<PathBuf> {
1125        unreachable!();
1126    }
1127
1128    async fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
1129
1130    async fn disk_based_diagnostic_sources(&self) -> Vec<String> {
1131        self.disk_based_diagnostics_sources.clone()
1132    }
1133
1134    async fn disk_based_diagnostics_progress_token(&self) -> Option<String> {
1135        self.disk_based_diagnostics_progress_token.clone()
1136    }
1137}
1138
1139fn get_capture_indices(query: &Query, captures: &mut [(&str, &mut Option<u32>)]) {
1140    for (ix, name) in query.capture_names().iter().enumerate() {
1141        for (capture_name, index) in captures.iter_mut() {
1142            if capture_name == name {
1143                **index = Some(ix as u32);
1144                break;
1145            }
1146        }
1147    }
1148}
1149
1150pub fn point_to_lsp(point: PointUtf16) -> lsp::Position {
1151    lsp::Position::new(point.row, point.column)
1152}
1153
1154pub fn point_from_lsp(point: lsp::Position) -> Unclipped<PointUtf16> {
1155    Unclipped(PointUtf16::new(point.line, point.character))
1156}
1157
1158pub fn range_to_lsp(range: Range<PointUtf16>) -> lsp::Range {
1159    lsp::Range {
1160        start: point_to_lsp(range.start),
1161        end: point_to_lsp(range.end),
1162    }
1163}
1164
1165pub fn range_from_lsp(range: lsp::Range) -> Range<Unclipped<PointUtf16>> {
1166    let mut start = point_from_lsp(range.start);
1167    let mut end = point_from_lsp(range.end);
1168    if start > end {
1169        mem::swap(&mut start, &mut end);
1170    }
1171    start..end
1172}