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 outline;
  15pub mod proto;
  16mod syntax_map;
  17mod task_context;
  18mod toolchain;
  19
  20#[cfg(test)]
  21pub mod buffer_tests;
  22pub mod markdown;
  23
  24use crate::language_settings::SoftWrap;
  25use anyhow::{anyhow, Context, Result};
  26use async_trait::async_trait;
  27use collections::{HashMap, HashSet};
  28use futures::Future;
  29use gpui::{AppContext, AsyncAppContext, Model, SharedString, Task};
  30pub use highlight_map::HighlightMap;
  31use http_client::HttpClient;
  32pub use language_registry::{LanguageName, LoadedLanguage};
  33use lsp::{
  34    CodeActionKind, InitializeParams, LanguageServerBinary, LanguageServerBinaryOptions,
  35    LanguageServerName,
  36};
  37use parking_lot::Mutex;
  38use regex::Regex;
  39use schemars::{
  40    gen::SchemaGenerator,
  41    schema::{InstanceType, Schema, SchemaObject},
  42    JsonSchema,
  43};
  44use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
  45use serde_json::Value;
  46use settings::WorktreeId;
  47use smol::future::FutureExt as _;
  48use std::num::NonZeroU32;
  49use std::{
  50    any::Any,
  51    ffi::OsStr,
  52    fmt::Debug,
  53    hash::Hash,
  54    mem,
  55    ops::{DerefMut, Range},
  56    path::{Path, PathBuf},
  57    pin::Pin,
  58    str,
  59    sync::{
  60        atomic::{AtomicU64, AtomicUsize, Ordering::SeqCst},
  61        Arc, LazyLock,
  62    },
  63};
  64use syntax_map::{QueryCursorHandle, SyntaxSnapshot};
  65use task::RunnableTag;
  66pub use task_context::{ContextProvider, RunnableRange};
  67use theme::SyntaxTheme;
  68pub use toolchain::{LanguageToolchainStore, Toolchain, ToolchainList, ToolchainLister};
  69use tree_sitter::{self, wasmtime, Query, QueryCursor, WasmStore};
  70use util::serde::default_true;
  71
  72pub use buffer::Operation;
  73pub use buffer::*;
  74pub use diagnostic_set::DiagnosticEntry;
  75pub use language_registry::{
  76    AvailableLanguage, LanguageNotFound, LanguageQueries, LanguageRegistry,
  77    LanguageServerBinaryStatus, QUERY_FILENAME_PREFIXES,
  78};
  79pub use lsp::LanguageServerId;
  80pub use outline::*;
  81pub use syntax_map::{OwnedSyntaxLayer, SyntaxLayer};
  82pub use text::{AnchorRangeExt, LineEnding};
  83pub use tree_sitter::{Node, Parser, Tree, TreeCursor};
  84
  85/// Initializes the `language` crate.
  86///
  87/// This should be called before making use of items from the create.
  88pub fn init(cx: &mut AppContext) {
  89    language_settings::init(cx);
  90}
  91
  92static QUERY_CURSORS: Mutex<Vec<QueryCursor>> = Mutex::new(vec![]);
  93static PARSERS: Mutex<Vec<Parser>> = Mutex::new(vec![]);
  94
  95pub fn with_parser<F, R>(func: F) -> R
  96where
  97    F: FnOnce(&mut Parser) -> R,
  98{
  99    let mut parser = PARSERS.lock().pop().unwrap_or_else(|| {
 100        let mut parser = Parser::new();
 101        parser
 102            .set_wasm_store(WasmStore::new(&WASM_ENGINE).unwrap())
 103            .unwrap();
 104        parser
 105    });
 106    parser.set_included_ranges(&[]).unwrap();
 107    let result = func(&mut parser);
 108    PARSERS.lock().push(parser);
 109    result
 110}
 111
 112pub fn with_query_cursor<F, R>(func: F) -> R
 113where
 114    F: FnOnce(&mut QueryCursor) -> R,
 115{
 116    let mut cursor = QueryCursorHandle::new();
 117    func(cursor.deref_mut())
 118}
 119
 120static NEXT_LANGUAGE_ID: LazyLock<AtomicUsize> = LazyLock::new(Default::default);
 121static NEXT_GRAMMAR_ID: LazyLock<AtomicUsize> = LazyLock::new(Default::default);
 122static WASM_ENGINE: LazyLock<wasmtime::Engine> = LazyLock::new(|| {
 123    wasmtime::Engine::new(&wasmtime::Config::new()).expect("Failed to create Wasmtime engine")
 124});
 125
 126/// A shared grammar for plain text, exposed for reuse by downstream crates.
 127pub static PLAIN_TEXT: LazyLock<Arc<Language>> = LazyLock::new(|| {
 128    Arc::new(Language::new(
 129        LanguageConfig {
 130            name: "Plain Text".into(),
 131            soft_wrap: Some(SoftWrap::EditorWidth),
 132            ..Default::default()
 133        },
 134        None,
 135    ))
 136});
 137
 138/// Types that represent a position in a buffer, and can be converted into
 139/// an LSP position, to send to a language server.
 140pub trait ToLspPosition {
 141    /// Converts the value into an LSP position.
 142    fn to_lsp_position(self) -> lsp::Position;
 143}
 144
 145#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 146pub struct Location {
 147    pub buffer: Model<Buffer>,
 148    pub range: Range<Anchor>,
 149}
 150
 151/// Represents a Language Server, with certain cached sync properties.
 152/// Uses [`LspAdapter`] under the hood, but calls all 'static' methods
 153/// once at startup, and caches the results.
 154pub struct CachedLspAdapter {
 155    pub name: LanguageServerName,
 156    pub disk_based_diagnostic_sources: Vec<String>,
 157    pub disk_based_diagnostics_progress_token: Option<String>,
 158    language_ids: HashMap<String, String>,
 159    pub adapter: Arc<dyn LspAdapter>,
 160    pub reinstall_attempt_count: AtomicU64,
 161    cached_binary: futures::lock::Mutex<Option<LanguageServerBinary>>,
 162}
 163
 164impl Debug for CachedLspAdapter {
 165    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 166        f.debug_struct("CachedLspAdapter")
 167            .field("name", &self.name)
 168            .field(
 169                "disk_based_diagnostic_sources",
 170                &self.disk_based_diagnostic_sources,
 171            )
 172            .field(
 173                "disk_based_diagnostics_progress_token",
 174                &self.disk_based_diagnostics_progress_token,
 175            )
 176            .field("language_ids", &self.language_ids)
 177            .field("reinstall_attempt_count", &self.reinstall_attempt_count)
 178            .finish_non_exhaustive()
 179    }
 180}
 181
 182impl CachedLspAdapter {
 183    pub fn new(adapter: Arc<dyn LspAdapter>) -> Arc<Self> {
 184        let name = adapter.name();
 185        let disk_based_diagnostic_sources = adapter.disk_based_diagnostic_sources();
 186        let disk_based_diagnostics_progress_token = adapter.disk_based_diagnostics_progress_token();
 187        let language_ids = adapter.language_ids();
 188
 189        Arc::new(CachedLspAdapter {
 190            name,
 191            disk_based_diagnostic_sources,
 192            disk_based_diagnostics_progress_token,
 193            language_ids,
 194            adapter,
 195            cached_binary: Default::default(),
 196            reinstall_attempt_count: AtomicU64::new(0),
 197        })
 198    }
 199
 200    pub fn name(&self) -> LanguageServerName {
 201        self.adapter.name().clone()
 202    }
 203
 204    pub async fn get_language_server_command(
 205        self: Arc<Self>,
 206        delegate: Arc<dyn LspAdapterDelegate>,
 207        toolchains: Arc<dyn LanguageToolchainStore>,
 208        binary_options: LanguageServerBinaryOptions,
 209        cx: &mut AsyncAppContext,
 210    ) -> Result<LanguageServerBinary> {
 211        let cached_binary = self.cached_binary.lock().await;
 212        self.adapter
 213            .clone()
 214            .get_language_server_command(delegate, toolchains, binary_options, cached_binary, cx)
 215            .await
 216    }
 217
 218    pub fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
 219        self.adapter.code_action_kinds()
 220    }
 221
 222    pub fn process_diagnostics(&self, params: &mut lsp::PublishDiagnosticsParams) {
 223        self.adapter.process_diagnostics(params)
 224    }
 225
 226    pub async fn process_completions(&self, completion_items: &mut [lsp::CompletionItem]) {
 227        self.adapter.process_completions(completion_items).await
 228    }
 229
 230    pub async fn labels_for_completions(
 231        &self,
 232        completion_items: &[lsp::CompletionItem],
 233        language: &Arc<Language>,
 234    ) -> Result<Vec<Option<CodeLabel>>> {
 235        self.adapter
 236            .clone()
 237            .labels_for_completions(completion_items, language)
 238            .await
 239    }
 240
 241    pub async fn labels_for_symbols(
 242        &self,
 243        symbols: &[(String, lsp::SymbolKind)],
 244        language: &Arc<Language>,
 245    ) -> Result<Vec<Option<CodeLabel>>> {
 246        self.adapter
 247            .clone()
 248            .labels_for_symbols(symbols, language)
 249            .await
 250    }
 251
 252    pub fn language_id(&self, language_name: &LanguageName) -> String {
 253        self.language_ids
 254            .get(language_name.0.as_ref())
 255            .cloned()
 256            .unwrap_or_else(|| language_name.lsp_id())
 257    }
 258}
 259
 260/// [`LspAdapterDelegate`] allows [`LspAdapter]` implementations to interface with the application
 261// e.g. to display a notification or fetch data from the web.
 262#[async_trait]
 263pub trait LspAdapterDelegate: Send + Sync {
 264    fn show_notification(&self, message: &str, cx: &mut AppContext);
 265    fn http_client(&self) -> Arc<dyn HttpClient>;
 266    fn worktree_id(&self) -> WorktreeId;
 267    fn worktree_root_path(&self) -> &Path;
 268    fn update_status(&self, language: LanguageServerName, status: LanguageServerBinaryStatus);
 269    async fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>>;
 270
 271    async fn npm_package_installed_version(
 272        &self,
 273        package_name: &str,
 274    ) -> Result<Option<(PathBuf, String)>>;
 275    async fn which(&self, command: &OsStr) -> Option<PathBuf>;
 276    async fn shell_env(&self) -> HashMap<String, String>;
 277    async fn read_text_file(&self, path: PathBuf) -> Result<String>;
 278    async fn try_exec(&self, binary: LanguageServerBinary) -> Result<()>;
 279}
 280
 281#[async_trait(?Send)]
 282pub trait LspAdapter: 'static + Send + Sync {
 283    fn name(&self) -> LanguageServerName;
 284
 285    fn get_language_server_command<'a>(
 286        self: Arc<Self>,
 287        delegate: Arc<dyn LspAdapterDelegate>,
 288        toolchains: Arc<dyn LanguageToolchainStore>,
 289        binary_options: LanguageServerBinaryOptions,
 290        mut cached_binary: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
 291        cx: &'a mut AsyncAppContext,
 292    ) -> Pin<Box<dyn 'a + Future<Output = Result<LanguageServerBinary>>>> {
 293        async move {
 294            // First we check whether the adapter can give us a user-installed binary.
 295            // If so, we do *not* want to cache that, because each worktree might give us a different
 296            // binary:
 297            //
 298            //      worktree 1: user-installed at `.bin/gopls`
 299            //      worktree 2: user-installed at `~/bin/gopls`
 300            //      worktree 3: no gopls found in PATH -> fallback to Zed installation
 301            //
 302            // We only want to cache when we fall back to the global one,
 303            // because we don't want to download and overwrite our global one
 304            // for each worktree we might have open.
 305            if binary_options.allow_path_lookup {
 306                if let Some(binary) = self.check_if_user_installed(delegate.as_ref(), toolchains, cx).await {
 307                    log::info!(
 308                        "found user-installed language server for {}. path: {:?}, arguments: {:?}",
 309                        self.name().0,
 310                        binary.path,
 311                        binary.arguments
 312                    );
 313                    return Ok(binary);
 314                }
 315            }
 316
 317            if !binary_options.allow_binary_download {
 318                return Err(anyhow!("downloading language servers disabled"));
 319            }
 320
 321            if let Some(cached_binary) = cached_binary.as_ref() {
 322                return Ok(cached_binary.clone());
 323            }
 324
 325            let Some(container_dir) = delegate.language_server_download_dir(&self.name()).await else {
 326                anyhow::bail!("no language server download dir defined")
 327            };
 328
 329            let mut binary = try_fetch_server_binary(self.as_ref(), &delegate, container_dir.to_path_buf(), cx).await;
 330
 331            if let Err(error) = binary.as_ref() {
 332                if let Some(prev_downloaded_binary) = self
 333                    .cached_server_binary(container_dir.to_path_buf(), delegate.as_ref())
 334                    .await
 335                {
 336                    log::info!(
 337                        "failed to fetch newest version of language server {:?}. error: {:?}, falling back to using {:?}",
 338                        self.name(),
 339                        error,
 340                        prev_downloaded_binary.path
 341                    );
 342                    binary = Ok(prev_downloaded_binary);
 343                } else {
 344                    delegate.update_status(
 345                        self.name(),
 346                        LanguageServerBinaryStatus::Failed {
 347                            error: format!("{error:?}"),
 348                        },
 349                    );
 350                }
 351            }
 352
 353            if let Ok(binary) = &binary {
 354                *cached_binary = Some(binary.clone());
 355            }
 356
 357            binary
 358        }
 359        .boxed_local()
 360    }
 361
 362    async fn check_if_user_installed(
 363        &self,
 364        _: &dyn LspAdapterDelegate,
 365        _: Arc<dyn LanguageToolchainStore>,
 366        _: &AsyncAppContext,
 367    ) -> Option<LanguageServerBinary> {
 368        None
 369    }
 370
 371    async fn fetch_latest_server_version(
 372        &self,
 373        delegate: &dyn LspAdapterDelegate,
 374    ) -> Result<Box<dyn 'static + Send + Any>>;
 375
 376    fn will_fetch_server(
 377        &self,
 378        _: &Arc<dyn LspAdapterDelegate>,
 379        _: &mut AsyncAppContext,
 380    ) -> Option<Task<Result<()>>> {
 381        None
 382    }
 383
 384    async fn fetch_server_binary(
 385        &self,
 386        latest_version: Box<dyn 'static + Send + Any>,
 387        container_dir: PathBuf,
 388        delegate: &dyn LspAdapterDelegate,
 389    ) -> Result<LanguageServerBinary>;
 390
 391    async fn cached_server_binary(
 392        &self,
 393        container_dir: PathBuf,
 394        delegate: &dyn LspAdapterDelegate,
 395    ) -> Option<LanguageServerBinary>;
 396
 397    fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
 398
 399    /// Post-processes completions provided by the language server.
 400    async fn process_completions(&self, _: &mut [lsp::CompletionItem]) {}
 401
 402    async fn labels_for_completions(
 403        self: Arc<Self>,
 404        completions: &[lsp::CompletionItem],
 405        language: &Arc<Language>,
 406    ) -> Result<Vec<Option<CodeLabel>>> {
 407        let mut labels = Vec::new();
 408        for (ix, completion) in completions.iter().enumerate() {
 409            let label = self.label_for_completion(completion, language).await;
 410            if let Some(label) = label {
 411                labels.resize(ix + 1, None);
 412                *labels.last_mut().unwrap() = Some(label);
 413            }
 414        }
 415        Ok(labels)
 416    }
 417
 418    async fn label_for_completion(
 419        &self,
 420        _: &lsp::CompletionItem,
 421        _: &Arc<Language>,
 422    ) -> Option<CodeLabel> {
 423        None
 424    }
 425
 426    async fn labels_for_symbols(
 427        self: Arc<Self>,
 428        symbols: &[(String, lsp::SymbolKind)],
 429        language: &Arc<Language>,
 430    ) -> Result<Vec<Option<CodeLabel>>> {
 431        let mut labels = Vec::new();
 432        for (ix, (name, kind)) in symbols.iter().enumerate() {
 433            let label = self.label_for_symbol(name, *kind, language).await;
 434            if let Some(label) = label {
 435                labels.resize(ix + 1, None);
 436                *labels.last_mut().unwrap() = Some(label);
 437            }
 438        }
 439        Ok(labels)
 440    }
 441
 442    async fn label_for_symbol(
 443        &self,
 444        _: &str,
 445        _: lsp::SymbolKind,
 446        _: &Arc<Language>,
 447    ) -> Option<CodeLabel> {
 448        None
 449    }
 450
 451    /// Returns initialization options that are going to be sent to a LSP server as a part of [`lsp::InitializeParams`]
 452    async fn initialization_options(
 453        self: Arc<Self>,
 454        _: &Arc<dyn LspAdapterDelegate>,
 455    ) -> Result<Option<Value>> {
 456        Ok(None)
 457    }
 458
 459    async fn workspace_configuration(
 460        self: Arc<Self>,
 461        _: &Arc<dyn LspAdapterDelegate>,
 462        _: Arc<dyn LanguageToolchainStore>,
 463        _cx: &mut AsyncAppContext,
 464    ) -> Result<Value> {
 465        Ok(serde_json::json!({}))
 466    }
 467
 468    /// Returns a list of code actions supported by a given LspAdapter
 469    fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
 470        Some(vec![
 471            CodeActionKind::EMPTY,
 472            CodeActionKind::QUICKFIX,
 473            CodeActionKind::REFACTOR,
 474            CodeActionKind::REFACTOR_EXTRACT,
 475            CodeActionKind::SOURCE,
 476        ])
 477    }
 478
 479    fn disk_based_diagnostic_sources(&self) -> Vec<String> {
 480        Default::default()
 481    }
 482
 483    fn disk_based_diagnostics_progress_token(&self) -> Option<String> {
 484        None
 485    }
 486
 487    fn language_ids(&self) -> HashMap<String, String> {
 488        Default::default()
 489    }
 490
 491    /// Support custom initialize params.
 492    fn prepare_initialize_params(&self, original: InitializeParams) -> Result<InitializeParams> {
 493        Ok(original)
 494    }
 495}
 496
 497async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>(
 498    adapter: &L,
 499    delegate: &Arc<dyn LspAdapterDelegate>,
 500    container_dir: PathBuf,
 501    cx: &mut AsyncAppContext,
 502) -> Result<LanguageServerBinary> {
 503    if let Some(task) = adapter.will_fetch_server(delegate, cx) {
 504        task.await?;
 505    }
 506
 507    let name = adapter.name();
 508    log::info!("fetching latest version of language server {:?}", name.0);
 509    delegate.update_status(name.clone(), LanguageServerBinaryStatus::CheckingForUpdate);
 510
 511    let latest_version = adapter
 512        .fetch_latest_server_version(delegate.as_ref())
 513        .await?;
 514
 515    log::info!("downloading language server {:?}", name.0);
 516    delegate.update_status(adapter.name(), LanguageServerBinaryStatus::Downloading);
 517    let binary = adapter
 518        .fetch_server_binary(latest_version, container_dir, delegate.as_ref())
 519        .await;
 520
 521    delegate.update_status(name.clone(), LanguageServerBinaryStatus::None);
 522    binary
 523}
 524
 525#[derive(Clone, Debug, Default, PartialEq, Eq)]
 526pub struct CodeLabel {
 527    /// The text to display.
 528    pub text: String,
 529    /// Syntax highlighting runs.
 530    pub runs: Vec<(Range<usize>, HighlightId)>,
 531    /// The portion of the text that should be used in fuzzy filtering.
 532    pub filter_range: Range<usize>,
 533}
 534
 535#[derive(Clone, Deserialize, JsonSchema)]
 536pub struct LanguageConfig {
 537    /// Human-readable name of the language.
 538    pub name: LanguageName,
 539    /// The name of this language for a Markdown code fence block
 540    pub code_fence_block_name: Option<Arc<str>>,
 541    // The name of the grammar in a WASM bundle (experimental).
 542    pub grammar: Option<Arc<str>>,
 543    /// The criteria for matching this language to a given file.
 544    #[serde(flatten)]
 545    pub matcher: LanguageMatcher,
 546    /// List of bracket types in a language.
 547    #[serde(default)]
 548    #[schemars(schema_with = "bracket_pair_config_json_schema")]
 549    pub brackets: BracketPairConfig,
 550    /// If set to true, auto indentation uses last non empty line to determine
 551    /// the indentation level for a new line.
 552    #[serde(default = "auto_indent_using_last_non_empty_line_default")]
 553    pub auto_indent_using_last_non_empty_line: bool,
 554    // Whether indentation of pasted content should be adjusted based on the context.
 555    #[serde(default)]
 556    pub auto_indent_on_paste: Option<bool>,
 557    /// A regex that is used to determine whether the indentation level should be
 558    /// increased in the following line.
 559    #[serde(default, deserialize_with = "deserialize_regex")]
 560    #[schemars(schema_with = "regex_json_schema")]
 561    pub increase_indent_pattern: Option<Regex>,
 562    /// A regex that is used to determine whether the indentation level should be
 563    /// decreased in the following line.
 564    #[serde(default, deserialize_with = "deserialize_regex")]
 565    #[schemars(schema_with = "regex_json_schema")]
 566    pub decrease_indent_pattern: Option<Regex>,
 567    /// A list of characters that trigger the automatic insertion of a closing
 568    /// bracket when they immediately precede the point where an opening
 569    /// bracket is inserted.
 570    #[serde(default)]
 571    pub autoclose_before: String,
 572    /// A placeholder used internally by Semantic Index.
 573    #[serde(default)]
 574    pub collapsed_placeholder: String,
 575    /// A line comment string that is inserted in e.g. `toggle comments` action.
 576    /// A language can have multiple flavours of line comments. All of the provided line comments are
 577    /// used for comment continuations on the next line, but only the first one is used for Editor::ToggleComments.
 578    #[serde(default)]
 579    pub line_comments: Vec<Arc<str>>,
 580    /// Starting and closing characters of a block comment.
 581    #[serde(default)]
 582    pub block_comment: Option<(Arc<str>, Arc<str>)>,
 583    /// A list of language servers that are allowed to run on subranges of a given language.
 584    #[serde(default)]
 585    pub scope_opt_in_language_servers: Vec<LanguageServerName>,
 586    #[serde(default)]
 587    pub overrides: HashMap<String, LanguageConfigOverride>,
 588    /// A list of characters that Zed should treat as word characters for the
 589    /// purpose of features that operate on word boundaries, like 'move to next word end'
 590    /// or a whole-word search in buffer search.
 591    #[serde(default)]
 592    pub word_characters: HashSet<char>,
 593    /// Whether to indent lines using tab characters, as opposed to multiple
 594    /// spaces.
 595    #[serde(default)]
 596    pub hard_tabs: Option<bool>,
 597    /// How many columns a tab should occupy.
 598    #[serde(default)]
 599    pub tab_size: Option<NonZeroU32>,
 600    /// How to soft-wrap long lines of text.
 601    #[serde(default)]
 602    pub soft_wrap: Option<SoftWrap>,
 603    /// The name of a Prettier parser that will be used for this language when no file path is available.
 604    /// If there's a parser name in the language settings, that will be used instead.
 605    #[serde(default)]
 606    pub prettier_parser_name: Option<String>,
 607    /// If true, this language is only for syntax highlighting via an injection into other
 608    /// languages, but should not appear to the user as a distinct language.
 609    #[serde(default)]
 610    pub hidden: bool,
 611}
 612
 613#[derive(Clone, Debug, Serialize, Deserialize, Default, JsonSchema)]
 614pub struct LanguageMatcher {
 615    /// 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`.
 616    #[serde(default)]
 617    pub path_suffixes: Vec<String>,
 618    /// A regex pattern that determines whether the language should be assigned to a file or not.
 619    #[serde(
 620        default,
 621        serialize_with = "serialize_regex",
 622        deserialize_with = "deserialize_regex"
 623    )]
 624    #[schemars(schema_with = "regex_json_schema")]
 625    pub first_line_pattern: Option<Regex>,
 626}
 627
 628/// Represents a language for the given range. Some languages (e.g. HTML)
 629/// interleave several languages together, thus a single buffer might actually contain
 630/// several nested scopes.
 631#[derive(Clone, Debug)]
 632pub struct LanguageScope {
 633    language: Arc<Language>,
 634    override_id: Option<u32>,
 635}
 636
 637#[derive(Clone, Deserialize, Default, Debug, JsonSchema)]
 638pub struct LanguageConfigOverride {
 639    #[serde(default)]
 640    pub line_comments: Override<Vec<Arc<str>>>,
 641    #[serde(default)]
 642    pub block_comment: Override<(Arc<str>, Arc<str>)>,
 643    #[serde(skip_deserializing)]
 644    #[schemars(skip)]
 645    pub disabled_bracket_ixs: Vec<u16>,
 646    #[serde(default)]
 647    pub word_characters: Override<HashSet<char>>,
 648    #[serde(default)]
 649    pub opt_into_language_servers: Vec<LanguageServerName>,
 650}
 651
 652#[derive(Clone, Deserialize, Debug, Serialize, JsonSchema)]
 653#[serde(untagged)]
 654pub enum Override<T> {
 655    Remove { remove: bool },
 656    Set(T),
 657}
 658
 659impl<T> Default for Override<T> {
 660    fn default() -> Self {
 661        Override::Remove { remove: false }
 662    }
 663}
 664
 665impl<T> Override<T> {
 666    fn as_option<'a>(this: Option<&'a Self>, original: Option<&'a T>) -> Option<&'a T> {
 667        match this {
 668            Some(Self::Set(value)) => Some(value),
 669            Some(Self::Remove { remove: true }) => None,
 670            Some(Self::Remove { remove: false }) | None => original,
 671        }
 672    }
 673}
 674
 675impl Default for LanguageConfig {
 676    fn default() -> Self {
 677        Self {
 678            name: LanguageName::new(""),
 679            code_fence_block_name: None,
 680            grammar: None,
 681            matcher: LanguageMatcher::default(),
 682            brackets: Default::default(),
 683            auto_indent_using_last_non_empty_line: auto_indent_using_last_non_empty_line_default(),
 684            auto_indent_on_paste: None,
 685            increase_indent_pattern: Default::default(),
 686            decrease_indent_pattern: Default::default(),
 687            autoclose_before: Default::default(),
 688            line_comments: Default::default(),
 689            block_comment: Default::default(),
 690            scope_opt_in_language_servers: Default::default(),
 691            overrides: Default::default(),
 692            word_characters: Default::default(),
 693            collapsed_placeholder: Default::default(),
 694            hard_tabs: None,
 695            tab_size: None,
 696            soft_wrap: None,
 697            prettier_parser_name: None,
 698            hidden: false,
 699        }
 700    }
 701}
 702
 703fn auto_indent_using_last_non_empty_line_default() -> bool {
 704    true
 705}
 706
 707fn deserialize_regex<'de, D: Deserializer<'de>>(d: D) -> Result<Option<Regex>, D::Error> {
 708    let source = Option::<String>::deserialize(d)?;
 709    if let Some(source) = source {
 710        Ok(Some(regex::Regex::new(&source).map_err(de::Error::custom)?))
 711    } else {
 712        Ok(None)
 713    }
 714}
 715
 716fn regex_json_schema(_: &mut SchemaGenerator) -> Schema {
 717    Schema::Object(SchemaObject {
 718        instance_type: Some(InstanceType::String.into()),
 719        ..Default::default()
 720    })
 721}
 722
 723fn serialize_regex<S>(regex: &Option<Regex>, serializer: S) -> Result<S::Ok, S::Error>
 724where
 725    S: Serializer,
 726{
 727    match regex {
 728        Some(regex) => serializer.serialize_str(regex.as_str()),
 729        None => serializer.serialize_none(),
 730    }
 731}
 732
 733#[doc(hidden)]
 734#[cfg(any(test, feature = "test-support"))]
 735pub struct FakeLspAdapter {
 736    pub name: &'static str,
 737    pub initialization_options: Option<Value>,
 738    pub prettier_plugins: Vec<&'static str>,
 739    pub disk_based_diagnostics_progress_token: Option<String>,
 740    pub disk_based_diagnostics_sources: Vec<String>,
 741    pub language_server_binary: LanguageServerBinary,
 742
 743    pub capabilities: lsp::ServerCapabilities,
 744    pub initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,
 745}
 746
 747/// Configuration of handling bracket pairs for a given language.
 748///
 749/// This struct includes settings for defining which pairs of characters are considered brackets and
 750/// also specifies any language-specific scopes where these pairs should be ignored for bracket matching purposes.
 751#[derive(Clone, Debug, Default, JsonSchema)]
 752pub struct BracketPairConfig {
 753    /// A list of character pairs that should be treated as brackets in the context of a given language.
 754    pub pairs: Vec<BracketPair>,
 755    /// A list of tree-sitter scopes for which a given bracket should not be active.
 756    /// N-th entry in `[Self::disabled_scopes_by_bracket_ix]` contains a list of disabled scopes for an n-th entry in `[Self::pairs]`
 757    #[schemars(skip)]
 758    pub disabled_scopes_by_bracket_ix: Vec<Vec<String>>,
 759}
 760
 761fn bracket_pair_config_json_schema(gen: &mut SchemaGenerator) -> Schema {
 762    Option::<Vec<BracketPairContent>>::json_schema(gen)
 763}
 764
 765#[derive(Deserialize, JsonSchema)]
 766pub struct BracketPairContent {
 767    #[serde(flatten)]
 768    pub bracket_pair: BracketPair,
 769    #[serde(default)]
 770    pub not_in: Vec<String>,
 771}
 772
 773impl<'de> Deserialize<'de> for BracketPairConfig {
 774    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
 775    where
 776        D: Deserializer<'de>,
 777    {
 778        let result = Vec::<BracketPairContent>::deserialize(deserializer)?;
 779        let mut brackets = Vec::with_capacity(result.len());
 780        let mut disabled_scopes_by_bracket_ix = Vec::with_capacity(result.len());
 781        for entry in result {
 782            brackets.push(entry.bracket_pair);
 783            disabled_scopes_by_bracket_ix.push(entry.not_in);
 784        }
 785
 786        Ok(BracketPairConfig {
 787            pairs: brackets,
 788            disabled_scopes_by_bracket_ix,
 789        })
 790    }
 791}
 792
 793/// Describes a single bracket pair and how an editor should react to e.g. inserting
 794/// an opening bracket or to a newline character insertion in between `start` and `end` characters.
 795#[derive(Clone, Debug, Default, Deserialize, PartialEq, JsonSchema)]
 796pub struct BracketPair {
 797    /// Starting substring for a bracket.
 798    pub start: String,
 799    /// Ending substring for a bracket.
 800    pub end: String,
 801    /// True if `end` should be automatically inserted right after `start` characters.
 802    pub close: bool,
 803    /// True if selected text should be surrounded by `start` and `end` characters.
 804    #[serde(default = "default_true")]
 805    pub surround: bool,
 806    /// True if an extra newline should be inserted while the cursor is in the middle
 807    /// of that bracket pair.
 808    pub newline: bool,
 809}
 810
 811#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
 812pub(crate) struct LanguageId(usize);
 813
 814impl LanguageId {
 815    pub(crate) fn new() -> Self {
 816        Self(NEXT_LANGUAGE_ID.fetch_add(1, SeqCst))
 817    }
 818}
 819
 820pub struct Language {
 821    pub(crate) id: LanguageId,
 822    pub(crate) config: LanguageConfig,
 823    pub(crate) grammar: Option<Arc<Grammar>>,
 824    pub(crate) context_provider: Option<Arc<dyn ContextProvider>>,
 825    pub(crate) toolchain: Option<Arc<dyn ToolchainLister>>,
 826}
 827
 828#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
 829pub struct GrammarId(pub usize);
 830
 831impl GrammarId {
 832    pub(crate) fn new() -> Self {
 833        Self(NEXT_GRAMMAR_ID.fetch_add(1, SeqCst))
 834    }
 835}
 836
 837pub struct Grammar {
 838    id: GrammarId,
 839    pub ts_language: tree_sitter::Language,
 840    pub(crate) error_query: Query,
 841    pub(crate) highlights_query: Option<Query>,
 842    pub(crate) brackets_config: Option<BracketConfig>,
 843    pub(crate) redactions_config: Option<RedactionConfig>,
 844    pub(crate) runnable_config: Option<RunnableConfig>,
 845    pub(crate) indents_config: Option<IndentConfig>,
 846    pub outline_config: Option<OutlineConfig>,
 847    pub embedding_config: Option<EmbeddingConfig>,
 848    pub(crate) injection_config: Option<InjectionConfig>,
 849    pub(crate) override_config: Option<OverrideConfig>,
 850    pub(crate) highlight_map: Mutex<HighlightMap>,
 851}
 852
 853struct IndentConfig {
 854    query: Query,
 855    indent_capture_ix: u32,
 856    start_capture_ix: Option<u32>,
 857    end_capture_ix: Option<u32>,
 858    outdent_capture_ix: Option<u32>,
 859}
 860
 861pub struct OutlineConfig {
 862    pub query: Query,
 863    pub item_capture_ix: u32,
 864    pub name_capture_ix: u32,
 865    pub context_capture_ix: Option<u32>,
 866    pub extra_context_capture_ix: Option<u32>,
 867    pub open_capture_ix: Option<u32>,
 868    pub close_capture_ix: Option<u32>,
 869    pub annotation_capture_ix: Option<u32>,
 870}
 871
 872#[derive(Debug)]
 873pub struct EmbeddingConfig {
 874    pub query: Query,
 875    pub item_capture_ix: u32,
 876    pub name_capture_ix: Option<u32>,
 877    pub context_capture_ix: Option<u32>,
 878    pub collapse_capture_ix: Option<u32>,
 879    pub keep_capture_ix: Option<u32>,
 880}
 881
 882struct InjectionConfig {
 883    query: Query,
 884    content_capture_ix: u32,
 885    language_capture_ix: Option<u32>,
 886    patterns: Vec<InjectionPatternConfig>,
 887}
 888
 889struct RedactionConfig {
 890    pub query: Query,
 891    pub redaction_capture_ix: u32,
 892}
 893
 894#[derive(Clone, Debug, PartialEq)]
 895enum RunnableCapture {
 896    Named(SharedString),
 897    Run,
 898}
 899
 900struct RunnableConfig {
 901    pub query: Query,
 902    /// A mapping from capture indice to capture kind
 903    pub extra_captures: Vec<RunnableCapture>,
 904}
 905
 906struct OverrideConfig {
 907    query: Query,
 908    values: HashMap<u32, OverrideEntry>,
 909}
 910
 911#[derive(Debug)]
 912struct OverrideEntry {
 913    name: String,
 914    range_is_inclusive: bool,
 915    value: LanguageConfigOverride,
 916}
 917
 918#[derive(Default, Clone)]
 919struct InjectionPatternConfig {
 920    language: Option<Box<str>>,
 921    combined: bool,
 922}
 923
 924struct BracketConfig {
 925    query: Query,
 926    open_capture_ix: u32,
 927    close_capture_ix: u32,
 928}
 929
 930impl Language {
 931    pub fn new(config: LanguageConfig, ts_language: Option<tree_sitter::Language>) -> Self {
 932        Self::new_with_id(LanguageId::new(), config, ts_language)
 933    }
 934
 935    fn new_with_id(
 936        id: LanguageId,
 937        config: LanguageConfig,
 938        ts_language: Option<tree_sitter::Language>,
 939    ) -> Self {
 940        Self {
 941            id,
 942            config,
 943            grammar: ts_language.map(|ts_language| {
 944                Arc::new(Grammar {
 945                    id: GrammarId::new(),
 946                    highlights_query: None,
 947                    brackets_config: None,
 948                    outline_config: None,
 949                    embedding_config: None,
 950                    indents_config: None,
 951                    injection_config: None,
 952                    override_config: None,
 953                    redactions_config: None,
 954                    runnable_config: None,
 955                    error_query: Query::new(&ts_language, "(ERROR) @error").unwrap(),
 956                    ts_language,
 957                    highlight_map: Default::default(),
 958                })
 959            }),
 960            context_provider: None,
 961            toolchain: None,
 962        }
 963    }
 964
 965    pub fn with_context_provider(mut self, provider: Option<Arc<dyn ContextProvider>>) -> Self {
 966        self.context_provider = provider;
 967        self
 968    }
 969
 970    pub fn with_toolchain_lister(mut self, provider: Option<Arc<dyn ToolchainLister>>) -> Self {
 971        self.toolchain = provider;
 972        self
 973    }
 974
 975    pub fn with_queries(mut self, queries: LanguageQueries) -> Result<Self> {
 976        if let Some(query) = queries.highlights {
 977            self = self
 978                .with_highlights_query(query.as_ref())
 979                .context("Error loading highlights query")?;
 980        }
 981        if let Some(query) = queries.brackets {
 982            self = self
 983                .with_brackets_query(query.as_ref())
 984                .context("Error loading brackets query")?;
 985        }
 986        if let Some(query) = queries.indents {
 987            self = self
 988                .with_indents_query(query.as_ref())
 989                .context("Error loading indents query")?;
 990        }
 991        if let Some(query) = queries.outline {
 992            self = self
 993                .with_outline_query(query.as_ref())
 994                .context("Error loading outline query")?;
 995        }
 996        if let Some(query) = queries.embedding {
 997            self = self
 998                .with_embedding_query(query.as_ref())
 999                .context("Error loading embedding query")?;
1000        }
1001        if let Some(query) = queries.injections {
1002            self = self
1003                .with_injection_query(query.as_ref())
1004                .context("Error loading injection query")?;
1005        }
1006        if let Some(query) = queries.overrides {
1007            self = self
1008                .with_override_query(query.as_ref())
1009                .context("Error loading override query")?;
1010        }
1011        if let Some(query) = queries.redactions {
1012            self = self
1013                .with_redaction_query(query.as_ref())
1014                .context("Error loading redaction query")?;
1015        }
1016        if let Some(query) = queries.runnables {
1017            self = self
1018                .with_runnable_query(query.as_ref())
1019                .context("Error loading tests query")?;
1020        }
1021        Ok(self)
1022    }
1023
1024    pub fn with_highlights_query(mut self, source: &str) -> Result<Self> {
1025        let grammar = self
1026            .grammar_mut()
1027            .ok_or_else(|| anyhow!("cannot mutate grammar"))?;
1028        grammar.highlights_query = Some(Query::new(&grammar.ts_language, source)?);
1029        Ok(self)
1030    }
1031
1032    pub fn with_runnable_query(mut self, source: &str) -> Result<Self> {
1033        let grammar = self
1034            .grammar_mut()
1035            .ok_or_else(|| anyhow!("cannot mutate grammar"))?;
1036
1037        let query = Query::new(&grammar.ts_language, source)?;
1038        let mut extra_captures = Vec::with_capacity(query.capture_names().len());
1039
1040        for name in query.capture_names().iter() {
1041            let kind = if *name == "run" {
1042                RunnableCapture::Run
1043            } else {
1044                RunnableCapture::Named(name.to_string().into())
1045            };
1046            extra_captures.push(kind);
1047        }
1048
1049        grammar.runnable_config = Some(RunnableConfig {
1050            extra_captures,
1051            query,
1052        });
1053
1054        Ok(self)
1055    }
1056
1057    pub fn with_outline_query(mut self, source: &str) -> Result<Self> {
1058        let grammar = self
1059            .grammar_mut()
1060            .ok_or_else(|| anyhow!("cannot mutate grammar"))?;
1061        let query = Query::new(&grammar.ts_language, source)?;
1062        let mut item_capture_ix = None;
1063        let mut name_capture_ix = None;
1064        let mut context_capture_ix = None;
1065        let mut extra_context_capture_ix = None;
1066        let mut open_capture_ix = None;
1067        let mut close_capture_ix = None;
1068        let mut annotation_capture_ix = None;
1069        get_capture_indices(
1070            &query,
1071            &mut [
1072                ("item", &mut item_capture_ix),
1073                ("name", &mut name_capture_ix),
1074                ("context", &mut context_capture_ix),
1075                ("context.extra", &mut extra_context_capture_ix),
1076                ("open", &mut open_capture_ix),
1077                ("close", &mut close_capture_ix),
1078                ("annotation", &mut annotation_capture_ix),
1079            ],
1080        );
1081        if let Some((item_capture_ix, name_capture_ix)) = item_capture_ix.zip(name_capture_ix) {
1082            grammar.outline_config = Some(OutlineConfig {
1083                query,
1084                item_capture_ix,
1085                name_capture_ix,
1086                context_capture_ix,
1087                extra_context_capture_ix,
1088                open_capture_ix,
1089                close_capture_ix,
1090                annotation_capture_ix,
1091            });
1092        }
1093        Ok(self)
1094    }
1095
1096    pub fn with_embedding_query(mut self, source: &str) -> Result<Self> {
1097        let grammar = self
1098            .grammar_mut()
1099            .ok_or_else(|| anyhow!("cannot mutate grammar"))?;
1100        let query = Query::new(&grammar.ts_language, source)?;
1101        let mut item_capture_ix = None;
1102        let mut name_capture_ix = None;
1103        let mut context_capture_ix = None;
1104        let mut collapse_capture_ix = None;
1105        let mut keep_capture_ix = None;
1106        get_capture_indices(
1107            &query,
1108            &mut [
1109                ("item", &mut item_capture_ix),
1110                ("name", &mut name_capture_ix),
1111                ("context", &mut context_capture_ix),
1112                ("keep", &mut keep_capture_ix),
1113                ("collapse", &mut collapse_capture_ix),
1114            ],
1115        );
1116        if let Some(item_capture_ix) = item_capture_ix {
1117            grammar.embedding_config = Some(EmbeddingConfig {
1118                query,
1119                item_capture_ix,
1120                name_capture_ix,
1121                context_capture_ix,
1122                collapse_capture_ix,
1123                keep_capture_ix,
1124            });
1125        }
1126        Ok(self)
1127    }
1128
1129    pub fn with_brackets_query(mut self, source: &str) -> Result<Self> {
1130        let grammar = self
1131            .grammar_mut()
1132            .ok_or_else(|| anyhow!("cannot mutate grammar"))?;
1133        let query = Query::new(&grammar.ts_language, source)?;
1134        let mut open_capture_ix = None;
1135        let mut close_capture_ix = None;
1136        get_capture_indices(
1137            &query,
1138            &mut [
1139                ("open", &mut open_capture_ix),
1140                ("close", &mut close_capture_ix),
1141            ],
1142        );
1143        if let Some((open_capture_ix, close_capture_ix)) = open_capture_ix.zip(close_capture_ix) {
1144            grammar.brackets_config = Some(BracketConfig {
1145                query,
1146                open_capture_ix,
1147                close_capture_ix,
1148            });
1149        }
1150        Ok(self)
1151    }
1152
1153    pub fn with_indents_query(mut self, source: &str) -> Result<Self> {
1154        let grammar = self
1155            .grammar_mut()
1156            .ok_or_else(|| anyhow!("cannot mutate grammar"))?;
1157        let query = Query::new(&grammar.ts_language, source)?;
1158        let mut indent_capture_ix = None;
1159        let mut start_capture_ix = None;
1160        let mut end_capture_ix = None;
1161        let mut outdent_capture_ix = None;
1162        get_capture_indices(
1163            &query,
1164            &mut [
1165                ("indent", &mut indent_capture_ix),
1166                ("start", &mut start_capture_ix),
1167                ("end", &mut end_capture_ix),
1168                ("outdent", &mut outdent_capture_ix),
1169            ],
1170        );
1171        if let Some(indent_capture_ix) = indent_capture_ix {
1172            grammar.indents_config = Some(IndentConfig {
1173                query,
1174                indent_capture_ix,
1175                start_capture_ix,
1176                end_capture_ix,
1177                outdent_capture_ix,
1178            });
1179        }
1180        Ok(self)
1181    }
1182
1183    pub fn with_injection_query(mut self, source: &str) -> Result<Self> {
1184        let grammar = self
1185            .grammar_mut()
1186            .ok_or_else(|| anyhow!("cannot mutate grammar"))?;
1187        let query = Query::new(&grammar.ts_language, source)?;
1188        let mut language_capture_ix = None;
1189        let mut content_capture_ix = None;
1190        get_capture_indices(
1191            &query,
1192            &mut [
1193                ("language", &mut language_capture_ix),
1194                ("content", &mut content_capture_ix),
1195            ],
1196        );
1197        let patterns = (0..query.pattern_count())
1198            .map(|ix| {
1199                let mut config = InjectionPatternConfig::default();
1200                for setting in query.property_settings(ix) {
1201                    match setting.key.as_ref() {
1202                        "language" => {
1203                            config.language.clone_from(&setting.value);
1204                        }
1205                        "combined" => {
1206                            config.combined = true;
1207                        }
1208                        _ => {}
1209                    }
1210                }
1211                config
1212            })
1213            .collect();
1214        if let Some(content_capture_ix) = content_capture_ix {
1215            grammar.injection_config = Some(InjectionConfig {
1216                query,
1217                language_capture_ix,
1218                content_capture_ix,
1219                patterns,
1220            });
1221        }
1222        Ok(self)
1223    }
1224
1225    pub fn with_override_query(mut self, source: &str) -> anyhow::Result<Self> {
1226        let query = {
1227            let grammar = self
1228                .grammar
1229                .as_ref()
1230                .ok_or_else(|| anyhow!("no grammar for language"))?;
1231            Query::new(&grammar.ts_language, source)?
1232        };
1233
1234        let mut override_configs_by_id = HashMap::default();
1235        for (ix, mut name) in query.capture_names().iter().copied().enumerate() {
1236            let mut range_is_inclusive = false;
1237            if name.starts_with('_') {
1238                continue;
1239            }
1240            if let Some(prefix) = name.strip_suffix(".inclusive") {
1241                name = prefix;
1242                range_is_inclusive = true;
1243            }
1244
1245            let value = self.config.overrides.get(name).cloned().unwrap_or_default();
1246            for server_name in &value.opt_into_language_servers {
1247                if !self
1248                    .config
1249                    .scope_opt_in_language_servers
1250                    .contains(server_name)
1251                {
1252                    util::debug_panic!("Server {server_name:?} has been opted-in by scope {name:?} but has not been marked as an opt-in server");
1253                }
1254            }
1255
1256            override_configs_by_id.insert(
1257                ix as u32,
1258                OverrideEntry {
1259                    name: name.to_string(),
1260                    range_is_inclusive,
1261                    value,
1262                },
1263            );
1264        }
1265
1266        let referenced_override_names = self.config.overrides.keys().chain(
1267            self.config
1268                .brackets
1269                .disabled_scopes_by_bracket_ix
1270                .iter()
1271                .flatten(),
1272        );
1273
1274        for referenced_name in referenced_override_names {
1275            if !override_configs_by_id
1276                .values()
1277                .any(|entry| entry.name == *referenced_name)
1278            {
1279                Err(anyhow!(
1280                    "language {:?} has overrides in config not in query: {referenced_name:?}",
1281                    self.config.name
1282                ))?;
1283            }
1284        }
1285
1286        for entry in override_configs_by_id.values_mut() {
1287            entry.value.disabled_bracket_ixs = self
1288                .config
1289                .brackets
1290                .disabled_scopes_by_bracket_ix
1291                .iter()
1292                .enumerate()
1293                .filter_map(|(ix, disabled_scope_names)| {
1294                    if disabled_scope_names.contains(&entry.name) {
1295                        Some(ix as u16)
1296                    } else {
1297                        None
1298                    }
1299                })
1300                .collect();
1301        }
1302
1303        self.config.brackets.disabled_scopes_by_bracket_ix.clear();
1304
1305        let grammar = self
1306            .grammar_mut()
1307            .ok_or_else(|| anyhow!("cannot mutate grammar"))?;
1308        grammar.override_config = Some(OverrideConfig {
1309            query,
1310            values: override_configs_by_id,
1311        });
1312        Ok(self)
1313    }
1314
1315    pub fn with_redaction_query(mut self, source: &str) -> anyhow::Result<Self> {
1316        let grammar = self
1317            .grammar_mut()
1318            .ok_or_else(|| anyhow!("cannot mutate grammar"))?;
1319
1320        let query = Query::new(&grammar.ts_language, source)?;
1321        let mut redaction_capture_ix = None;
1322        get_capture_indices(&query, &mut [("redact", &mut redaction_capture_ix)]);
1323
1324        if let Some(redaction_capture_ix) = redaction_capture_ix {
1325            grammar.redactions_config = Some(RedactionConfig {
1326                query,
1327                redaction_capture_ix,
1328            });
1329        }
1330
1331        Ok(self)
1332    }
1333
1334    fn grammar_mut(&mut self) -> Option<&mut Grammar> {
1335        Arc::get_mut(self.grammar.as_mut()?)
1336    }
1337
1338    pub fn name(&self) -> LanguageName {
1339        self.config.name.clone()
1340    }
1341
1342    pub fn code_fence_block_name(&self) -> Arc<str> {
1343        self.config
1344            .code_fence_block_name
1345            .clone()
1346            .unwrap_or_else(|| self.config.name.0.to_lowercase().into())
1347    }
1348
1349    pub fn context_provider(&self) -> Option<Arc<dyn ContextProvider>> {
1350        self.context_provider.clone()
1351    }
1352
1353    pub fn toolchain_lister(&self) -> Option<Arc<dyn ToolchainLister>> {
1354        self.toolchain.clone()
1355    }
1356
1357    pub fn highlight_text<'a>(
1358        self: &'a Arc<Self>,
1359        text: &'a Rope,
1360        range: Range<usize>,
1361    ) -> Vec<(Range<usize>, HighlightId)> {
1362        let mut result = Vec::new();
1363        if let Some(grammar) = &self.grammar {
1364            let tree = grammar.parse_text(text, None);
1365            let captures =
1366                SyntaxSnapshot::single_tree_captures(range.clone(), text, &tree, self, |grammar| {
1367                    grammar.highlights_query.as_ref()
1368                });
1369            let highlight_maps = vec![grammar.highlight_map()];
1370            let mut offset = 0;
1371            for chunk in
1372                BufferChunks::new(text, range, Some((captures, highlight_maps)), false, None)
1373            {
1374                let end_offset = offset + chunk.text.len();
1375                if let Some(highlight_id) = chunk.syntax_highlight_id {
1376                    if !highlight_id.is_default() {
1377                        result.push((offset..end_offset, highlight_id));
1378                    }
1379                }
1380                offset = end_offset;
1381            }
1382        }
1383        result
1384    }
1385
1386    pub fn path_suffixes(&self) -> &[String] {
1387        &self.config.matcher.path_suffixes
1388    }
1389
1390    pub fn should_autoclose_before(&self, c: char) -> bool {
1391        c.is_whitespace() || self.config.autoclose_before.contains(c)
1392    }
1393
1394    pub fn set_theme(&self, theme: &SyntaxTheme) {
1395        if let Some(grammar) = self.grammar.as_ref() {
1396            if let Some(highlights_query) = &grammar.highlights_query {
1397                *grammar.highlight_map.lock() =
1398                    HighlightMap::new(highlights_query.capture_names(), theme);
1399            }
1400        }
1401    }
1402
1403    pub fn grammar(&self) -> Option<&Arc<Grammar>> {
1404        self.grammar.as_ref()
1405    }
1406
1407    pub fn default_scope(self: &Arc<Self>) -> LanguageScope {
1408        LanguageScope {
1409            language: self.clone(),
1410            override_id: None,
1411        }
1412    }
1413
1414    pub fn lsp_id(&self) -> String {
1415        self.config.name.lsp_id()
1416    }
1417
1418    pub fn prettier_parser_name(&self) -> Option<&str> {
1419        self.config.prettier_parser_name.as_deref()
1420    }
1421}
1422
1423impl LanguageScope {
1424    pub fn path_suffixes(&self) -> &[String] {
1425        &self.language.path_suffixes()
1426    }
1427
1428    pub fn language_name(&self) -> LanguageName {
1429        self.language.config.name.clone()
1430    }
1431
1432    pub fn collapsed_placeholder(&self) -> &str {
1433        self.language.config.collapsed_placeholder.as_ref()
1434    }
1435
1436    /// Returns line prefix that is inserted in e.g. line continuations or
1437    /// in `toggle comments` action.
1438    pub fn line_comment_prefixes(&self) -> &[Arc<str>] {
1439        Override::as_option(
1440            self.config_override().map(|o| &o.line_comments),
1441            Some(&self.language.config.line_comments),
1442        )
1443        .map_or(&[] as &[_], |e| e.as_slice())
1444    }
1445
1446    pub fn block_comment_delimiters(&self) -> Option<(&Arc<str>, &Arc<str>)> {
1447        Override::as_option(
1448            self.config_override().map(|o| &o.block_comment),
1449            self.language.config.block_comment.as_ref(),
1450        )
1451        .map(|e| (&e.0, &e.1))
1452    }
1453
1454    /// Returns a list of language-specific word characters.
1455    ///
1456    /// By default, Zed treats alphanumeric characters (and '_') as word characters for
1457    /// the purpose of actions like 'move to next word end` or whole-word search.
1458    /// It additionally accounts for language's additional word characters.
1459    pub fn word_characters(&self) -> Option<&HashSet<char>> {
1460        Override::as_option(
1461            self.config_override().map(|o| &o.word_characters),
1462            Some(&self.language.config.word_characters),
1463        )
1464    }
1465
1466    /// Returns a list of bracket pairs for a given language with an additional
1467    /// piece of information about whether the particular bracket pair is currently active for a given language.
1468    pub fn brackets(&self) -> impl Iterator<Item = (&BracketPair, bool)> {
1469        let mut disabled_ids = self
1470            .config_override()
1471            .map_or(&[] as _, |o| o.disabled_bracket_ixs.as_slice());
1472        self.language
1473            .config
1474            .brackets
1475            .pairs
1476            .iter()
1477            .enumerate()
1478            .map(move |(ix, bracket)| {
1479                let mut is_enabled = true;
1480                if let Some(next_disabled_ix) = disabled_ids.first() {
1481                    if ix == *next_disabled_ix as usize {
1482                        disabled_ids = &disabled_ids[1..];
1483                        is_enabled = false;
1484                    }
1485                }
1486                (bracket, is_enabled)
1487            })
1488    }
1489
1490    pub fn should_autoclose_before(&self, c: char) -> bool {
1491        c.is_whitespace() || self.language.config.autoclose_before.contains(c)
1492    }
1493
1494    pub fn language_allowed(&self, name: &LanguageServerName) -> bool {
1495        let config = &self.language.config;
1496        let opt_in_servers = &config.scope_opt_in_language_servers;
1497        if opt_in_servers.iter().any(|o| *o == *name) {
1498            if let Some(over) = self.config_override() {
1499                over.opt_into_language_servers.iter().any(|o| *o == *name)
1500            } else {
1501                false
1502            }
1503        } else {
1504            true
1505        }
1506    }
1507
1508    pub fn override_name(&self) -> Option<&str> {
1509        let id = self.override_id?;
1510        let grammar = self.language.grammar.as_ref()?;
1511        let override_config = grammar.override_config.as_ref()?;
1512        override_config.values.get(&id).map(|e| e.name.as_str())
1513    }
1514
1515    fn config_override(&self) -> Option<&LanguageConfigOverride> {
1516        let id = self.override_id?;
1517        let grammar = self.language.grammar.as_ref()?;
1518        let override_config = grammar.override_config.as_ref()?;
1519        override_config.values.get(&id).map(|e| &e.value)
1520    }
1521}
1522
1523impl Hash for Language {
1524    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1525        self.id.hash(state)
1526    }
1527}
1528
1529impl PartialEq for Language {
1530    fn eq(&self, other: &Self) -> bool {
1531        self.id.eq(&other.id)
1532    }
1533}
1534
1535impl Eq for Language {}
1536
1537impl Debug for Language {
1538    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1539        f.debug_struct("Language")
1540            .field("name", &self.config.name)
1541            .finish()
1542    }
1543}
1544
1545impl Grammar {
1546    pub fn id(&self) -> GrammarId {
1547        self.id
1548    }
1549
1550    fn parse_text(&self, text: &Rope, old_tree: Option<Tree>) -> Tree {
1551        with_parser(|parser| {
1552            parser
1553                .set_language(&self.ts_language)
1554                .expect("incompatible grammar");
1555            let mut chunks = text.chunks_in_range(0..text.len());
1556            parser
1557                .parse_with(
1558                    &mut move |offset, _| {
1559                        chunks.seek(offset);
1560                        chunks.next().unwrap_or("").as_bytes()
1561                    },
1562                    old_tree.as_ref(),
1563                )
1564                .unwrap()
1565        })
1566    }
1567
1568    pub fn highlight_map(&self) -> HighlightMap {
1569        self.highlight_map.lock().clone()
1570    }
1571
1572    pub fn highlight_id_for_name(&self, name: &str) -> Option<HighlightId> {
1573        let capture_id = self
1574            .highlights_query
1575            .as_ref()?
1576            .capture_index_for_name(name)?;
1577        Some(self.highlight_map.lock().get(capture_id))
1578    }
1579}
1580
1581impl CodeLabel {
1582    pub fn plain(text: String, filter_text: Option<&str>) -> Self {
1583        let mut result = Self {
1584            runs: Vec::new(),
1585            filter_range: 0..text.len(),
1586            text,
1587        };
1588        if let Some(filter_text) = filter_text {
1589            if let Some(ix) = result.text.find(filter_text) {
1590                result.filter_range = ix..ix + filter_text.len();
1591            }
1592        }
1593        result
1594    }
1595
1596    pub fn push_str(&mut self, text: &str, highlight: Option<HighlightId>) {
1597        let start_ix = self.text.len();
1598        self.text.push_str(text);
1599        let end_ix = self.text.len();
1600        if let Some(highlight) = highlight {
1601            self.runs.push((start_ix..end_ix, highlight));
1602        }
1603    }
1604
1605    pub fn text(&self) -> &str {
1606        self.text.as_str()
1607    }
1608}
1609
1610impl From<String> for CodeLabel {
1611    fn from(value: String) -> Self {
1612        Self::plain(value, None)
1613    }
1614}
1615
1616impl From<&str> for CodeLabel {
1617    fn from(value: &str) -> Self {
1618        Self::plain(value.to_string(), None)
1619    }
1620}
1621
1622impl Ord for LanguageMatcher {
1623    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1624        self.path_suffixes.cmp(&other.path_suffixes).then_with(|| {
1625            self.first_line_pattern
1626                .as_ref()
1627                .map(Regex::as_str)
1628                .cmp(&other.first_line_pattern.as_ref().map(Regex::as_str))
1629        })
1630    }
1631}
1632
1633impl PartialOrd for LanguageMatcher {
1634    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1635        Some(self.cmp(other))
1636    }
1637}
1638
1639impl Eq for LanguageMatcher {}
1640
1641impl PartialEq for LanguageMatcher {
1642    fn eq(&self, other: &Self) -> bool {
1643        self.path_suffixes == other.path_suffixes
1644            && self.first_line_pattern.as_ref().map(Regex::as_str)
1645                == other.first_line_pattern.as_ref().map(Regex::as_str)
1646    }
1647}
1648
1649#[cfg(any(test, feature = "test-support"))]
1650impl Default for FakeLspAdapter {
1651    fn default() -> Self {
1652        Self {
1653            name: "the-fake-language-server",
1654            capabilities: lsp::LanguageServer::full_capabilities(),
1655            initializer: None,
1656            disk_based_diagnostics_progress_token: None,
1657            initialization_options: None,
1658            disk_based_diagnostics_sources: Vec::new(),
1659            prettier_plugins: Vec::new(),
1660            language_server_binary: LanguageServerBinary {
1661                path: "/the/fake/lsp/path".into(),
1662                arguments: vec![],
1663                env: Default::default(),
1664            },
1665        }
1666    }
1667}
1668
1669#[cfg(any(test, feature = "test-support"))]
1670#[async_trait(?Send)]
1671impl LspAdapter for FakeLspAdapter {
1672    fn name(&self) -> LanguageServerName {
1673        LanguageServerName(self.name.into())
1674    }
1675
1676    async fn check_if_user_installed(
1677        &self,
1678        _: &dyn LspAdapterDelegate,
1679        _: Arc<dyn LanguageToolchainStore>,
1680        _: &AsyncAppContext,
1681    ) -> Option<LanguageServerBinary> {
1682        Some(self.language_server_binary.clone())
1683    }
1684
1685    fn get_language_server_command<'a>(
1686        self: Arc<Self>,
1687        _: Arc<dyn LspAdapterDelegate>,
1688        _: Arc<dyn LanguageToolchainStore>,
1689        _: LanguageServerBinaryOptions,
1690        _: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
1691        _: &'a mut AsyncAppContext,
1692    ) -> Pin<Box<dyn 'a + Future<Output = Result<LanguageServerBinary>>>> {
1693        async move { Ok(self.language_server_binary.clone()) }.boxed_local()
1694    }
1695
1696    async fn fetch_latest_server_version(
1697        &self,
1698        _: &dyn LspAdapterDelegate,
1699    ) -> Result<Box<dyn 'static + Send + Any>> {
1700        unreachable!();
1701    }
1702
1703    async fn fetch_server_binary(
1704        &self,
1705        _: Box<dyn 'static + Send + Any>,
1706        _: PathBuf,
1707        _: &dyn LspAdapterDelegate,
1708    ) -> Result<LanguageServerBinary> {
1709        unreachable!();
1710    }
1711
1712    async fn cached_server_binary(
1713        &self,
1714        _: PathBuf,
1715        _: &dyn LspAdapterDelegate,
1716    ) -> Option<LanguageServerBinary> {
1717        unreachable!();
1718    }
1719
1720    fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
1721
1722    fn disk_based_diagnostic_sources(&self) -> Vec<String> {
1723        self.disk_based_diagnostics_sources.clone()
1724    }
1725
1726    fn disk_based_diagnostics_progress_token(&self) -> Option<String> {
1727        self.disk_based_diagnostics_progress_token.clone()
1728    }
1729
1730    async fn initialization_options(
1731        self: Arc<Self>,
1732        _: &Arc<dyn LspAdapterDelegate>,
1733    ) -> Result<Option<Value>> {
1734        Ok(self.initialization_options.clone())
1735    }
1736}
1737
1738fn get_capture_indices(query: &Query, captures: &mut [(&str, &mut Option<u32>)]) {
1739    for (ix, name) in query.capture_names().iter().enumerate() {
1740        for (capture_name, index) in captures.iter_mut() {
1741            if capture_name == name {
1742                **index = Some(ix as u32);
1743                break;
1744            }
1745        }
1746    }
1747}
1748
1749pub fn point_to_lsp(point: PointUtf16) -> lsp::Position {
1750    lsp::Position::new(point.row, point.column)
1751}
1752
1753pub fn point_from_lsp(point: lsp::Position) -> Unclipped<PointUtf16> {
1754    Unclipped(PointUtf16::new(point.line, point.character))
1755}
1756
1757pub fn range_to_lsp(range: Range<PointUtf16>) -> lsp::Range {
1758    lsp::Range {
1759        start: point_to_lsp(range.start),
1760        end: point_to_lsp(range.end),
1761    }
1762}
1763
1764pub fn range_from_lsp(range: lsp::Range) -> Range<Unclipped<PointUtf16>> {
1765    let mut start = point_from_lsp(range.start);
1766    let mut end = point_from_lsp(range.end);
1767    if start > end {
1768        mem::swap(&mut start, &mut end);
1769    }
1770    start..end
1771}
1772
1773#[cfg(test)]
1774mod tests {
1775    use super::*;
1776    use gpui::TestAppContext;
1777
1778    #[gpui::test(iterations = 10)]
1779    async fn test_language_loading(cx: &mut TestAppContext) {
1780        let languages = LanguageRegistry::test(cx.executor());
1781        let languages = Arc::new(languages);
1782        languages.register_native_grammars([
1783            ("json", tree_sitter_json::LANGUAGE),
1784            ("rust", tree_sitter_rust::LANGUAGE),
1785        ]);
1786        languages.register_test_language(LanguageConfig {
1787            name: "JSON".into(),
1788            grammar: Some("json".into()),
1789            matcher: LanguageMatcher {
1790                path_suffixes: vec!["json".into()],
1791                ..Default::default()
1792            },
1793            ..Default::default()
1794        });
1795        languages.register_test_language(LanguageConfig {
1796            name: "Rust".into(),
1797            grammar: Some("rust".into()),
1798            matcher: LanguageMatcher {
1799                path_suffixes: vec!["rs".into()],
1800                ..Default::default()
1801            },
1802            ..Default::default()
1803        });
1804        assert_eq!(
1805            languages.language_names(),
1806            &[
1807                "JSON".to_string(),
1808                "Plain Text".to_string(),
1809                "Rust".to_string(),
1810            ]
1811        );
1812
1813        let rust1 = languages.language_for_name("Rust");
1814        let rust2 = languages.language_for_name("Rust");
1815
1816        // Ensure language is still listed even if it's being loaded.
1817        assert_eq!(
1818            languages.language_names(),
1819            &[
1820                "JSON".to_string(),
1821                "Plain Text".to_string(),
1822                "Rust".to_string(),
1823            ]
1824        );
1825
1826        let (rust1, rust2) = futures::join!(rust1, rust2);
1827        assert!(Arc::ptr_eq(&rust1.unwrap(), &rust2.unwrap()));
1828
1829        // Ensure language is still listed even after loading it.
1830        assert_eq!(
1831            languages.language_names(),
1832            &[
1833                "JSON".to_string(),
1834                "Plain Text".to_string(),
1835                "Rust".to_string(),
1836            ]
1837        );
1838
1839        // Loading an unknown language returns an error.
1840        assert!(languages.language_for_name("Unknown").await.is_err());
1841    }
1842}