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;
  11mod diagnostic_set;
  12mod file_content;
  13mod language_registry;
  14
  15pub mod language_settings;
  16mod manifest;
  17pub mod modeline;
  18mod outline;
  19pub mod proto;
  20mod syntax_map;
  21mod task_context;
  22mod text_diff;
  23mod toolchain;
  24
  25#[cfg(test)]
  26pub mod buffer_tests;
  27
  28pub use crate::language_settings::{AutoIndentMode, EditPredictionsMode, IndentGuideSettings};
  29use anyhow::{Context as _, Result};
  30use async_trait::async_trait;
  31use collections::{HashMap, HashSet};
  32use futures::Future;
  33use futures::future::LocalBoxFuture;
  34use futures::lock::OwnedMutexGuard;
  35use gpui::{App, AsyncApp, Entity};
  36use http_client::HttpClient;
  37
  38pub use language_core::highlight_map::{HighlightId, HighlightMap};
  39
  40pub use language_core::{
  41    BlockCommentConfig, BracketPair, BracketPairConfig, BracketPairContent, BracketsConfig,
  42    BracketsPatternConfig, CodeLabel, CodeLabelBuilder, DebugVariablesConfig, DebuggerTextObject,
  43    DecreaseIndentConfig, Grammar, GrammarId, HighlightsConfig, IndentConfig, InjectionConfig,
  44    InjectionPatternConfig, JsxTagAutoCloseConfig, LanguageConfig, LanguageConfigOverride,
  45    LanguageId, LanguageMatcher, OrderedListConfig, OutlineConfig, Override, OverrideConfig,
  46    OverrideEntry, PromptResponseContext, RedactionConfig, RunnableCapture, RunnableConfig,
  47    SoftWrap, Symbol, TaskListConfig, TextObject, TextObjectConfig, ToLspPosition,
  48    WrapCharactersConfig, auto_indent_using_last_non_empty_line_default, deserialize_regex,
  49    deserialize_regex_vec, regex_json_schema, regex_vec_json_schema, serialize_regex,
  50};
  51pub use language_registry::{
  52    LanguageName, LanguageServerStatusUpdate, LoadedLanguage, ServerHealth,
  53};
  54use lsp::{
  55    CodeActionKind, InitializeParams, LanguageServerBinary, LanguageServerBinaryOptions, Uri,
  56};
  57pub use manifest::{ManifestDelegate, ManifestName, ManifestProvider, ManifestQuery};
  58pub use modeline::{ModelineSettings, parse_modeline};
  59use parking_lot::Mutex;
  60use regex::Regex;
  61use semver::Version;
  62use serde_json::Value;
  63use settings::WorktreeId;
  64use smol::future::FutureExt as _;
  65use std::{
  66    ffi::OsStr,
  67    fmt::Debug,
  68    hash::Hash,
  69    mem,
  70    ops::{DerefMut, Range},
  71    path::{Path, PathBuf},
  72    str,
  73    sync::{Arc, LazyLock},
  74};
  75use syntax_map::{QueryCursorHandle, SyntaxSnapshot};
  76use task::RunnableTag;
  77pub use task_context::{ContextLocation, ContextProvider, RunnableRange};
  78pub use text_diff::{
  79    DiffOptions, apply_diff_patch, apply_reversed_diff_patch, char_diff, line_diff, text_diff,
  80    text_diff_with_options, unified_diff, unified_diff_with_context, unified_diff_with_offsets,
  81    word_diff_ranges,
  82};
  83use theme::SyntaxTheme;
  84pub use toolchain::{
  85    LanguageToolchainStore, LocalLanguageToolchainStore, Toolchain, ToolchainList, ToolchainLister,
  86    ToolchainMetadata, ToolchainScope,
  87};
  88use tree_sitter::{self, QueryCursor, WasmStore, wasmtime};
  89use util::rel_path::RelPath;
  90
  91pub use buffer::Operation;
  92pub use buffer::*;
  93pub use diagnostic::{Diagnostic, DiagnosticSourceKind};
  94pub use diagnostic_set::{DiagnosticEntry, DiagnosticEntryRef, DiagnosticGroup};
  95pub use file_content::{ByteContent, FILE_ANALYSIS_BYTES, analyze_byte_content};
  96pub use language_registry::{
  97    AvailableLanguage, BinaryStatus, LanguageNotFound, LanguageQueries, LanguageRegistry,
  98    QUERY_FILENAME_PREFIXES,
  99};
 100pub use lsp::{LanguageServerId, LanguageServerName};
 101pub use outline::*;
 102pub use syntax_map::{
 103    OwnedSyntaxLayer, SyntaxLayer, SyntaxMapMatches, ToTreeSitterPoint, TreeSitterOptions,
 104};
 105pub use text::{AnchorRangeExt, LineEnding};
 106pub use tree_sitter::{Node, Parser, Tree, TreeCursor};
 107
 108pub(crate) fn to_settings_soft_wrap(value: language_core::SoftWrap) -> settings::SoftWrap {
 109    match value {
 110        language_core::SoftWrap::None => settings::SoftWrap::None,
 111        language_core::SoftWrap::PreferLine => settings::SoftWrap::PreferLine,
 112        language_core::SoftWrap::EditorWidth => settings::SoftWrap::EditorWidth,
 113        language_core::SoftWrap::Bounded => settings::SoftWrap::Bounded,
 114    }
 115}
 116
 117static QUERY_CURSORS: Mutex<Vec<QueryCursor>> = Mutex::new(vec![]);
 118static PARSERS: Mutex<Vec<Parser>> = Mutex::new(vec![]);
 119
 120#[ztracing::instrument(skip_all)]
 121pub fn with_parser<F, R>(func: F) -> R
 122where
 123    F: FnOnce(&mut Parser) -> R,
 124{
 125    let mut parser = PARSERS.lock().pop().unwrap_or_else(|| {
 126        let mut parser = Parser::new();
 127        parser
 128            .set_wasm_store(WasmStore::new(&WASM_ENGINE).unwrap())
 129            .unwrap();
 130        parser
 131    });
 132    parser.set_included_ranges(&[]).unwrap();
 133    let result = func(&mut parser);
 134    PARSERS.lock().push(parser);
 135    result
 136}
 137
 138pub fn with_query_cursor<F, R>(func: F) -> R
 139where
 140    F: FnOnce(&mut QueryCursor) -> R,
 141{
 142    let mut cursor = QueryCursorHandle::new();
 143    func(cursor.deref_mut())
 144}
 145
 146static WASM_ENGINE: LazyLock<wasmtime::Engine> = LazyLock::new(|| {
 147    wasmtime::Engine::new(&wasmtime::Config::new()).expect("Failed to create Wasmtime engine")
 148});
 149
 150/// A shared grammar for plain text, exposed for reuse by downstream crates.
 151pub static PLAIN_TEXT: LazyLock<Arc<Language>> = LazyLock::new(|| {
 152    Arc::new(Language::new(
 153        LanguageConfig {
 154            name: "Plain Text".into(),
 155            soft_wrap: Some(SoftWrap::EditorWidth),
 156            matcher: LanguageMatcher {
 157                path_suffixes: vec!["txt".to_owned()],
 158                first_line_pattern: None,
 159                modeline_aliases: vec!["text".to_owned(), "txt".to_owned()],
 160            },
 161            brackets: BracketPairConfig {
 162                pairs: vec![
 163                    BracketPair {
 164                        start: "(".to_string(),
 165                        end: ")".to_string(),
 166                        close: true,
 167                        surround: true,
 168                        newline: false,
 169                    },
 170                    BracketPair {
 171                        start: "[".to_string(),
 172                        end: "]".to_string(),
 173                        close: true,
 174                        surround: true,
 175                        newline: false,
 176                    },
 177                    BracketPair {
 178                        start: "{".to_string(),
 179                        end: "}".to_string(),
 180                        close: true,
 181                        surround: true,
 182                        newline: false,
 183                    },
 184                    BracketPair {
 185                        start: "\"".to_string(),
 186                        end: "\"".to_string(),
 187                        close: true,
 188                        surround: true,
 189                        newline: false,
 190                    },
 191                    BracketPair {
 192                        start: "'".to_string(),
 193                        end: "'".to_string(),
 194                        close: true,
 195                        surround: true,
 196                        newline: false,
 197                    },
 198                ],
 199                disabled_scopes_by_bracket_ix: Default::default(),
 200            },
 201            ..Default::default()
 202        },
 203        None,
 204    ))
 205});
 206
 207/// Commands that the client (editor) handles locally rather than forwarding
 208/// to the language server. Servers embed these in code lens and code action
 209/// responses when they want the editor to perform a well-known UI action.
 210#[derive(Debug, Clone)]
 211pub enum ClientCommand {
 212    /// Open a location list (references panel / peek view).
 213    ShowLocations,
 214    /// Schedule a task from an LSP command's arguments.
 215    ScheduleTask(task::TaskTemplate),
 216}
 217
 218#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 219pub struct Location {
 220    pub buffer: Entity<Buffer>,
 221    pub range: Range<Anchor>,
 222}
 223
 224type ServerBinaryCache = futures::lock::Mutex<Option<(bool, LanguageServerBinary)>>;
 225type DownloadableLanguageServerBinary = LocalBoxFuture<'static, Result<LanguageServerBinary>>;
 226pub type LanguageServerBinaryLocations = LocalBoxFuture<
 227    'static,
 228    (
 229        Result<LanguageServerBinary>,
 230        Option<DownloadableLanguageServerBinary>,
 231    ),
 232>;
 233/// Represents a Language Server, with certain cached sync properties.
 234/// Uses [`LspAdapter`] under the hood, but calls all 'static' methods
 235/// once at startup, and caches the results.
 236pub struct CachedLspAdapter {
 237    pub name: LanguageServerName,
 238    pub disk_based_diagnostic_sources: Vec<String>,
 239    pub disk_based_diagnostics_progress_token: Option<String>,
 240    language_ids: HashMap<LanguageName, String>,
 241    pub adapter: Arc<dyn LspAdapter>,
 242    cached_binary: Arc<ServerBinaryCache>,
 243}
 244
 245impl Debug for CachedLspAdapter {
 246    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 247        f.debug_struct("CachedLspAdapter")
 248            .field("name", &self.name)
 249            .field(
 250                "disk_based_diagnostic_sources",
 251                &self.disk_based_diagnostic_sources,
 252            )
 253            .field(
 254                "disk_based_diagnostics_progress_token",
 255                &self.disk_based_diagnostics_progress_token,
 256            )
 257            .field("language_ids", &self.language_ids)
 258            .finish_non_exhaustive()
 259    }
 260}
 261
 262impl CachedLspAdapter {
 263    pub fn new(adapter: Arc<dyn LspAdapter>) -> Arc<Self> {
 264        let name = adapter.name();
 265        let disk_based_diagnostic_sources = adapter.disk_based_diagnostic_sources();
 266        let disk_based_diagnostics_progress_token = adapter.disk_based_diagnostics_progress_token();
 267        let language_ids = adapter.language_ids();
 268
 269        Arc::new(CachedLspAdapter {
 270            name,
 271            disk_based_diagnostic_sources,
 272            disk_based_diagnostics_progress_token,
 273            language_ids,
 274            adapter,
 275            cached_binary: Default::default(),
 276        })
 277    }
 278
 279    pub fn name(&self) -> LanguageServerName {
 280        self.adapter.name()
 281    }
 282
 283    pub async fn get_language_server_command(
 284        self: Arc<Self>,
 285        delegate: Arc<dyn LspAdapterDelegate>,
 286        toolchains: Option<Toolchain>,
 287        binary_options: LanguageServerBinaryOptions,
 288        cx: &mut AsyncApp,
 289    ) -> LanguageServerBinaryLocations {
 290        let cached_binary = self.cached_binary.clone().lock_owned().await;
 291        self.adapter.clone().get_language_server_command(
 292            delegate,
 293            toolchains,
 294            binary_options,
 295            cached_binary,
 296            cx.clone(),
 297        )
 298    }
 299
 300    pub fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
 301        self.adapter.code_action_kinds()
 302    }
 303
 304    pub fn process_diagnostics(
 305        &self,
 306        params: &mut lsp::PublishDiagnosticsParams,
 307        server_id: LanguageServerId,
 308    ) {
 309        self.adapter.process_diagnostics(params, server_id)
 310    }
 311
 312    pub fn retain_old_diagnostic(&self, previous_diagnostic: &Diagnostic) -> bool {
 313        self.adapter.retain_old_diagnostic(previous_diagnostic)
 314    }
 315
 316    pub fn underline_diagnostic(&self, diagnostic: &lsp::Diagnostic) -> bool {
 317        self.adapter.underline_diagnostic(diagnostic)
 318    }
 319
 320    pub fn diagnostic_message_to_markdown(&self, message: &str) -> Option<String> {
 321        self.adapter.diagnostic_message_to_markdown(message)
 322    }
 323
 324    pub async fn process_completions(&self, completion_items: &mut [lsp::CompletionItem]) {
 325        self.adapter.process_completions(completion_items).await
 326    }
 327
 328    pub async fn labels_for_completions(
 329        &self,
 330        completion_items: &[lsp::CompletionItem],
 331        language: &Arc<Language>,
 332    ) -> Result<Vec<Option<CodeLabel>>> {
 333        self.adapter
 334            .clone()
 335            .labels_for_completions(completion_items, language)
 336            .await
 337    }
 338
 339    pub async fn labels_for_symbols(
 340        &self,
 341        symbols: &[Symbol],
 342        language: &Arc<Language>,
 343    ) -> Result<Vec<Option<CodeLabel>>> {
 344        self.adapter
 345            .clone()
 346            .labels_for_symbols(symbols, language)
 347            .await
 348    }
 349
 350    pub fn language_id(&self, language_name: &LanguageName) -> String {
 351        self.language_ids
 352            .get(language_name)
 353            .cloned()
 354            .unwrap_or_else(|| language_name.lsp_id())
 355    }
 356
 357    pub async fn initialization_options_schema(
 358        &self,
 359        delegate: &Arc<dyn LspAdapterDelegate>,
 360        cx: &mut AsyncApp,
 361    ) -> Option<serde_json::Value> {
 362        self.adapter
 363            .clone()
 364            .initialization_options_schema(
 365                delegate,
 366                self.cached_binary.clone().lock_owned().await,
 367                cx,
 368            )
 369            .await
 370    }
 371
 372    pub async fn settings_schema(
 373        &self,
 374        delegate: &Arc<dyn LspAdapterDelegate>,
 375        cx: &mut AsyncApp,
 376    ) -> Option<serde_json::Value> {
 377        self.adapter
 378            .clone()
 379            .settings_schema(delegate, self.cached_binary.clone().lock_owned().await, cx)
 380            .await
 381    }
 382
 383    pub fn process_prompt_response(&self, context: &PromptResponseContext, cx: &mut AsyncApp) {
 384        self.adapter.process_prompt_response(context, cx)
 385    }
 386}
 387
 388/// [`LspAdapterDelegate`] allows [`LspAdapter]` implementations to interface with the application
 389// e.g. to display a notification or fetch data from the web.
 390#[async_trait]
 391pub trait LspAdapterDelegate: Send + Sync {
 392    fn show_notification(&self, message: &str, cx: &mut App);
 393    fn http_client(&self) -> Arc<dyn HttpClient>;
 394    fn worktree_id(&self) -> WorktreeId;
 395    fn worktree_root_path(&self) -> &Path;
 396    fn resolve_relative_path(&self, path: PathBuf) -> PathBuf;
 397    fn update_status(&self, language: LanguageServerName, status: BinaryStatus);
 398    fn registered_lsp_adapters(&self) -> Vec<Arc<dyn LspAdapter>>;
 399    async fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>>;
 400
 401    async fn npm_package_installed_version(
 402        &self,
 403        package_name: &str,
 404    ) -> Result<Option<(PathBuf, Version)>>;
 405    async fn which(&self, command: &OsStr) -> Option<PathBuf>;
 406    async fn shell_env(&self) -> HashMap<String, String>;
 407    async fn read_text_file(&self, path: &RelPath) -> Result<String>;
 408    async fn try_exec(&self, binary: LanguageServerBinary) -> Result<()>;
 409}
 410
 411#[async_trait(?Send)]
 412pub trait LspAdapter: 'static + Send + Sync + DynLspInstaller {
 413    fn name(&self) -> LanguageServerName;
 414
 415    fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams, _: LanguageServerId) {}
 416
 417    /// When processing new `lsp::PublishDiagnosticsParams` diagnostics, whether to retain previous one(s) or not.
 418    fn retain_old_diagnostic(&self, _previous_diagnostic: &Diagnostic) -> bool {
 419        false
 420    }
 421
 422    /// Whether to underline a given diagnostic or not, when rendering in the editor.
 423    ///
 424    /// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnosticTag
 425    /// states that
 426    /// > Clients are allowed to render diagnostics with this tag faded out instead of having an error squiggle.
 427    /// for the unnecessary diagnostics, so do not underline them.
 428    fn underline_diagnostic(&self, _diagnostic: &lsp::Diagnostic) -> bool {
 429        true
 430    }
 431
 432    /// Post-processes completions provided by the language server.
 433    async fn process_completions(&self, _: &mut [lsp::CompletionItem]) {}
 434
 435    fn diagnostic_message_to_markdown(&self, _message: &str) -> Option<String> {
 436        None
 437    }
 438
 439    async fn labels_for_completions(
 440        self: Arc<Self>,
 441        completions: &[lsp::CompletionItem],
 442        language: &Arc<Language>,
 443    ) -> Result<Vec<Option<CodeLabel>>> {
 444        let mut labels = Vec::new();
 445        for (ix, completion) in completions.iter().enumerate() {
 446            let label = self.label_for_completion(completion, language).await;
 447            if let Some(label) = label {
 448                labels.resize(ix + 1, None);
 449                *labels.last_mut().unwrap() = Some(label);
 450            }
 451        }
 452        Ok(labels)
 453    }
 454
 455    async fn label_for_completion(
 456        &self,
 457        _: &lsp::CompletionItem,
 458        _: &Arc<Language>,
 459    ) -> Option<CodeLabel> {
 460        None
 461    }
 462
 463    async fn labels_for_symbols(
 464        self: Arc<Self>,
 465        symbols: &[Symbol],
 466        language: &Arc<Language>,
 467    ) -> Result<Vec<Option<CodeLabel>>> {
 468        let mut labels = Vec::new();
 469        for (ix, symbol) in symbols.iter().enumerate() {
 470            let label = self.label_for_symbol(symbol, language).await;
 471            if let Some(label) = label {
 472                labels.resize(ix + 1, None);
 473                *labels.last_mut().unwrap() = Some(label);
 474            }
 475        }
 476        Ok(labels)
 477    }
 478
 479    async fn label_for_symbol(
 480        &self,
 481        _symbol: &Symbol,
 482        _language: &Arc<Language>,
 483    ) -> Option<CodeLabel> {
 484        None
 485    }
 486
 487    /// Returns initialization options that are going to be sent to a LSP server as a part of [`lsp::InitializeParams`]
 488    async fn initialization_options(
 489        self: Arc<Self>,
 490        _: &Arc<dyn LspAdapterDelegate>,
 491        _cx: &mut AsyncApp,
 492    ) -> Result<Option<Value>> {
 493        Ok(None)
 494    }
 495
 496    /// Returns the JSON schema of the initialization_options for the language server.
 497    async fn initialization_options_schema(
 498        self: Arc<Self>,
 499        _delegate: &Arc<dyn LspAdapterDelegate>,
 500        _cached_binary: OwnedMutexGuard<Option<(bool, LanguageServerBinary)>>,
 501        _cx: &mut AsyncApp,
 502    ) -> Option<serde_json::Value> {
 503        None
 504    }
 505
 506    /// Returns the JSON schema of the settings for the language server.
 507    /// This corresponds to the `settings` field in `LspSettings`, which is used
 508    /// to respond to `workspace/configuration` requests from the language server.
 509    async fn settings_schema(
 510        self: Arc<Self>,
 511        _delegate: &Arc<dyn LspAdapterDelegate>,
 512        _cached_binary: OwnedMutexGuard<Option<(bool, LanguageServerBinary)>>,
 513        _cx: &mut AsyncApp,
 514    ) -> Option<serde_json::Value> {
 515        None
 516    }
 517
 518    async fn workspace_configuration(
 519        self: Arc<Self>,
 520        _: &Arc<dyn LspAdapterDelegate>,
 521        _: Option<Toolchain>,
 522        _: Option<Uri>,
 523        _cx: &mut AsyncApp,
 524    ) -> Result<Value> {
 525        Ok(serde_json::json!({}))
 526    }
 527
 528    async fn additional_initialization_options(
 529        self: Arc<Self>,
 530        _target_language_server_id: LanguageServerName,
 531        _: &Arc<dyn LspAdapterDelegate>,
 532    ) -> Result<Option<Value>> {
 533        Ok(None)
 534    }
 535
 536    async fn additional_workspace_configuration(
 537        self: Arc<Self>,
 538        _target_language_server_id: LanguageServerName,
 539        _: &Arc<dyn LspAdapterDelegate>,
 540        _cx: &mut AsyncApp,
 541    ) -> Result<Option<Value>> {
 542        Ok(None)
 543    }
 544
 545    /// Returns a list of code actions supported by a given LspAdapter
 546    fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
 547        None
 548    }
 549
 550    fn disk_based_diagnostic_sources(&self) -> Vec<String> {
 551        Default::default()
 552    }
 553
 554    fn disk_based_diagnostics_progress_token(&self) -> Option<String> {
 555        None
 556    }
 557
 558    fn language_ids(&self) -> HashMap<LanguageName, String> {
 559        HashMap::default()
 560    }
 561
 562    /// Support custom initialize params.
 563    fn prepare_initialize_params(
 564        &self,
 565        original: InitializeParams,
 566        _: &App,
 567    ) -> Result<InitializeParams> {
 568        Ok(original)
 569    }
 570
 571    fn client_command(
 572        &self,
 573        _command_name: &str,
 574        _arguments: &[serde_json::Value],
 575    ) -> Option<ClientCommand> {
 576        None
 577    }
 578
 579    /// Method only implemented by the default JSON language server adapter.
 580    /// Used to provide dynamic reloading of the JSON schemas used to
 581    /// provide autocompletion and diagnostics in Zed setting and keybind
 582    /// files
 583    fn is_primary_zed_json_schema_adapter(&self) -> bool {
 584        false
 585    }
 586
 587    /// True for the extension adapter and false otherwise.
 588    fn is_extension(&self) -> bool {
 589        false
 590    }
 591
 592    /// Called when a user responds to a ShowMessageRequest from this language server.
 593    /// This allows adapters to intercept preference selections (like "Always" or "Never")
 594    /// for settings that should be persisted to Zed's settings file.
 595    fn process_prompt_response(&self, _context: &PromptResponseContext, _cx: &mut AsyncApp) {}
 596}
 597
 598pub trait LspInstaller {
 599    type BinaryVersion;
 600    fn check_if_user_installed(
 601        &self,
 602        _: &dyn LspAdapterDelegate,
 603        _: Option<Toolchain>,
 604        _: &AsyncApp,
 605    ) -> impl Future<Output = Option<LanguageServerBinary>> {
 606        async { None }
 607    }
 608
 609    fn fetch_latest_server_version(
 610        &self,
 611        delegate: &dyn LspAdapterDelegate,
 612        pre_release: bool,
 613        cx: &mut AsyncApp,
 614    ) -> impl Future<Output = Result<Self::BinaryVersion>>;
 615
 616    fn check_if_version_installed(
 617        &self,
 618        _version: &Self::BinaryVersion,
 619        _container_dir: &PathBuf,
 620        _delegate: &dyn LspAdapterDelegate,
 621    ) -> impl Send + Future<Output = Option<LanguageServerBinary>> {
 622        async { None }
 623    }
 624
 625    fn fetch_server_binary(
 626        &self,
 627        latest_version: Self::BinaryVersion,
 628        container_dir: PathBuf,
 629        delegate: &dyn LspAdapterDelegate,
 630    ) -> impl Send + Future<Output = Result<LanguageServerBinary>>;
 631
 632    fn cached_server_binary(
 633        &self,
 634        container_dir: PathBuf,
 635        delegate: &dyn LspAdapterDelegate,
 636    ) -> impl Future<Output = Option<LanguageServerBinary>>;
 637}
 638
 639#[async_trait(?Send)]
 640pub trait DynLspInstaller {
 641    async fn try_fetch_server_binary(
 642        &self,
 643        delegate: &Arc<dyn LspAdapterDelegate>,
 644        container_dir: PathBuf,
 645        pre_release: bool,
 646        cx: &mut AsyncApp,
 647    ) -> Result<LanguageServerBinary>;
 648
 649    fn get_language_server_command(
 650        self: Arc<Self>,
 651        delegate: Arc<dyn LspAdapterDelegate>,
 652        toolchains: Option<Toolchain>,
 653        binary_options: LanguageServerBinaryOptions,
 654        cached_binary: OwnedMutexGuard<Option<(bool, LanguageServerBinary)>>,
 655        cx: AsyncApp,
 656    ) -> LanguageServerBinaryLocations;
 657}
 658
 659#[async_trait(?Send)]
 660impl<LI, BinaryVersion> DynLspInstaller for LI
 661where
 662    BinaryVersion: Send + Sync,
 663    LI: LspInstaller<BinaryVersion = BinaryVersion> + LspAdapter,
 664{
 665    async fn try_fetch_server_binary(
 666        &self,
 667        delegate: &Arc<dyn LspAdapterDelegate>,
 668        container_dir: PathBuf,
 669        pre_release: bool,
 670        cx: &mut AsyncApp,
 671    ) -> Result<LanguageServerBinary> {
 672        let name = self.name();
 673
 674        log::debug!("fetching latest version of language server {:?}", name.0);
 675        delegate.update_status(name.clone(), BinaryStatus::CheckingForUpdate);
 676
 677        let latest_version = self
 678            .fetch_latest_server_version(delegate.as_ref(), pre_release, cx)
 679            .await?;
 680
 681        if let Some(binary) = cx
 682            .background_executor()
 683            .await_on_background(self.check_if_version_installed(
 684                &latest_version,
 685                &container_dir,
 686                delegate.as_ref(),
 687            ))
 688            .await
 689        {
 690            log::debug!("language server {:?} is already installed", name.0);
 691            delegate.update_status(name.clone(), BinaryStatus::None);
 692            Ok(binary)
 693        } else {
 694            log::debug!("downloading language server {:?}", name.0);
 695            delegate.update_status(name.clone(), BinaryStatus::Downloading);
 696            let binary = cx
 697                .background_executor()
 698                .await_on_background(self.fetch_server_binary(
 699                    latest_version,
 700                    container_dir,
 701                    delegate.as_ref(),
 702                ))
 703                .await;
 704
 705            delegate.update_status(name.clone(), BinaryStatus::None);
 706            binary
 707        }
 708    }
 709    fn get_language_server_command(
 710        self: Arc<Self>,
 711        delegate: Arc<dyn LspAdapterDelegate>,
 712        toolchain: Option<Toolchain>,
 713        binary_options: LanguageServerBinaryOptions,
 714        mut cached_binary: OwnedMutexGuard<Option<(bool, LanguageServerBinary)>>,
 715        mut cx: AsyncApp,
 716    ) -> LanguageServerBinaryLocations {
 717        async move {
 718            let cached_binary_deref = cached_binary.deref_mut();
 719            // First we check whether the adapter can give us a user-installed binary.
 720            // If so, we do *not* want to cache that, because each worktree might give us a different
 721            // binary:
 722            //
 723            //      worktree 1: user-installed at `.bin/gopls`
 724            //      worktree 2: user-installed at `~/bin/gopls`
 725            //      worktree 3: no gopls found in PATH -> fallback to Zed installation
 726            //
 727            // We only want to cache when we fall back to the global one,
 728            // because we don't want to download and overwrite our global one
 729            // for each worktree we might have open.
 730            if binary_options.allow_path_lookup
 731                && let Some(binary) = self
 732                    .check_if_user_installed(delegate.as_ref(), toolchain, &mut cx)
 733                    .await
 734            {
 735                log::info!(
 736                    "found user-installed language server for {}. path: {:?}, arguments: {:?}",
 737                    self.name().0,
 738                    binary.path,
 739                    binary.arguments
 740                );
 741                return (Ok(binary), None);
 742            }
 743
 744            if let Some((pre_release, cached_binary)) = cached_binary_deref
 745                && *pre_release == binary_options.pre_release
 746            {
 747                return (Ok(cached_binary.clone()), None);
 748            }
 749
 750            if !binary_options.allow_binary_download {
 751                return (
 752                    Err(anyhow::anyhow!("downloading language servers disabled")),
 753                    None,
 754                );
 755            }
 756
 757            let Some(container_dir) = delegate.language_server_download_dir(&self.name()).await
 758            else {
 759                return (
 760                    Err(anyhow::anyhow!("no language server download dir defined")),
 761                    None,
 762                );
 763            };
 764
 765            let last_downloaded_binary = self
 766                .cached_server_binary(container_dir.to_path_buf(), delegate.as_ref())
 767                .await
 768                .context(
 769                    "did not find existing language server binary, falling back to downloading",
 770                );
 771            let download_binary = async move {
 772                let mut binary = self
 773                    .try_fetch_server_binary(
 774                        &delegate,
 775                        container_dir.to_path_buf(),
 776                        binary_options.pre_release,
 777                        &mut cx,
 778                    )
 779                    .await;
 780
 781                if let Err(error) = binary.as_ref() {
 782                    if let Some(prev_downloaded_binary) = self
 783                        .cached_server_binary(container_dir.to_path_buf(), delegate.as_ref())
 784                        .await
 785                    {
 786                        log::info!(
 787                            "failed to fetch newest version of language server {:?}. \
 788                            error: {:?}, falling back to using {:?}",
 789                            self.name(),
 790                            error,
 791                            prev_downloaded_binary.path
 792                        );
 793                        binary = Ok(prev_downloaded_binary);
 794                    } else {
 795                        delegate.update_status(
 796                            self.name(),
 797                            BinaryStatus::Failed {
 798                                error: format!("{error:?}"),
 799                            },
 800                        );
 801                    }
 802                }
 803
 804                if let Ok(binary) = &binary {
 805                    *cached_binary = Some((binary_options.pre_release, binary.clone()));
 806                }
 807
 808                binary
 809            }
 810            .boxed_local();
 811            (last_downloaded_binary, Some(download_binary))
 812        }
 813        .boxed_local()
 814    }
 815}
 816
 817/// Represents a language for the given range. Some languages (e.g. HTML)
 818/// interleave several languages together, thus a single buffer might actually contain
 819/// several nested scopes.
 820#[derive(Clone, Debug)]
 821pub struct LanguageScope {
 822    language: Arc<Language>,
 823    override_id: Option<u32>,
 824}
 825
 826#[doc(hidden)]
 827#[cfg(any(test, feature = "test-support"))]
 828pub struct FakeLspAdapter {
 829    pub name: &'static str,
 830    pub initialization_options: Option<Value>,
 831    pub prettier_plugins: Vec<&'static str>,
 832    pub disk_based_diagnostics_progress_token: Option<String>,
 833    pub disk_based_diagnostics_sources: Vec<String>,
 834    pub language_server_binary: LanguageServerBinary,
 835
 836    pub capabilities: lsp::ServerCapabilities,
 837    pub initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,
 838    pub label_for_completion: Option<
 839        Box<
 840            dyn 'static
 841                + Send
 842                + Sync
 843                + Fn(&lsp::CompletionItem, &Arc<Language>) -> Option<CodeLabel>,
 844        >,
 845    >,
 846}
 847
 848pub struct Language {
 849    pub(crate) id: LanguageId,
 850    pub(crate) config: LanguageConfig,
 851    pub(crate) grammar: Option<Arc<Grammar>>,
 852    pub(crate) context_provider: Option<Arc<dyn ContextProvider>>,
 853    pub(crate) toolchain: Option<Arc<dyn ToolchainLister>>,
 854    pub(crate) manifest_name: Option<ManifestName>,
 855}
 856
 857impl Language {
 858    pub fn new(config: LanguageConfig, ts_language: Option<tree_sitter::Language>) -> Self {
 859        Self::new_with_id(LanguageId::new(), config, ts_language)
 860    }
 861
 862    pub fn id(&self) -> LanguageId {
 863        self.id
 864    }
 865
 866    fn new_with_id(
 867        id: LanguageId,
 868        config: LanguageConfig,
 869        ts_language: Option<tree_sitter::Language>,
 870    ) -> Self {
 871        Self {
 872            id,
 873            config,
 874            grammar: ts_language.map(|ts_language| Arc::new(Grammar::new(ts_language))),
 875            context_provider: None,
 876            toolchain: None,
 877            manifest_name: None,
 878        }
 879    }
 880
 881    pub fn with_context_provider(mut self, provider: Option<Arc<dyn ContextProvider>>) -> Self {
 882        self.context_provider = provider;
 883        self
 884    }
 885
 886    pub fn with_toolchain_lister(mut self, provider: Option<Arc<dyn ToolchainLister>>) -> Self {
 887        self.toolchain = provider;
 888        self
 889    }
 890
 891    pub fn with_manifest(mut self, name: Option<ManifestName>) -> Self {
 892        self.manifest_name = name;
 893        self
 894    }
 895
 896    pub fn with_queries(mut self, queries: LanguageQueries) -> Result<Self> {
 897        if let Some(grammar) = self.grammar.take() {
 898            let grammar =
 899                Arc::try_unwrap(grammar).map_err(|_| anyhow::anyhow!("cannot mutate grammar"))?;
 900            let grammar = grammar.with_queries(queries, &mut self.config)?;
 901            self.grammar = Some(Arc::new(grammar));
 902        }
 903        Ok(self)
 904    }
 905
 906    pub fn with_highlights_query(self, source: &str) -> Result<Self> {
 907        self.with_grammar_query(|grammar| grammar.with_highlights_query(source))
 908    }
 909
 910    pub fn with_runnable_query(self, source: &str) -> Result<Self> {
 911        self.with_grammar_query(|grammar| grammar.with_runnable_query(source))
 912    }
 913
 914    pub fn with_outline_query(self, source: &str) -> Result<Self> {
 915        self.with_grammar_query_and_name(|grammar, name| grammar.with_outline_query(source, name))
 916    }
 917
 918    pub fn with_text_object_query(self, source: &str) -> Result<Self> {
 919        self.with_grammar_query_and_name(|grammar, name| {
 920            grammar.with_text_object_query(source, name)
 921        })
 922    }
 923
 924    pub fn with_debug_variables_query(self, source: &str) -> Result<Self> {
 925        self.with_grammar_query_and_name(|grammar, name| {
 926            grammar.with_debug_variables_query(source, name)
 927        })
 928    }
 929
 930    pub fn with_brackets_query(self, source: &str) -> Result<Self> {
 931        self.with_grammar_query_and_name(|grammar, name| grammar.with_brackets_query(source, name))
 932    }
 933
 934    pub fn with_indents_query(self, source: &str) -> Result<Self> {
 935        self.with_grammar_query_and_name(|grammar, name| grammar.with_indents_query(source, name))
 936    }
 937
 938    pub fn with_injection_query(self, source: &str) -> Result<Self> {
 939        self.with_grammar_query_and_name(|grammar, name| grammar.with_injection_query(source, name))
 940    }
 941
 942    pub fn with_override_query(mut self, source: &str) -> Result<Self> {
 943        if let Some(grammar_arc) = self.grammar.take() {
 944            let grammar = Arc::try_unwrap(grammar_arc)
 945                .map_err(|_| anyhow::anyhow!("cannot mutate grammar"))?;
 946            let grammar = grammar.with_override_query(
 947                source,
 948                &self.config.name,
 949                &self.config.overrides,
 950                &mut self.config.brackets,
 951                &self.config.scope_opt_in_language_servers,
 952            )?;
 953            self.grammar = Some(Arc::new(grammar));
 954        }
 955        Ok(self)
 956    }
 957
 958    pub fn with_redaction_query(self, source: &str) -> Result<Self> {
 959        self.with_grammar_query_and_name(|grammar, name| grammar.with_redaction_query(source, name))
 960    }
 961
 962    fn with_grammar_query(
 963        mut self,
 964        build: impl FnOnce(Grammar) -> Result<Grammar>,
 965    ) -> Result<Self> {
 966        if let Some(grammar_arc) = self.grammar.take() {
 967            let grammar = Arc::try_unwrap(grammar_arc)
 968                .map_err(|_| anyhow::anyhow!("cannot mutate grammar"))?;
 969            self.grammar = Some(Arc::new(build(grammar)?));
 970        }
 971        Ok(self)
 972    }
 973
 974    fn with_grammar_query_and_name(
 975        mut self,
 976        build: impl FnOnce(Grammar, &LanguageName) -> Result<Grammar>,
 977    ) -> Result<Self> {
 978        if let Some(grammar_arc) = self.grammar.take() {
 979            let grammar = Arc::try_unwrap(grammar_arc)
 980                .map_err(|_| anyhow::anyhow!("cannot mutate grammar"))?;
 981            self.grammar = Some(Arc::new(build(grammar, &self.config.name)?));
 982        }
 983        Ok(self)
 984    }
 985
 986    pub fn name(&self) -> LanguageName {
 987        self.config.name.clone()
 988    }
 989    pub fn manifest(&self) -> Option<&ManifestName> {
 990        self.manifest_name.as_ref()
 991    }
 992
 993    pub fn code_fence_block_name(&self) -> Arc<str> {
 994        self.config
 995            .code_fence_block_name
 996            .clone()
 997            .unwrap_or_else(|| self.config.name.as_ref().to_lowercase().into())
 998    }
 999
1000    pub fn matches_kernel_language(&self, kernel_language: &str) -> bool {
1001        let kernel_language_lower = kernel_language.to_lowercase();
1002
1003        if self.code_fence_block_name().to_lowercase() == kernel_language_lower {
1004            return true;
1005        }
1006
1007        if self.config.name.as_ref().to_lowercase() == kernel_language_lower {
1008            return true;
1009        }
1010
1011        self.config
1012            .kernel_language_names
1013            .iter()
1014            .any(|name| name.to_lowercase() == kernel_language_lower)
1015    }
1016
1017    pub fn context_provider(&self) -> Option<Arc<dyn ContextProvider>> {
1018        self.context_provider.clone()
1019    }
1020
1021    pub fn toolchain_lister(&self) -> Option<Arc<dyn ToolchainLister>> {
1022        self.toolchain.clone()
1023    }
1024
1025    pub fn highlight_text<'a>(
1026        self: &'a Arc<Self>,
1027        text: &'a Rope,
1028        range: Range<usize>,
1029    ) -> Vec<(Range<usize>, HighlightId)> {
1030        let mut result = Vec::new();
1031        if let Some(grammar) = &self.grammar {
1032            let tree = parse_text(grammar, text, None);
1033            let captures =
1034                SyntaxSnapshot::single_tree_captures(range.clone(), text, &tree, self, |grammar| {
1035                    grammar
1036                        .highlights_config
1037                        .as_ref()
1038                        .map(|config| &config.query)
1039                });
1040            let highlight_maps = vec![grammar.highlight_map()];
1041            let mut offset = 0;
1042            for chunk in
1043                BufferChunks::new(text, range, Some((captures, highlight_maps)), false, None)
1044            {
1045                let end_offset = offset + chunk.text.len();
1046                if let Some(highlight_id) = chunk.syntax_highlight_id {
1047                    result.push((offset..end_offset, highlight_id));
1048                }
1049                offset = end_offset;
1050            }
1051        }
1052        result
1053    }
1054
1055    pub fn path_suffixes(&self) -> &[String] {
1056        &self.config.matcher.path_suffixes
1057    }
1058
1059    pub fn should_autoclose_before(&self, c: char) -> bool {
1060        c.is_whitespace() || self.config.autoclose_before.contains(c)
1061    }
1062
1063    pub fn set_theme(&self, theme: &SyntaxTheme) {
1064        if let Some(grammar) = self.grammar.as_ref()
1065            && let Some(highlights_config) = &grammar.highlights_config
1066        {
1067            *grammar.highlight_map.lock() =
1068                build_highlight_map(highlights_config.query.capture_names(), theme);
1069        }
1070    }
1071
1072    pub fn grammar(&self) -> Option<&Arc<Grammar>> {
1073        self.grammar.as_ref()
1074    }
1075
1076    pub fn default_scope(self: &Arc<Self>) -> LanguageScope {
1077        LanguageScope {
1078            language: self.clone(),
1079            override_id: None,
1080        }
1081    }
1082
1083    pub fn lsp_id(&self) -> String {
1084        self.config.name.lsp_id()
1085    }
1086
1087    pub fn prettier_parser_name(&self) -> Option<&str> {
1088        self.config.prettier_parser_name.as_deref()
1089    }
1090
1091    pub fn config(&self) -> &LanguageConfig {
1092        &self.config
1093    }
1094}
1095
1096#[inline]
1097pub fn build_highlight_map(capture_names: &[&str], theme: &SyntaxTheme) -> HighlightMap {
1098    HighlightMap::from_ids(
1099        capture_names
1100            .iter()
1101            .map(|capture_name| theme.highlight_id(capture_name).map(HighlightId::new)),
1102    )
1103}
1104
1105impl LanguageScope {
1106    pub fn path_suffixes(&self) -> &[String] {
1107        self.language.path_suffixes()
1108    }
1109
1110    pub fn language_name(&self) -> LanguageName {
1111        self.language.config.name.clone()
1112    }
1113
1114    pub fn collapsed_placeholder(&self) -> &str {
1115        self.language.config.collapsed_placeholder.as_ref()
1116    }
1117
1118    /// Returns line prefix that is inserted in e.g. line continuations or
1119    /// in `toggle comments` action.
1120    pub fn line_comment_prefixes(&self) -> &[Arc<str>] {
1121        Override::as_option(
1122            self.config_override().map(|o| &o.line_comments),
1123            Some(&self.language.config.line_comments),
1124        )
1125        .map_or([].as_slice(), |e| e.as_slice())
1126    }
1127
1128    /// Config for block comments for this language.
1129    pub fn block_comment(&self) -> Option<&BlockCommentConfig> {
1130        Override::as_option(
1131            self.config_override().map(|o| &o.block_comment),
1132            self.language.config.block_comment.as_ref(),
1133        )
1134    }
1135
1136    /// Config for documentation-style block comments for this language.
1137    pub fn documentation_comment(&self) -> Option<&BlockCommentConfig> {
1138        self.language.config.documentation_comment.as_ref()
1139    }
1140
1141    /// Returns list markers that are inserted unchanged on newline (e.g., `- `, `* `, `+ `).
1142    pub fn unordered_list(&self) -> &[Arc<str>] {
1143        &self.language.config.unordered_list
1144    }
1145
1146    /// Returns configuration for ordered lists with auto-incrementing numbers (e.g., `1. ` becomes `2. `).
1147    pub fn ordered_list(&self) -> &[OrderedListConfig] {
1148        &self.language.config.ordered_list
1149    }
1150
1151    /// Returns configuration for task list continuation, if any (e.g., `- [x] ` continues as `- [ ] `).
1152    pub fn task_list(&self) -> Option<&TaskListConfig> {
1153        self.language.config.task_list.as_ref()
1154    }
1155
1156    /// Returns additional regex patterns that act as prefix markers for creating
1157    /// boundaries during rewrapping.
1158    ///
1159    /// By default, Zed treats as paragraph and comment prefixes as boundaries.
1160    pub fn rewrap_prefixes(&self) -> &[Regex] {
1161        &self.language.config.rewrap_prefixes
1162    }
1163
1164    /// Returns a list of language-specific word characters.
1165    ///
1166    /// By default, Zed treats alphanumeric characters (and '_') as word characters for
1167    /// the purpose of actions like 'move to next word end` or whole-word search.
1168    /// It additionally accounts for language's additional word characters.
1169    pub fn word_characters(&self) -> Option<&HashSet<char>> {
1170        Override::as_option(
1171            self.config_override().map(|o| &o.word_characters),
1172            Some(&self.language.config.word_characters),
1173        )
1174    }
1175
1176    /// Returns a list of language-specific characters that are considered part of
1177    /// a completion query.
1178    pub fn completion_query_characters(&self) -> Option<&HashSet<char>> {
1179        Override::as_option(
1180            self.config_override()
1181                .map(|o| &o.completion_query_characters),
1182            Some(&self.language.config.completion_query_characters),
1183        )
1184    }
1185
1186    /// Returns a list of language-specific characters that are considered part of
1187    /// identifiers during linked editing operations.
1188    pub fn linked_edit_characters(&self) -> Option<&HashSet<char>> {
1189        Override::as_option(
1190            self.config_override().map(|o| &o.linked_edit_characters),
1191            Some(&self.language.config.linked_edit_characters),
1192        )
1193    }
1194
1195    /// Returns whether to prefer snippet `label` over `new_text` to replace text when
1196    /// completion is accepted.
1197    ///
1198    /// In cases like when cursor is in string or renaming existing function,
1199    /// you don't want to expand function signature instead just want function name
1200    /// to replace existing one.
1201    pub fn prefers_label_for_snippet_in_completion(&self) -> bool {
1202        self.config_override()
1203            .and_then(|o| o.prefer_label_for_snippet)
1204            .unwrap_or(false)
1205    }
1206
1207    /// Returns a list of bracket pairs for a given language with an additional
1208    /// piece of information about whether the particular bracket pair is currently active for a given language.
1209    pub fn brackets(&self) -> impl Iterator<Item = (&BracketPair, bool)> {
1210        let mut disabled_ids = self
1211            .config_override()
1212            .map_or(&[] as _, |o| o.disabled_bracket_ixs.as_slice());
1213        self.language
1214            .config
1215            .brackets
1216            .pairs
1217            .iter()
1218            .enumerate()
1219            .map(move |(ix, bracket)| {
1220                let mut is_enabled = true;
1221                if let Some(next_disabled_ix) = disabled_ids.first()
1222                    && ix == *next_disabled_ix as usize
1223                {
1224                    disabled_ids = &disabled_ids[1..];
1225                    is_enabled = false;
1226                }
1227                (bracket, is_enabled)
1228            })
1229    }
1230
1231    pub fn should_autoclose_before(&self, c: char) -> bool {
1232        c.is_whitespace() || self.language.config.autoclose_before.contains(c)
1233    }
1234
1235    pub fn language_allowed(&self, name: &LanguageServerName) -> bool {
1236        let config = &self.language.config;
1237        let opt_in_servers = &config.scope_opt_in_language_servers;
1238        if opt_in_servers.contains(name) {
1239            if let Some(over) = self.config_override() {
1240                over.opt_into_language_servers.contains(name)
1241            } else {
1242                false
1243            }
1244        } else {
1245            true
1246        }
1247    }
1248
1249    pub fn override_name(&self) -> Option<&str> {
1250        let id = self.override_id?;
1251        let grammar = self.language.grammar.as_ref()?;
1252        let override_config = grammar.override_config.as_ref()?;
1253        override_config.values.get(&id).map(|e| e.name.as_str())
1254    }
1255
1256    fn config_override(&self) -> Option<&LanguageConfigOverride> {
1257        let id = self.override_id?;
1258        let grammar = self.language.grammar.as_ref()?;
1259        let override_config = grammar.override_config.as_ref()?;
1260        override_config.values.get(&id).map(|e| &e.value)
1261    }
1262}
1263
1264impl Hash for Language {
1265    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1266        self.id.hash(state)
1267    }
1268}
1269
1270impl PartialEq for Language {
1271    fn eq(&self, other: &Self) -> bool {
1272        self.id.eq(&other.id)
1273    }
1274}
1275
1276impl Eq for Language {}
1277
1278impl Debug for Language {
1279    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1280        f.debug_struct("Language")
1281            .field("name", &self.config.name)
1282            .finish()
1283    }
1284}
1285
1286pub(crate) fn parse_text(grammar: &Grammar, text: &Rope, old_tree: Option<Tree>) -> Tree {
1287    with_parser(|parser| {
1288        parser
1289            .set_language(&grammar.ts_language)
1290            .expect("incompatible grammar");
1291        let mut chunks = text.chunks_in_range(0..text.len());
1292        parser
1293            .parse_with_options(
1294                &mut move |offset, _| {
1295                    chunks.seek(offset);
1296                    chunks.next().unwrap_or("").as_bytes()
1297                },
1298                old_tree.as_ref(),
1299                None,
1300            )
1301            .unwrap()
1302    })
1303}
1304
1305pub trait CodeLabelExt {
1306    fn fallback_for_completion(
1307        item: &lsp::CompletionItem,
1308        language: Option<&Language>,
1309    ) -> CodeLabel;
1310}
1311
1312impl CodeLabelExt for CodeLabel {
1313    fn fallback_for_completion(
1314        item: &lsp::CompletionItem,
1315        language: Option<&Language>,
1316    ) -> CodeLabel {
1317        let highlight_id = item.kind.and_then(|kind| {
1318            let grammar = language?.grammar()?;
1319            use lsp::CompletionItemKind as Kind;
1320            match kind {
1321                Kind::CLASS => grammar.highlight_id_for_name("type"),
1322                Kind::CONSTANT => grammar.highlight_id_for_name("constant"),
1323                Kind::CONSTRUCTOR => grammar.highlight_id_for_name("constructor"),
1324                Kind::ENUM => grammar
1325                    .highlight_id_for_name("enum")
1326                    .or_else(|| grammar.highlight_id_for_name("type")),
1327                Kind::ENUM_MEMBER => grammar
1328                    .highlight_id_for_name("variant")
1329                    .or_else(|| grammar.highlight_id_for_name("property")),
1330                Kind::FIELD => grammar.highlight_id_for_name("property"),
1331                Kind::FUNCTION => grammar.highlight_id_for_name("function"),
1332                Kind::INTERFACE => grammar.highlight_id_for_name("type"),
1333                Kind::METHOD => grammar
1334                    .highlight_id_for_name("function.method")
1335                    .or_else(|| grammar.highlight_id_for_name("function")),
1336                Kind::OPERATOR => grammar.highlight_id_for_name("operator"),
1337                Kind::PROPERTY => grammar.highlight_id_for_name("property"),
1338                Kind::STRUCT => grammar.highlight_id_for_name("type"),
1339                Kind::VARIABLE => grammar.highlight_id_for_name("variable"),
1340                Kind::KEYWORD => grammar.highlight_id_for_name("keyword"),
1341                _ => None,
1342            }
1343        });
1344
1345        let label = &item.label;
1346        let label_length = label.len();
1347        let runs = highlight_id
1348            .map(|highlight_id| vec![(0..label_length, highlight_id)])
1349            .unwrap_or_default();
1350        let text = if let Some(detail) = item.detail.as_deref().filter(|detail| detail != label) {
1351            format!("{label} {detail}")
1352        } else if let Some(description) = item
1353            .label_details
1354            .as_ref()
1355            .and_then(|label_details| label_details.description.as_deref())
1356            .filter(|description| description != label)
1357        {
1358            format!("{label} {description}")
1359        } else {
1360            label.clone()
1361        };
1362        let filter_range = item
1363            .filter_text
1364            .as_deref()
1365            .and_then(|filter| text.find(filter).map(|ix| ix..ix + filter.len()))
1366            .unwrap_or(0..label_length);
1367        CodeLabel {
1368            text,
1369            runs,
1370            filter_range,
1371        }
1372    }
1373}
1374
1375#[cfg(any(test, feature = "test-support"))]
1376impl Default for FakeLspAdapter {
1377    fn default() -> Self {
1378        Self {
1379            name: "the-fake-language-server",
1380            capabilities: lsp::LanguageServer::full_capabilities(),
1381            initializer: None,
1382            disk_based_diagnostics_progress_token: None,
1383            initialization_options: None,
1384            disk_based_diagnostics_sources: Vec::new(),
1385            prettier_plugins: Vec::new(),
1386            language_server_binary: LanguageServerBinary {
1387                path: "/the/fake/lsp/path".into(),
1388                arguments: vec![],
1389                env: Default::default(),
1390            },
1391            label_for_completion: None,
1392        }
1393    }
1394}
1395
1396#[cfg(any(test, feature = "test-support"))]
1397impl LspInstaller for FakeLspAdapter {
1398    type BinaryVersion = ();
1399
1400    async fn fetch_latest_server_version(
1401        &self,
1402        _: &dyn LspAdapterDelegate,
1403        _: bool,
1404        _: &mut AsyncApp,
1405    ) -> Result<Self::BinaryVersion> {
1406        unreachable!()
1407    }
1408
1409    async fn check_if_user_installed(
1410        &self,
1411        _: &dyn LspAdapterDelegate,
1412        _: Option<Toolchain>,
1413        _: &AsyncApp,
1414    ) -> Option<LanguageServerBinary> {
1415        Some(self.language_server_binary.clone())
1416    }
1417
1418    async fn fetch_server_binary(
1419        &self,
1420        _: (),
1421        _: PathBuf,
1422        _: &dyn LspAdapterDelegate,
1423    ) -> Result<LanguageServerBinary> {
1424        unreachable!();
1425    }
1426
1427    async fn cached_server_binary(
1428        &self,
1429        _: PathBuf,
1430        _: &dyn LspAdapterDelegate,
1431    ) -> Option<LanguageServerBinary> {
1432        unreachable!();
1433    }
1434}
1435
1436#[cfg(any(test, feature = "test-support"))]
1437#[async_trait(?Send)]
1438impl LspAdapter for FakeLspAdapter {
1439    fn name(&self) -> LanguageServerName {
1440        LanguageServerName(self.name.into())
1441    }
1442
1443    fn disk_based_diagnostic_sources(&self) -> Vec<String> {
1444        self.disk_based_diagnostics_sources.clone()
1445    }
1446
1447    fn disk_based_diagnostics_progress_token(&self) -> Option<String> {
1448        self.disk_based_diagnostics_progress_token.clone()
1449    }
1450
1451    async fn initialization_options(
1452        self: Arc<Self>,
1453        _: &Arc<dyn LspAdapterDelegate>,
1454        _cx: &mut AsyncApp,
1455    ) -> Result<Option<Value>> {
1456        Ok(self.initialization_options.clone())
1457    }
1458
1459    async fn label_for_completion(
1460        &self,
1461        item: &lsp::CompletionItem,
1462        language: &Arc<Language>,
1463    ) -> Option<CodeLabel> {
1464        let label_for_completion = self.label_for_completion.as_ref()?;
1465        label_for_completion(item, language)
1466    }
1467
1468    fn is_extension(&self) -> bool {
1469        false
1470    }
1471}
1472
1473pub fn point_to_lsp(point: PointUtf16) -> lsp::Position {
1474    lsp::Position::new(point.row, point.column)
1475}
1476
1477pub fn point_from_lsp(point: lsp::Position) -> Unclipped<PointUtf16> {
1478    Unclipped(PointUtf16::new(point.line, point.character))
1479}
1480
1481pub fn range_to_lsp(range: Range<PointUtf16>) -> Result<lsp::Range> {
1482    anyhow::ensure!(
1483        range.start <= range.end,
1484        "Inverted range provided to an LSP request: {:?}-{:?}",
1485        range.start,
1486        range.end
1487    );
1488    Ok(lsp::Range {
1489        start: point_to_lsp(range.start),
1490        end: point_to_lsp(range.end),
1491    })
1492}
1493
1494pub fn range_from_lsp(range: lsp::Range) -> Range<Unclipped<PointUtf16>> {
1495    let mut start = point_from_lsp(range.start);
1496    let mut end = point_from_lsp(range.end);
1497    if start > end {
1498        // We debug instead of warn so that this is not logged by default unless explicitly requested.
1499        // Using warn would write to the log file, and since we receive an enormous amount of
1500        // range_from_lsp calls (especially during completions), that can hang the main thread.
1501        //
1502        // See issue #36223.
1503        zlog::debug!("range_from_lsp called with inverted range {start:?}-{end:?}");
1504        mem::swap(&mut start, &mut end);
1505    }
1506    start..end
1507}
1508
1509#[doc(hidden)]
1510#[cfg(any(test, feature = "test-support"))]
1511pub fn rust_lang() -> Arc<Language> {
1512    use std::borrow::Cow;
1513
1514    let language = Language::new(
1515        LanguageConfig {
1516            name: "Rust".into(),
1517            matcher: LanguageMatcher {
1518                path_suffixes: vec!["rs".to_string()],
1519                ..Default::default()
1520            },
1521            line_comments: vec!["// ".into(), "/// ".into(), "//! ".into()],
1522            brackets: BracketPairConfig {
1523                pairs: vec![
1524                    BracketPair {
1525                        start: "{".into(),
1526                        end: "}".into(),
1527                        close: true,
1528                        surround: false,
1529                        newline: true,
1530                    },
1531                    BracketPair {
1532                        start: "[".into(),
1533                        end: "]".into(),
1534                        close: true,
1535                        surround: false,
1536                        newline: true,
1537                    },
1538                    BracketPair {
1539                        start: "(".into(),
1540                        end: ")".into(),
1541                        close: true,
1542                        surround: false,
1543                        newline: true,
1544                    },
1545                    BracketPair {
1546                        start: "<".into(),
1547                        end: ">".into(),
1548                        close: false,
1549                        surround: false,
1550                        newline: true,
1551                    },
1552                    BracketPair {
1553                        start: "\"".into(),
1554                        end: "\"".into(),
1555                        close: true,
1556                        surround: false,
1557                        newline: false,
1558                    },
1559                ],
1560                ..Default::default()
1561            },
1562            ..Default::default()
1563        },
1564        Some(tree_sitter_rust::LANGUAGE.into()),
1565    )
1566    .with_queries(LanguageQueries {
1567        outline: Some(Cow::from(include_str!(
1568            "../../grammars/src/rust/outline.scm"
1569        ))),
1570        indents: Some(Cow::from(include_str!(
1571            "../../grammars/src/rust/indents.scm"
1572        ))),
1573        brackets: Some(Cow::from(include_str!(
1574            "../../grammars/src/rust/brackets.scm"
1575        ))),
1576        text_objects: Some(Cow::from(include_str!(
1577            "../../grammars/src/rust/textobjects.scm"
1578        ))),
1579        highlights: Some(Cow::from(include_str!(
1580            "../../grammars/src/rust/highlights.scm"
1581        ))),
1582        injections: Some(Cow::from(include_str!(
1583            "../../grammars/src/rust/injections.scm"
1584        ))),
1585        overrides: Some(Cow::from(include_str!(
1586            "../../grammars/src/rust/overrides.scm"
1587        ))),
1588        redactions: None,
1589        runnables: Some(Cow::from(include_str!(
1590            "../../grammars/src/rust/runnables.scm"
1591        ))),
1592        debugger: Some(Cow::from(include_str!(
1593            "../../grammars/src/rust/debugger.scm"
1594        ))),
1595    })
1596    .expect("Could not parse queries");
1597    Arc::new(language)
1598}
1599
1600#[doc(hidden)]
1601#[cfg(any(test, feature = "test-support"))]
1602pub fn markdown_lang() -> Arc<Language> {
1603    use std::borrow::Cow;
1604
1605    let language = Language::new(
1606        LanguageConfig {
1607            name: "Markdown".into(),
1608            matcher: LanguageMatcher {
1609                path_suffixes: vec!["md".into()],
1610                ..Default::default()
1611            },
1612            ..LanguageConfig::default()
1613        },
1614        Some(tree_sitter_md::LANGUAGE.into()),
1615    )
1616    .with_queries(LanguageQueries {
1617        brackets: Some(Cow::from(include_str!(
1618            "../../grammars/src/markdown/brackets.scm"
1619        ))),
1620        injections: Some(Cow::from(include_str!(
1621            "../../grammars/src/markdown/injections.scm"
1622        ))),
1623        highlights: Some(Cow::from(include_str!(
1624            "../../grammars/src/markdown/highlights.scm"
1625        ))),
1626        indents: Some(Cow::from(include_str!(
1627            "../../grammars/src/markdown/indents.scm"
1628        ))),
1629        outline: Some(Cow::from(include_str!(
1630            "../../grammars/src/markdown/outline.scm"
1631        ))),
1632        ..LanguageQueries::default()
1633    })
1634    .expect("Could not parse markdown queries");
1635    Arc::new(language)
1636}
1637
1638#[cfg(test)]
1639mod tests {
1640    use super::*;
1641    use gpui::{TestAppContext, rgba};
1642    use pretty_assertions::assert_matches;
1643
1644    #[test]
1645    fn test_highlight_map() {
1646        let theme = SyntaxTheme::new(
1647            [
1648                ("function", rgba(0x100000ff)),
1649                ("function.method", rgba(0x200000ff)),
1650                ("function.async", rgba(0x300000ff)),
1651                ("variable.builtin.self.rust", rgba(0x400000ff)),
1652                ("variable.builtin", rgba(0x500000ff)),
1653                ("variable", rgba(0x600000ff)),
1654            ]
1655            .iter()
1656            .map(|(name, color)| (name.to_string(), (*color).into())),
1657        );
1658
1659        let capture_names = &[
1660            "function.special",
1661            "function.async.rust",
1662            "variable.builtin.self",
1663        ];
1664
1665        let map = build_highlight_map(capture_names, &theme);
1666        assert_eq!(
1667            theme.get_capture_name(map.get(0).unwrap()),
1668            Some("function")
1669        );
1670        assert_eq!(
1671            theme.get_capture_name(map.get(1).unwrap()),
1672            Some("function.async")
1673        );
1674        assert_eq!(
1675            theme.get_capture_name(map.get(2).unwrap()),
1676            Some("variable.builtin")
1677        );
1678    }
1679
1680    #[gpui::test(iterations = 10)]
1681
1682    async fn test_language_loading(cx: &mut TestAppContext) {
1683        let languages = LanguageRegistry::test(cx.executor());
1684        let languages = Arc::new(languages);
1685        languages.register_native_grammars([
1686            ("json", tree_sitter_json::LANGUAGE),
1687            ("rust", tree_sitter_rust::LANGUAGE),
1688        ]);
1689        languages.register_test_language(LanguageConfig {
1690            name: "JSON".into(),
1691            grammar: Some("json".into()),
1692            matcher: LanguageMatcher {
1693                path_suffixes: vec!["json".into()],
1694                ..Default::default()
1695            },
1696            ..Default::default()
1697        });
1698        languages.register_test_language(LanguageConfig {
1699            name: "Rust".into(),
1700            grammar: Some("rust".into()),
1701            matcher: LanguageMatcher {
1702                path_suffixes: vec!["rs".into()],
1703                ..Default::default()
1704            },
1705            ..Default::default()
1706        });
1707        assert_eq!(
1708            languages.language_names(),
1709            &[
1710                LanguageName::new_static("JSON"),
1711                LanguageName::new_static("Plain Text"),
1712                LanguageName::new_static("Rust"),
1713            ]
1714        );
1715
1716        let rust1 = languages.language_for_name("Rust");
1717        let rust2 = languages.language_for_name("Rust");
1718
1719        // Ensure language is still listed even if it's being loaded.
1720        assert_eq!(
1721            languages.language_names(),
1722            &[
1723                LanguageName::new_static("JSON"),
1724                LanguageName::new_static("Plain Text"),
1725                LanguageName::new_static("Rust"),
1726            ]
1727        );
1728
1729        let (rust1, rust2) = futures::join!(rust1, rust2);
1730        assert!(Arc::ptr_eq(&rust1.unwrap(), &rust2.unwrap()));
1731
1732        // Ensure language is still listed even after loading it.
1733        assert_eq!(
1734            languages.language_names(),
1735            &[
1736                LanguageName::new_static("JSON"),
1737                LanguageName::new_static("Plain Text"),
1738                LanguageName::new_static("Rust"),
1739            ]
1740        );
1741
1742        // Loading an unknown language returns an error.
1743        assert!(languages.language_for_name("Unknown").await.is_err());
1744    }
1745
1746    #[gpui::test]
1747    async fn test_completion_label_omits_duplicate_data() {
1748        let regular_completion_item_1 = lsp::CompletionItem {
1749            label: "regular1".to_string(),
1750            detail: Some("detail1".to_string()),
1751            label_details: Some(lsp::CompletionItemLabelDetails {
1752                detail: None,
1753                description: Some("description 1".to_string()),
1754            }),
1755            ..lsp::CompletionItem::default()
1756        };
1757
1758        let regular_completion_item_2 = lsp::CompletionItem {
1759            label: "regular2".to_string(),
1760            label_details: Some(lsp::CompletionItemLabelDetails {
1761                detail: None,
1762                description: Some("description 2".to_string()),
1763            }),
1764            ..lsp::CompletionItem::default()
1765        };
1766
1767        let completion_item_with_duplicate_detail_and_proper_description = lsp::CompletionItem {
1768            detail: Some(regular_completion_item_1.label.clone()),
1769            ..regular_completion_item_1.clone()
1770        };
1771
1772        let completion_item_with_duplicate_detail = lsp::CompletionItem {
1773            detail: Some(regular_completion_item_1.label.clone()),
1774            label_details: None,
1775            ..regular_completion_item_1.clone()
1776        };
1777
1778        let completion_item_with_duplicate_description = lsp::CompletionItem {
1779            label_details: Some(lsp::CompletionItemLabelDetails {
1780                detail: None,
1781                description: Some(regular_completion_item_2.label.clone()),
1782            }),
1783            ..regular_completion_item_2.clone()
1784        };
1785
1786        assert_eq!(
1787            CodeLabel::fallback_for_completion(&regular_completion_item_1, None).text,
1788            format!(
1789                "{} {}",
1790                regular_completion_item_1.label,
1791                regular_completion_item_1.detail.unwrap()
1792            ),
1793            "LSP completion items with both detail and label_details.description should prefer detail"
1794        );
1795        assert_eq!(
1796            CodeLabel::fallback_for_completion(&regular_completion_item_2, None).text,
1797            format!(
1798                "{} {}",
1799                regular_completion_item_2.label,
1800                regular_completion_item_2
1801                    .label_details
1802                    .as_ref()
1803                    .unwrap()
1804                    .description
1805                    .as_ref()
1806                    .unwrap()
1807            ),
1808            "LSP completion items without detail but with label_details.description should use that"
1809        );
1810        assert_eq!(
1811            CodeLabel::fallback_for_completion(
1812                &completion_item_with_duplicate_detail_and_proper_description,
1813                None
1814            )
1815            .text,
1816            format!(
1817                "{} {}",
1818                regular_completion_item_1.label,
1819                regular_completion_item_1
1820                    .label_details
1821                    .as_ref()
1822                    .unwrap()
1823                    .description
1824                    .as_ref()
1825                    .unwrap()
1826            ),
1827            "LSP completion items with both detail and label_details.description should prefer description only if the detail duplicates the completion label"
1828        );
1829        assert_eq!(
1830            CodeLabel::fallback_for_completion(&completion_item_with_duplicate_detail, None).text,
1831            regular_completion_item_1.label,
1832            "LSP completion items with duplicate label and detail, should omit the detail"
1833        );
1834        assert_eq!(
1835            CodeLabel::fallback_for_completion(&completion_item_with_duplicate_description, None)
1836                .text,
1837            regular_completion_item_2.label,
1838            "LSP completion items with duplicate label and detail, should omit the detail"
1839        );
1840    }
1841
1842    #[test]
1843    fn test_deserializing_comments_backwards_compat() {
1844        // current version of `block_comment` and `documentation_comment` work
1845        {
1846            let config: LanguageConfig = ::toml::from_str(
1847                r#"
1848                name = "Foo"
1849                block_comment = { start = "a", end = "b", prefix = "c", tab_size = 1 }
1850                documentation_comment = { start = "d", end = "e", prefix = "f", tab_size = 2 }
1851                "#,
1852            )
1853            .unwrap();
1854            assert_matches!(config.block_comment, Some(BlockCommentConfig { .. }));
1855            assert_matches!(
1856                config.documentation_comment,
1857                Some(BlockCommentConfig { .. })
1858            );
1859
1860            let block_config = config.block_comment.unwrap();
1861            assert_eq!(block_config.start.as_ref(), "a");
1862            assert_eq!(block_config.end.as_ref(), "b");
1863            assert_eq!(block_config.prefix.as_ref(), "c");
1864            assert_eq!(block_config.tab_size, 1);
1865
1866            let doc_config = config.documentation_comment.unwrap();
1867            assert_eq!(doc_config.start.as_ref(), "d");
1868            assert_eq!(doc_config.end.as_ref(), "e");
1869            assert_eq!(doc_config.prefix.as_ref(), "f");
1870            assert_eq!(doc_config.tab_size, 2);
1871        }
1872
1873        // former `documentation` setting is read into `documentation_comment`
1874        {
1875            let config: LanguageConfig = ::toml::from_str(
1876                r#"
1877                name = "Foo"
1878                documentation = { start = "a", end = "b", prefix = "c", tab_size = 1}
1879                "#,
1880            )
1881            .unwrap();
1882            assert_matches!(
1883                config.documentation_comment,
1884                Some(BlockCommentConfig { .. })
1885            );
1886
1887            let config = config.documentation_comment.unwrap();
1888            assert_eq!(config.start.as_ref(), "a");
1889            assert_eq!(config.end.as_ref(), "b");
1890            assert_eq!(config.prefix.as_ref(), "c");
1891            assert_eq!(config.tab_size, 1);
1892        }
1893
1894        // old block_comment format is read into BlockCommentConfig
1895        {
1896            let config: LanguageConfig = ::toml::from_str(
1897                r#"
1898                name = "Foo"
1899                block_comment = ["a", "b"]
1900                "#,
1901            )
1902            .unwrap();
1903            assert_matches!(config.block_comment, Some(BlockCommentConfig { .. }));
1904
1905            let config = config.block_comment.unwrap();
1906            assert_eq!(config.start.as_ref(), "a");
1907            assert_eq!(config.end.as_ref(), "b");
1908            assert_eq!(config.prefix.as_ref(), "");
1909            assert_eq!(config.tab_size, 0);
1910        }
1911    }
1912}