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