language.rs

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