language.rs

   1//! The `language` crate provides a large chunk of Zed's language-related
   2//! features (the other big contributors being project and lsp crates that revolve around LSP features).
   3//! Namely, this crate:
   4//! - Provides [`Language`], [`Grammar`] and [`LanguageRegistry`] types that
   5//!   use Tree-sitter to provide syntax highlighting to the editor; note though that `language` doesn't perform the highlighting by itself. It only maps ranges in a buffer to colors. Treesitter is also used for buffer outlines (lists of symbols in a buffer)
   6//! - Exposes [`LanguageConfig`] that describes how constructs (like brackets or line comments) should be handled by the editor for a source file of a particular language.
   7//!
   8//! Notably we do *not* assign a single language to a single file; in real world a single file can consist of multiple programming languages - HTML is a good example of that - and `language` crate tends to reflect that status quo in its API.
   9mod buffer;
  10mod diagnostic_set;
  11mod highlight_map;
  12mod language_registry;
  13pub mod language_settings;
  14mod manifest;
  15mod outline;
  16pub mod proto;
  17mod syntax_map;
  18mod task_context;
  19mod text_diff;
  20mod toolchain;
  21
  22#[cfg(test)]
  23pub mod buffer_tests;
  24
  25use crate::language_settings::SoftWrap;
  26pub use crate::language_settings::{EditPredictionsMode, IndentGuideSettings};
  27use anyhow::{Context as _, Result};
  28use async_trait::async_trait;
  29use collections::{HashMap, HashSet, IndexSet};
  30use futures::Future;
  31use futures::future::LocalBoxFuture;
  32use futures::lock::OwnedMutexGuard;
  33use gpui::{App, AsyncApp, Entity, SharedString};
  34pub use highlight_map::HighlightMap;
  35use http_client::HttpClient;
  36pub use language_registry::{
  37    LanguageName, LanguageServerStatusUpdate, LoadedLanguage, ServerHealth,
  38};
  39use lsp::{
  40    CodeActionKind, InitializeParams, LanguageServerBinary, LanguageServerBinaryOptions, Uri,
  41};
  42pub use manifest::{ManifestDelegate, ManifestName, ManifestProvider, ManifestQuery};
  43use parking_lot::Mutex;
  44use regex::Regex;
  45use schemars::{JsonSchema, SchemaGenerator, json_schema};
  46use semver::Version;
  47use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
  48use serde_json::Value;
  49use settings::WorktreeId;
  50use smol::future::FutureExt as _;
  51use std::num::NonZeroU32;
  52use std::{
  53    ffi::OsStr,
  54    fmt::Debug,
  55    hash::Hash,
  56    mem,
  57    ops::{DerefMut, Range},
  58    path::{Path, PathBuf},
  59    str,
  60    sync::{
  61        Arc, LazyLock,
  62        atomic::{AtomicUsize, Ordering::SeqCst},
  63    },
  64};
  65use syntax_map::{QueryCursorHandle, SyntaxSnapshot};
  66use task::RunnableTag;
  67pub use task_context::{ContextLocation, ContextProvider, RunnableRange};
  68pub use text_diff::{
  69    DiffOptions, apply_diff_patch, apply_reversed_diff_patch, line_diff, text_diff,
  70    text_diff_with_options, unified_diff, unified_diff_with_context, unified_diff_with_offsets,
  71    word_diff_ranges,
  72};
  73use theme::SyntaxTheme;
  74pub use toolchain::{
  75    LanguageToolchainStore, LocalLanguageToolchainStore, Toolchain, ToolchainList, ToolchainLister,
  76    ToolchainMetadata, ToolchainScope,
  77};
  78use tree_sitter::{self, Query, QueryCursor, WasmStore, wasmtime};
  79use util::rel_path::RelPath;
  80use util::serde::default_true;
  81
  82pub use buffer::Operation;
  83pub use buffer::*;
  84pub use diagnostic_set::{DiagnosticEntry, DiagnosticEntryRef, DiagnosticGroup};
  85pub use language_registry::{
  86    AvailableLanguage, BinaryStatus, LanguageNotFound, LanguageQueries, LanguageRegistry,
  87    QUERY_FILENAME_PREFIXES,
  88};
  89pub use lsp::{LanguageServerId, LanguageServerName};
  90pub use outline::*;
  91pub use syntax_map::{
  92    OwnedSyntaxLayer, SyntaxLayer, SyntaxMapMatches, ToTreeSitterPoint, TreeSitterOptions,
  93};
  94pub use text::{AnchorRangeExt, LineEnding};
  95pub use tree_sitter::{Node, Parser, Tree, TreeCursor};
  96
  97static QUERY_CURSORS: Mutex<Vec<QueryCursor>> = Mutex::new(vec![]);
  98static PARSERS: Mutex<Vec<Parser>> = Mutex::new(vec![]);
  99
 100pub fn with_parser<F, R>(func: F) -> R
 101where
 102    F: FnOnce(&mut Parser) -> R,
 103{
 104    let mut parser = PARSERS.lock().pop().unwrap_or_else(|| {
 105        let mut parser = Parser::new();
 106        parser
 107            .set_wasm_store(WasmStore::new(&WASM_ENGINE).unwrap())
 108            .unwrap();
 109        parser
 110    });
 111    parser.set_included_ranges(&[]).unwrap();
 112    let result = func(&mut parser);
 113    PARSERS.lock().push(parser);
 114    result
 115}
 116
 117pub fn with_query_cursor<F, R>(func: F) -> R
 118where
 119    F: FnOnce(&mut QueryCursor) -> R,
 120{
 121    let mut cursor = QueryCursorHandle::new();
 122    func(cursor.deref_mut())
 123}
 124
 125static NEXT_LANGUAGE_ID: AtomicUsize = AtomicUsize::new(0);
 126static NEXT_GRAMMAR_ID: AtomicUsize = AtomicUsize::new(0);
 127static WASM_ENGINE: LazyLock<wasmtime::Engine> = LazyLock::new(|| {
 128    wasmtime::Engine::new(&wasmtime::Config::new()).expect("Failed to create Wasmtime engine")
 129});
 130
 131/// A shared grammar for plain text, exposed for reuse by downstream crates.
 132pub static PLAIN_TEXT: LazyLock<Arc<Language>> = LazyLock::new(|| {
 133    Arc::new(Language::new(
 134        LanguageConfig {
 135            name: "Plain Text".into(),
 136            soft_wrap: Some(SoftWrap::EditorWidth),
 137            matcher: LanguageMatcher {
 138                path_suffixes: vec!["txt".to_owned()],
 139                first_line_pattern: None,
 140            },
 141            brackets: BracketPairConfig {
 142                pairs: vec![
 143                    BracketPair {
 144                        start: "(".to_string(),
 145                        end: ")".to_string(),
 146                        close: true,
 147                        surround: true,
 148                        newline: false,
 149                    },
 150                    BracketPair {
 151                        start: "[".to_string(),
 152                        end: "]".to_string(),
 153                        close: true,
 154                        surround: true,
 155                        newline: false,
 156                    },
 157                    BracketPair {
 158                        start: "{".to_string(),
 159                        end: "}".to_string(),
 160                        close: true,
 161                        surround: true,
 162                        newline: false,
 163                    },
 164                    BracketPair {
 165                        start: "\"".to_string(),
 166                        end: "\"".to_string(),
 167                        close: true,
 168                        surround: true,
 169                        newline: false,
 170                    },
 171                    BracketPair {
 172                        start: "'".to_string(),
 173                        end: "'".to_string(),
 174                        close: true,
 175                        surround: true,
 176                        newline: false,
 177                    },
 178                ],
 179                disabled_scopes_by_bracket_ix: Default::default(),
 180            },
 181            ..Default::default()
 182        },
 183        None,
 184    ))
 185});
 186
 187/// Types that represent a position in a buffer, and can be converted into
 188/// an LSP position, to send to a language server.
 189pub trait ToLspPosition {
 190    /// Converts the value into an LSP position.
 191    fn to_lsp_position(self) -> lsp::Position;
 192}
 193
 194#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 195pub struct Location {
 196    pub buffer: Entity<Buffer>,
 197    pub range: Range<Anchor>,
 198}
 199
 200type ServerBinaryCache = futures::lock::Mutex<Option<(bool, LanguageServerBinary)>>;
 201type DownloadableLanguageServerBinary = LocalBoxFuture<'static, Result<LanguageServerBinary>>;
 202pub type LanguageServerBinaryLocations = LocalBoxFuture<
 203    'static,
 204    (
 205        Result<LanguageServerBinary>,
 206        Option<DownloadableLanguageServerBinary>,
 207    ),
 208>;
 209/// Represents a Language Server, with certain cached sync properties.
 210/// Uses [`LspAdapter`] under the hood, but calls all 'static' methods
 211/// once at startup, and caches the results.
 212pub struct CachedLspAdapter {
 213    pub name: LanguageServerName,
 214    pub disk_based_diagnostic_sources: Vec<String>,
 215    pub disk_based_diagnostics_progress_token: Option<String>,
 216    language_ids: HashMap<LanguageName, String>,
 217    pub adapter: Arc<dyn LspAdapter>,
 218    cached_binary: Arc<ServerBinaryCache>,
 219}
 220
 221impl Debug for CachedLspAdapter {
 222    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 223        f.debug_struct("CachedLspAdapter")
 224            .field("name", &self.name)
 225            .field(
 226                "disk_based_diagnostic_sources",
 227                &self.disk_based_diagnostic_sources,
 228            )
 229            .field(
 230                "disk_based_diagnostics_progress_token",
 231                &self.disk_based_diagnostics_progress_token,
 232            )
 233            .field("language_ids", &self.language_ids)
 234            .finish_non_exhaustive()
 235    }
 236}
 237
 238impl CachedLspAdapter {
 239    pub fn new(adapter: Arc<dyn LspAdapter>) -> Arc<Self> {
 240        let name = adapter.name();
 241        let disk_based_diagnostic_sources = adapter.disk_based_diagnostic_sources();
 242        let disk_based_diagnostics_progress_token = adapter.disk_based_diagnostics_progress_token();
 243        let language_ids = adapter.language_ids();
 244
 245        Arc::new(CachedLspAdapter {
 246            name,
 247            disk_based_diagnostic_sources,
 248            disk_based_diagnostics_progress_token,
 249            language_ids,
 250            adapter,
 251            cached_binary: Default::default(),
 252        })
 253    }
 254
 255    pub fn name(&self) -> LanguageServerName {
 256        self.adapter.name()
 257    }
 258
 259    pub async fn get_language_server_command(
 260        self: Arc<Self>,
 261        delegate: Arc<dyn LspAdapterDelegate>,
 262        toolchains: Option<Toolchain>,
 263        binary_options: LanguageServerBinaryOptions,
 264        cx: &mut AsyncApp,
 265    ) -> LanguageServerBinaryLocations {
 266        let cached_binary = self.cached_binary.clone().lock_owned().await;
 267        self.adapter.clone().get_language_server_command(
 268            delegate,
 269            toolchains,
 270            binary_options,
 271            cached_binary,
 272            cx.clone(),
 273        )
 274    }
 275
 276    pub fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
 277        self.adapter.code_action_kinds()
 278    }
 279
 280    pub fn process_diagnostics(
 281        &self,
 282        params: &mut lsp::PublishDiagnosticsParams,
 283        server_id: LanguageServerId,
 284        existing_diagnostics: Option<&'_ Buffer>,
 285    ) {
 286        self.adapter
 287            .process_diagnostics(params, server_id, existing_diagnostics)
 288    }
 289
 290    pub fn retain_old_diagnostic(&self, previous_diagnostic: &Diagnostic, cx: &App) -> bool {
 291        self.adapter.retain_old_diagnostic(previous_diagnostic, cx)
 292    }
 293
 294    pub fn underline_diagnostic(&self, diagnostic: &lsp::Diagnostic) -> bool {
 295        self.adapter.underline_diagnostic(diagnostic)
 296    }
 297
 298    pub fn diagnostic_message_to_markdown(&self, message: &str) -> Option<String> {
 299        self.adapter.diagnostic_message_to_markdown(message)
 300    }
 301
 302    pub async fn process_completions(&self, completion_items: &mut [lsp::CompletionItem]) {
 303        self.adapter.process_completions(completion_items).await
 304    }
 305
 306    pub async fn labels_for_completions(
 307        &self,
 308        completion_items: &[lsp::CompletionItem],
 309        language: &Arc<Language>,
 310    ) -> Result<Vec<Option<CodeLabel>>> {
 311        self.adapter
 312            .clone()
 313            .labels_for_completions(completion_items, language)
 314            .await
 315    }
 316
 317    pub async fn labels_for_symbols(
 318        &self,
 319        symbols: &[(String, lsp::SymbolKind)],
 320        language: &Arc<Language>,
 321    ) -> Result<Vec<Option<CodeLabel>>> {
 322        self.adapter
 323            .clone()
 324            .labels_for_symbols(symbols, language)
 325            .await
 326    }
 327
 328    pub fn language_id(&self, language_name: &LanguageName) -> String {
 329        self.language_ids
 330            .get(language_name)
 331            .cloned()
 332            .unwrap_or_else(|| language_name.lsp_id())
 333    }
 334
 335    pub async fn initialization_options_schema(
 336        &self,
 337        delegate: &Arc<dyn LspAdapterDelegate>,
 338        cx: &mut AsyncApp,
 339    ) -> Option<serde_json::Value> {
 340        self.adapter
 341            .clone()
 342            .initialization_options_schema(
 343                delegate,
 344                self.cached_binary.clone().lock_owned().await,
 345                cx,
 346            )
 347            .await
 348    }
 349
 350    pub fn process_prompt_response(&self, context: &PromptResponseContext, cx: &mut AsyncApp) {
 351        self.adapter.process_prompt_response(context, cx)
 352    }
 353}
 354
 355/// [`LspAdapterDelegate`] allows [`LspAdapter]` implementations to interface with the application
 356// e.g. to display a notification or fetch data from the web.
 357#[async_trait]
 358pub trait LspAdapterDelegate: Send + Sync {
 359    fn show_notification(&self, message: &str, cx: &mut App);
 360    fn http_client(&self) -> Arc<dyn HttpClient>;
 361    fn worktree_id(&self) -> WorktreeId;
 362    fn worktree_root_path(&self) -> &Path;
 363    fn resolve_executable_path(&self, path: PathBuf) -> PathBuf;
 364    fn update_status(&self, language: LanguageServerName, status: BinaryStatus);
 365    fn registered_lsp_adapters(&self) -> Vec<Arc<dyn LspAdapter>>;
 366    async fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>>;
 367
 368    async fn npm_package_installed_version(
 369        &self,
 370        package_name: &str,
 371    ) -> Result<Option<(PathBuf, Version)>>;
 372    async fn which(&self, command: &OsStr) -> Option<PathBuf>;
 373    async fn shell_env(&self) -> HashMap<String, String>;
 374    async fn read_text_file(&self, path: &RelPath) -> Result<String>;
 375    async fn try_exec(&self, binary: LanguageServerBinary) -> Result<()>;
 376}
 377
 378/// Context provided to LSP adapters when a user responds to a ShowMessageRequest prompt.
 379/// This allows adapters to intercept preference selections (like "Always" or "Never")
 380/// and potentially persist them to Zed's settings.
 381#[derive(Debug, Clone)]
 382pub struct PromptResponseContext {
 383    /// The original message shown to the user
 384    pub message: String,
 385    /// The action (button) the user selected
 386    pub selected_action: lsp::MessageActionItem,
 387}
 388
 389#[async_trait(?Send)]
 390pub trait LspAdapter: 'static + Send + Sync + DynLspInstaller {
 391    fn name(&self) -> LanguageServerName;
 392
 393    fn process_diagnostics(
 394        &self,
 395        _: &mut lsp::PublishDiagnosticsParams,
 396        _: LanguageServerId,
 397        _: Option<&'_ Buffer>,
 398    ) {
 399    }
 400
 401    /// When processing new `lsp::PublishDiagnosticsParams` diagnostics, whether to retain previous one(s) or not.
 402    fn retain_old_diagnostic(&self, _previous_diagnostic: &Diagnostic, _cx: &App) -> bool {
 403        false
 404    }
 405
 406    /// Whether to underline a given diagnostic or not, when rendering in the editor.
 407    ///
 408    /// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnosticTag
 409    /// states that
 410    /// > Clients are allowed to render diagnostics with this tag faded out instead of having an error squiggle.
 411    /// for the unnecessary diagnostics, so do not underline them.
 412    fn underline_diagnostic(&self, _diagnostic: &lsp::Diagnostic) -> bool {
 413        true
 414    }
 415
 416    /// Post-processes completions provided by the language server.
 417    async fn process_completions(&self, _: &mut [lsp::CompletionItem]) {}
 418
 419    fn diagnostic_message_to_markdown(&self, _message: &str) -> Option<String> {
 420        None
 421    }
 422
 423    async fn labels_for_completions(
 424        self: Arc<Self>,
 425        completions: &[lsp::CompletionItem],
 426        language: &Arc<Language>,
 427    ) -> Result<Vec<Option<CodeLabel>>> {
 428        let mut labels = Vec::new();
 429        for (ix, completion) in completions.iter().enumerate() {
 430            let label = self.label_for_completion(completion, language).await;
 431            if let Some(label) = label {
 432                labels.resize(ix + 1, None);
 433                *labels.last_mut().unwrap() = Some(label);
 434            }
 435        }
 436        Ok(labels)
 437    }
 438
 439    async fn label_for_completion(
 440        &self,
 441        _: &lsp::CompletionItem,
 442        _: &Arc<Language>,
 443    ) -> Option<CodeLabel> {
 444        None
 445    }
 446
 447    async fn labels_for_symbols(
 448        self: Arc<Self>,
 449        symbols: &[(String, lsp::SymbolKind)],
 450        language: &Arc<Language>,
 451    ) -> Result<Vec<Option<CodeLabel>>> {
 452        let mut labels = Vec::new();
 453        for (ix, (name, kind)) in symbols.iter().enumerate() {
 454            let label = self.label_for_symbol(name, *kind, language).await;
 455            if let Some(label) = label {
 456                labels.resize(ix + 1, None);
 457                *labels.last_mut().unwrap() = Some(label);
 458            }
 459        }
 460        Ok(labels)
 461    }
 462
 463    async fn label_for_symbol(
 464        &self,
 465        _: &str,
 466        _: lsp::SymbolKind,
 467        _: &Arc<Language>,
 468    ) -> Option<CodeLabel> {
 469        None
 470    }
 471
 472    /// Returns initialization options that are going to be sent to a LSP server as a part of [`lsp::InitializeParams`]
 473    async fn initialization_options(
 474        self: Arc<Self>,
 475        _: &Arc<dyn LspAdapterDelegate>,
 476    ) -> Result<Option<Value>> {
 477        Ok(None)
 478    }
 479
 480    /// Returns the JSON schema of the initialization_options for the language server.
 481    async fn initialization_options_schema(
 482        self: Arc<Self>,
 483        _delegate: &Arc<dyn LspAdapterDelegate>,
 484        _cached_binary: OwnedMutexGuard<Option<(bool, LanguageServerBinary)>>,
 485        _cx: &mut AsyncApp,
 486    ) -> Option<serde_json::Value> {
 487        None
 488    }
 489
 490    async fn workspace_configuration(
 491        self: Arc<Self>,
 492        _: &Arc<dyn LspAdapterDelegate>,
 493        _: Option<Toolchain>,
 494        _: Option<Uri>,
 495        _cx: &mut AsyncApp,
 496    ) -> Result<Value> {
 497        Ok(serde_json::json!({}))
 498    }
 499
 500    async fn additional_initialization_options(
 501        self: Arc<Self>,
 502        _target_language_server_id: LanguageServerName,
 503        _: &Arc<dyn LspAdapterDelegate>,
 504    ) -> Result<Option<Value>> {
 505        Ok(None)
 506    }
 507
 508    async fn additional_workspace_configuration(
 509        self: Arc<Self>,
 510        _target_language_server_id: LanguageServerName,
 511        _: &Arc<dyn LspAdapterDelegate>,
 512        _cx: &mut AsyncApp,
 513    ) -> Result<Option<Value>> {
 514        Ok(None)
 515    }
 516
 517    /// Returns a list of code actions supported by a given LspAdapter
 518    fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
 519        None
 520    }
 521
 522    fn disk_based_diagnostic_sources(&self) -> Vec<String> {
 523        Default::default()
 524    }
 525
 526    fn disk_based_diagnostics_progress_token(&self) -> Option<String> {
 527        None
 528    }
 529
 530    fn language_ids(&self) -> HashMap<LanguageName, String> {
 531        HashMap::default()
 532    }
 533
 534    /// Support custom initialize params.
 535    fn prepare_initialize_params(
 536        &self,
 537        original: InitializeParams,
 538        _: &App,
 539    ) -> Result<InitializeParams> {
 540        Ok(original)
 541    }
 542
 543    /// Method only implemented by the default JSON language server adapter.
 544    /// Used to provide dynamic reloading of the JSON schemas used to
 545    /// provide autocompletion and diagnostics in Zed setting and keybind
 546    /// files
 547    fn is_primary_zed_json_schema_adapter(&self) -> bool {
 548        false
 549    }
 550
 551    /// True for the extension adapter and false otherwise.
 552    fn is_extension(&self) -> bool {
 553        false
 554    }
 555
 556    /// Called when a user responds to a ShowMessageRequest from this language server.
 557    /// This allows adapters to intercept preference selections (like "Always" or "Never")
 558    /// for settings that should be persisted to Zed's settings file.
 559    fn process_prompt_response(&self, _context: &PromptResponseContext, _cx: &mut AsyncApp) {}
 560}
 561
 562pub trait LspInstaller {
 563    type BinaryVersion;
 564    fn check_if_user_installed(
 565        &self,
 566        _: &dyn LspAdapterDelegate,
 567        _: Option<Toolchain>,
 568        _: &AsyncApp,
 569    ) -> impl Future<Output = Option<LanguageServerBinary>> {
 570        async { None }
 571    }
 572
 573    fn fetch_latest_server_version(
 574        &self,
 575        delegate: &dyn LspAdapterDelegate,
 576        pre_release: bool,
 577        cx: &mut AsyncApp,
 578    ) -> impl Future<Output = Result<Self::BinaryVersion>>;
 579
 580    fn check_if_version_installed(
 581        &self,
 582        _version: &Self::BinaryVersion,
 583        _container_dir: &PathBuf,
 584        _delegate: &dyn LspAdapterDelegate,
 585    ) -> impl Send + Future<Output = Option<LanguageServerBinary>> {
 586        async { None }
 587    }
 588
 589    fn fetch_server_binary(
 590        &self,
 591        latest_version: Self::BinaryVersion,
 592        container_dir: PathBuf,
 593        delegate: &dyn LspAdapterDelegate,
 594    ) -> impl Send + Future<Output = Result<LanguageServerBinary>>;
 595
 596    fn cached_server_binary(
 597        &self,
 598        container_dir: PathBuf,
 599        delegate: &dyn LspAdapterDelegate,
 600    ) -> impl Future<Output = Option<LanguageServerBinary>>;
 601}
 602
 603#[async_trait(?Send)]
 604pub trait DynLspInstaller {
 605    async fn try_fetch_server_binary(
 606        &self,
 607        delegate: &Arc<dyn LspAdapterDelegate>,
 608        container_dir: PathBuf,
 609        pre_release: bool,
 610        cx: &mut AsyncApp,
 611    ) -> Result<LanguageServerBinary>;
 612
 613    fn get_language_server_command(
 614        self: Arc<Self>,
 615        delegate: Arc<dyn LspAdapterDelegate>,
 616        toolchains: Option<Toolchain>,
 617        binary_options: LanguageServerBinaryOptions,
 618        cached_binary: OwnedMutexGuard<Option<(bool, LanguageServerBinary)>>,
 619        cx: AsyncApp,
 620    ) -> LanguageServerBinaryLocations;
 621}
 622
 623#[async_trait(?Send)]
 624impl<LI, BinaryVersion> DynLspInstaller for LI
 625where
 626    BinaryVersion: Send + Sync,
 627    LI: LspInstaller<BinaryVersion = BinaryVersion> + LspAdapter,
 628{
 629    async fn try_fetch_server_binary(
 630        &self,
 631        delegate: &Arc<dyn LspAdapterDelegate>,
 632        container_dir: PathBuf,
 633        pre_release: bool,
 634        cx: &mut AsyncApp,
 635    ) -> Result<LanguageServerBinary> {
 636        let name = self.name();
 637
 638        log::debug!("fetching latest version of language server {:?}", name.0);
 639        delegate.update_status(name.clone(), BinaryStatus::CheckingForUpdate);
 640
 641        let latest_version = self
 642            .fetch_latest_server_version(delegate.as_ref(), pre_release, cx)
 643            .await?;
 644
 645        if let Some(binary) = cx
 646            .background_executor()
 647            .await_on_background(self.check_if_version_installed(
 648                &latest_version,
 649                &container_dir,
 650                delegate.as_ref(),
 651            ))
 652            .await
 653        {
 654            log::debug!("language server {:?} is already installed", name.0);
 655            delegate.update_status(name.clone(), BinaryStatus::None);
 656            Ok(binary)
 657        } else {
 658            log::debug!("downloading language server {:?}", name.0);
 659            delegate.update_status(name.clone(), BinaryStatus::Downloading);
 660            let binary = cx
 661                .background_executor()
 662                .await_on_background(self.fetch_server_binary(
 663                    latest_version,
 664                    container_dir,
 665                    delegate.as_ref(),
 666                ))
 667                .await;
 668
 669            delegate.update_status(name.clone(), BinaryStatus::None);
 670            binary
 671        }
 672    }
 673    fn get_language_server_command(
 674        self: Arc<Self>,
 675        delegate: Arc<dyn LspAdapterDelegate>,
 676        toolchain: Option<Toolchain>,
 677        binary_options: LanguageServerBinaryOptions,
 678        mut cached_binary: OwnedMutexGuard<Option<(bool, LanguageServerBinary)>>,
 679        mut cx: AsyncApp,
 680    ) -> LanguageServerBinaryLocations {
 681        async move {
 682            let cached_binary_deref = cached_binary.deref_mut();
 683            // First we check whether the adapter can give us a user-installed binary.
 684            // If so, we do *not* want to cache that, because each worktree might give us a different
 685            // binary:
 686            //
 687            //      worktree 1: user-installed at `.bin/gopls`
 688            //      worktree 2: user-installed at `~/bin/gopls`
 689            //      worktree 3: no gopls found in PATH -> fallback to Zed installation
 690            //
 691            // We only want to cache when we fall back to the global one,
 692            // because we don't want to download and overwrite our global one
 693            // for each worktree we might have open.
 694            if binary_options.allow_path_lookup
 695                && let Some(binary) = self
 696                    .check_if_user_installed(delegate.as_ref(), toolchain, &mut cx)
 697                    .await
 698            {
 699                log::info!(
 700                    "found user-installed language server for {}. path: {:?}, arguments: {:?}",
 701                    self.name().0,
 702                    binary.path,
 703                    binary.arguments
 704                );
 705                return (Ok(binary), None);
 706            }
 707
 708            if let Some((pre_release, cached_binary)) = cached_binary_deref
 709                && *pre_release == binary_options.pre_release
 710            {
 711                return (Ok(cached_binary.clone()), None);
 712            }
 713
 714            if !binary_options.allow_binary_download {
 715                return (
 716                    Err(anyhow::anyhow!("downloading language servers disabled")),
 717                    None,
 718                );
 719            }
 720
 721            let Some(container_dir) = delegate.language_server_download_dir(&self.name()).await
 722            else {
 723                return (
 724                    Err(anyhow::anyhow!("no language server download dir defined")),
 725                    None,
 726                );
 727            };
 728
 729            let last_downloaded_binary = self
 730                .cached_server_binary(container_dir.to_path_buf(), delegate.as_ref())
 731                .await
 732                .context(
 733                    "did not find existing language server binary, falling back to downloading",
 734                );
 735            let download_binary = async move {
 736                let mut binary = self
 737                    .try_fetch_server_binary(
 738                        &delegate,
 739                        container_dir.to_path_buf(),
 740                        binary_options.pre_release,
 741                        &mut cx,
 742                    )
 743                    .await;
 744
 745                if let Err(error) = binary.as_ref() {
 746                    if let Some(prev_downloaded_binary) = self
 747                        .cached_server_binary(container_dir.to_path_buf(), delegate.as_ref())
 748                        .await
 749                    {
 750                        log::info!(
 751                            "failed to fetch newest version of language server {:?}. \
 752                            error: {:?}, falling back to using {:?}",
 753                            self.name(),
 754                            error,
 755                            prev_downloaded_binary.path
 756                        );
 757                        binary = Ok(prev_downloaded_binary);
 758                    } else {
 759                        delegate.update_status(
 760                            self.name(),
 761                            BinaryStatus::Failed {
 762                                error: format!("{error:?}"),
 763                            },
 764                        );
 765                    }
 766                }
 767
 768                if let Ok(binary) = &binary {
 769                    *cached_binary = Some((binary_options.pre_release, binary.clone()));
 770                }
 771
 772                binary
 773            }
 774            .boxed_local();
 775            (last_downloaded_binary, Some(download_binary))
 776        }
 777        .boxed_local()
 778    }
 779}
 780
 781#[derive(Clone, Debug, Default, PartialEq, Eq)]
 782pub struct CodeLabel {
 783    /// The text to display.
 784    pub text: String,
 785    /// Syntax highlighting runs.
 786    pub runs: Vec<(Range<usize>, HighlightId)>,
 787    /// The portion of the text that should be used in fuzzy filtering.
 788    pub filter_range: Range<usize>,
 789}
 790
 791#[derive(Clone, Debug, Default, PartialEq, Eq)]
 792pub struct CodeLabelBuilder {
 793    /// The text to display.
 794    text: String,
 795    /// Syntax highlighting runs.
 796    runs: Vec<(Range<usize>, HighlightId)>,
 797    /// The portion of the text that should be used in fuzzy filtering.
 798    filter_range: Range<usize>,
 799}
 800
 801#[derive(Clone, Deserialize, JsonSchema, Debug)]
 802pub struct LanguageConfig {
 803    /// Human-readable name of the language.
 804    pub name: LanguageName,
 805    /// The name of this language for a Markdown code fence block
 806    pub code_fence_block_name: Option<Arc<str>>,
 807    // The name of the grammar in a WASM bundle (experimental).
 808    pub grammar: Option<Arc<str>>,
 809    /// The criteria for matching this language to a given file.
 810    #[serde(flatten)]
 811    pub matcher: LanguageMatcher,
 812    /// List of bracket types in a language.
 813    #[serde(default)]
 814    pub brackets: BracketPairConfig,
 815    /// If set to true, auto indentation uses last non empty line to determine
 816    /// the indentation level for a new line.
 817    #[serde(default = "auto_indent_using_last_non_empty_line_default")]
 818    pub auto_indent_using_last_non_empty_line: bool,
 819    // Whether indentation of pasted content should be adjusted based on the context.
 820    #[serde(default)]
 821    pub auto_indent_on_paste: Option<bool>,
 822    /// A regex that is used to determine whether the indentation level should be
 823    /// increased in the following line.
 824    #[serde(default, deserialize_with = "deserialize_regex")]
 825    #[schemars(schema_with = "regex_json_schema")]
 826    pub increase_indent_pattern: Option<Regex>,
 827    /// A regex that is used to determine whether the indentation level should be
 828    /// decreased in the following line.
 829    #[serde(default, deserialize_with = "deserialize_regex")]
 830    #[schemars(schema_with = "regex_json_schema")]
 831    pub decrease_indent_pattern: Option<Regex>,
 832    /// A list of rules for decreasing indentation. Each rule pairs a regex with a set of valid
 833    /// "block-starting" tokens. When a line matches a pattern, its indentation is aligned with
 834    /// the most recent line that began with a corresponding token. This enables context-aware
 835    /// outdenting, like aligning an `else` with its `if`.
 836    #[serde(default)]
 837    pub decrease_indent_patterns: Vec<DecreaseIndentConfig>,
 838    /// A list of characters that trigger the automatic insertion of a closing
 839    /// bracket when they immediately precede the point where an opening
 840    /// bracket is inserted.
 841    #[serde(default)]
 842    pub autoclose_before: String,
 843    /// A placeholder used internally by Semantic Index.
 844    #[serde(default)]
 845    pub collapsed_placeholder: String,
 846    /// A line comment string that is inserted in e.g. `toggle comments` action.
 847    /// A language can have multiple flavours of line comments. All of the provided line comments are
 848    /// used for comment continuations on the next line, but only the first one is used for Editor::ToggleComments.
 849    #[serde(default)]
 850    pub line_comments: Vec<Arc<str>>,
 851    /// Delimiters and configuration for recognizing and formatting block comments.
 852    #[serde(default)]
 853    pub block_comment: Option<BlockCommentConfig>,
 854    /// Delimiters and configuration for recognizing and formatting documentation comments.
 855    #[serde(default, alias = "documentation")]
 856    pub documentation_comment: Option<BlockCommentConfig>,
 857    /// List markers that are inserted unchanged on newline (e.g., `- `, `* `, `+ `).
 858    #[serde(default)]
 859    pub unordered_list: Vec<Arc<str>>,
 860    /// Configuration for ordered lists with auto-incrementing numbers on newline (e.g., `1. ` becomes `2. `).
 861    #[serde(default)]
 862    pub ordered_list: Vec<OrderedListConfig>,
 863    /// Configuration for task lists where multiple markers map to a single continuation prefix (e.g., `- [x] ` continues as `- [ ] `).
 864    #[serde(default)]
 865    pub task_list: Option<TaskListConfig>,
 866    /// A list of additional regex patterns that should be treated as prefixes
 867    /// for creating boundaries during rewrapping, ensuring content from one
 868    /// prefixed section doesn't merge with another (e.g., markdown list items).
 869    /// By default, Zed treats as paragraph and comment prefixes as boundaries.
 870    #[serde(default, deserialize_with = "deserialize_regex_vec")]
 871    #[schemars(schema_with = "regex_vec_json_schema")]
 872    pub rewrap_prefixes: Vec<Regex>,
 873    /// A list of language servers that are allowed to run on subranges of a given language.
 874    #[serde(default)]
 875    pub scope_opt_in_language_servers: Vec<LanguageServerName>,
 876    #[serde(default)]
 877    pub overrides: HashMap<String, LanguageConfigOverride>,
 878    /// A list of characters that Zed should treat as word characters for the
 879    /// purpose of features that operate on word boundaries, like 'move to next word end'
 880    /// or a whole-word search in buffer search.
 881    #[serde(default)]
 882    pub word_characters: HashSet<char>,
 883    /// Whether to indent lines using tab characters, as opposed to multiple
 884    /// spaces.
 885    #[serde(default)]
 886    pub hard_tabs: Option<bool>,
 887    /// How many columns a tab should occupy.
 888    #[serde(default)]
 889    #[schemars(range(min = 1, max = 128))]
 890    pub tab_size: Option<NonZeroU32>,
 891    /// How to soft-wrap long lines of text.
 892    #[serde(default)]
 893    pub soft_wrap: Option<SoftWrap>,
 894    /// When set, selections can be wrapped using prefix/suffix pairs on both sides.
 895    #[serde(default)]
 896    pub wrap_characters: Option<WrapCharactersConfig>,
 897    /// The name of a Prettier parser that will be used for this language when no file path is available.
 898    /// If there's a parser name in the language settings, that will be used instead.
 899    #[serde(default)]
 900    pub prettier_parser_name: Option<String>,
 901    /// If true, this language is only for syntax highlighting via an injection into other
 902    /// languages, but should not appear to the user as a distinct language.
 903    #[serde(default)]
 904    pub hidden: bool,
 905    /// If configured, this language contains JSX style tags, and should support auto-closing of those tags.
 906    #[serde(default)]
 907    pub jsx_tag_auto_close: Option<JsxTagAutoCloseConfig>,
 908    /// A list of characters that Zed should treat as word characters for completion queries.
 909    #[serde(default)]
 910    pub completion_query_characters: HashSet<char>,
 911    /// A list of characters that Zed should treat as word characters for linked edit operations.
 912    #[serde(default)]
 913    pub linked_edit_characters: HashSet<char>,
 914    /// A list of preferred debuggers for this language.
 915    #[serde(default)]
 916    pub debuggers: IndexSet<SharedString>,
 917    /// A list of import namespace segments that aren't expected to appear in file paths. For
 918    /// example, "super" and "crate" in Rust.
 919    #[serde(default)]
 920    pub ignored_import_segments: HashSet<Arc<str>>,
 921    /// Regular expression that matches substrings to omit from import paths, to make the paths more
 922    /// similar to how they are specified when imported. For example, "/mod\.rs$" or "/__init__\.py$".
 923    #[serde(default, deserialize_with = "deserialize_regex")]
 924    #[schemars(schema_with = "regex_json_schema")]
 925    pub import_path_strip_regex: Option<Regex>,
 926}
 927
 928#[derive(Clone, Debug, Deserialize, Default, JsonSchema)]
 929pub struct DecreaseIndentConfig {
 930    #[serde(default, deserialize_with = "deserialize_regex")]
 931    #[schemars(schema_with = "regex_json_schema")]
 932    pub pattern: Option<Regex>,
 933    #[serde(default)]
 934    pub valid_after: Vec<String>,
 935}
 936
 937/// Configuration for continuing ordered lists with auto-incrementing numbers.
 938#[derive(Clone, Debug, Deserialize, JsonSchema)]
 939pub struct OrderedListConfig {
 940    /// A regex pattern with a capture group for the number portion (e.g., `(\\d+)\\. `).
 941    pub pattern: String,
 942    /// A format string where `{1}` is replaced with the incremented number (e.g., `{1}. `).
 943    pub format: String,
 944}
 945
 946/// Configuration for continuing task lists on newline.
 947#[derive(Clone, Debug, Deserialize, JsonSchema)]
 948pub struct TaskListConfig {
 949    /// The list markers to match (e.g., `- [ ] `, `- [x] `).
 950    pub prefixes: Vec<Arc<str>>,
 951    /// The marker to insert when continuing the list on a new line (e.g., `- [ ] `).
 952    pub continuation: Arc<str>,
 953}
 954
 955#[derive(Clone, Debug, Serialize, Deserialize, Default, JsonSchema)]
 956pub struct LanguageMatcher {
 957    /// Given a list of `LanguageConfig`'s, the language of a file can be determined based on the path extension matching any of the `path_suffixes`.
 958    #[serde(default)]
 959    pub path_suffixes: Vec<String>,
 960    /// A regex pattern that determines whether the language should be assigned to a file or not.
 961    #[serde(
 962        default,
 963        serialize_with = "serialize_regex",
 964        deserialize_with = "deserialize_regex"
 965    )]
 966    #[schemars(schema_with = "regex_json_schema")]
 967    pub first_line_pattern: Option<Regex>,
 968}
 969
 970/// The configuration for JSX tag auto-closing.
 971#[derive(Clone, Deserialize, JsonSchema, Debug)]
 972pub struct JsxTagAutoCloseConfig {
 973    /// The name of the node for a opening tag
 974    pub open_tag_node_name: String,
 975    /// The name of the node for an closing tag
 976    pub close_tag_node_name: String,
 977    /// The name of the node for a complete element with children for open and close tags
 978    pub jsx_element_node_name: String,
 979    /// The name of the node found within both opening and closing
 980    /// tags that describes the tag name
 981    pub tag_name_node_name: String,
 982    /// Alternate Node names for tag names.
 983    /// Specifically needed as TSX represents the name in `<Foo.Bar>`
 984    /// as `member_expression` rather than `identifier` as usual
 985    #[serde(default)]
 986    pub tag_name_node_name_alternates: Vec<String>,
 987    /// Some grammars are smart enough to detect a closing tag
 988    /// that is not valid i.e. doesn't match it's corresponding
 989    /// opening tag or does not have a corresponding opening tag
 990    /// This should be set to the name of the node for invalid
 991    /// closing tags if the grammar contains such a node, otherwise
 992    /// detecting already closed tags will not work properly
 993    #[serde(default)]
 994    pub erroneous_close_tag_node_name: Option<String>,
 995    /// See above for erroneous_close_tag_node_name for details
 996    /// This should be set if the node used for the tag name
 997    /// within erroneous closing tags is different from the
 998    /// normal tag name node name
 999    #[serde(default)]
1000    pub erroneous_close_tag_name_node_name: Option<String>,
1001}
1002
1003/// The configuration for block comments for this language.
1004#[derive(Clone, Debug, JsonSchema, PartialEq)]
1005pub struct BlockCommentConfig {
1006    /// A start tag of block comment.
1007    pub start: Arc<str>,
1008    /// A end tag of block comment.
1009    pub end: Arc<str>,
1010    /// A character to add as a prefix when a new line is added to a block comment.
1011    pub prefix: Arc<str>,
1012    /// A indent to add for prefix and end line upon new line.
1013    #[schemars(range(min = 1, max = 128))]
1014    pub tab_size: u32,
1015}
1016
1017impl<'de> Deserialize<'de> for BlockCommentConfig {
1018    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1019    where
1020        D: Deserializer<'de>,
1021    {
1022        #[derive(Deserialize)]
1023        #[serde(untagged)]
1024        enum BlockCommentConfigHelper {
1025            New {
1026                start: Arc<str>,
1027                end: Arc<str>,
1028                prefix: Arc<str>,
1029                tab_size: u32,
1030            },
1031            Old([Arc<str>; 2]),
1032        }
1033
1034        match BlockCommentConfigHelper::deserialize(deserializer)? {
1035            BlockCommentConfigHelper::New {
1036                start,
1037                end,
1038                prefix,
1039                tab_size,
1040            } => Ok(BlockCommentConfig {
1041                start,
1042                end,
1043                prefix,
1044                tab_size,
1045            }),
1046            BlockCommentConfigHelper::Old([start, end]) => Ok(BlockCommentConfig {
1047                start,
1048                end,
1049                prefix: "".into(),
1050                tab_size: 0,
1051            }),
1052        }
1053    }
1054}
1055
1056/// Represents a language for the given range. Some languages (e.g. HTML)
1057/// interleave several languages together, thus a single buffer might actually contain
1058/// several nested scopes.
1059#[derive(Clone, Debug)]
1060pub struct LanguageScope {
1061    language: Arc<Language>,
1062    override_id: Option<u32>,
1063}
1064
1065#[derive(Clone, Deserialize, Default, Debug, JsonSchema)]
1066pub struct LanguageConfigOverride {
1067    #[serde(default)]
1068    pub line_comments: Override<Vec<Arc<str>>>,
1069    #[serde(default)]
1070    pub block_comment: Override<BlockCommentConfig>,
1071    #[serde(skip)]
1072    pub disabled_bracket_ixs: Vec<u16>,
1073    #[serde(default)]
1074    pub word_characters: Override<HashSet<char>>,
1075    #[serde(default)]
1076    pub completion_query_characters: Override<HashSet<char>>,
1077    #[serde(default)]
1078    pub linked_edit_characters: Override<HashSet<char>>,
1079    #[serde(default)]
1080    pub opt_into_language_servers: Vec<LanguageServerName>,
1081    #[serde(default)]
1082    pub prefer_label_for_snippet: Option<bool>,
1083}
1084
1085#[derive(Clone, Deserialize, Debug, Serialize, JsonSchema)]
1086#[serde(untagged)]
1087pub enum Override<T> {
1088    Remove { remove: bool },
1089    Set(T),
1090}
1091
1092impl<T> Default for Override<T> {
1093    fn default() -> Self {
1094        Override::Remove { remove: false }
1095    }
1096}
1097
1098impl<T> Override<T> {
1099    fn as_option<'a>(this: Option<&'a Self>, original: Option<&'a T>) -> Option<&'a T> {
1100        match this {
1101            Some(Self::Set(value)) => Some(value),
1102            Some(Self::Remove { remove: true }) => None,
1103            Some(Self::Remove { remove: false }) | None => original,
1104        }
1105    }
1106}
1107
1108impl Default for LanguageConfig {
1109    fn default() -> Self {
1110        Self {
1111            name: LanguageName::new_static(""),
1112            code_fence_block_name: None,
1113            grammar: None,
1114            matcher: LanguageMatcher::default(),
1115            brackets: Default::default(),
1116            auto_indent_using_last_non_empty_line: auto_indent_using_last_non_empty_line_default(),
1117            auto_indent_on_paste: None,
1118            increase_indent_pattern: Default::default(),
1119            decrease_indent_pattern: Default::default(),
1120            decrease_indent_patterns: Default::default(),
1121            autoclose_before: Default::default(),
1122            line_comments: Default::default(),
1123            block_comment: Default::default(),
1124            documentation_comment: Default::default(),
1125            unordered_list: Default::default(),
1126            ordered_list: Default::default(),
1127            task_list: Default::default(),
1128            rewrap_prefixes: Default::default(),
1129            scope_opt_in_language_servers: Default::default(),
1130            overrides: Default::default(),
1131            word_characters: Default::default(),
1132            collapsed_placeholder: Default::default(),
1133            hard_tabs: None,
1134            tab_size: None,
1135            soft_wrap: None,
1136            wrap_characters: None,
1137            prettier_parser_name: None,
1138            hidden: false,
1139            jsx_tag_auto_close: None,
1140            completion_query_characters: Default::default(),
1141            linked_edit_characters: Default::default(),
1142            debuggers: Default::default(),
1143            ignored_import_segments: Default::default(),
1144            import_path_strip_regex: None,
1145        }
1146    }
1147}
1148
1149#[derive(Clone, Debug, Deserialize, JsonSchema)]
1150pub struct WrapCharactersConfig {
1151    /// Opening token split into a prefix and suffix. The first caret goes
1152    /// after the prefix (i.e., between prefix and suffix).
1153    pub start_prefix: String,
1154    pub start_suffix: String,
1155    /// Closing token split into a prefix and suffix. The second caret goes
1156    /// after the prefix (i.e., between prefix and suffix).
1157    pub end_prefix: String,
1158    pub end_suffix: String,
1159}
1160
1161fn auto_indent_using_last_non_empty_line_default() -> bool {
1162    true
1163}
1164
1165fn deserialize_regex<'de, D: Deserializer<'de>>(d: D) -> Result<Option<Regex>, D::Error> {
1166    let source = Option::<String>::deserialize(d)?;
1167    if let Some(source) = source {
1168        Ok(Some(regex::Regex::new(&source).map_err(de::Error::custom)?))
1169    } else {
1170        Ok(None)
1171    }
1172}
1173
1174fn regex_json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
1175    json_schema!({
1176        "type": "string"
1177    })
1178}
1179
1180fn serialize_regex<S>(regex: &Option<Regex>, serializer: S) -> Result<S::Ok, S::Error>
1181where
1182    S: Serializer,
1183{
1184    match regex {
1185        Some(regex) => serializer.serialize_str(regex.as_str()),
1186        None => serializer.serialize_none(),
1187    }
1188}
1189
1190fn deserialize_regex_vec<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<Regex>, D::Error> {
1191    let sources = Vec::<String>::deserialize(d)?;
1192    sources
1193        .into_iter()
1194        .map(|source| regex::Regex::new(&source))
1195        .collect::<Result<_, _>>()
1196        .map_err(de::Error::custom)
1197}
1198
1199fn regex_vec_json_schema(_: &mut SchemaGenerator) -> schemars::Schema {
1200    json_schema!({
1201        "type": "array",
1202        "items": { "type": "string" }
1203    })
1204}
1205
1206#[doc(hidden)]
1207#[cfg(any(test, feature = "test-support"))]
1208pub struct FakeLspAdapter {
1209    pub name: &'static str,
1210    pub initialization_options: Option<Value>,
1211    pub prettier_plugins: Vec<&'static str>,
1212    pub disk_based_diagnostics_progress_token: Option<String>,
1213    pub disk_based_diagnostics_sources: Vec<String>,
1214    pub language_server_binary: LanguageServerBinary,
1215
1216    pub capabilities: lsp::ServerCapabilities,
1217    pub initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,
1218    pub label_for_completion: Option<
1219        Box<
1220            dyn 'static
1221                + Send
1222                + Sync
1223                + Fn(&lsp::CompletionItem, &Arc<Language>) -> Option<CodeLabel>,
1224        >,
1225    >,
1226}
1227
1228/// Configuration of handling bracket pairs for a given language.
1229///
1230/// This struct includes settings for defining which pairs of characters are considered brackets and
1231/// also specifies any language-specific scopes where these pairs should be ignored for bracket matching purposes.
1232#[derive(Clone, Debug, Default, JsonSchema)]
1233#[schemars(with = "Vec::<BracketPairContent>")]
1234pub struct BracketPairConfig {
1235    /// A list of character pairs that should be treated as brackets in the context of a given language.
1236    pub pairs: Vec<BracketPair>,
1237    /// A list of tree-sitter scopes for which a given bracket should not be active.
1238    /// N-th entry in `[Self::disabled_scopes_by_bracket_ix]` contains a list of disabled scopes for an n-th entry in `[Self::pairs]`
1239    pub disabled_scopes_by_bracket_ix: Vec<Vec<String>>,
1240}
1241
1242impl BracketPairConfig {
1243    pub fn is_closing_brace(&self, c: char) -> bool {
1244        self.pairs.iter().any(|pair| pair.end.starts_with(c))
1245    }
1246}
1247
1248#[derive(Deserialize, JsonSchema)]
1249pub struct BracketPairContent {
1250    #[serde(flatten)]
1251    pub bracket_pair: BracketPair,
1252    #[serde(default)]
1253    pub not_in: Vec<String>,
1254}
1255
1256impl<'de> Deserialize<'de> for BracketPairConfig {
1257    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
1258    where
1259        D: Deserializer<'de>,
1260    {
1261        let result = Vec::<BracketPairContent>::deserialize(deserializer)?;
1262        let (brackets, disabled_scopes_by_bracket_ix) = result
1263            .into_iter()
1264            .map(|entry| (entry.bracket_pair, entry.not_in))
1265            .unzip();
1266
1267        Ok(BracketPairConfig {
1268            pairs: brackets,
1269            disabled_scopes_by_bracket_ix,
1270        })
1271    }
1272}
1273
1274/// Describes a single bracket pair and how an editor should react to e.g. inserting
1275/// an opening bracket or to a newline character insertion in between `start` and `end` characters.
1276#[derive(Clone, Debug, Default, Deserialize, PartialEq, JsonSchema)]
1277pub struct BracketPair {
1278    /// Starting substring for a bracket.
1279    pub start: String,
1280    /// Ending substring for a bracket.
1281    pub end: String,
1282    /// True if `end` should be automatically inserted right after `start` characters.
1283    pub close: bool,
1284    /// True if selected text should be surrounded by `start` and `end` characters.
1285    #[serde(default = "default_true")]
1286    pub surround: bool,
1287    /// True if an extra newline should be inserted while the cursor is in the middle
1288    /// of that bracket pair.
1289    pub newline: bool,
1290}
1291
1292#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1293pub struct LanguageId(usize);
1294
1295impl LanguageId {
1296    pub(crate) fn new() -> Self {
1297        Self(NEXT_LANGUAGE_ID.fetch_add(1, SeqCst))
1298    }
1299}
1300
1301pub struct Language {
1302    pub(crate) id: LanguageId,
1303    pub(crate) config: LanguageConfig,
1304    pub(crate) grammar: Option<Arc<Grammar>>,
1305    pub(crate) context_provider: Option<Arc<dyn ContextProvider>>,
1306    pub(crate) toolchain: Option<Arc<dyn ToolchainLister>>,
1307    pub(crate) manifest_name: Option<ManifestName>,
1308}
1309
1310#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1311pub struct GrammarId(pub usize);
1312
1313impl GrammarId {
1314    pub(crate) fn new() -> Self {
1315        Self(NEXT_GRAMMAR_ID.fetch_add(1, SeqCst))
1316    }
1317}
1318
1319pub struct Grammar {
1320    id: GrammarId,
1321    pub ts_language: tree_sitter::Language,
1322    pub(crate) error_query: Option<Query>,
1323    pub highlights_config: Option<HighlightsConfig>,
1324    pub(crate) brackets_config: Option<BracketsConfig>,
1325    pub(crate) redactions_config: Option<RedactionConfig>,
1326    pub(crate) runnable_config: Option<RunnableConfig>,
1327    pub(crate) indents_config: Option<IndentConfig>,
1328    pub outline_config: Option<OutlineConfig>,
1329    pub text_object_config: Option<TextObjectConfig>,
1330    pub(crate) injection_config: Option<InjectionConfig>,
1331    pub(crate) override_config: Option<OverrideConfig>,
1332    pub(crate) debug_variables_config: Option<DebugVariablesConfig>,
1333    pub(crate) imports_config: Option<ImportsConfig>,
1334    pub(crate) highlight_map: Mutex<HighlightMap>,
1335}
1336
1337pub struct HighlightsConfig {
1338    pub query: Query,
1339    pub identifier_capture_indices: Vec<u32>,
1340}
1341
1342struct IndentConfig {
1343    query: Query,
1344    indent_capture_ix: u32,
1345    start_capture_ix: Option<u32>,
1346    end_capture_ix: Option<u32>,
1347    outdent_capture_ix: Option<u32>,
1348    suffixed_start_captures: HashMap<u32, SharedString>,
1349}
1350
1351pub struct OutlineConfig {
1352    pub query: Query,
1353    pub item_capture_ix: u32,
1354    pub name_capture_ix: u32,
1355    pub context_capture_ix: Option<u32>,
1356    pub extra_context_capture_ix: Option<u32>,
1357    pub open_capture_ix: Option<u32>,
1358    pub close_capture_ix: Option<u32>,
1359    pub annotation_capture_ix: Option<u32>,
1360}
1361
1362#[derive(Debug, Clone, Copy, PartialEq)]
1363pub enum DebuggerTextObject {
1364    Variable,
1365    Scope,
1366}
1367
1368impl DebuggerTextObject {
1369    pub fn from_capture_name(name: &str) -> Option<DebuggerTextObject> {
1370        match name {
1371            "debug-variable" => Some(DebuggerTextObject::Variable),
1372            "debug-scope" => Some(DebuggerTextObject::Scope),
1373            _ => None,
1374        }
1375    }
1376}
1377
1378#[derive(Debug, Clone, Copy, PartialEq)]
1379pub enum TextObject {
1380    InsideFunction,
1381    AroundFunction,
1382    InsideClass,
1383    AroundClass,
1384    InsideComment,
1385    AroundComment,
1386}
1387
1388impl TextObject {
1389    pub fn from_capture_name(name: &str) -> Option<TextObject> {
1390        match name {
1391            "function.inside" => Some(TextObject::InsideFunction),
1392            "function.around" => Some(TextObject::AroundFunction),
1393            "class.inside" => Some(TextObject::InsideClass),
1394            "class.around" => Some(TextObject::AroundClass),
1395            "comment.inside" => Some(TextObject::InsideComment),
1396            "comment.around" => Some(TextObject::AroundComment),
1397            _ => None,
1398        }
1399    }
1400
1401    pub fn around(&self) -> Option<Self> {
1402        match self {
1403            TextObject::InsideFunction => Some(TextObject::AroundFunction),
1404            TextObject::InsideClass => Some(TextObject::AroundClass),
1405            TextObject::InsideComment => Some(TextObject::AroundComment),
1406            _ => None,
1407        }
1408    }
1409}
1410
1411pub struct TextObjectConfig {
1412    pub query: Query,
1413    pub text_objects_by_capture_ix: Vec<(u32, TextObject)>,
1414}
1415
1416struct InjectionConfig {
1417    query: Query,
1418    content_capture_ix: u32,
1419    language_capture_ix: Option<u32>,
1420    patterns: Vec<InjectionPatternConfig>,
1421}
1422
1423struct RedactionConfig {
1424    pub query: Query,
1425    pub redaction_capture_ix: u32,
1426}
1427
1428#[derive(Clone, Debug, PartialEq)]
1429enum RunnableCapture {
1430    Named(SharedString),
1431    Run,
1432}
1433
1434struct RunnableConfig {
1435    pub query: Query,
1436    /// A mapping from capture indice to capture kind
1437    pub extra_captures: Vec<RunnableCapture>,
1438}
1439
1440struct OverrideConfig {
1441    query: Query,
1442    values: HashMap<u32, OverrideEntry>,
1443}
1444
1445#[derive(Debug)]
1446struct OverrideEntry {
1447    name: String,
1448    range_is_inclusive: bool,
1449    value: LanguageConfigOverride,
1450}
1451
1452#[derive(Default, Clone)]
1453struct InjectionPatternConfig {
1454    language: Option<Box<str>>,
1455    combined: bool,
1456}
1457
1458#[derive(Debug)]
1459struct BracketsConfig {
1460    query: Query,
1461    open_capture_ix: u32,
1462    close_capture_ix: u32,
1463    patterns: Vec<BracketsPatternConfig>,
1464}
1465
1466#[derive(Clone, Debug, Default)]
1467struct BracketsPatternConfig {
1468    newline_only: bool,
1469    rainbow_exclude: bool,
1470}
1471
1472pub struct DebugVariablesConfig {
1473    pub query: Query,
1474    pub objects_by_capture_ix: Vec<(u32, DebuggerTextObject)>,
1475}
1476
1477pub struct ImportsConfig {
1478    pub query: Query,
1479    pub import_ix: u32,
1480    pub name_ix: Option<u32>,
1481    pub namespace_ix: Option<u32>,
1482    pub source_ix: Option<u32>,
1483    pub list_ix: Option<u32>,
1484    pub wildcard_ix: Option<u32>,
1485    pub alias_ix: Option<u32>,
1486}
1487
1488impl Language {
1489    pub fn new(config: LanguageConfig, ts_language: Option<tree_sitter::Language>) -> Self {
1490        Self::new_with_id(LanguageId::new(), config, ts_language)
1491    }
1492
1493    pub fn id(&self) -> LanguageId {
1494        self.id
1495    }
1496
1497    fn new_with_id(
1498        id: LanguageId,
1499        config: LanguageConfig,
1500        ts_language: Option<tree_sitter::Language>,
1501    ) -> Self {
1502        Self {
1503            id,
1504            config,
1505            grammar: ts_language.map(|ts_language| {
1506                Arc::new(Grammar {
1507                    id: GrammarId::new(),
1508                    highlights_config: None,
1509                    brackets_config: None,
1510                    outline_config: None,
1511                    text_object_config: None,
1512                    indents_config: None,
1513                    injection_config: None,
1514                    override_config: None,
1515                    redactions_config: None,
1516                    runnable_config: None,
1517                    error_query: Query::new(&ts_language, "(ERROR) @error").ok(),
1518                    debug_variables_config: None,
1519                    imports_config: None,
1520                    ts_language,
1521                    highlight_map: Default::default(),
1522                })
1523            }),
1524            context_provider: None,
1525            toolchain: None,
1526            manifest_name: None,
1527        }
1528    }
1529
1530    pub fn with_context_provider(mut self, provider: Option<Arc<dyn ContextProvider>>) -> Self {
1531        self.context_provider = provider;
1532        self
1533    }
1534
1535    pub fn with_toolchain_lister(mut self, provider: Option<Arc<dyn ToolchainLister>>) -> Self {
1536        self.toolchain = provider;
1537        self
1538    }
1539
1540    pub fn with_manifest(mut self, name: Option<ManifestName>) -> Self {
1541        self.manifest_name = name;
1542        self
1543    }
1544
1545    pub fn with_queries(mut self, queries: LanguageQueries) -> Result<Self> {
1546        if let Some(query) = queries.highlights {
1547            self = self
1548                .with_highlights_query(query.as_ref())
1549                .context("Error loading highlights query")?;
1550        }
1551        if let Some(query) = queries.brackets {
1552            self = self
1553                .with_brackets_query(query.as_ref())
1554                .context("Error loading brackets query")?;
1555        }
1556        if let Some(query) = queries.indents {
1557            self = self
1558                .with_indents_query(query.as_ref())
1559                .context("Error loading indents query")?;
1560        }
1561        if let Some(query) = queries.outline {
1562            self = self
1563                .with_outline_query(query.as_ref())
1564                .context("Error loading outline query")?;
1565        }
1566        if let Some(query) = queries.injections {
1567            self = self
1568                .with_injection_query(query.as_ref())
1569                .context("Error loading injection query")?;
1570        }
1571        if let Some(query) = queries.overrides {
1572            self = self
1573                .with_override_query(query.as_ref())
1574                .context("Error loading override query")?;
1575        }
1576        if let Some(query) = queries.redactions {
1577            self = self
1578                .with_redaction_query(query.as_ref())
1579                .context("Error loading redaction query")?;
1580        }
1581        if let Some(query) = queries.runnables {
1582            self = self
1583                .with_runnable_query(query.as_ref())
1584                .context("Error loading runnables query")?;
1585        }
1586        if let Some(query) = queries.text_objects {
1587            self = self
1588                .with_text_object_query(query.as_ref())
1589                .context("Error loading textobject query")?;
1590        }
1591        if let Some(query) = queries.debugger {
1592            self = self
1593                .with_debug_variables_query(query.as_ref())
1594                .context("Error loading debug variables query")?;
1595        }
1596        if let Some(query) = queries.imports {
1597            self = self
1598                .with_imports_query(query.as_ref())
1599                .context("Error loading imports query")?;
1600        }
1601        Ok(self)
1602    }
1603
1604    pub fn with_highlights_query(mut self, source: &str) -> Result<Self> {
1605        let grammar = self.grammar_mut()?;
1606        let query = Query::new(&grammar.ts_language, source)?;
1607
1608        let mut identifier_capture_indices = Vec::new();
1609        for name in [
1610            "variable",
1611            "constant",
1612            "constructor",
1613            "function",
1614            "function.method",
1615            "function.method.call",
1616            "function.special",
1617            "property",
1618            "type",
1619            "type.interface",
1620        ] {
1621            identifier_capture_indices.extend(query.capture_index_for_name(name));
1622        }
1623
1624        grammar.highlights_config = Some(HighlightsConfig {
1625            query,
1626            identifier_capture_indices,
1627        });
1628
1629        Ok(self)
1630    }
1631
1632    pub fn with_runnable_query(mut self, source: &str) -> Result<Self> {
1633        let grammar = self.grammar_mut()?;
1634
1635        let query = Query::new(&grammar.ts_language, source)?;
1636        let extra_captures: Vec<_> = query
1637            .capture_names()
1638            .iter()
1639            .map(|&name| match name {
1640                "run" => RunnableCapture::Run,
1641                name => RunnableCapture::Named(name.to_string().into()),
1642            })
1643            .collect();
1644
1645        grammar.runnable_config = Some(RunnableConfig {
1646            extra_captures,
1647            query,
1648        });
1649
1650        Ok(self)
1651    }
1652
1653    pub fn with_outline_query(mut self, source: &str) -> Result<Self> {
1654        let query = Query::new(&self.expect_grammar()?.ts_language, source)?;
1655        let mut item_capture_ix = 0;
1656        let mut name_capture_ix = 0;
1657        let mut context_capture_ix = None;
1658        let mut extra_context_capture_ix = None;
1659        let mut open_capture_ix = None;
1660        let mut close_capture_ix = None;
1661        let mut annotation_capture_ix = None;
1662        if populate_capture_indices(
1663            &query,
1664            &self.config.name,
1665            "outline",
1666            &[],
1667            &mut [
1668                Capture::Required("item", &mut item_capture_ix),
1669                Capture::Required("name", &mut name_capture_ix),
1670                Capture::Optional("context", &mut context_capture_ix),
1671                Capture::Optional("context.extra", &mut extra_context_capture_ix),
1672                Capture::Optional("open", &mut open_capture_ix),
1673                Capture::Optional("close", &mut close_capture_ix),
1674                Capture::Optional("annotation", &mut annotation_capture_ix),
1675            ],
1676        ) {
1677            self.grammar_mut()?.outline_config = Some(OutlineConfig {
1678                query,
1679                item_capture_ix,
1680                name_capture_ix,
1681                context_capture_ix,
1682                extra_context_capture_ix,
1683                open_capture_ix,
1684                close_capture_ix,
1685                annotation_capture_ix,
1686            });
1687        }
1688        Ok(self)
1689    }
1690
1691    pub fn with_text_object_query(mut self, source: &str) -> Result<Self> {
1692        let query = Query::new(&self.expect_grammar()?.ts_language, source)?;
1693
1694        let mut text_objects_by_capture_ix = Vec::new();
1695        for (ix, name) in query.capture_names().iter().enumerate() {
1696            if let Some(text_object) = TextObject::from_capture_name(name) {
1697                text_objects_by_capture_ix.push((ix as u32, text_object));
1698            } else {
1699                log::warn!(
1700                    "unrecognized capture name '{}' in {} textobjects TreeSitter query",
1701                    name,
1702                    self.config.name,
1703                );
1704            }
1705        }
1706
1707        self.grammar_mut()?.text_object_config = Some(TextObjectConfig {
1708            query,
1709            text_objects_by_capture_ix,
1710        });
1711        Ok(self)
1712    }
1713
1714    pub fn with_debug_variables_query(mut self, source: &str) -> Result<Self> {
1715        let query = Query::new(&self.expect_grammar()?.ts_language, source)?;
1716
1717        let mut objects_by_capture_ix = Vec::new();
1718        for (ix, name) in query.capture_names().iter().enumerate() {
1719            if let Some(text_object) = DebuggerTextObject::from_capture_name(name) {
1720                objects_by_capture_ix.push((ix as u32, text_object));
1721            } else {
1722                log::warn!(
1723                    "unrecognized capture name '{}' in {} debugger TreeSitter query",
1724                    name,
1725                    self.config.name,
1726                );
1727            }
1728        }
1729
1730        self.grammar_mut()?.debug_variables_config = Some(DebugVariablesConfig {
1731            query,
1732            objects_by_capture_ix,
1733        });
1734        Ok(self)
1735    }
1736
1737    pub fn with_imports_query(mut self, source: &str) -> Result<Self> {
1738        let query = Query::new(&self.expect_grammar()?.ts_language, source)?;
1739
1740        let mut import_ix = 0;
1741        let mut name_ix = None;
1742        let mut namespace_ix = None;
1743        let mut source_ix = None;
1744        let mut list_ix = None;
1745        let mut wildcard_ix = None;
1746        let mut alias_ix = None;
1747        if populate_capture_indices(
1748            &query,
1749            &self.config.name,
1750            "imports",
1751            &[],
1752            &mut [
1753                Capture::Required("import", &mut import_ix),
1754                Capture::Optional("name", &mut name_ix),
1755                Capture::Optional("namespace", &mut namespace_ix),
1756                Capture::Optional("source", &mut source_ix),
1757                Capture::Optional("list", &mut list_ix),
1758                Capture::Optional("wildcard", &mut wildcard_ix),
1759                Capture::Optional("alias", &mut alias_ix),
1760            ],
1761        ) {
1762            self.grammar_mut()?.imports_config = Some(ImportsConfig {
1763                query,
1764                import_ix,
1765                name_ix,
1766                namespace_ix,
1767                source_ix,
1768                list_ix,
1769                wildcard_ix,
1770                alias_ix,
1771            });
1772        }
1773        return Ok(self);
1774    }
1775
1776    pub fn with_brackets_query(mut self, source: &str) -> Result<Self> {
1777        let query = Query::new(&self.expect_grammar()?.ts_language, source)?;
1778        let mut open_capture_ix = 0;
1779        let mut close_capture_ix = 0;
1780        if populate_capture_indices(
1781            &query,
1782            &self.config.name,
1783            "brackets",
1784            &[],
1785            &mut [
1786                Capture::Required("open", &mut open_capture_ix),
1787                Capture::Required("close", &mut close_capture_ix),
1788            ],
1789        ) {
1790            let patterns = (0..query.pattern_count())
1791                .map(|ix| {
1792                    let mut config = BracketsPatternConfig::default();
1793                    for setting in query.property_settings(ix) {
1794                        let setting_key = setting.key.as_ref();
1795                        if setting_key == "newline.only" {
1796                            config.newline_only = true
1797                        }
1798                        if setting_key == "rainbow.exclude" {
1799                            config.rainbow_exclude = true
1800                        }
1801                    }
1802                    config
1803                })
1804                .collect();
1805            self.grammar_mut()?.brackets_config = Some(BracketsConfig {
1806                query,
1807                open_capture_ix,
1808                close_capture_ix,
1809                patterns,
1810            });
1811        }
1812        Ok(self)
1813    }
1814
1815    pub fn with_indents_query(mut self, source: &str) -> Result<Self> {
1816        let query = Query::new(&self.expect_grammar()?.ts_language, source)?;
1817        let mut indent_capture_ix = 0;
1818        let mut start_capture_ix = None;
1819        let mut end_capture_ix = None;
1820        let mut outdent_capture_ix = None;
1821        if populate_capture_indices(
1822            &query,
1823            &self.config.name,
1824            "indents",
1825            &["start."],
1826            &mut [
1827                Capture::Required("indent", &mut indent_capture_ix),
1828                Capture::Optional("start", &mut start_capture_ix),
1829                Capture::Optional("end", &mut end_capture_ix),
1830                Capture::Optional("outdent", &mut outdent_capture_ix),
1831            ],
1832        ) {
1833            let mut suffixed_start_captures = HashMap::default();
1834            for (ix, name) in query.capture_names().iter().enumerate() {
1835                if let Some(suffix) = name.strip_prefix("start.") {
1836                    suffixed_start_captures.insert(ix as u32, suffix.to_owned().into());
1837                }
1838            }
1839
1840            self.grammar_mut()?.indents_config = Some(IndentConfig {
1841                query,
1842                indent_capture_ix,
1843                start_capture_ix,
1844                end_capture_ix,
1845                outdent_capture_ix,
1846                suffixed_start_captures,
1847            });
1848        }
1849        Ok(self)
1850    }
1851
1852    pub fn with_injection_query(mut self, source: &str) -> Result<Self> {
1853        let query = Query::new(&self.expect_grammar()?.ts_language, source)?;
1854        let mut language_capture_ix = None;
1855        let mut injection_language_capture_ix = None;
1856        let mut content_capture_ix = None;
1857        let mut injection_content_capture_ix = None;
1858        if populate_capture_indices(
1859            &query,
1860            &self.config.name,
1861            "injections",
1862            &[],
1863            &mut [
1864                Capture::Optional("language", &mut language_capture_ix),
1865                Capture::Optional("injection.language", &mut injection_language_capture_ix),
1866                Capture::Optional("content", &mut content_capture_ix),
1867                Capture::Optional("injection.content", &mut injection_content_capture_ix),
1868            ],
1869        ) {
1870            language_capture_ix = match (language_capture_ix, injection_language_capture_ix) {
1871                (None, Some(ix)) => Some(ix),
1872                (Some(_), Some(_)) => {
1873                    anyhow::bail!("both language and injection.language captures are present");
1874                }
1875                _ => language_capture_ix,
1876            };
1877            content_capture_ix = match (content_capture_ix, injection_content_capture_ix) {
1878                (None, Some(ix)) => Some(ix),
1879                (Some(_), Some(_)) => {
1880                    anyhow::bail!("both content and injection.content captures are present")
1881                }
1882                _ => content_capture_ix,
1883            };
1884            let patterns = (0..query.pattern_count())
1885                .map(|ix| {
1886                    let mut config = InjectionPatternConfig::default();
1887                    for setting in query.property_settings(ix) {
1888                        match setting.key.as_ref() {
1889                            "language" | "injection.language" => {
1890                                config.language.clone_from(&setting.value);
1891                            }
1892                            "combined" | "injection.combined" => {
1893                                config.combined = true;
1894                            }
1895                            _ => {}
1896                        }
1897                    }
1898                    config
1899                })
1900                .collect();
1901            if let Some(content_capture_ix) = content_capture_ix {
1902                self.grammar_mut()?.injection_config = Some(InjectionConfig {
1903                    query,
1904                    language_capture_ix,
1905                    content_capture_ix,
1906                    patterns,
1907                });
1908            } else {
1909                log::error!(
1910                    "missing required capture in injections {} TreeSitter query: \
1911                    content or injection.content",
1912                    &self.config.name,
1913                );
1914            }
1915        }
1916        Ok(self)
1917    }
1918
1919    pub fn with_override_query(mut self, source: &str) -> anyhow::Result<Self> {
1920        let query = Query::new(&self.expect_grammar()?.ts_language, source)?;
1921
1922        let mut override_configs_by_id = HashMap::default();
1923        for (ix, mut name) in query.capture_names().iter().copied().enumerate() {
1924            let mut range_is_inclusive = false;
1925            if name.starts_with('_') {
1926                continue;
1927            }
1928            if let Some(prefix) = name.strip_suffix(".inclusive") {
1929                name = prefix;
1930                range_is_inclusive = true;
1931            }
1932
1933            let value = self.config.overrides.get(name).cloned().unwrap_or_default();
1934            for server_name in &value.opt_into_language_servers {
1935                if !self
1936                    .config
1937                    .scope_opt_in_language_servers
1938                    .contains(server_name)
1939                {
1940                    util::debug_panic!(
1941                        "Server {server_name:?} has been opted-in by scope {name:?} but has not been marked as an opt-in server"
1942                    );
1943                }
1944            }
1945
1946            override_configs_by_id.insert(
1947                ix as u32,
1948                OverrideEntry {
1949                    name: name.to_string(),
1950                    range_is_inclusive,
1951                    value,
1952                },
1953            );
1954        }
1955
1956        let referenced_override_names = self.config.overrides.keys().chain(
1957            self.config
1958                .brackets
1959                .disabled_scopes_by_bracket_ix
1960                .iter()
1961                .flatten(),
1962        );
1963
1964        for referenced_name in referenced_override_names {
1965            if !override_configs_by_id
1966                .values()
1967                .any(|entry| entry.name == *referenced_name)
1968            {
1969                anyhow::bail!(
1970                    "language {:?} has overrides in config not in query: {referenced_name:?}",
1971                    self.config.name
1972                );
1973            }
1974        }
1975
1976        for entry in override_configs_by_id.values_mut() {
1977            entry.value.disabled_bracket_ixs = self
1978                .config
1979                .brackets
1980                .disabled_scopes_by_bracket_ix
1981                .iter()
1982                .enumerate()
1983                .filter_map(|(ix, disabled_scope_names)| {
1984                    if disabled_scope_names.contains(&entry.name) {
1985                        Some(ix as u16)
1986                    } else {
1987                        None
1988                    }
1989                })
1990                .collect();
1991        }
1992
1993        self.config.brackets.disabled_scopes_by_bracket_ix.clear();
1994
1995        let grammar = self.grammar_mut()?;
1996        grammar.override_config = Some(OverrideConfig {
1997            query,
1998            values: override_configs_by_id,
1999        });
2000        Ok(self)
2001    }
2002
2003    pub fn with_redaction_query(mut self, source: &str) -> anyhow::Result<Self> {
2004        let query = Query::new(&self.expect_grammar()?.ts_language, source)?;
2005        let mut redaction_capture_ix = 0;
2006        if populate_capture_indices(
2007            &query,
2008            &self.config.name,
2009            "redactions",
2010            &[],
2011            &mut [Capture::Required("redact", &mut redaction_capture_ix)],
2012        ) {
2013            self.grammar_mut()?.redactions_config = Some(RedactionConfig {
2014                query,
2015                redaction_capture_ix,
2016            });
2017        }
2018        Ok(self)
2019    }
2020
2021    fn expect_grammar(&self) -> Result<&Grammar> {
2022        self.grammar
2023            .as_ref()
2024            .map(|grammar| grammar.as_ref())
2025            .context("no grammar for language")
2026    }
2027
2028    fn grammar_mut(&mut self) -> Result<&mut Grammar> {
2029        Arc::get_mut(self.grammar.as_mut().context("no grammar for language")?)
2030            .context("cannot mutate grammar")
2031    }
2032
2033    pub fn name(&self) -> LanguageName {
2034        self.config.name.clone()
2035    }
2036    pub fn manifest(&self) -> Option<&ManifestName> {
2037        self.manifest_name.as_ref()
2038    }
2039
2040    pub fn code_fence_block_name(&self) -> Arc<str> {
2041        self.config
2042            .code_fence_block_name
2043            .clone()
2044            .unwrap_or_else(|| self.config.name.as_ref().to_lowercase().into())
2045    }
2046
2047    pub fn context_provider(&self) -> Option<Arc<dyn ContextProvider>> {
2048        self.context_provider.clone()
2049    }
2050
2051    pub fn toolchain_lister(&self) -> Option<Arc<dyn ToolchainLister>> {
2052        self.toolchain.clone()
2053    }
2054
2055    pub fn highlight_text<'a>(
2056        self: &'a Arc<Self>,
2057        text: &'a Rope,
2058        range: Range<usize>,
2059    ) -> Vec<(Range<usize>, HighlightId)> {
2060        let mut result = Vec::new();
2061        if let Some(grammar) = &self.grammar {
2062            let tree = grammar.parse_text(text, None);
2063            let captures =
2064                SyntaxSnapshot::single_tree_captures(range.clone(), text, &tree, self, |grammar| {
2065                    grammar
2066                        .highlights_config
2067                        .as_ref()
2068                        .map(|config| &config.query)
2069                });
2070            let highlight_maps = vec![grammar.highlight_map()];
2071            let mut offset = 0;
2072            for chunk in
2073                BufferChunks::new(text, range, Some((captures, highlight_maps)), false, None)
2074            {
2075                let end_offset = offset + chunk.text.len();
2076                if let Some(highlight_id) = chunk.syntax_highlight_id
2077                    && !highlight_id.is_default()
2078                {
2079                    result.push((offset..end_offset, highlight_id));
2080                }
2081                offset = end_offset;
2082            }
2083        }
2084        result
2085    }
2086
2087    pub fn path_suffixes(&self) -> &[String] {
2088        &self.config.matcher.path_suffixes
2089    }
2090
2091    pub fn should_autoclose_before(&self, c: char) -> bool {
2092        c.is_whitespace() || self.config.autoclose_before.contains(c)
2093    }
2094
2095    pub fn set_theme(&self, theme: &SyntaxTheme) {
2096        if let Some(grammar) = self.grammar.as_ref()
2097            && let Some(highlights_config) = &grammar.highlights_config
2098        {
2099            *grammar.highlight_map.lock() =
2100                HighlightMap::new(highlights_config.query.capture_names(), theme);
2101        }
2102    }
2103
2104    pub fn grammar(&self) -> Option<&Arc<Grammar>> {
2105        self.grammar.as_ref()
2106    }
2107
2108    pub fn default_scope(self: &Arc<Self>) -> LanguageScope {
2109        LanguageScope {
2110            language: self.clone(),
2111            override_id: None,
2112        }
2113    }
2114
2115    pub fn lsp_id(&self) -> String {
2116        self.config.name.lsp_id()
2117    }
2118
2119    pub fn prettier_parser_name(&self) -> Option<&str> {
2120        self.config.prettier_parser_name.as_deref()
2121    }
2122
2123    pub fn config(&self) -> &LanguageConfig {
2124        &self.config
2125    }
2126}
2127
2128impl LanguageScope {
2129    pub fn path_suffixes(&self) -> &[String] {
2130        self.language.path_suffixes()
2131    }
2132
2133    pub fn language_name(&self) -> LanguageName {
2134        self.language.config.name.clone()
2135    }
2136
2137    pub fn collapsed_placeholder(&self) -> &str {
2138        self.language.config.collapsed_placeholder.as_ref()
2139    }
2140
2141    /// Returns line prefix that is inserted in e.g. line continuations or
2142    /// in `toggle comments` action.
2143    pub fn line_comment_prefixes(&self) -> &[Arc<str>] {
2144        Override::as_option(
2145            self.config_override().map(|o| &o.line_comments),
2146            Some(&self.language.config.line_comments),
2147        )
2148        .map_or([].as_slice(), |e| e.as_slice())
2149    }
2150
2151    /// Config for block comments for this language.
2152    pub fn block_comment(&self) -> Option<&BlockCommentConfig> {
2153        Override::as_option(
2154            self.config_override().map(|o| &o.block_comment),
2155            self.language.config.block_comment.as_ref(),
2156        )
2157    }
2158
2159    /// Config for documentation-style block comments for this language.
2160    pub fn documentation_comment(&self) -> Option<&BlockCommentConfig> {
2161        self.language.config.documentation_comment.as_ref()
2162    }
2163
2164    /// Returns list markers that are inserted unchanged on newline (e.g., `- `, `* `, `+ `).
2165    pub fn unordered_list(&self) -> &[Arc<str>] {
2166        &self.language.config.unordered_list
2167    }
2168
2169    /// Returns configuration for ordered lists with auto-incrementing numbers (e.g., `1. ` becomes `2. `).
2170    pub fn ordered_list(&self) -> &[OrderedListConfig] {
2171        &self.language.config.ordered_list
2172    }
2173
2174    /// Returns configuration for task list continuation, if any (e.g., `- [x] ` continues as `- [ ] `).
2175    pub fn task_list(&self) -> Option<&TaskListConfig> {
2176        self.language.config.task_list.as_ref()
2177    }
2178
2179    /// Returns additional regex patterns that act as prefix markers for creating
2180    /// boundaries during rewrapping.
2181    ///
2182    /// By default, Zed treats as paragraph and comment prefixes as boundaries.
2183    pub fn rewrap_prefixes(&self) -> &[Regex] {
2184        &self.language.config.rewrap_prefixes
2185    }
2186
2187    /// Returns a list of language-specific word characters.
2188    ///
2189    /// By default, Zed treats alphanumeric characters (and '_') as word characters for
2190    /// the purpose of actions like 'move to next word end` or whole-word search.
2191    /// It additionally accounts for language's additional word characters.
2192    pub fn word_characters(&self) -> Option<&HashSet<char>> {
2193        Override::as_option(
2194            self.config_override().map(|o| &o.word_characters),
2195            Some(&self.language.config.word_characters),
2196        )
2197    }
2198
2199    /// Returns a list of language-specific characters that are considered part of
2200    /// a completion query.
2201    pub fn completion_query_characters(&self) -> Option<&HashSet<char>> {
2202        Override::as_option(
2203            self.config_override()
2204                .map(|o| &o.completion_query_characters),
2205            Some(&self.language.config.completion_query_characters),
2206        )
2207    }
2208
2209    /// Returns a list of language-specific characters that are considered part of
2210    /// identifiers during linked editing operations.
2211    pub fn linked_edit_characters(&self) -> Option<&HashSet<char>> {
2212        Override::as_option(
2213            self.config_override().map(|o| &o.linked_edit_characters),
2214            Some(&self.language.config.linked_edit_characters),
2215        )
2216    }
2217
2218    /// Returns whether to prefer snippet `label` over `new_text` to replace text when
2219    /// completion is accepted.
2220    ///
2221    /// In cases like when cursor is in string or renaming existing function,
2222    /// you don't want to expand function signature instead just want function name
2223    /// to replace existing one.
2224    pub fn prefers_label_for_snippet_in_completion(&self) -> bool {
2225        self.config_override()
2226            .and_then(|o| o.prefer_label_for_snippet)
2227            .unwrap_or(false)
2228    }
2229
2230    /// Returns a list of bracket pairs for a given language with an additional
2231    /// piece of information about whether the particular bracket pair is currently active for a given language.
2232    pub fn brackets(&self) -> impl Iterator<Item = (&BracketPair, bool)> {
2233        let mut disabled_ids = self
2234            .config_override()
2235            .map_or(&[] as _, |o| o.disabled_bracket_ixs.as_slice());
2236        self.language
2237            .config
2238            .brackets
2239            .pairs
2240            .iter()
2241            .enumerate()
2242            .map(move |(ix, bracket)| {
2243                let mut is_enabled = true;
2244                if let Some(next_disabled_ix) = disabled_ids.first()
2245                    && ix == *next_disabled_ix as usize
2246                {
2247                    disabled_ids = &disabled_ids[1..];
2248                    is_enabled = false;
2249                }
2250                (bracket, is_enabled)
2251            })
2252    }
2253
2254    pub fn should_autoclose_before(&self, c: char) -> bool {
2255        c.is_whitespace() || self.language.config.autoclose_before.contains(c)
2256    }
2257
2258    pub fn language_allowed(&self, name: &LanguageServerName) -> bool {
2259        let config = &self.language.config;
2260        let opt_in_servers = &config.scope_opt_in_language_servers;
2261        if opt_in_servers.contains(name) {
2262            if let Some(over) = self.config_override() {
2263                over.opt_into_language_servers.contains(name)
2264            } else {
2265                false
2266            }
2267        } else {
2268            true
2269        }
2270    }
2271
2272    pub fn override_name(&self) -> Option<&str> {
2273        let id = self.override_id?;
2274        let grammar = self.language.grammar.as_ref()?;
2275        let override_config = grammar.override_config.as_ref()?;
2276        override_config.values.get(&id).map(|e| e.name.as_str())
2277    }
2278
2279    fn config_override(&self) -> Option<&LanguageConfigOverride> {
2280        let id = self.override_id?;
2281        let grammar = self.language.grammar.as_ref()?;
2282        let override_config = grammar.override_config.as_ref()?;
2283        override_config.values.get(&id).map(|e| &e.value)
2284    }
2285}
2286
2287impl Hash for Language {
2288    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2289        self.id.hash(state)
2290    }
2291}
2292
2293impl PartialEq for Language {
2294    fn eq(&self, other: &Self) -> bool {
2295        self.id.eq(&other.id)
2296    }
2297}
2298
2299impl Eq for Language {}
2300
2301impl Debug for Language {
2302    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2303        f.debug_struct("Language")
2304            .field("name", &self.config.name)
2305            .finish()
2306    }
2307}
2308
2309impl Grammar {
2310    pub fn id(&self) -> GrammarId {
2311        self.id
2312    }
2313
2314    fn parse_text(&self, text: &Rope, old_tree: Option<Tree>) -> Tree {
2315        with_parser(|parser| {
2316            parser
2317                .set_language(&self.ts_language)
2318                .expect("incompatible grammar");
2319            let mut chunks = text.chunks_in_range(0..text.len());
2320            parser
2321                .parse_with_options(
2322                    &mut move |offset, _| {
2323                        chunks.seek(offset);
2324                        chunks.next().unwrap_or("").as_bytes()
2325                    },
2326                    old_tree.as_ref(),
2327                    None,
2328                )
2329                .unwrap()
2330        })
2331    }
2332
2333    pub fn highlight_map(&self) -> HighlightMap {
2334        self.highlight_map.lock().clone()
2335    }
2336
2337    pub fn highlight_id_for_name(&self, name: &str) -> Option<HighlightId> {
2338        let capture_id = self
2339            .highlights_config
2340            .as_ref()?
2341            .query
2342            .capture_index_for_name(name)?;
2343        Some(self.highlight_map.lock().get(capture_id))
2344    }
2345
2346    pub fn debug_variables_config(&self) -> Option<&DebugVariablesConfig> {
2347        self.debug_variables_config.as_ref()
2348    }
2349
2350    pub fn imports_config(&self) -> Option<&ImportsConfig> {
2351        self.imports_config.as_ref()
2352    }
2353}
2354
2355impl CodeLabelBuilder {
2356    pub fn respan_filter_range(&mut self, filter_text: Option<&str>) {
2357        self.filter_range = filter_text
2358            .and_then(|filter| self.text.find(filter).map(|ix| ix..ix + filter.len()))
2359            .unwrap_or(0..self.text.len());
2360    }
2361
2362    pub fn push_str(&mut self, text: &str, highlight: Option<HighlightId>) {
2363        let start_ix = self.text.len();
2364        self.text.push_str(text);
2365        if let Some(highlight) = highlight {
2366            let end_ix = self.text.len();
2367            self.runs.push((start_ix..end_ix, highlight));
2368        }
2369    }
2370
2371    pub fn build(mut self) -> CodeLabel {
2372        if self.filter_range.end == 0 {
2373            self.respan_filter_range(None);
2374        }
2375        CodeLabel {
2376            text: self.text,
2377            runs: self.runs,
2378            filter_range: self.filter_range,
2379        }
2380    }
2381}
2382
2383impl CodeLabel {
2384    pub fn fallback_for_completion(
2385        item: &lsp::CompletionItem,
2386        language: Option<&Language>,
2387    ) -> Self {
2388        let highlight_id = item.kind.and_then(|kind| {
2389            let grammar = language?.grammar()?;
2390            use lsp::CompletionItemKind as Kind;
2391            match kind {
2392                Kind::CLASS => grammar.highlight_id_for_name("type"),
2393                Kind::CONSTANT => grammar.highlight_id_for_name("constant"),
2394                Kind::CONSTRUCTOR => grammar.highlight_id_for_name("constructor"),
2395                Kind::ENUM => grammar
2396                    .highlight_id_for_name("enum")
2397                    .or_else(|| grammar.highlight_id_for_name("type")),
2398                Kind::ENUM_MEMBER => grammar
2399                    .highlight_id_for_name("variant")
2400                    .or_else(|| grammar.highlight_id_for_name("property")),
2401                Kind::FIELD => grammar.highlight_id_for_name("property"),
2402                Kind::FUNCTION => grammar.highlight_id_for_name("function"),
2403                Kind::INTERFACE => grammar.highlight_id_for_name("type"),
2404                Kind::METHOD => grammar
2405                    .highlight_id_for_name("function.method")
2406                    .or_else(|| grammar.highlight_id_for_name("function")),
2407                Kind::OPERATOR => grammar.highlight_id_for_name("operator"),
2408                Kind::PROPERTY => grammar.highlight_id_for_name("property"),
2409                Kind::STRUCT => grammar.highlight_id_for_name("type"),
2410                Kind::VARIABLE => grammar.highlight_id_for_name("variable"),
2411                Kind::KEYWORD => grammar.highlight_id_for_name("keyword"),
2412                _ => None,
2413            }
2414        });
2415
2416        let label = &item.label;
2417        let label_length = label.len();
2418        let runs = highlight_id
2419            .map(|highlight_id| vec![(0..label_length, highlight_id)])
2420            .unwrap_or_default();
2421        let text = if let Some(detail) = item.detail.as_deref().filter(|detail| detail != label) {
2422            format!("{label} {detail}")
2423        } else if let Some(description) = item
2424            .label_details
2425            .as_ref()
2426            .and_then(|label_details| label_details.description.as_deref())
2427            .filter(|description| description != label)
2428        {
2429            format!("{label} {description}")
2430        } else {
2431            label.clone()
2432        };
2433        let filter_range = item
2434            .filter_text
2435            .as_deref()
2436            .and_then(|filter| text.find(filter).map(|ix| ix..ix + filter.len()))
2437            .unwrap_or(0..label_length);
2438        Self {
2439            text,
2440            runs,
2441            filter_range,
2442        }
2443    }
2444
2445    pub fn plain(text: String, filter_text: Option<&str>) -> Self {
2446        Self::filtered(text.clone(), text.len(), filter_text, Vec::new())
2447    }
2448
2449    pub fn filtered(
2450        text: String,
2451        label_len: usize,
2452        filter_text: Option<&str>,
2453        runs: Vec<(Range<usize>, HighlightId)>,
2454    ) -> Self {
2455        assert!(label_len <= text.len());
2456        let filter_range = filter_text
2457            .and_then(|filter| text.find(filter).map(|ix| ix..ix + filter.len()))
2458            .unwrap_or(0..label_len);
2459        Self::new(text, filter_range, runs)
2460    }
2461
2462    pub fn new(
2463        text: String,
2464        filter_range: Range<usize>,
2465        runs: Vec<(Range<usize>, HighlightId)>,
2466    ) -> Self {
2467        assert!(
2468            text.get(filter_range.clone()).is_some(),
2469            "invalid filter range"
2470        );
2471        runs.iter().for_each(|(range, _)| {
2472            assert!(
2473                text.get(range.clone()).is_some(),
2474                "invalid run range with inputs. Requested range {range:?} in text '{text}'",
2475            );
2476        });
2477        Self {
2478            runs,
2479            filter_range,
2480            text,
2481        }
2482    }
2483
2484    pub fn text(&self) -> &str {
2485        self.text.as_str()
2486    }
2487
2488    pub fn filter_text(&self) -> &str {
2489        &self.text[self.filter_range.clone()]
2490    }
2491}
2492
2493impl From<String> for CodeLabel {
2494    fn from(value: String) -> Self {
2495        Self::plain(value, None)
2496    }
2497}
2498
2499impl From<&str> for CodeLabel {
2500    fn from(value: &str) -> Self {
2501        Self::plain(value.to_string(), None)
2502    }
2503}
2504
2505impl Ord for LanguageMatcher {
2506    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
2507        self.path_suffixes.cmp(&other.path_suffixes).then_with(|| {
2508            self.first_line_pattern
2509                .as_ref()
2510                .map(Regex::as_str)
2511                .cmp(&other.first_line_pattern.as_ref().map(Regex::as_str))
2512        })
2513    }
2514}
2515
2516impl PartialOrd for LanguageMatcher {
2517    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
2518        Some(self.cmp(other))
2519    }
2520}
2521
2522impl Eq for LanguageMatcher {}
2523
2524impl PartialEq for LanguageMatcher {
2525    fn eq(&self, other: &Self) -> bool {
2526        self.path_suffixes == other.path_suffixes
2527            && self.first_line_pattern.as_ref().map(Regex::as_str)
2528                == other.first_line_pattern.as_ref().map(Regex::as_str)
2529    }
2530}
2531
2532#[cfg(any(test, feature = "test-support"))]
2533impl Default for FakeLspAdapter {
2534    fn default() -> Self {
2535        Self {
2536            name: "the-fake-language-server",
2537            capabilities: lsp::LanguageServer::full_capabilities(),
2538            initializer: None,
2539            disk_based_diagnostics_progress_token: None,
2540            initialization_options: None,
2541            disk_based_diagnostics_sources: Vec::new(),
2542            prettier_plugins: Vec::new(),
2543            language_server_binary: LanguageServerBinary {
2544                path: "/the/fake/lsp/path".into(),
2545                arguments: vec![],
2546                env: Default::default(),
2547            },
2548            label_for_completion: None,
2549        }
2550    }
2551}
2552
2553#[cfg(any(test, feature = "test-support"))]
2554impl LspInstaller for FakeLspAdapter {
2555    type BinaryVersion = ();
2556
2557    async fn fetch_latest_server_version(
2558        &self,
2559        _: &dyn LspAdapterDelegate,
2560        _: bool,
2561        _: &mut AsyncApp,
2562    ) -> Result<Self::BinaryVersion> {
2563        unreachable!()
2564    }
2565
2566    async fn check_if_user_installed(
2567        &self,
2568        _: &dyn LspAdapterDelegate,
2569        _: Option<Toolchain>,
2570        _: &AsyncApp,
2571    ) -> Option<LanguageServerBinary> {
2572        Some(self.language_server_binary.clone())
2573    }
2574
2575    async fn fetch_server_binary(
2576        &self,
2577        _: (),
2578        _: PathBuf,
2579        _: &dyn LspAdapterDelegate,
2580    ) -> Result<LanguageServerBinary> {
2581        unreachable!();
2582    }
2583
2584    async fn cached_server_binary(
2585        &self,
2586        _: PathBuf,
2587        _: &dyn LspAdapterDelegate,
2588    ) -> Option<LanguageServerBinary> {
2589        unreachable!();
2590    }
2591}
2592
2593#[cfg(any(test, feature = "test-support"))]
2594#[async_trait(?Send)]
2595impl LspAdapter for FakeLspAdapter {
2596    fn name(&self) -> LanguageServerName {
2597        LanguageServerName(self.name.into())
2598    }
2599
2600    fn disk_based_diagnostic_sources(&self) -> Vec<String> {
2601        self.disk_based_diagnostics_sources.clone()
2602    }
2603
2604    fn disk_based_diagnostics_progress_token(&self) -> Option<String> {
2605        self.disk_based_diagnostics_progress_token.clone()
2606    }
2607
2608    async fn initialization_options(
2609        self: Arc<Self>,
2610        _: &Arc<dyn LspAdapterDelegate>,
2611    ) -> Result<Option<Value>> {
2612        Ok(self.initialization_options.clone())
2613    }
2614
2615    async fn label_for_completion(
2616        &self,
2617        item: &lsp::CompletionItem,
2618        language: &Arc<Language>,
2619    ) -> Option<CodeLabel> {
2620        let label_for_completion = self.label_for_completion.as_ref()?;
2621        label_for_completion(item, language)
2622    }
2623
2624    fn is_extension(&self) -> bool {
2625        false
2626    }
2627}
2628
2629enum Capture<'a> {
2630    Required(&'static str, &'a mut u32),
2631    Optional(&'static str, &'a mut Option<u32>),
2632}
2633
2634fn populate_capture_indices(
2635    query: &Query,
2636    language_name: &LanguageName,
2637    query_type: &str,
2638    expected_prefixes: &[&str],
2639    captures: &mut [Capture<'_>],
2640) -> bool {
2641    let mut found_required_indices = Vec::new();
2642    'outer: for (ix, name) in query.capture_names().iter().enumerate() {
2643        for (required_ix, capture) in captures.iter_mut().enumerate() {
2644            match capture {
2645                Capture::Required(capture_name, index) if capture_name == name => {
2646                    **index = ix as u32;
2647                    found_required_indices.push(required_ix);
2648                    continue 'outer;
2649                }
2650                Capture::Optional(capture_name, index) if capture_name == name => {
2651                    **index = Some(ix as u32);
2652                    continue 'outer;
2653                }
2654                _ => {}
2655            }
2656        }
2657        if !name.starts_with("_")
2658            && !expected_prefixes
2659                .iter()
2660                .any(|&prefix| name.starts_with(prefix))
2661        {
2662            log::warn!(
2663                "unrecognized capture name '{}' in {} {} TreeSitter query \
2664                (suppress this warning by prefixing with '_')",
2665                name,
2666                language_name,
2667                query_type
2668            );
2669        }
2670    }
2671    let mut missing_required_captures = Vec::new();
2672    for (capture_ix, capture) in captures.iter().enumerate() {
2673        if let Capture::Required(capture_name, _) = capture
2674            && !found_required_indices.contains(&capture_ix)
2675        {
2676            missing_required_captures.push(*capture_name);
2677        }
2678    }
2679    let success = missing_required_captures.is_empty();
2680    if !success {
2681        log::error!(
2682            "missing required capture(s) in {} {} TreeSitter query: {}",
2683            language_name,
2684            query_type,
2685            missing_required_captures.join(", ")
2686        );
2687    }
2688    success
2689}
2690
2691pub fn point_to_lsp(point: PointUtf16) -> lsp::Position {
2692    lsp::Position::new(point.row, point.column)
2693}
2694
2695pub fn point_from_lsp(point: lsp::Position) -> Unclipped<PointUtf16> {
2696    Unclipped(PointUtf16::new(point.line, point.character))
2697}
2698
2699pub fn range_to_lsp(range: Range<PointUtf16>) -> Result<lsp::Range> {
2700    anyhow::ensure!(
2701        range.start <= range.end,
2702        "Inverted range provided to an LSP request: {:?}-{:?}",
2703        range.start,
2704        range.end
2705    );
2706    Ok(lsp::Range {
2707        start: point_to_lsp(range.start),
2708        end: point_to_lsp(range.end),
2709    })
2710}
2711
2712pub fn range_from_lsp(range: lsp::Range) -> Range<Unclipped<PointUtf16>> {
2713    let mut start = point_from_lsp(range.start);
2714    let mut end = point_from_lsp(range.end);
2715    if start > end {
2716        // We debug instead of warn so that this is not logged by default unless explicitly requested.
2717        // Using warn would write to the log file, and since we receive an enormous amount of
2718        // range_from_lsp calls (especially during completions), that can hang the main thread.
2719        //
2720        // See issue #36223.
2721        zlog::debug!("range_from_lsp called with inverted range {start:?}-{end:?}");
2722        mem::swap(&mut start, &mut end);
2723    }
2724    start..end
2725}
2726
2727#[doc(hidden)]
2728#[cfg(any(test, feature = "test-support"))]
2729pub fn rust_lang() -> Arc<Language> {
2730    use std::borrow::Cow;
2731
2732    let language = Language::new(
2733        LanguageConfig {
2734            name: "Rust".into(),
2735            matcher: LanguageMatcher {
2736                path_suffixes: vec!["rs".to_string()],
2737                ..Default::default()
2738            },
2739            line_comments: vec!["// ".into(), "/// ".into(), "//! ".into()],
2740            ..Default::default()
2741        },
2742        Some(tree_sitter_rust::LANGUAGE.into()),
2743    )
2744    .with_queries(LanguageQueries {
2745        outline: Some(Cow::from(include_str!(
2746            "../../languages/src/rust/outline.scm"
2747        ))),
2748        indents: Some(Cow::from(include_str!(
2749            "../../languages/src/rust/indents.scm"
2750        ))),
2751        brackets: Some(Cow::from(include_str!(
2752            "../../languages/src/rust/brackets.scm"
2753        ))),
2754        text_objects: Some(Cow::from(include_str!(
2755            "../../languages/src/rust/textobjects.scm"
2756        ))),
2757        highlights: Some(Cow::from(include_str!(
2758            "../../languages/src/rust/highlights.scm"
2759        ))),
2760        injections: Some(Cow::from(include_str!(
2761            "../../languages/src/rust/injections.scm"
2762        ))),
2763        overrides: Some(Cow::from(include_str!(
2764            "../../languages/src/rust/overrides.scm"
2765        ))),
2766        redactions: None,
2767        runnables: Some(Cow::from(include_str!(
2768            "../../languages/src/rust/runnables.scm"
2769        ))),
2770        debugger: Some(Cow::from(include_str!(
2771            "../../languages/src/rust/debugger.scm"
2772        ))),
2773        imports: Some(Cow::from(include_str!(
2774            "../../languages/src/rust/imports.scm"
2775        ))),
2776    })
2777    .expect("Could not parse queries");
2778    Arc::new(language)
2779}
2780
2781#[doc(hidden)]
2782#[cfg(any(test, feature = "test-support"))]
2783pub fn markdown_lang() -> Arc<Language> {
2784    use std::borrow::Cow;
2785
2786    let language = Language::new(
2787        LanguageConfig {
2788            name: "Markdown".into(),
2789            matcher: LanguageMatcher {
2790                path_suffixes: vec!["md".into()],
2791                ..Default::default()
2792            },
2793            ..LanguageConfig::default()
2794        },
2795        Some(tree_sitter_md::LANGUAGE.into()),
2796    )
2797    .with_queries(LanguageQueries {
2798        brackets: Some(Cow::from(include_str!(
2799            "../../languages/src/markdown/brackets.scm"
2800        ))),
2801        injections: Some(Cow::from(include_str!(
2802            "../../languages/src/markdown/injections.scm"
2803        ))),
2804        highlights: Some(Cow::from(include_str!(
2805            "../../languages/src/markdown/highlights.scm"
2806        ))),
2807        indents: Some(Cow::from(include_str!(
2808            "../../languages/src/markdown/indents.scm"
2809        ))),
2810        outline: Some(Cow::from(include_str!(
2811            "../../languages/src/markdown/outline.scm"
2812        ))),
2813        ..LanguageQueries::default()
2814    })
2815    .expect("Could not parse markdown queries");
2816    Arc::new(language)
2817}
2818
2819#[cfg(test)]
2820mod tests {
2821    use super::*;
2822    use gpui::TestAppContext;
2823    use pretty_assertions::assert_matches;
2824
2825    #[gpui::test(iterations = 10)]
2826    async fn test_language_loading(cx: &mut TestAppContext) {
2827        let languages = LanguageRegistry::test(cx.executor());
2828        let languages = Arc::new(languages);
2829        languages.register_native_grammars([
2830            ("json", tree_sitter_json::LANGUAGE),
2831            ("rust", tree_sitter_rust::LANGUAGE),
2832        ]);
2833        languages.register_test_language(LanguageConfig {
2834            name: "JSON".into(),
2835            grammar: Some("json".into()),
2836            matcher: LanguageMatcher {
2837                path_suffixes: vec!["json".into()],
2838                ..Default::default()
2839            },
2840            ..Default::default()
2841        });
2842        languages.register_test_language(LanguageConfig {
2843            name: "Rust".into(),
2844            grammar: Some("rust".into()),
2845            matcher: LanguageMatcher {
2846                path_suffixes: vec!["rs".into()],
2847                ..Default::default()
2848            },
2849            ..Default::default()
2850        });
2851        assert_eq!(
2852            languages.language_names(),
2853            &[
2854                LanguageName::new_static("JSON"),
2855                LanguageName::new_static("Plain Text"),
2856                LanguageName::new_static("Rust"),
2857            ]
2858        );
2859
2860        let rust1 = languages.language_for_name("Rust");
2861        let rust2 = languages.language_for_name("Rust");
2862
2863        // Ensure language is still listed even if it's being loaded.
2864        assert_eq!(
2865            languages.language_names(),
2866            &[
2867                LanguageName::new_static("JSON"),
2868                LanguageName::new_static("Plain Text"),
2869                LanguageName::new_static("Rust"),
2870            ]
2871        );
2872
2873        let (rust1, rust2) = futures::join!(rust1, rust2);
2874        assert!(Arc::ptr_eq(&rust1.unwrap(), &rust2.unwrap()));
2875
2876        // Ensure language is still listed even after loading it.
2877        assert_eq!(
2878            languages.language_names(),
2879            &[
2880                LanguageName::new_static("JSON"),
2881                LanguageName::new_static("Plain Text"),
2882                LanguageName::new_static("Rust"),
2883            ]
2884        );
2885
2886        // Loading an unknown language returns an error.
2887        assert!(languages.language_for_name("Unknown").await.is_err());
2888    }
2889
2890    #[gpui::test]
2891    async fn test_completion_label_omits_duplicate_data() {
2892        let regular_completion_item_1 = lsp::CompletionItem {
2893            label: "regular1".to_string(),
2894            detail: Some("detail1".to_string()),
2895            label_details: Some(lsp::CompletionItemLabelDetails {
2896                detail: None,
2897                description: Some("description 1".to_string()),
2898            }),
2899            ..lsp::CompletionItem::default()
2900        };
2901
2902        let regular_completion_item_2 = lsp::CompletionItem {
2903            label: "regular2".to_string(),
2904            label_details: Some(lsp::CompletionItemLabelDetails {
2905                detail: None,
2906                description: Some("description 2".to_string()),
2907            }),
2908            ..lsp::CompletionItem::default()
2909        };
2910
2911        let completion_item_with_duplicate_detail_and_proper_description = lsp::CompletionItem {
2912            detail: Some(regular_completion_item_1.label.clone()),
2913            ..regular_completion_item_1.clone()
2914        };
2915
2916        let completion_item_with_duplicate_detail = lsp::CompletionItem {
2917            detail: Some(regular_completion_item_1.label.clone()),
2918            label_details: None,
2919            ..regular_completion_item_1.clone()
2920        };
2921
2922        let completion_item_with_duplicate_description = lsp::CompletionItem {
2923            label_details: Some(lsp::CompletionItemLabelDetails {
2924                detail: None,
2925                description: Some(regular_completion_item_2.label.clone()),
2926            }),
2927            ..regular_completion_item_2.clone()
2928        };
2929
2930        assert_eq!(
2931            CodeLabel::fallback_for_completion(&regular_completion_item_1, None).text,
2932            format!(
2933                "{} {}",
2934                regular_completion_item_1.label,
2935                regular_completion_item_1.detail.unwrap()
2936            ),
2937            "LSP completion items with both detail and label_details.description should prefer detail"
2938        );
2939        assert_eq!(
2940            CodeLabel::fallback_for_completion(&regular_completion_item_2, None).text,
2941            format!(
2942                "{} {}",
2943                regular_completion_item_2.label,
2944                regular_completion_item_2
2945                    .label_details
2946                    .as_ref()
2947                    .unwrap()
2948                    .description
2949                    .as_ref()
2950                    .unwrap()
2951            ),
2952            "LSP completion items without detail but with label_details.description should use that"
2953        );
2954        assert_eq!(
2955            CodeLabel::fallback_for_completion(
2956                &completion_item_with_duplicate_detail_and_proper_description,
2957                None
2958            )
2959            .text,
2960            format!(
2961                "{} {}",
2962                regular_completion_item_1.label,
2963                regular_completion_item_1
2964                    .label_details
2965                    .as_ref()
2966                    .unwrap()
2967                    .description
2968                    .as_ref()
2969                    .unwrap()
2970            ),
2971            "LSP completion items with both detail and label_details.description should prefer description only if the detail duplicates the completion label"
2972        );
2973        assert_eq!(
2974            CodeLabel::fallback_for_completion(&completion_item_with_duplicate_detail, None).text,
2975            regular_completion_item_1.label,
2976            "LSP completion items with duplicate label and detail, should omit the detail"
2977        );
2978        assert_eq!(
2979            CodeLabel::fallback_for_completion(&completion_item_with_duplicate_description, None)
2980                .text,
2981            regular_completion_item_2.label,
2982            "LSP completion items with duplicate label and detail, should omit the detail"
2983        );
2984    }
2985
2986    #[test]
2987    fn test_deserializing_comments_backwards_compat() {
2988        // current version of `block_comment` and `documentation_comment` work
2989        {
2990            let config: LanguageConfig = ::toml::from_str(
2991                r#"
2992                name = "Foo"
2993                block_comment = { start = "a", end = "b", prefix = "c", tab_size = 1 }
2994                documentation_comment = { start = "d", end = "e", prefix = "f", tab_size = 2 }
2995                "#,
2996            )
2997            .unwrap();
2998            assert_matches!(config.block_comment, Some(BlockCommentConfig { .. }));
2999            assert_matches!(
3000                config.documentation_comment,
3001                Some(BlockCommentConfig { .. })
3002            );
3003
3004            let block_config = config.block_comment.unwrap();
3005            assert_eq!(block_config.start.as_ref(), "a");
3006            assert_eq!(block_config.end.as_ref(), "b");
3007            assert_eq!(block_config.prefix.as_ref(), "c");
3008            assert_eq!(block_config.tab_size, 1);
3009
3010            let doc_config = config.documentation_comment.unwrap();
3011            assert_eq!(doc_config.start.as_ref(), "d");
3012            assert_eq!(doc_config.end.as_ref(), "e");
3013            assert_eq!(doc_config.prefix.as_ref(), "f");
3014            assert_eq!(doc_config.tab_size, 2);
3015        }
3016
3017        // former `documentation` setting is read into `documentation_comment`
3018        {
3019            let config: LanguageConfig = ::toml::from_str(
3020                r#"
3021                name = "Foo"
3022                documentation = { start = "a", end = "b", prefix = "c", tab_size = 1}
3023                "#,
3024            )
3025            .unwrap();
3026            assert_matches!(
3027                config.documentation_comment,
3028                Some(BlockCommentConfig { .. })
3029            );
3030
3031            let config = config.documentation_comment.unwrap();
3032            assert_eq!(config.start.as_ref(), "a");
3033            assert_eq!(config.end.as_ref(), "b");
3034            assert_eq!(config.prefix.as_ref(), "c");
3035            assert_eq!(config.tab_size, 1);
3036        }
3037
3038        // old block_comment format is read into BlockCommentConfig
3039        {
3040            let config: LanguageConfig = ::toml::from_str(
3041                r#"
3042                name = "Foo"
3043                block_comment = ["a", "b"]
3044                "#,
3045            )
3046            .unwrap();
3047            assert_matches!(config.block_comment, Some(BlockCommentConfig { .. }));
3048
3049            let config = config.block_comment.unwrap();
3050            assert_eq!(config.start.as_ref(), "a");
3051            assert_eq!(config.end.as_ref(), "b");
3052            assert_eq!(config.prefix.as_ref(), "");
3053            assert_eq!(config.tab_size, 0);
3054        }
3055    }
3056}