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