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