lsp_store.rs

   1pub mod clangd_ext;
   2pub mod lsp_ext_command;
   3pub mod rust_analyzer_ext;
   4
   5use crate::{
   6    buffer_store::{BufferStore, BufferStoreEvent},
   7    deserialize_code_actions,
   8    environment::ProjectEnvironment,
   9    lsp_command::{self, *},
  10    prettier_store::{self, PrettierStore, PrettierStoreEvent},
  11    project_settings::{LspSettings, ProjectSettings},
  12    project_tree::{AdapterQuery, LanguageServerTree, LaunchDisposition, ProjectTree},
  13    relativize_path, resolve_path,
  14    toolchain_store::{EmptyToolchainStore, ToolchainStoreEvent},
  15    worktree_store::{WorktreeStore, WorktreeStoreEvent},
  16    yarn::YarnPathStore,
  17    CodeAction, Completion, CompletionSource, CoreCompletion, Hover, InlayHint, LspAction,
  18    ProjectItem as _, ProjectPath, ProjectTransaction, ResolveState, Symbol, ToolchainStore,
  19};
  20use anyhow::{anyhow, Context as _, Result};
  21use async_trait::async_trait;
  22use client::{proto, TypedEnvelope};
  23use collections::{btree_map, BTreeMap, BTreeSet, HashMap, HashSet};
  24use futures::{
  25    future::{join_all, Shared},
  26    select, select_biased,
  27    stream::FuturesUnordered,
  28    AsyncWriteExt, Future, FutureExt, StreamExt,
  29};
  30use globset::{Glob, GlobBuilder, GlobMatcher, GlobSet, GlobSetBuilder};
  31use gpui::{
  32    App, AppContext, AsyncApp, Context, Entity, EventEmitter, PromptLevel, SharedString, Task,
  33    WeakEntity,
  34};
  35use http_client::HttpClient;
  36use itertools::Itertools as _;
  37use language::{
  38    language_settings::{
  39        language_settings, FormatOnSave, Formatter, LanguageSettings, SelectedFormatter,
  40    },
  41    point_to_lsp,
  42    proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
  43    range_from_lsp, range_to_lsp, Bias, BinaryStatus, Buffer, BufferSnapshot, CachedLspAdapter,
  44    CodeLabel, Diagnostic, DiagnosticEntry, DiagnosticSet, Diff, File as _, Language,
  45    LanguageRegistry, LanguageToolchainStore, LocalFile, LspAdapter, LspAdapterDelegate, Patch,
  46    PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction, Unclipped,
  47};
  48use lsp::{
  49    notification::DidRenameFiles, CodeActionKind, CompletionContext, DiagnosticSeverity,
  50    DiagnosticTag, DidChangeWatchedFilesRegistrationOptions, Edit, FileOperationFilter,
  51    FileOperationPatternKind, FileOperationRegistrationOptions, FileRename, FileSystemWatcher,
  52    LanguageServer, LanguageServerBinary, LanguageServerBinaryOptions, LanguageServerId,
  53    LanguageServerName, LspRequestFuture, MessageActionItem, MessageType, OneOf, RenameFilesParams,
  54    SymbolKind, TextEdit, WillRenameFiles, WorkDoneProgressCancelParams, WorkspaceFolder,
  55};
  56use node_runtime::read_package_installed_version;
  57use parking_lot::Mutex;
  58use postage::watch;
  59use rand::prelude::*;
  60
  61use rpc::{
  62    proto::{FromProto, ToProto},
  63    AnyProtoClient,
  64};
  65use serde::Serialize;
  66use settings::{Settings, SettingsLocation, SettingsStore};
  67use sha2::{Digest, Sha256};
  68use smol::channel::Sender;
  69use snippet::Snippet;
  70use std::{
  71    any::Any,
  72    borrow::Cow,
  73    cell::RefCell,
  74    cmp::Ordering,
  75    convert::TryInto,
  76    ffi::OsStr,
  77    iter, mem,
  78    ops::{ControlFlow, Range},
  79    path::{self, Path, PathBuf},
  80    rc::Rc,
  81    str,
  82    sync::Arc,
  83    time::{Duration, Instant},
  84};
  85use text::{Anchor, BufferId, LineEnding, OffsetRangeExt, TransactionId};
  86use url::Url;
  87use util::{
  88    debug_panic, defer, maybe, merge_json_value_into, paths::SanitizedPath, post_inc, ResultExt,
  89    TryFutureExt as _,
  90};
  91
  92pub use fs::*;
  93pub use language::Location;
  94#[cfg(any(test, feature = "test-support"))]
  95pub use prettier::FORMAT_SUFFIX as TEST_PRETTIER_FORMAT_SUFFIX;
  96pub use worktree::{
  97    Entry, EntryKind, File, LocalWorktree, PathChange, ProjectEntryId, UpdatedEntriesSet,
  98    UpdatedGitRepositoriesSet, Worktree, WorktreeId, WorktreeSettings, FS_WATCH_LATENCY,
  99};
 100
 101const SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
 102pub const SERVER_PROGRESS_THROTTLE_TIMEOUT: Duration = Duration::from_millis(100);
 103
 104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 105pub enum FormatTrigger {
 106    Save,
 107    Manual,
 108}
 109
 110pub enum LspFormatTarget {
 111    Buffers,
 112    Ranges(BTreeMap<BufferId, Vec<Range<Anchor>>>),
 113}
 114
 115pub type OpenLspBufferHandle = Entity<Entity<Buffer>>;
 116
 117// Currently, formatting operations are represented differently depending on
 118// whether they come from a language server or an external command.
 119#[derive(Debug)]
 120pub enum FormatOperation {
 121    Lsp(Vec<(Range<Anchor>, Arc<str>)>),
 122    External(Diff),
 123    Prettier(Diff),
 124}
 125
 126impl FormatTrigger {
 127    fn from_proto(value: i32) -> FormatTrigger {
 128        match value {
 129            0 => FormatTrigger::Save,
 130            1 => FormatTrigger::Manual,
 131            _ => FormatTrigger::Save,
 132        }
 133    }
 134}
 135
 136pub struct LocalLspStore {
 137    weak: WeakEntity<LspStore>,
 138    worktree_store: Entity<WorktreeStore>,
 139    toolchain_store: Entity<ToolchainStore>,
 140    http_client: Arc<dyn HttpClient>,
 141    environment: Entity<ProjectEnvironment>,
 142    fs: Arc<dyn Fs>,
 143    languages: Arc<LanguageRegistry>,
 144    language_server_ids: HashMap<(WorktreeId, LanguageServerName), BTreeSet<LanguageServerId>>,
 145    yarn: Entity<YarnPathStore>,
 146    pub language_servers: HashMap<LanguageServerId, LanguageServerState>,
 147    buffers_being_formatted: HashSet<BufferId>,
 148    last_workspace_edits_by_language_server: HashMap<LanguageServerId, ProjectTransaction>,
 149    language_server_watched_paths: HashMap<LanguageServerId, LanguageServerWatchedPaths>,
 150    language_server_paths_watched_for_rename:
 151        HashMap<LanguageServerId, RenamePathsWatchedForServer>,
 152    language_server_watcher_registrations:
 153        HashMap<LanguageServerId, HashMap<String, Vec<FileSystemWatcher>>>,
 154    supplementary_language_servers:
 155        HashMap<LanguageServerId, (LanguageServerName, Arc<LanguageServer>)>,
 156    prettier_store: Entity<PrettierStore>,
 157    next_diagnostic_group_id: usize,
 158    diagnostics: HashMap<
 159        WorktreeId,
 160        HashMap<
 161            Arc<Path>,
 162            Vec<(
 163                LanguageServerId,
 164                Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
 165            )>,
 166        >,
 167    >,
 168    buffer_snapshots: HashMap<BufferId, HashMap<LanguageServerId, Vec<LspBufferSnapshot>>>, // buffer_id -> server_id -> vec of snapshots
 169    _subscription: gpui::Subscription,
 170    lsp_tree: Entity<LanguageServerTree>,
 171    registered_buffers: HashMap<BufferId, usize>,
 172}
 173
 174impl LocalLspStore {
 175    /// Returns the running language server for the given ID. Note if the language server is starting, it will not be returned.
 176    pub fn running_language_server_for_id(
 177        &self,
 178        id: LanguageServerId,
 179    ) -> Option<&Arc<LanguageServer>> {
 180        let language_server_state = self.language_servers.get(&id)?;
 181
 182        match language_server_state {
 183            LanguageServerState::Running { server, .. } => Some(server),
 184            LanguageServerState::Starting { .. } => None,
 185        }
 186    }
 187
 188    fn start_language_server(
 189        &mut self,
 190        worktree_handle: &Entity<Worktree>,
 191        delegate: Arc<LocalLspAdapterDelegate>,
 192        adapter: Arc<CachedLspAdapter>,
 193        settings: Arc<LspSettings>,
 194        cx: &mut App,
 195    ) -> LanguageServerId {
 196        let worktree = worktree_handle.read(cx);
 197        let worktree_id = worktree.id();
 198        let root_path = worktree.abs_path();
 199        let key = (worktree_id, adapter.name.clone());
 200
 201        let override_options = settings.initialization_options.clone();
 202
 203        let stderr_capture = Arc::new(Mutex::new(Some(String::new())));
 204
 205        let server_id = self.languages.next_language_server_id();
 206        log::info!(
 207            "attempting to start language server {:?}, path: {root_path:?}, id: {server_id}",
 208            adapter.name.0
 209        );
 210
 211        let binary = self.get_language_server_binary(adapter.clone(), delegate.clone(), true, cx);
 212        let pending_workspace_folders: Arc<Mutex<BTreeSet<Url>>> = Default::default();
 213        let pending_server = cx.spawn({
 214            let adapter = adapter.clone();
 215            let server_name = adapter.name.clone();
 216            let stderr_capture = stderr_capture.clone();
 217            #[cfg(any(test, feature = "test-support"))]
 218            let lsp_store = self.weak.clone();
 219            let pending_workspace_folders = pending_workspace_folders.clone();
 220            async move |cx| {
 221                let binary = binary.await?;
 222                #[cfg(any(test, feature = "test-support"))]
 223                if let Some(server) = lsp_store
 224                    .update(&mut cx.clone(), |this, cx| {
 225                        this.languages.create_fake_language_server(
 226                            server_id,
 227                            &server_name,
 228                            binary.clone(),
 229                            &mut cx.to_async(),
 230                        )
 231                    })
 232                    .ok()
 233                    .flatten()
 234                {
 235                    return Ok(server);
 236                }
 237
 238                lsp::LanguageServer::new(
 239                    stderr_capture,
 240                    server_id,
 241                    server_name,
 242                    binary,
 243                    &root_path,
 244                    adapter.code_action_kinds(),
 245                    pending_workspace_folders,
 246                    cx,
 247                )
 248            }
 249        });
 250
 251        let startup = {
 252            let server_name = adapter.name.0.clone();
 253            let delegate = delegate as Arc<dyn LspAdapterDelegate>;
 254            let key = key.clone();
 255            let adapter = adapter.clone();
 256            let this = self.weak.clone();
 257            let pending_workspace_folders = pending_workspace_folders.clone();
 258            let fs = self.fs.clone();
 259            cx.spawn(async move |cx| {
 260                let result = async {
 261                    let toolchains = this.update(cx, |this, cx| this.toolchain_store(cx))?;
 262                    let language_server = pending_server.await?;
 263
 264                    let workspace_config = adapter
 265                        .adapter
 266                        .clone()
 267                        .workspace_configuration(fs.as_ref(), &delegate, toolchains.clone(), cx)
 268                        .await?;
 269
 270                    let mut initialization_options = adapter
 271                        .adapter
 272                        .clone()
 273                        .initialization_options(fs.as_ref(), &(delegate))
 274                        .await?;
 275
 276                    match (&mut initialization_options, override_options) {
 277                        (Some(initialization_options), Some(override_options)) => {
 278                            merge_json_value_into(override_options, initialization_options);
 279                        }
 280                        (None, override_options) => initialization_options = override_options,
 281                        _ => {}
 282                    }
 283
 284                    let initialization_params = cx.update(|cx| {
 285                        let mut params = language_server.default_initialize_params(cx);
 286                        params.initialization_options = initialization_options;
 287                        adapter.adapter.prepare_initialize_params(params)
 288                    })??;
 289
 290                    Self::setup_lsp_messages(
 291                        this.clone(),
 292                        fs,
 293                        &language_server,
 294                        delegate.clone(),
 295                        adapter.clone(),
 296                    );
 297
 298                    let did_change_configuration_params =
 299                        Arc::new(lsp::DidChangeConfigurationParams {
 300                            settings: workspace_config,
 301                        });
 302                    let language_server = cx
 303                        .update(|cx| {
 304                            language_server.initialize(
 305                                initialization_params,
 306                                did_change_configuration_params.clone(),
 307                                cx,
 308                            )
 309                        })?
 310                        .await
 311                        .inspect_err(|_| {
 312                            if let Some(this) = this.upgrade() {
 313                                this.update(cx, |_, cx| {
 314                                    cx.emit(LspStoreEvent::LanguageServerRemoved(server_id))
 315                                })
 316                                .ok();
 317                            }
 318                        })?;
 319
 320                    language_server
 321                        .notify::<lsp::notification::DidChangeConfiguration>(
 322                            &did_change_configuration_params,
 323                        )
 324                        .ok();
 325
 326                    anyhow::Ok(language_server)
 327                }
 328                .await;
 329
 330                match result {
 331                    Ok(server) => {
 332                        this.update(cx, |this, mut cx| {
 333                            this.insert_newly_running_language_server(
 334                                adapter,
 335                                server.clone(),
 336                                server_id,
 337                                key,
 338                                pending_workspace_folders,
 339                                &mut cx,
 340                            );
 341                        })
 342                        .ok();
 343                        stderr_capture.lock().take();
 344                        Some(server)
 345                    }
 346
 347                    Err(err) => {
 348                        let log = stderr_capture.lock().take().unwrap_or_default();
 349                        delegate.update_status(
 350                            adapter.name(),
 351                            BinaryStatus::Failed {
 352                                error: format!("{err}\n-- stderr--\n{}", log),
 353                            },
 354                        );
 355                        log::error!("Failed to start language server {server_name:?}: {err}");
 356                        log::error!("server stderr: {:?}", log);
 357                        None
 358                    }
 359                }
 360            })
 361        };
 362        let state = LanguageServerState::Starting {
 363            startup,
 364            pending_workspace_folders,
 365        };
 366
 367        self.language_servers.insert(server_id, state);
 368        self.language_server_ids
 369            .entry(key)
 370            .or_default()
 371            .insert(server_id);
 372        server_id
 373    }
 374
 375    fn get_language_server_binary(
 376        &self,
 377        adapter: Arc<CachedLspAdapter>,
 378        delegate: Arc<dyn LspAdapterDelegate>,
 379        allow_binary_download: bool,
 380        cx: &mut App,
 381    ) -> Task<Result<LanguageServerBinary>> {
 382        let settings = ProjectSettings::get(
 383            Some(SettingsLocation {
 384                worktree_id: delegate.worktree_id(),
 385                path: Path::new(""),
 386            }),
 387            cx,
 388        )
 389        .lsp
 390        .get(&adapter.name)
 391        .and_then(|s| s.binary.clone());
 392
 393        if settings.as_ref().is_some_and(|b| b.path.is_some()) {
 394            let settings = settings.unwrap();
 395            return cx.spawn(async move |_| {
 396                Ok(LanguageServerBinary {
 397                    path: PathBuf::from(&settings.path.unwrap()),
 398                    env: Some(delegate.shell_env().await),
 399                    arguments: settings
 400                        .arguments
 401                        .unwrap_or_default()
 402                        .iter()
 403                        .map(Into::into)
 404                        .collect(),
 405                })
 406            });
 407        }
 408        let lsp_binary_options = LanguageServerBinaryOptions {
 409            allow_path_lookup: !settings
 410                .as_ref()
 411                .and_then(|b| b.ignore_system_version)
 412                .unwrap_or_default(),
 413            allow_binary_download,
 414        };
 415        let toolchains = self.toolchain_store.read(cx).as_language_toolchain_store();
 416        cx.spawn(async move |cx| {
 417            let binary_result = adapter
 418                .clone()
 419                .get_language_server_command(delegate.clone(), toolchains, lsp_binary_options, cx)
 420                .await;
 421
 422            delegate.update_status(adapter.name.clone(), BinaryStatus::None);
 423
 424            let mut binary = binary_result?;
 425            if let Some(arguments) = settings.and_then(|b| b.arguments) {
 426                binary.arguments = arguments.into_iter().map(Into::into).collect();
 427            }
 428
 429            let mut shell_env = delegate.shell_env().await;
 430            shell_env.extend(binary.env.unwrap_or_default());
 431            binary.env = Some(shell_env);
 432            Ok(binary)
 433        })
 434    }
 435
 436    fn setup_lsp_messages(
 437        this: WeakEntity<LspStore>,
 438        fs: Arc<dyn Fs>,
 439        language_server: &LanguageServer,
 440        delegate: Arc<dyn LspAdapterDelegate>,
 441        adapter: Arc<CachedLspAdapter>,
 442    ) {
 443        let name = language_server.name();
 444        let server_id = language_server.server_id();
 445        language_server
 446            .on_notification::<lsp::notification::PublishDiagnostics, _>({
 447                let adapter = adapter.clone();
 448                let this = this.clone();
 449                move |mut params, cx| {
 450                    let adapter = adapter.clone();
 451                    if let Some(this) = this.upgrade() {
 452                        adapter.process_diagnostics(&mut params);
 453                        this.update(cx, |this, cx| {
 454                            this.update_diagnostics(
 455                                server_id,
 456                                params,
 457                                &adapter.disk_based_diagnostic_sources,
 458                                cx,
 459                            )
 460                            .log_err();
 461                        })
 462                        .ok();
 463                    }
 464                }
 465            })
 466            .detach();
 467        language_server
 468            .on_request::<lsp::request::WorkspaceConfiguration, _, _>({
 469                let adapter = adapter.adapter.clone();
 470                let delegate = delegate.clone();
 471                let this = this.clone();
 472                let fs = fs.clone();
 473                move |params, cx| {
 474                    let adapter = adapter.clone();
 475                    let delegate = delegate.clone();
 476                    let this = this.clone();
 477                    let fs = fs.clone();
 478                    let mut cx = cx.clone();
 479                    async move {
 480                        let toolchains =
 481                            this.update(&mut cx, |this, cx| this.toolchain_store(cx))?;
 482                        let workspace_config = adapter
 483                            .workspace_configuration(fs.as_ref(), &delegate, toolchains, &mut cx)
 484                            .await?;
 485                        Ok(params
 486                            .items
 487                            .into_iter()
 488                            .map(|item| {
 489                                if let Some(section) = &item.section {
 490                                    workspace_config
 491                                        .get(section)
 492                                        .cloned()
 493                                        .unwrap_or(serde_json::Value::Null)
 494                                } else {
 495                                    workspace_config.clone()
 496                                }
 497                            })
 498                            .collect())
 499                    }
 500                }
 501            })
 502            .detach();
 503
 504        language_server
 505            .on_request::<lsp::request::WorkspaceFoldersRequest, _, _>({
 506                let this = this.clone();
 507                move |_, cx| {
 508                    let this = this.clone();
 509                    let mut cx = cx.clone();
 510                    async move {
 511                        let Some(server) =
 512                            this.update(&mut cx, |this, _| this.language_server_for_id(server_id))?
 513                        else {
 514                            return Ok(None);
 515                        };
 516                        let root = server.workspace_folders();
 517                        Ok(Some(
 518                            root.iter()
 519                                .cloned()
 520                                .map(|uri| WorkspaceFolder {
 521                                    uri,
 522                                    name: Default::default(),
 523                                })
 524                                .collect(),
 525                        ))
 526                    }
 527                }
 528            })
 529            .detach();
 530        // Even though we don't have handling for these requests, respond to them to
 531        // avoid stalling any language server like `gopls` which waits for a response
 532        // to these requests when initializing.
 533        language_server
 534            .on_request::<lsp::request::WorkDoneProgressCreate, _, _>({
 535                let this = this.clone();
 536                move |params, cx| {
 537                    let this = this.clone();
 538                    let mut cx = cx.clone();
 539                    async move {
 540                        this.update(&mut cx, |this, _| {
 541                            if let Some(status) = this.language_server_statuses.get_mut(&server_id)
 542                            {
 543                                if let lsp::NumberOrString::String(token) = params.token {
 544                                    status.progress_tokens.insert(token);
 545                                }
 546                            }
 547                        })?;
 548
 549                        Ok(())
 550                    }
 551                }
 552            })
 553            .detach();
 554
 555        language_server
 556            .on_request::<lsp::request::RegisterCapability, _, _>({
 557                let this = this.clone();
 558                move |params, cx| {
 559                    let this = this.clone();
 560                    let mut cx = cx.clone();
 561                    async move {
 562                        for reg in params.registrations {
 563                            match reg.method.as_str() {
 564                                "workspace/didChangeWatchedFiles" => {
 565                                    if let Some(options) = reg.register_options {
 566                                        let options = serde_json::from_value(options)?;
 567                                        this.update(&mut cx, |this, cx| {
 568                                            this.as_local_mut()?.on_lsp_did_change_watched_files(
 569                                                server_id, &reg.id, options, cx,
 570                                            );
 571                                            Some(())
 572                                        })?;
 573                                    }
 574                                }
 575                                "textDocument/rangeFormatting" => {
 576                                    this.update(&mut cx, |this, _| {
 577                                        if let Some(server) = this.language_server_for_id(server_id)
 578                                        {
 579                                            let options = reg
 580                                                .register_options
 581                                                .map(|options| {
 582                                                    serde_json::from_value::<
 583                                                        lsp::DocumentRangeFormattingOptions,
 584                                                    >(
 585                                                        options
 586                                                    )
 587                                                })
 588                                                .transpose()?;
 589                                            let provider = match options {
 590                                                None => OneOf::Left(true),
 591                                                Some(options) => OneOf::Right(options),
 592                                            };
 593                                            server.update_capabilities(|capabilities| {
 594                                                capabilities.document_range_formatting_provider =
 595                                                    Some(provider);
 596                                            })
 597                                        }
 598                                        anyhow::Ok(())
 599                                    })??;
 600                                }
 601                                "textDocument/onTypeFormatting" => {
 602                                    this.update(&mut cx, |this, _| {
 603                                        if let Some(server) = this.language_server_for_id(server_id)
 604                                        {
 605                                            let options = reg
 606                                                .register_options
 607                                                .map(|options| {
 608                                                    serde_json::from_value::<
 609                                                        lsp::DocumentOnTypeFormattingOptions,
 610                                                    >(
 611                                                        options
 612                                                    )
 613                                                })
 614                                                .transpose()?;
 615                                            if let Some(options) = options {
 616                                                server.update_capabilities(|capabilities| {
 617                                                    capabilities
 618                                                        .document_on_type_formatting_provider =
 619                                                        Some(options);
 620                                                })
 621                                            }
 622                                        }
 623                                        anyhow::Ok(())
 624                                    })??;
 625                                }
 626                                "textDocument/formatting" => {
 627                                    this.update(&mut cx, |this, _| {
 628                                        if let Some(server) = this.language_server_for_id(server_id)
 629                                        {
 630                                            let options = reg
 631                                                .register_options
 632                                                .map(|options| {
 633                                                    serde_json::from_value::<
 634                                                        lsp::DocumentFormattingOptions,
 635                                                    >(
 636                                                        options
 637                                                    )
 638                                                })
 639                                                .transpose()?;
 640                                            let provider = match options {
 641                                                None => OneOf::Left(true),
 642                                                Some(options) => OneOf::Right(options),
 643                                            };
 644                                            server.update_capabilities(|capabilities| {
 645                                                capabilities.document_formatting_provider =
 646                                                    Some(provider);
 647                                            })
 648                                        }
 649                                        anyhow::Ok(())
 650                                    })??;
 651                                }
 652                                "workspace/didChangeConfiguration" => {
 653                                    // Ignore payload since we notify clients of setting changes unconditionally, relying on them pulling the latest settings.
 654                                }
 655                                "textDocument/rename" => {
 656                                    this.update(&mut cx, |this, _| {
 657                                        if let Some(server) = this.language_server_for_id(server_id)
 658                                        {
 659                                            let options = reg
 660                                                .register_options
 661                                                .map(|options| {
 662                                                    serde_json::from_value::<lsp::RenameOptions>(
 663                                                        options,
 664                                                    )
 665                                                })
 666                                                .transpose()?;
 667                                            let options = match options {
 668                                                None => OneOf::Left(true),
 669                                                Some(options) => OneOf::Right(options),
 670                                            };
 671
 672                                            server.update_capabilities(|capabilities| {
 673                                                capabilities.rename_provider = Some(options);
 674                                            })
 675                                        }
 676                                        anyhow::Ok(())
 677                                    })??;
 678                                }
 679                                _ => log::warn!("unhandled capability registration: {reg:?}"),
 680                            }
 681                        }
 682                        Ok(())
 683                    }
 684                }
 685            })
 686            .detach();
 687
 688        language_server
 689            .on_request::<lsp::request::UnregisterCapability, _, _>({
 690                let this = this.clone();
 691                move |params, cx| {
 692                    let this = this.clone();
 693                    let mut cx = cx.clone();
 694                    async move {
 695                        for unreg in params.unregisterations.iter() {
 696                            match unreg.method.as_str() {
 697                                "workspace/didChangeWatchedFiles" => {
 698                                    this.update(&mut cx, |this, cx| {
 699                                        this.as_local_mut()?
 700                                            .on_lsp_unregister_did_change_watched_files(
 701                                                server_id, &unreg.id, cx,
 702                                            );
 703                                        Some(())
 704                                    })?;
 705                                }
 706                                "workspace/didChangeConfiguration" => {
 707                                    // Ignore payload since we notify clients of setting changes unconditionally, relying on them pulling the latest settings.
 708                                }
 709                                "textDocument/rename" => {
 710                                    this.update(&mut cx, |this, _| {
 711                                        if let Some(server) = this.language_server_for_id(server_id)
 712                                        {
 713                                            server.update_capabilities(|capabilities| {
 714                                                capabilities.rename_provider = None
 715                                            })
 716                                        }
 717                                    })?;
 718                                }
 719                                "textDocument/rangeFormatting" => {
 720                                    this.update(&mut cx, |this, _| {
 721                                        if let Some(server) = this.language_server_for_id(server_id)
 722                                        {
 723                                            server.update_capabilities(|capabilities| {
 724                                                capabilities.document_range_formatting_provider =
 725                                                    None
 726                                            })
 727                                        }
 728                                    })?;
 729                                }
 730                                "textDocument/onTypeFormatting" => {
 731                                    this.update(&mut cx, |this, _| {
 732                                        if let Some(server) = this.language_server_for_id(server_id)
 733                                        {
 734                                            server.update_capabilities(|capabilities| {
 735                                                capabilities.document_on_type_formatting_provider =
 736                                                    None;
 737                                            })
 738                                        }
 739                                    })?;
 740                                }
 741                                "textDocument/formatting" => {
 742                                    this.update(&mut cx, |this, _| {
 743                                        if let Some(server) = this.language_server_for_id(server_id)
 744                                        {
 745                                            server.update_capabilities(|capabilities| {
 746                                                capabilities.document_formatting_provider = None;
 747                                            })
 748                                        }
 749                                    })?;
 750                                }
 751                                _ => log::warn!("unhandled capability unregistration: {unreg:?}"),
 752                            }
 753                        }
 754                        Ok(())
 755                    }
 756                }
 757            })
 758            .detach();
 759
 760        language_server
 761            .on_request::<lsp::request::ApplyWorkspaceEdit, _, _>({
 762                let adapter = adapter.clone();
 763                let this = this.clone();
 764                move |params, cx| {
 765                    let mut cx = cx.clone();
 766                    let this = this.clone();
 767                    let adapter = adapter.clone();
 768                    async move {
 769                        LocalLspStore::on_lsp_workspace_edit(
 770                            this.clone(),
 771                            params,
 772                            server_id,
 773                            adapter.clone(),
 774                            &mut cx,
 775                        )
 776                        .await
 777                    }
 778                }
 779            })
 780            .detach();
 781
 782        language_server
 783            .on_request::<lsp::request::InlayHintRefreshRequest, _, _>({
 784                let this = this.clone();
 785                move |(), cx| {
 786                    let this = this.clone();
 787                    let mut cx = cx.clone();
 788                    async move {
 789                        this.update(&mut cx, |this, cx| {
 790                            cx.emit(LspStoreEvent::RefreshInlayHints);
 791                            this.downstream_client.as_ref().map(|(client, project_id)| {
 792                                client.send(proto::RefreshInlayHints {
 793                                    project_id: *project_id,
 794                                })
 795                            })
 796                        })?
 797                        .transpose()?;
 798                        Ok(())
 799                    }
 800                }
 801            })
 802            .detach();
 803
 804        language_server
 805            .on_request::<lsp::request::CodeLensRefresh, _, _>({
 806                let this = this.clone();
 807                move |(), cx| {
 808                    let this = this.clone();
 809                    let mut cx = cx.clone();
 810                    async move {
 811                        this.update(&mut cx, |this, cx| {
 812                            cx.emit(LspStoreEvent::RefreshCodeLens);
 813                            this.downstream_client.as_ref().map(|(client, project_id)| {
 814                                client.send(proto::RefreshCodeLens {
 815                                    project_id: *project_id,
 816                                })
 817                            })
 818                        })?
 819                        .transpose()?;
 820                        Ok(())
 821                    }
 822                }
 823            })
 824            .detach();
 825
 826        language_server
 827            .on_request::<lsp::request::ShowMessageRequest, _, _>({
 828                let this = this.clone();
 829                let name = name.to_string();
 830                move |params, cx| {
 831                    let this = this.clone();
 832                    let name = name.to_string();
 833                    let mut cx = cx.clone();
 834                    async move {
 835                        let actions = params.actions.unwrap_or_default();
 836                        let (tx, rx) = smol::channel::bounded(1);
 837                        let request = LanguageServerPromptRequest {
 838                            level: match params.typ {
 839                                lsp::MessageType::ERROR => PromptLevel::Critical,
 840                                lsp::MessageType::WARNING => PromptLevel::Warning,
 841                                _ => PromptLevel::Info,
 842                            },
 843                            message: params.message,
 844                            actions,
 845                            response_channel: tx,
 846                            lsp_name: name.clone(),
 847                        };
 848
 849                        let did_update = this
 850                            .update(&mut cx, |_, cx| {
 851                                cx.emit(LspStoreEvent::LanguageServerPrompt(request));
 852                            })
 853                            .is_ok();
 854                        if did_update {
 855                            let response = rx.recv().await.ok();
 856                            Ok(response)
 857                        } else {
 858                            Ok(None)
 859                        }
 860                    }
 861                }
 862            })
 863            .detach();
 864        language_server
 865            .on_notification::<lsp::notification::ShowMessage, _>({
 866                let this = this.clone();
 867                let name = name.to_string();
 868                move |params, cx| {
 869                    let this = this.clone();
 870                    let name = name.to_string();
 871                    let mut cx = cx.clone();
 872
 873                    let (tx, _) = smol::channel::bounded(1);
 874                    let request = LanguageServerPromptRequest {
 875                        level: match params.typ {
 876                            lsp::MessageType::ERROR => PromptLevel::Critical,
 877                            lsp::MessageType::WARNING => PromptLevel::Warning,
 878                            _ => PromptLevel::Info,
 879                        },
 880                        message: params.message,
 881                        actions: vec![],
 882                        response_channel: tx,
 883                        lsp_name: name.clone(),
 884                    };
 885
 886                    let _ = this.update(&mut cx, |_, cx| {
 887                        cx.emit(LspStoreEvent::LanguageServerPrompt(request));
 888                    });
 889                }
 890            })
 891            .detach();
 892
 893        let disk_based_diagnostics_progress_token =
 894            adapter.disk_based_diagnostics_progress_token.clone();
 895
 896        language_server
 897            .on_notification::<lsp::notification::Progress, _>({
 898                let this = this.clone();
 899                move |params, cx| {
 900                    if let Some(this) = this.upgrade() {
 901                        this.update(cx, |this, cx| {
 902                            this.on_lsp_progress(
 903                                params,
 904                                server_id,
 905                                disk_based_diagnostics_progress_token.clone(),
 906                                cx,
 907                            );
 908                        })
 909                        .ok();
 910                    }
 911                }
 912            })
 913            .detach();
 914
 915        language_server
 916            .on_notification::<lsp::notification::LogMessage, _>({
 917                let this = this.clone();
 918                move |params, cx| {
 919                    if let Some(this) = this.upgrade() {
 920                        this.update(cx, |_, cx| {
 921                            cx.emit(LspStoreEvent::LanguageServerLog(
 922                                server_id,
 923                                LanguageServerLogType::Log(params.typ),
 924                                params.message,
 925                            ));
 926                        })
 927                        .ok();
 928                    }
 929                }
 930            })
 931            .detach();
 932
 933        language_server
 934            .on_notification::<lsp::notification::LogTrace, _>({
 935                let this = this.clone();
 936                move |params, cx| {
 937                    let mut cx = cx.clone();
 938                    if let Some(this) = this.upgrade() {
 939                        this.update(&mut cx, |_, cx| {
 940                            cx.emit(LspStoreEvent::LanguageServerLog(
 941                                server_id,
 942                                LanguageServerLogType::Trace(params.verbose),
 943                                params.message,
 944                            ));
 945                        })
 946                        .ok();
 947                    }
 948                }
 949            })
 950            .detach();
 951
 952        rust_analyzer_ext::register_notifications(this.clone(), language_server);
 953        clangd_ext::register_notifications(this, language_server, adapter);
 954    }
 955
 956    fn shutdown_language_servers(
 957        &mut self,
 958        _cx: &mut Context<LspStore>,
 959    ) -> impl Future<Output = ()> {
 960        let shutdown_futures = self
 961            .language_servers
 962            .drain()
 963            .map(|(_, server_state)| async {
 964                use LanguageServerState::*;
 965                match server_state {
 966                    Running { server, .. } => server.shutdown()?.await,
 967                    Starting { startup, .. } => startup.await?.shutdown()?.await,
 968                }
 969            })
 970            .collect::<Vec<_>>();
 971
 972        async move {
 973            futures::future::join_all(shutdown_futures).await;
 974        }
 975    }
 976
 977    fn language_servers_for_worktree(
 978        &self,
 979        worktree_id: WorktreeId,
 980    ) -> impl Iterator<Item = &Arc<LanguageServer>> {
 981        self.language_server_ids
 982            .iter()
 983            .flat_map(move |((language_server_path, _), ids)| {
 984                ids.iter().filter_map(move |id| {
 985                    if *language_server_path != worktree_id {
 986                        return None;
 987                    }
 988                    if let Some(LanguageServerState::Running { server, .. }) =
 989                        self.language_servers.get(id)
 990                    {
 991                        return Some(server);
 992                    } else {
 993                        None
 994                    }
 995                })
 996            })
 997    }
 998
 999    fn language_server_ids_for_project_path(
1000        &self,
1001        project_path: ProjectPath,
1002        language: &Language,
1003        cx: &mut App,
1004    ) -> Vec<LanguageServerId> {
1005        let Some(worktree) = self
1006            .worktree_store
1007            .read(cx)
1008            .worktree_for_id(project_path.worktree_id, cx)
1009        else {
1010            return vec![];
1011        };
1012        let delegate = LocalLspAdapterDelegate::from_local_lsp(self, &worktree, cx);
1013        let root = self.lsp_tree.update(cx, |this, cx| {
1014            this.get(
1015                project_path,
1016                AdapterQuery::Language(&language.name()),
1017                delegate,
1018                cx,
1019            )
1020            .filter_map(|node| node.server_id())
1021            .collect::<Vec<_>>()
1022        });
1023
1024        root
1025    }
1026
1027    fn language_server_ids_for_buffer(
1028        &self,
1029        buffer: &Buffer,
1030        cx: &mut App,
1031    ) -> Vec<LanguageServerId> {
1032        if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) {
1033            let worktree_id = file.worktree_id(cx);
1034
1035            let path: Arc<Path> = file
1036                .path()
1037                .parent()
1038                .map(Arc::from)
1039                .unwrap_or_else(|| file.path().clone());
1040            let worktree_path = ProjectPath { worktree_id, path };
1041            self.language_server_ids_for_project_path(worktree_path, language, cx)
1042        } else {
1043            Vec::new()
1044        }
1045    }
1046
1047    fn language_servers_for_buffer<'a>(
1048        &'a self,
1049        buffer: &'a Buffer,
1050        cx: &'a mut App,
1051    ) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
1052        self.language_server_ids_for_buffer(buffer, cx)
1053            .into_iter()
1054            .filter_map(|server_id| match self.language_servers.get(&server_id)? {
1055                LanguageServerState::Running {
1056                    adapter, server, ..
1057                } => Some((adapter, server)),
1058                _ => None,
1059            })
1060    }
1061
1062    fn primary_language_server_for_buffer<'a>(
1063        &'a self,
1064        buffer: &'a Buffer,
1065        cx: &'a mut App,
1066    ) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
1067        // The list of language servers is ordered based on the `language_servers` setting
1068        // for each language, thus we can consider the first one in the list to be the
1069        // primary one.
1070        self.language_servers_for_buffer(buffer, cx).next()
1071    }
1072
1073    async fn execute_code_action_kind_locally(
1074        lsp_store: WeakEntity<LspStore>,
1075        mut buffers: Vec<Entity<Buffer>>,
1076        kind: CodeActionKind,
1077        push_to_history: bool,
1078        cx: &mut AsyncApp,
1079    ) -> anyhow::Result<ProjectTransaction> {
1080        // Do not allow multiple concurrent code actions requests for the
1081        // same buffer.
1082        lsp_store.update(cx, |this, cx| {
1083            let this = this.as_local_mut().unwrap();
1084            buffers.retain(|buffer| {
1085                this.buffers_being_formatted
1086                    .insert(buffer.read(cx).remote_id())
1087            });
1088        })?;
1089        let _cleanup = defer({
1090            let this = lsp_store.clone();
1091            let mut cx = cx.clone();
1092            let buffers = &buffers;
1093            move || {
1094                this.update(&mut cx, |this, cx| {
1095                    let this = this.as_local_mut().unwrap();
1096                    for buffer in buffers {
1097                        this.buffers_being_formatted
1098                            .remove(&buffer.read(cx).remote_id());
1099                    }
1100                })
1101                .ok();
1102            }
1103        });
1104        let mut project_transaction = ProjectTransaction::default();
1105
1106        for buffer in &buffers {
1107            let adapters_and_servers = lsp_store.update(cx, |lsp_store, cx| {
1108                buffer.update(cx, |buffer, cx| {
1109                    lsp_store
1110                        .as_local()
1111                        .unwrap()
1112                        .language_servers_for_buffer(buffer, cx)
1113                        .map(|(adapter, lsp)| (adapter.clone(), lsp.clone()))
1114                        .collect::<Vec<_>>()
1115                })
1116            })?;
1117            Self::execute_code_actions_on_servers(
1118                &lsp_store,
1119                &adapters_and_servers,
1120                vec![kind.clone()],
1121                &buffer,
1122                push_to_history,
1123                &mut project_transaction,
1124                cx,
1125            )
1126            .await?;
1127        }
1128        Ok(project_transaction)
1129    }
1130
1131    async fn format_locally(
1132        lsp_store: WeakEntity<LspStore>,
1133        mut buffers: Vec<FormattableBuffer>,
1134        push_to_history: bool,
1135        trigger: FormatTrigger,
1136        cx: &mut AsyncApp,
1137    ) -> anyhow::Result<ProjectTransaction> {
1138        // Do not allow multiple concurrent formatting requests for the
1139        // same buffer.
1140        lsp_store.update(cx, |this, cx| {
1141            let this = this.as_local_mut().unwrap();
1142            buffers.retain(|buffer| {
1143                this.buffers_being_formatted
1144                    .insert(buffer.handle.read(cx).remote_id())
1145            });
1146        })?;
1147
1148        let _cleanup = defer({
1149            let this = lsp_store.clone();
1150            let mut cx = cx.clone();
1151            let buffers = &buffers;
1152            move || {
1153                this.update(&mut cx, |this, cx| {
1154                    let this = this.as_local_mut().unwrap();
1155                    for buffer in buffers {
1156                        this.buffers_being_formatted
1157                            .remove(&buffer.handle.read(cx).remote_id());
1158                    }
1159                })
1160                .ok();
1161            }
1162        });
1163
1164        let mut project_transaction = ProjectTransaction::default();
1165        for buffer in &buffers {
1166            let adapters_and_servers = lsp_store.update(cx, |lsp_store, cx| {
1167                buffer.handle.update(cx, |buffer, cx| {
1168                    lsp_store
1169                        .as_local()
1170                        .unwrap()
1171                        .language_servers_for_buffer(buffer, cx)
1172                        .map(|(adapter, lsp)| (adapter.clone(), lsp.clone()))
1173                        .collect::<Vec<_>>()
1174                })
1175            })?;
1176
1177            let settings = buffer.handle.update(cx, |buffer, cx| {
1178                language_settings(buffer.language().map(|l| l.name()), buffer.file(), cx)
1179                    .into_owned()
1180            })?;
1181
1182            let remove_trailing_whitespace = settings.remove_trailing_whitespace_on_save;
1183            let ensure_final_newline = settings.ensure_final_newline_on_save;
1184
1185            // First, format buffer's whitespace according to the settings.
1186            let trailing_whitespace_diff = if remove_trailing_whitespace {
1187                Some(
1188                    buffer
1189                        .handle
1190                        .update(cx, |b, cx| b.remove_trailing_whitespace(cx))?
1191                        .await,
1192                )
1193            } else {
1194                None
1195            };
1196            let whitespace_transaction_id = buffer.handle.update(cx, |buffer, cx| {
1197                buffer.finalize_last_transaction();
1198                buffer.start_transaction();
1199                if let Some(diff) = trailing_whitespace_diff {
1200                    buffer.apply_diff(diff, cx);
1201                }
1202                if ensure_final_newline {
1203                    buffer.ensure_final_newline(cx);
1204                }
1205                buffer.end_transaction(cx)
1206            })?;
1207
1208            let initial_transaction_id = whitespace_transaction_id;
1209
1210            // Apply the `code_actions_on_format` before we run the formatter.
1211            let code_actions = deserialize_code_actions(&settings.code_actions_on_format);
1212            #[allow(clippy::nonminimal_bool)]
1213            if !code_actions.is_empty()
1214                && !(trigger == FormatTrigger::Save && settings.format_on_save == FormatOnSave::Off)
1215            {
1216                Self::execute_code_actions_on_servers(
1217                    &lsp_store,
1218                    &adapters_and_servers,
1219                    code_actions,
1220                    &buffer.handle,
1221                    push_to_history,
1222                    &mut project_transaction,
1223                    cx,
1224                )
1225                .await?;
1226            }
1227
1228            let prettier_settings = buffer.handle.read_with(cx, |buffer, cx| {
1229                language_settings(buffer.language().map(|l| l.name()), buffer.file(), cx)
1230                    .prettier
1231                    .clone()
1232            })?;
1233
1234            let formatters = match (trigger, &settings.format_on_save) {
1235                (FormatTrigger::Save, FormatOnSave::Off) => &[],
1236                (FormatTrigger::Save, FormatOnSave::List(formatters)) => formatters.as_ref(),
1237                (FormatTrigger::Manual, _) | (FormatTrigger::Save, FormatOnSave::On) => {
1238                    match &settings.formatter {
1239                        SelectedFormatter::Auto => {
1240                            if prettier_settings.allowed {
1241                                std::slice::from_ref(&Formatter::Prettier)
1242                            } else {
1243                                std::slice::from_ref(&Formatter::LanguageServer { name: None })
1244                            }
1245                        }
1246                        SelectedFormatter::List(formatter_list) => formatter_list.as_ref(),
1247                    }
1248                }
1249            };
1250            Self::execute_formatters(
1251                lsp_store.clone(),
1252                formatters,
1253                buffer,
1254                &settings,
1255                &adapters_and_servers,
1256                push_to_history,
1257                initial_transaction_id,
1258                &mut project_transaction,
1259                cx,
1260            )
1261            .await?;
1262        }
1263
1264        Ok(project_transaction)
1265    }
1266
1267    async fn execute_formatters(
1268        lsp_store: WeakEntity<LspStore>,
1269        formatters: &[Formatter],
1270        buffer: &FormattableBuffer,
1271        settings: &LanguageSettings,
1272        adapters_and_servers: &[(Arc<CachedLspAdapter>, Arc<LanguageServer>)],
1273        push_to_history: bool,
1274        mut initial_transaction_id: Option<TransactionId>,
1275        project_transaction: &mut ProjectTransaction,
1276        cx: &mut AsyncApp,
1277    ) -> anyhow::Result<()> {
1278        let mut prev_transaction_id = initial_transaction_id;
1279
1280        for formatter in formatters {
1281            let operation = match formatter {
1282                Formatter::LanguageServer { name } => {
1283                    let Some(language_server) = lsp_store.update(cx, |lsp_store, cx| {
1284                        buffer.handle.update(cx, |buffer, cx| {
1285                            lsp_store
1286                                .as_local()
1287                                .unwrap()
1288                                .primary_language_server_for_buffer(buffer, cx)
1289                                .map(|(_, lsp)| lsp.clone())
1290                        })
1291                    })?
1292                    else {
1293                        continue;
1294                    };
1295                    let Some(buffer_abs_path) = buffer.abs_path.as_ref() else {
1296                        continue;
1297                    };
1298
1299                    let language_server = if let Some(name) = name {
1300                        adapters_and_servers
1301                            .iter()
1302                            .find_map(|(adapter, server)| {
1303                                adapter
1304                                    .name
1305                                    .0
1306                                    .as_ref()
1307                                    .eq(name.as_str())
1308                                    .then_some(server.clone())
1309                            })
1310                            .unwrap_or(language_server)
1311                    } else {
1312                        language_server
1313                    };
1314
1315                    let result = if let Some(ranges) = &buffer.ranges {
1316                        Self::format_ranges_via_lsp(
1317                            &lsp_store,
1318                            &buffer.handle,
1319                            ranges,
1320                            buffer_abs_path,
1321                            &language_server,
1322                            settings,
1323                            cx,
1324                        )
1325                        .await
1326                        .context("failed to format ranges via language server")?
1327                    } else {
1328                        Self::format_via_lsp(
1329                            &lsp_store,
1330                            &buffer.handle,
1331                            buffer_abs_path,
1332                            &language_server,
1333                            settings,
1334                            cx,
1335                        )
1336                        .await
1337                        .context("failed to format via language server")?
1338                    };
1339
1340                    Some(FormatOperation::Lsp(result))
1341                }
1342                Formatter::Prettier => {
1343                    let prettier = lsp_store.update(cx, |lsp_store, _cx| {
1344                        lsp_store.prettier_store().unwrap().downgrade()
1345                    })?;
1346                    prettier_store::format_with_prettier(&prettier, &buffer.handle, cx)
1347                        .await
1348                        .transpose()?
1349                }
1350                Formatter::External { command, arguments } => {
1351                    Self::format_via_external_command(buffer, command, arguments.as_deref(), cx)
1352                        .await
1353                        .context(format!(
1354                            "failed to format via external command {:?}",
1355                            command
1356                        ))?
1357                        .map(FormatOperation::External)
1358                }
1359                Formatter::CodeActions(code_actions) => {
1360                    let code_actions = deserialize_code_actions(code_actions);
1361                    if !code_actions.is_empty() {
1362                        Self::execute_code_actions_on_servers(
1363                            &lsp_store,
1364                            adapters_and_servers,
1365                            code_actions,
1366                            &buffer.handle,
1367                            push_to_history,
1368                            project_transaction,
1369                            cx,
1370                        )
1371                        .await?;
1372                        let buf_transaction_id =
1373                            project_transaction.0.get(&buffer.handle).map(|t| t.id);
1374                        // NOTE: same logic as in buffer.handle.update below
1375                        if initial_transaction_id.is_none() {
1376                            initial_transaction_id = buf_transaction_id;
1377                        }
1378                        if buf_transaction_id.is_some() {
1379                            prev_transaction_id = buf_transaction_id;
1380                        }
1381                    }
1382                    None
1383                }
1384            };
1385            let Some(operation) = operation else {
1386                continue;
1387            };
1388
1389            let should_continue_formatting = buffer.handle.update(cx, |b, cx| {
1390                // If a previous format succeeded and the buffer was edited while the language-specific
1391                // formatting information for this format was being computed, avoid applying the
1392                // language-specific formatting, because it can't be grouped with the previous formatting
1393                // in the undo history.
1394                let should_continue_formatting = match (prev_transaction_id, b.peek_undo_stack()) {
1395                    (Some(prev_transaction_id), Some(last_history_entry)) => {
1396                        let last_history_transaction_id = last_history_entry.transaction_id();
1397                        let is_same_as_prev = last_history_transaction_id == prev_transaction_id;
1398                        is_same_as_prev
1399                    }
1400                    (Some(_), None) => false,
1401                    (_, _) => true,
1402                };
1403
1404                if should_continue_formatting {
1405                    // Apply any language-specific formatting, and group the two formatting operations
1406                    // in the buffer's undo history.
1407                    let this_transaction_id = match operation {
1408                        FormatOperation::Lsp(edits) => b.edit(edits, None, cx),
1409                        FormatOperation::External(diff) => b.apply_diff(diff, cx),
1410                        FormatOperation::Prettier(diff) => b.apply_diff(diff, cx),
1411                    };
1412                    if initial_transaction_id.is_none() {
1413                        initial_transaction_id = this_transaction_id;
1414                    }
1415                    if this_transaction_id.is_some() {
1416                        prev_transaction_id = this_transaction_id;
1417                    }
1418                }
1419
1420                if let Some(transaction_id) = initial_transaction_id {
1421                    b.group_until_transaction(transaction_id);
1422                } else if let Some(transaction) = project_transaction.0.get(&buffer.handle) {
1423                    b.group_until_transaction(transaction.id)
1424                }
1425                return should_continue_formatting;
1426            })?;
1427            if !should_continue_formatting {
1428                break;
1429            }
1430        }
1431
1432        buffer.handle.update(cx, |b, _cx| {
1433            if let Some(transaction) = b.finalize_last_transaction().cloned() {
1434                if !push_to_history {
1435                    b.forget_transaction(transaction.id);
1436                    project_transaction
1437                        .0
1438                        .insert(buffer.handle.clone(), transaction);
1439                }
1440            }
1441        })?;
1442        return Ok(());
1443    }
1444
1445    pub async fn format_ranges_via_lsp(
1446        this: &WeakEntity<LspStore>,
1447        buffer_handle: &Entity<Buffer>,
1448        ranges: &[Range<Anchor>],
1449        abs_path: &Path,
1450        language_server: &Arc<LanguageServer>,
1451        settings: &LanguageSettings,
1452        cx: &mut AsyncApp,
1453    ) -> Result<Vec<(Range<Anchor>, Arc<str>)>> {
1454        let capabilities = &language_server.capabilities();
1455        let range_formatting_provider = capabilities.document_range_formatting_provider.as_ref();
1456        if range_formatting_provider.map_or(false, |provider| provider == &OneOf::Left(false)) {
1457            return Err(anyhow!(
1458                "{} language server does not support range formatting",
1459                language_server.name()
1460            ));
1461        }
1462
1463        let uri = lsp::Url::from_file_path(abs_path)
1464            .map_err(|_| anyhow!("failed to convert abs path to uri"))?;
1465        let text_document = lsp::TextDocumentIdentifier::new(uri);
1466
1467        let lsp_edits = {
1468            let mut lsp_ranges = Vec::new();
1469            this.update(cx, |_this, cx| {
1470                // TODO(#22930): In the case of formatting multibuffer selections, this buffer may
1471                // not have been sent to the language server. This seems like a fairly systemic
1472                // issue, though, the resolution probably is not specific to formatting.
1473                //
1474                // TODO: Instead of using current snapshot, should use the latest snapshot sent to
1475                // LSP.
1476                let snapshot = buffer_handle.read(cx).snapshot();
1477                for range in ranges {
1478                    lsp_ranges.push(range_to_lsp(range.to_point_utf16(&snapshot))?);
1479                }
1480                anyhow::Ok(())
1481            })??;
1482
1483            let mut edits = None;
1484            for range in lsp_ranges {
1485                if let Some(mut edit) = language_server
1486                    .request::<lsp::request::RangeFormatting>(lsp::DocumentRangeFormattingParams {
1487                        text_document: text_document.clone(),
1488                        range,
1489                        options: lsp_command::lsp_formatting_options(settings),
1490                        work_done_progress_params: Default::default(),
1491                    })
1492                    .await?
1493                {
1494                    edits.get_or_insert_with(Vec::new).append(&mut edit);
1495                }
1496            }
1497            edits
1498        };
1499
1500        if let Some(lsp_edits) = lsp_edits {
1501            this.update(cx, |this, cx| {
1502                this.as_local_mut().unwrap().edits_from_lsp(
1503                    &buffer_handle,
1504                    lsp_edits,
1505                    language_server.server_id(),
1506                    None,
1507                    cx,
1508                )
1509            })?
1510            .await
1511        } else {
1512            Ok(Vec::with_capacity(0))
1513        }
1514    }
1515
1516    async fn format_via_lsp(
1517        this: &WeakEntity<LspStore>,
1518        buffer: &Entity<Buffer>,
1519        abs_path: &Path,
1520        language_server: &Arc<LanguageServer>,
1521        settings: &LanguageSettings,
1522        cx: &mut AsyncApp,
1523    ) -> Result<Vec<(Range<Anchor>, Arc<str>)>> {
1524        let uri = lsp::Url::from_file_path(abs_path)
1525            .map_err(|_| anyhow!("failed to convert abs path to uri"))?;
1526        let text_document = lsp::TextDocumentIdentifier::new(uri);
1527        let capabilities = &language_server.capabilities();
1528
1529        let formatting_provider = capabilities.document_formatting_provider.as_ref();
1530        let range_formatting_provider = capabilities.document_range_formatting_provider.as_ref();
1531
1532        let lsp_edits = if matches!(formatting_provider, Some(p) if *p != OneOf::Left(false)) {
1533            language_server
1534                .request::<lsp::request::Formatting>(lsp::DocumentFormattingParams {
1535                    text_document,
1536                    options: lsp_command::lsp_formatting_options(settings),
1537                    work_done_progress_params: Default::default(),
1538                })
1539                .await?
1540        } else if matches!(range_formatting_provider, Some(p) if *p != OneOf::Left(false)) {
1541            let buffer_start = lsp::Position::new(0, 0);
1542            let buffer_end = buffer.update(cx, |b, _| point_to_lsp(b.max_point_utf16()))?;
1543            language_server
1544                .request::<lsp::request::RangeFormatting>(lsp::DocumentRangeFormattingParams {
1545                    text_document: text_document.clone(),
1546                    range: lsp::Range::new(buffer_start, buffer_end),
1547                    options: lsp_command::lsp_formatting_options(settings),
1548                    work_done_progress_params: Default::default(),
1549                })
1550                .await?
1551        } else {
1552            None
1553        };
1554
1555        if let Some(lsp_edits) = lsp_edits {
1556            this.update(cx, |this, cx| {
1557                this.as_local_mut().unwrap().edits_from_lsp(
1558                    buffer,
1559                    lsp_edits,
1560                    language_server.server_id(),
1561                    None,
1562                    cx,
1563                )
1564            })?
1565            .await
1566        } else {
1567            Ok(Vec::with_capacity(0))
1568        }
1569    }
1570
1571    async fn format_via_external_command(
1572        buffer: &FormattableBuffer,
1573        command: &str,
1574        arguments: Option<&[String]>,
1575        cx: &mut AsyncApp,
1576    ) -> Result<Option<Diff>> {
1577        let working_dir_path = buffer.handle.update(cx, |buffer, cx| {
1578            let file = File::from_dyn(buffer.file())?;
1579            let worktree = file.worktree.read(cx);
1580            let mut worktree_path = worktree.abs_path().to_path_buf();
1581            if worktree.root_entry()?.is_file() {
1582                worktree_path.pop();
1583            }
1584            Some(worktree_path)
1585        })?;
1586
1587        let mut child = util::command::new_smol_command(command);
1588
1589        if let Some(buffer_env) = buffer.env.as_ref() {
1590            child.envs(buffer_env);
1591        }
1592
1593        if let Some(working_dir_path) = working_dir_path {
1594            child.current_dir(working_dir_path);
1595        }
1596
1597        if let Some(arguments) = arguments {
1598            child.args(arguments.iter().map(|arg| {
1599                if let Some(buffer_abs_path) = buffer.abs_path.as_ref() {
1600                    arg.replace("{buffer_path}", &buffer_abs_path.to_string_lossy())
1601                } else {
1602                    arg.replace("{buffer_path}", "Untitled")
1603                }
1604            }));
1605        }
1606
1607        let mut child = child
1608            .stdin(smol::process::Stdio::piped())
1609            .stdout(smol::process::Stdio::piped())
1610            .stderr(smol::process::Stdio::piped())
1611            .spawn()?;
1612
1613        let stdin = child
1614            .stdin
1615            .as_mut()
1616            .ok_or_else(|| anyhow!("failed to acquire stdin"))?;
1617        let text = buffer
1618            .handle
1619            .update(cx, |buffer, _| buffer.as_rope().clone())?;
1620        for chunk in text.chunks() {
1621            stdin.write_all(chunk.as_bytes()).await?;
1622        }
1623        stdin.flush().await?;
1624
1625        let output = child.output().await?;
1626        if !output.status.success() {
1627            return Err(anyhow!(
1628                "command failed with exit code {:?}:\nstdout: {}\nstderr: {}",
1629                output.status.code(),
1630                String::from_utf8_lossy(&output.stdout),
1631                String::from_utf8_lossy(&output.stderr),
1632            ));
1633        }
1634
1635        let stdout = String::from_utf8(output.stdout)?;
1636        Ok(Some(
1637            buffer
1638                .handle
1639                .update(cx, |buffer, cx| buffer.diff(stdout, cx))?
1640                .await,
1641        ))
1642    }
1643
1644    async fn try_resolve_code_action(
1645        lang_server: &LanguageServer,
1646        action: &mut CodeAction,
1647    ) -> anyhow::Result<()> {
1648        match &mut action.lsp_action {
1649            LspAction::Action(lsp_action) => {
1650                if !action.resolved
1651                    && GetCodeActions::can_resolve_actions(&lang_server.capabilities())
1652                    && lsp_action.data.is_some()
1653                    && (lsp_action.command.is_none() || lsp_action.edit.is_none())
1654                {
1655                    *lsp_action = Box::new(
1656                        lang_server
1657                            .request::<lsp::request::CodeActionResolveRequest>(*lsp_action.clone())
1658                            .await?,
1659                    );
1660                }
1661            }
1662            LspAction::CodeLens(lens) => {
1663                if !action.resolved && GetCodeLens::can_resolve_lens(&lang_server.capabilities()) {
1664                    *lens = lang_server
1665                        .request::<lsp::request::CodeLensResolve>(lens.clone())
1666                        .await?;
1667                }
1668            }
1669            LspAction::Command(_) => {}
1670        }
1671
1672        action.resolved = true;
1673        anyhow::Ok(())
1674    }
1675
1676    fn initialize_buffer(&mut self, buffer_handle: &Entity<Buffer>, cx: &mut Context<LspStore>) {
1677        let buffer = buffer_handle.read(cx);
1678
1679        let file = buffer.file().cloned();
1680        let Some(file) = File::from_dyn(file.as_ref()) else {
1681            return;
1682        };
1683        if !file.is_local() {
1684            return;
1685        }
1686
1687        let worktree_id = file.worktree_id(cx);
1688        let language = buffer.language().cloned();
1689
1690        if let Some(diagnostics) = self.diagnostics.get(&worktree_id) {
1691            for (server_id, diagnostics) in
1692                diagnostics.get(file.path()).cloned().unwrap_or_default()
1693            {
1694                self.update_buffer_diagnostics(buffer_handle, server_id, None, diagnostics, cx)
1695                    .log_err();
1696            }
1697        }
1698        let Some(language) = language else {
1699            return;
1700        };
1701        for adapter in self.languages.lsp_adapters(&language.name()) {
1702            let servers = self
1703                .language_server_ids
1704                .get(&(worktree_id, adapter.name.clone()));
1705            if let Some(server_ids) = servers {
1706                for server_id in server_ids {
1707                    let server = self
1708                        .language_servers
1709                        .get(server_id)
1710                        .and_then(|server_state| {
1711                            if let LanguageServerState::Running { server, .. } = server_state {
1712                                Some(server.clone())
1713                            } else {
1714                                None
1715                            }
1716                        });
1717                    let server = match server {
1718                        Some(server) => server,
1719                        None => continue,
1720                    };
1721
1722                    buffer_handle.update(cx, |buffer, cx| {
1723                        buffer.set_completion_triggers(
1724                            server.server_id(),
1725                            server
1726                                .capabilities()
1727                                .completion_provider
1728                                .as_ref()
1729                                .and_then(|provider| {
1730                                    provider
1731                                        .trigger_characters
1732                                        .as_ref()
1733                                        .map(|characters| characters.iter().cloned().collect())
1734                                })
1735                                .unwrap_or_default(),
1736                            cx,
1737                        );
1738                    });
1739                }
1740            }
1741        }
1742    }
1743
1744    pub(crate) fn reset_buffer(&mut self, buffer: &Entity<Buffer>, old_file: &File, cx: &mut App) {
1745        buffer.update(cx, |buffer, cx| {
1746            let Some(language) = buffer.language() else {
1747                return;
1748            };
1749            let path = ProjectPath {
1750                worktree_id: old_file.worktree_id(cx),
1751                path: old_file.path.clone(),
1752            };
1753            for server_id in self.language_server_ids_for_project_path(path, language, cx) {
1754                buffer.update_diagnostics(server_id, DiagnosticSet::new([], buffer), cx);
1755                buffer.set_completion_triggers(server_id, Default::default(), cx);
1756            }
1757        });
1758    }
1759
1760    fn update_buffer_diagnostics(
1761        &mut self,
1762        buffer: &Entity<Buffer>,
1763        server_id: LanguageServerId,
1764        version: Option<i32>,
1765        mut diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
1766        cx: &mut Context<LspStore>,
1767    ) -> Result<()> {
1768        fn compare_diagnostics(a: &Diagnostic, b: &Diagnostic) -> Ordering {
1769            Ordering::Equal
1770                .then_with(|| b.is_primary.cmp(&a.is_primary))
1771                .then_with(|| a.is_disk_based.cmp(&b.is_disk_based))
1772                .then_with(|| a.severity.cmp(&b.severity))
1773                .then_with(|| a.message.cmp(&b.message))
1774        }
1775
1776        diagnostics.sort_unstable_by(|a, b| {
1777            Ordering::Equal
1778                .then_with(|| a.range.start.cmp(&b.range.start))
1779                .then_with(|| b.range.end.cmp(&a.range.end))
1780                .then_with(|| compare_diagnostics(&a.diagnostic, &b.diagnostic))
1781        });
1782
1783        let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx)?;
1784
1785        let edits_since_save = std::cell::LazyCell::new(|| {
1786            let saved_version = buffer.read(cx).saved_version();
1787            Patch::new(snapshot.edits_since::<PointUtf16>(saved_version).collect())
1788        });
1789
1790        let mut sanitized_diagnostics = Vec::new();
1791
1792        for entry in diagnostics {
1793            let start;
1794            let end;
1795            if entry.diagnostic.is_disk_based {
1796                // Some diagnostics are based on files on disk instead of buffers'
1797                // current contents. Adjust these diagnostics' ranges to reflect
1798                // any unsaved edits.
1799                start = Unclipped((*edits_since_save).old_to_new(entry.range.start.0));
1800                end = Unclipped((*edits_since_save).old_to_new(entry.range.end.0));
1801            } else {
1802                start = entry.range.start;
1803                end = entry.range.end;
1804            }
1805
1806            let mut range = snapshot.clip_point_utf16(start, Bias::Left)
1807                ..snapshot.clip_point_utf16(end, Bias::Right);
1808
1809            // Expand empty ranges by one codepoint
1810            if range.start == range.end {
1811                // This will be go to the next boundary when being clipped
1812                range.end.column += 1;
1813                range.end = snapshot.clip_point_utf16(Unclipped(range.end), Bias::Right);
1814                if range.start == range.end && range.end.column > 0 {
1815                    range.start.column -= 1;
1816                    range.start = snapshot.clip_point_utf16(Unclipped(range.start), Bias::Left);
1817                }
1818            }
1819
1820            sanitized_diagnostics.push(DiagnosticEntry {
1821                range,
1822                diagnostic: entry.diagnostic,
1823            });
1824        }
1825        drop(edits_since_save);
1826
1827        let set = DiagnosticSet::new(sanitized_diagnostics, &snapshot);
1828        buffer.update(cx, |buffer, cx| {
1829            buffer.update_diagnostics(server_id, set, cx)
1830        });
1831        Ok(())
1832    }
1833
1834    fn register_buffer_with_language_servers(
1835        &mut self,
1836        buffer_handle: &Entity<Buffer>,
1837        cx: &mut Context<LspStore>,
1838    ) {
1839        let buffer = buffer_handle.read(cx);
1840        let buffer_id = buffer.remote_id();
1841
1842        let Some(file) = File::from_dyn(buffer.file()) else {
1843            return;
1844        };
1845        if !file.is_local() {
1846            return;
1847        }
1848
1849        let abs_path = file.abs_path(cx);
1850        let Some(uri) = lsp::Url::from_file_path(&abs_path).log_err() else {
1851            return;
1852        };
1853        let initial_snapshot = buffer.text_snapshot();
1854        let worktree_id = file.worktree_id(cx);
1855
1856        let Some(language) = buffer.language().cloned() else {
1857            return;
1858        };
1859        let path: Arc<Path> = file
1860            .path()
1861            .parent()
1862            .map(Arc::from)
1863            .unwrap_or_else(|| file.path().clone());
1864        let Some(worktree) = self
1865            .worktree_store
1866            .read(cx)
1867            .worktree_for_id(worktree_id, cx)
1868        else {
1869            return;
1870        };
1871        let delegate = LocalLspAdapterDelegate::from_local_lsp(self, &worktree, cx);
1872        let servers = self.lsp_tree.clone().update(cx, |this, cx| {
1873            this.get(
1874                ProjectPath { worktree_id, path },
1875                AdapterQuery::Language(&language.name()),
1876                delegate.clone(),
1877                cx,
1878            )
1879            .collect::<Vec<_>>()
1880        });
1881        let servers = servers
1882            .into_iter()
1883            .filter_map(|server_node| {
1884                let server_id = server_node.server_id_or_init(
1885                    |LaunchDisposition {
1886                         server_name,
1887                         attach,
1888                         path,
1889                         settings,
1890                     }| match attach {
1891                        language::Attach::InstancePerRoot => {
1892                            // todo: handle instance per root proper.
1893                            if let Some(server_ids) = self
1894                                .language_server_ids
1895                                .get(&(worktree_id, server_name.clone()))
1896                            {
1897                                server_ids.iter().cloned().next().unwrap()
1898                            } else {
1899                                let language_name = language.name();
1900
1901                                self.start_language_server(
1902                                    &worktree,
1903                                    delegate.clone(),
1904                                    self.languages
1905                                        .lsp_adapters(&language_name)
1906                                        .into_iter()
1907                                        .find(|adapter| &adapter.name() == server_name)
1908                                        .expect("To find LSP adapter"),
1909                                    settings,
1910                                    cx,
1911                                )
1912                            }
1913                        }
1914                        language::Attach::Shared => {
1915                            let uri = Url::from_file_path(
1916                                worktree.read(cx).abs_path().join(&path.path),
1917                            );
1918                            let key = (worktree_id, server_name.clone());
1919                            if !self.language_server_ids.contains_key(&key) {
1920                                let language_name = language.name();
1921                                self.start_language_server(
1922                                    &worktree,
1923                                    delegate.clone(),
1924                                    self.languages
1925                                        .lsp_adapters(&language_name)
1926                                        .into_iter()
1927                                        .find(|adapter| &adapter.name() == server_name)
1928                                        .expect("To find LSP adapter"),
1929                                    settings,
1930                                    cx,
1931                                );
1932                            }
1933                            if let Some(server_ids) = self
1934                                .language_server_ids
1935                                .get(&key)
1936                            {
1937                                debug_assert_eq!(server_ids.len(), 1);
1938                                let server_id = server_ids.iter().cloned().next().unwrap();
1939
1940                                if let Some(state) = self.language_servers.get(&server_id) {
1941                                    if let Ok(uri) = uri {
1942                                        state.add_workspace_folder(uri);
1943                                    };
1944                                }
1945                                server_id
1946                            } else {
1947                                unreachable!("Language server ID should be available, as it's registered on demand")
1948                            }
1949                        }
1950                    },
1951                )?;
1952                let server_state = self.language_servers.get(&server_id)?;
1953                if let LanguageServerState::Running { server, .. } = server_state {
1954                    Some(server.clone())
1955                } else {
1956                    None
1957                }
1958            })
1959            .collect::<Vec<_>>();
1960        for server in servers {
1961            buffer_handle.update(cx, |buffer, cx| {
1962                buffer.set_completion_triggers(
1963                    server.server_id(),
1964                    server
1965                        .capabilities()
1966                        .completion_provider
1967                        .as_ref()
1968                        .and_then(|provider| {
1969                            provider
1970                                .trigger_characters
1971                                .as_ref()
1972                                .map(|characters| characters.iter().cloned().collect())
1973                        })
1974                        .unwrap_or_default(),
1975                    cx,
1976                );
1977            });
1978        }
1979        for adapter in self.languages.lsp_adapters(&language.name()) {
1980            let servers = self
1981                .language_server_ids
1982                .get(&(worktree_id, adapter.name.clone()))
1983                .map(|ids| {
1984                    ids.iter().flat_map(|id| {
1985                        self.language_servers.get(id).and_then(|server_state| {
1986                            if let LanguageServerState::Running { server, .. } = server_state {
1987                                Some(server.clone())
1988                            } else {
1989                                None
1990                            }
1991                        })
1992                    })
1993                });
1994            let servers = match servers {
1995                Some(server) => server,
1996                None => continue,
1997            };
1998
1999            for server in servers {
2000                let snapshot = LspBufferSnapshot {
2001                    version: 0,
2002                    snapshot: initial_snapshot.clone(),
2003                };
2004                self.buffer_snapshots
2005                    .entry(buffer_id)
2006                    .or_default()
2007                    .entry(server.server_id())
2008                    .or_insert_with(|| {
2009                        server.register_buffer(
2010                            uri.clone(),
2011                            adapter.language_id(&language.name()),
2012                            0,
2013                            initial_snapshot.text(),
2014                        );
2015
2016                        vec![snapshot]
2017                    });
2018            }
2019        }
2020    }
2021
2022    pub(crate) fn unregister_old_buffer_from_language_servers(
2023        &mut self,
2024        buffer: &Entity<Buffer>,
2025        old_file: &File,
2026        cx: &mut App,
2027    ) {
2028        let old_path = match old_file.as_local() {
2029            Some(local) => local.abs_path(cx),
2030            None => return,
2031        };
2032
2033        let Ok(file_url) = lsp::Url::from_file_path(old_path.as_path()) else {
2034            debug_panic!(
2035                "`{}` is not parseable as an URI",
2036                old_path.to_string_lossy()
2037            );
2038            return;
2039        };
2040        self.unregister_buffer_from_language_servers(buffer, &file_url, cx);
2041    }
2042
2043    pub(crate) fn unregister_buffer_from_language_servers(
2044        &mut self,
2045        buffer: &Entity<Buffer>,
2046        file_url: &lsp::Url,
2047        cx: &mut App,
2048    ) {
2049        buffer.update(cx, |buffer, cx| {
2050            let _ = self.buffer_snapshots.remove(&buffer.remote_id());
2051
2052            for (_, language_server) in self.language_servers_for_buffer(buffer, cx) {
2053                language_server.unregister_buffer(file_url.clone());
2054            }
2055        });
2056    }
2057
2058    fn buffer_snapshot_for_lsp_version(
2059        &mut self,
2060        buffer: &Entity<Buffer>,
2061        server_id: LanguageServerId,
2062        version: Option<i32>,
2063        cx: &App,
2064    ) -> Result<TextBufferSnapshot> {
2065        const OLD_VERSIONS_TO_RETAIN: i32 = 10;
2066
2067        if let Some(version) = version {
2068            let buffer_id = buffer.read(cx).remote_id();
2069            let snapshots = if let Some(snapshots) = self
2070                .buffer_snapshots
2071                .get_mut(&buffer_id)
2072                .and_then(|m| m.get_mut(&server_id))
2073            {
2074                snapshots
2075            } else if version == 0 {
2076                // Some language servers report version 0 even if the buffer hasn't been opened yet.
2077                // We detect this case and treat it as if the version was `None`.
2078                return Ok(buffer.read(cx).text_snapshot());
2079            } else {
2080                return Err(anyhow!(
2081                    "no snapshots found for buffer {buffer_id} and server {server_id}"
2082                ));
2083            };
2084
2085            let found_snapshot = snapshots
2086                    .binary_search_by_key(&version, |e| e.version)
2087                    .map(|ix| snapshots[ix].snapshot.clone())
2088                    .map_err(|_| {
2089                        anyhow!("snapshot not found for buffer {buffer_id} server {server_id} at version {version}")
2090                    })?;
2091
2092            snapshots.retain(|snapshot| snapshot.version + OLD_VERSIONS_TO_RETAIN >= version);
2093            Ok(found_snapshot)
2094        } else {
2095            Ok((buffer.read(cx)).text_snapshot())
2096        }
2097    }
2098
2099    async fn execute_code_actions_on_servers(
2100        lsp_store: &WeakEntity<LspStore>,
2101        adapters_and_servers: &[(Arc<CachedLspAdapter>, Arc<LanguageServer>)],
2102        code_actions: Vec<lsp::CodeActionKind>,
2103        buffer: &Entity<Buffer>,
2104        push_to_history: bool,
2105        project_transaction: &mut ProjectTransaction,
2106        cx: &mut AsyncApp,
2107    ) -> Result<(), anyhow::Error> {
2108        for (lsp_adapter, language_server) in adapters_and_servers.iter() {
2109            let code_actions = code_actions.clone();
2110
2111            let actions = lsp_store
2112                .update(cx, move |this, cx| {
2113                    let request = GetCodeActions {
2114                        range: text::Anchor::MIN..text::Anchor::MAX,
2115                        kinds: Some(code_actions),
2116                    };
2117                    let server = LanguageServerToQuery::Other(language_server.server_id());
2118                    this.request_lsp(buffer.clone(), server, request, cx)
2119                })?
2120                .await?;
2121
2122            for mut action in actions {
2123                Self::try_resolve_code_action(language_server, &mut action)
2124                    .await
2125                    .context("resolving a formatting code action")?;
2126
2127                if let Some(edit) = action.lsp_action.edit() {
2128                    if edit.changes.is_none() && edit.document_changes.is_none() {
2129                        continue;
2130                    }
2131
2132                    let new = Self::deserialize_workspace_edit(
2133                        lsp_store.upgrade().context("project dropped")?,
2134                        edit.clone(),
2135                        push_to_history,
2136                        lsp_adapter.clone(),
2137                        language_server.clone(),
2138                        cx,
2139                    )
2140                    .await?;
2141                    project_transaction.0.extend(new.0);
2142                }
2143
2144                if let Some(command) = action.lsp_action.command() {
2145                    let server_capabilities = language_server.capabilities();
2146                    let available_commands = server_capabilities
2147                        .execute_command_provider
2148                        .as_ref()
2149                        .map(|options| options.commands.as_slice())
2150                        .unwrap_or_default();
2151                    if available_commands.contains(&command.command) {
2152                        lsp_store.update(cx, |lsp_store, _| {
2153                            if let LspStoreMode::Local(mode) = &mut lsp_store.mode {
2154                                mode.last_workspace_edits_by_language_server
2155                                    .remove(&language_server.server_id());
2156                            }
2157                        })?;
2158
2159                        language_server
2160                            .request::<lsp::request::ExecuteCommand>(lsp::ExecuteCommandParams {
2161                                command: command.command.clone(),
2162                                arguments: command.arguments.clone().unwrap_or_default(),
2163                                ..Default::default()
2164                            })
2165                            .await?;
2166
2167                        lsp_store.update(cx, |this, _| {
2168                            if let LspStoreMode::Local(mode) = &mut this.mode {
2169                                project_transaction.0.extend(
2170                                    mode.last_workspace_edits_by_language_server
2171                                        .remove(&language_server.server_id())
2172                                        .unwrap_or_default()
2173                                        .0,
2174                                )
2175                            }
2176                        })?;
2177                    } else {
2178                        log::warn!("Cannot execute a command {} not listed in the language server capabilities", command.command)
2179                    }
2180                }
2181            }
2182        }
2183
2184        Ok(())
2185    }
2186
2187    pub async fn deserialize_text_edits(
2188        this: Entity<LspStore>,
2189        buffer_to_edit: Entity<Buffer>,
2190        edits: Vec<lsp::TextEdit>,
2191        push_to_history: bool,
2192        _: Arc<CachedLspAdapter>,
2193        language_server: Arc<LanguageServer>,
2194        cx: &mut AsyncApp,
2195    ) -> Result<Option<Transaction>> {
2196        let edits = this
2197            .update(cx, |this, cx| {
2198                this.as_local_mut().unwrap().edits_from_lsp(
2199                    &buffer_to_edit,
2200                    edits,
2201                    language_server.server_id(),
2202                    None,
2203                    cx,
2204                )
2205            })?
2206            .await?;
2207
2208        let transaction = buffer_to_edit.update(cx, |buffer, cx| {
2209            buffer.finalize_last_transaction();
2210            buffer.start_transaction();
2211            for (range, text) in edits {
2212                buffer.edit([(range, text)], None, cx);
2213            }
2214
2215            if buffer.end_transaction(cx).is_some() {
2216                let transaction = buffer.finalize_last_transaction().unwrap().clone();
2217                if !push_to_history {
2218                    buffer.forget_transaction(transaction.id);
2219                }
2220                Some(transaction)
2221            } else {
2222                None
2223            }
2224        })?;
2225
2226        Ok(transaction)
2227    }
2228
2229    #[allow(clippy::type_complexity)]
2230    pub(crate) fn edits_from_lsp(
2231        &mut self,
2232        buffer: &Entity<Buffer>,
2233        lsp_edits: impl 'static + Send + IntoIterator<Item = lsp::TextEdit>,
2234        server_id: LanguageServerId,
2235        version: Option<i32>,
2236        cx: &mut Context<LspStore>,
2237    ) -> Task<Result<Vec<(Range<Anchor>, Arc<str>)>>> {
2238        let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx);
2239        cx.background_spawn(async move {
2240            let snapshot = snapshot?;
2241            let mut lsp_edits = lsp_edits
2242                .into_iter()
2243                .map(|edit| (range_from_lsp(edit.range), edit.new_text))
2244                .collect::<Vec<_>>();
2245            lsp_edits.sort_by_key(|(range, _)| range.start);
2246
2247            let mut lsp_edits = lsp_edits.into_iter().peekable();
2248            let mut edits = Vec::new();
2249            while let Some((range, mut new_text)) = lsp_edits.next() {
2250                // Clip invalid ranges provided by the language server.
2251                let mut range = snapshot.clip_point_utf16(range.start, Bias::Left)
2252                    ..snapshot.clip_point_utf16(range.end, Bias::Left);
2253
2254                // Combine any LSP edits that are adjacent.
2255                //
2256                // Also, combine LSP edits that are separated from each other by only
2257                // a newline. This is important because for some code actions,
2258                // Rust-analyzer rewrites the entire buffer via a series of edits that
2259                // are separated by unchanged newline characters.
2260                //
2261                // In order for the diffing logic below to work properly, any edits that
2262                // cancel each other out must be combined into one.
2263                while let Some((next_range, next_text)) = lsp_edits.peek() {
2264                    if next_range.start.0 > range.end {
2265                        if next_range.start.0.row > range.end.row + 1
2266                            || next_range.start.0.column > 0
2267                            || snapshot.clip_point_utf16(
2268                                Unclipped(PointUtf16::new(range.end.row, u32::MAX)),
2269                                Bias::Left,
2270                            ) > range.end
2271                        {
2272                            break;
2273                        }
2274                        new_text.push('\n');
2275                    }
2276                    range.end = snapshot.clip_point_utf16(next_range.end, Bias::Left);
2277                    new_text.push_str(next_text);
2278                    lsp_edits.next();
2279                }
2280
2281                // For multiline edits, perform a diff of the old and new text so that
2282                // we can identify the changes more precisely, preserving the locations
2283                // of any anchors positioned in the unchanged regions.
2284                if range.end.row > range.start.row {
2285                    let offset = range.start.to_offset(&snapshot);
2286                    let old_text = snapshot.text_for_range(range).collect::<String>();
2287                    let range_edits = language::text_diff(old_text.as_str(), &new_text);
2288                    edits.extend(range_edits.into_iter().map(|(range, replacement)| {
2289                        (
2290                            snapshot.anchor_after(offset + range.start)
2291                                ..snapshot.anchor_before(offset + range.end),
2292                            replacement,
2293                        )
2294                    }));
2295                } else if range.end == range.start {
2296                    let anchor = snapshot.anchor_after(range.start);
2297                    edits.push((anchor..anchor, new_text.into()));
2298                } else {
2299                    let edit_start = snapshot.anchor_after(range.start);
2300                    let edit_end = snapshot.anchor_before(range.end);
2301                    edits.push((edit_start..edit_end, new_text.into()));
2302                }
2303            }
2304
2305            Ok(edits)
2306        })
2307    }
2308
2309    pub(crate) async fn deserialize_workspace_edit(
2310        this: Entity<LspStore>,
2311        edit: lsp::WorkspaceEdit,
2312        push_to_history: bool,
2313        lsp_adapter: Arc<CachedLspAdapter>,
2314        language_server: Arc<LanguageServer>,
2315        cx: &mut AsyncApp,
2316    ) -> Result<ProjectTransaction> {
2317        let fs = this.read_with(cx, |this, _| this.as_local().unwrap().fs.clone())?;
2318
2319        let mut operations = Vec::new();
2320        if let Some(document_changes) = edit.document_changes {
2321            match document_changes {
2322                lsp::DocumentChanges::Edits(edits) => {
2323                    operations.extend(edits.into_iter().map(lsp::DocumentChangeOperation::Edit))
2324                }
2325                lsp::DocumentChanges::Operations(ops) => operations = ops,
2326            }
2327        } else if let Some(changes) = edit.changes {
2328            operations.extend(changes.into_iter().map(|(uri, edits)| {
2329                lsp::DocumentChangeOperation::Edit(lsp::TextDocumentEdit {
2330                    text_document: lsp::OptionalVersionedTextDocumentIdentifier {
2331                        uri,
2332                        version: None,
2333                    },
2334                    edits: edits.into_iter().map(Edit::Plain).collect(),
2335                })
2336            }));
2337        }
2338
2339        let mut project_transaction = ProjectTransaction::default();
2340        for operation in operations {
2341            match operation {
2342                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Create(op)) => {
2343                    let abs_path = op
2344                        .uri
2345                        .to_file_path()
2346                        .map_err(|_| anyhow!("can't convert URI to path"))?;
2347
2348                    if let Some(parent_path) = abs_path.parent() {
2349                        fs.create_dir(parent_path).await?;
2350                    }
2351                    if abs_path.ends_with("/") {
2352                        fs.create_dir(&abs_path).await?;
2353                    } else {
2354                        fs.create_file(
2355                            &abs_path,
2356                            op.options
2357                                .map(|options| fs::CreateOptions {
2358                                    overwrite: options.overwrite.unwrap_or(false),
2359                                    ignore_if_exists: options.ignore_if_exists.unwrap_or(false),
2360                                })
2361                                .unwrap_or_default(),
2362                        )
2363                        .await?;
2364                    }
2365                }
2366
2367                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Rename(op)) => {
2368                    let source_abs_path = op
2369                        .old_uri
2370                        .to_file_path()
2371                        .map_err(|_| anyhow!("can't convert URI to path"))?;
2372                    let target_abs_path = op
2373                        .new_uri
2374                        .to_file_path()
2375                        .map_err(|_| anyhow!("can't convert URI to path"))?;
2376                    fs.rename(
2377                        &source_abs_path,
2378                        &target_abs_path,
2379                        op.options
2380                            .map(|options| fs::RenameOptions {
2381                                overwrite: options.overwrite.unwrap_or(false),
2382                                ignore_if_exists: options.ignore_if_exists.unwrap_or(false),
2383                            })
2384                            .unwrap_or_default(),
2385                    )
2386                    .await?;
2387                }
2388
2389                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Delete(op)) => {
2390                    let abs_path = op
2391                        .uri
2392                        .to_file_path()
2393                        .map_err(|_| anyhow!("can't convert URI to path"))?;
2394                    let options = op
2395                        .options
2396                        .map(|options| fs::RemoveOptions {
2397                            recursive: options.recursive.unwrap_or(false),
2398                            ignore_if_not_exists: options.ignore_if_not_exists.unwrap_or(false),
2399                        })
2400                        .unwrap_or_default();
2401                    if abs_path.ends_with("/") {
2402                        fs.remove_dir(&abs_path, options).await?;
2403                    } else {
2404                        fs.remove_file(&abs_path, options).await?;
2405                    }
2406                }
2407
2408                lsp::DocumentChangeOperation::Edit(op) => {
2409                    let buffer_to_edit = this
2410                        .update(cx, |this, cx| {
2411                            this.open_local_buffer_via_lsp(
2412                                op.text_document.uri.clone(),
2413                                language_server.server_id(),
2414                                lsp_adapter.name.clone(),
2415                                cx,
2416                            )
2417                        })?
2418                        .await?;
2419
2420                    let edits = this
2421                        .update(cx, |this, cx| {
2422                            let path = buffer_to_edit.read(cx).project_path(cx);
2423                            let active_entry = this.active_entry;
2424                            let is_active_entry = path.clone().map_or(false, |project_path| {
2425                                this.worktree_store
2426                                    .read(cx)
2427                                    .entry_for_path(&project_path, cx)
2428                                    .map_or(false, |entry| Some(entry.id) == active_entry)
2429                            });
2430                            let local = this.as_local_mut().unwrap();
2431
2432                            let (mut edits, mut snippet_edits) = (vec![], vec![]);
2433                            for edit in op.edits {
2434                                match edit {
2435                                    Edit::Plain(edit) => {
2436                                        if !edits.contains(&edit) {
2437                                            edits.push(edit)
2438                                        }
2439                                    }
2440                                    Edit::Annotated(edit) => {
2441                                        if !edits.contains(&edit.text_edit) {
2442                                            edits.push(edit.text_edit)
2443                                        }
2444                                    }
2445                                    Edit::Snippet(edit) => {
2446                                        let Ok(snippet) = Snippet::parse(&edit.snippet.value)
2447                                        else {
2448                                            continue;
2449                                        };
2450
2451                                        if is_active_entry {
2452                                            snippet_edits.push((edit.range, snippet));
2453                                        } else {
2454                                            // Since this buffer is not focused, apply a normal edit.
2455                                            let new_edit = TextEdit {
2456                                                range: edit.range,
2457                                                new_text: snippet.text,
2458                                            };
2459                                            if !edits.contains(&new_edit) {
2460                                                edits.push(new_edit);
2461                                            }
2462                                        }
2463                                    }
2464                                }
2465                            }
2466                            if !snippet_edits.is_empty() {
2467                                let buffer_id = buffer_to_edit.read(cx).remote_id();
2468                                let version = if let Some(buffer_version) = op.text_document.version
2469                                {
2470                                    local
2471                                        .buffer_snapshot_for_lsp_version(
2472                                            &buffer_to_edit,
2473                                            language_server.server_id(),
2474                                            Some(buffer_version),
2475                                            cx,
2476                                        )
2477                                        .ok()
2478                                        .map(|snapshot| snapshot.version)
2479                                } else {
2480                                    Some(buffer_to_edit.read(cx).saved_version().clone())
2481                                };
2482
2483                                let most_recent_edit = version.and_then(|version| {
2484                                    version.iter().max_by_key(|timestamp| timestamp.value)
2485                                });
2486                                // Check if the edit that triggered that edit has been made by this participant.
2487
2488                                if let Some(most_recent_edit) = most_recent_edit {
2489                                    cx.emit(LspStoreEvent::SnippetEdit {
2490                                        buffer_id,
2491                                        edits: snippet_edits,
2492                                        most_recent_edit,
2493                                    });
2494                                }
2495                            }
2496
2497                            local.edits_from_lsp(
2498                                &buffer_to_edit,
2499                                edits,
2500                                language_server.server_id(),
2501                                op.text_document.version,
2502                                cx,
2503                            )
2504                        })?
2505                        .await?;
2506
2507                    let transaction = buffer_to_edit.update(cx, |buffer, cx| {
2508                        buffer.finalize_last_transaction();
2509                        buffer.start_transaction();
2510                        for (range, text) in edits {
2511                            buffer.edit([(range, text)], None, cx);
2512                        }
2513                        let transaction = if buffer.end_transaction(cx).is_some() {
2514                            let transaction = buffer.finalize_last_transaction().unwrap().clone();
2515                            if !push_to_history {
2516                                buffer.forget_transaction(transaction.id);
2517                            }
2518                            Some(transaction)
2519                        } else {
2520                            None
2521                        };
2522
2523                        transaction
2524                    })?;
2525                    if let Some(transaction) = transaction {
2526                        project_transaction.0.insert(buffer_to_edit, transaction);
2527                    }
2528                }
2529            }
2530        }
2531
2532        Ok(project_transaction)
2533    }
2534
2535    async fn on_lsp_workspace_edit(
2536        this: WeakEntity<LspStore>,
2537        params: lsp::ApplyWorkspaceEditParams,
2538        server_id: LanguageServerId,
2539        adapter: Arc<CachedLspAdapter>,
2540        cx: &mut AsyncApp,
2541    ) -> Result<lsp::ApplyWorkspaceEditResponse> {
2542        let this = this
2543            .upgrade()
2544            .ok_or_else(|| anyhow!("project project closed"))?;
2545        let language_server = this
2546            .update(cx, |this, _| this.language_server_for_id(server_id))?
2547            .ok_or_else(|| anyhow!("language server not found"))?;
2548        let transaction = Self::deserialize_workspace_edit(
2549            this.clone(),
2550            params.edit,
2551            true,
2552            adapter.clone(),
2553            language_server.clone(),
2554            cx,
2555        )
2556        .await
2557        .log_err();
2558        this.update(cx, |this, _| {
2559            if let Some(transaction) = transaction {
2560                this.as_local_mut()
2561                    .unwrap()
2562                    .last_workspace_edits_by_language_server
2563                    .insert(server_id, transaction);
2564            }
2565        })?;
2566        Ok(lsp::ApplyWorkspaceEditResponse {
2567            applied: true,
2568            failed_change: None,
2569            failure_reason: None,
2570        })
2571    }
2572
2573    fn remove_worktree(
2574        &mut self,
2575        id_to_remove: WorktreeId,
2576        cx: &mut Context<'_, LspStore>,
2577    ) -> Vec<LanguageServerId> {
2578        self.diagnostics.remove(&id_to_remove);
2579        self.prettier_store.update(cx, |prettier_store, cx| {
2580            prettier_store.remove_worktree(id_to_remove, cx);
2581        });
2582
2583        let mut servers_to_remove = BTreeMap::default();
2584        let mut servers_to_preserve = HashSet::default();
2585        for ((path, server_name), ref server_ids) in &self.language_server_ids {
2586            if *path == id_to_remove {
2587                servers_to_remove.extend(server_ids.iter().map(|id| (*id, server_name.clone())));
2588            } else {
2589                servers_to_preserve.extend(server_ids.iter().cloned());
2590            }
2591        }
2592        servers_to_remove.retain(|server_id, _| !servers_to_preserve.contains(server_id));
2593
2594        for (server_id_to_remove, _) in &servers_to_remove {
2595            self.language_server_ids
2596                .values_mut()
2597                .for_each(|server_ids| {
2598                    server_ids.remove(server_id_to_remove);
2599                });
2600            self.language_server_watched_paths
2601                .remove(&server_id_to_remove);
2602            self.language_server_paths_watched_for_rename
2603                .remove(&server_id_to_remove);
2604            self.last_workspace_edits_by_language_server
2605                .remove(&server_id_to_remove);
2606            self.language_servers.remove(&server_id_to_remove);
2607            cx.emit(LspStoreEvent::LanguageServerRemoved(*server_id_to_remove));
2608        }
2609        servers_to_remove.into_keys().collect()
2610    }
2611
2612    fn rebuild_watched_paths_inner<'a>(
2613        &'a self,
2614        language_server_id: LanguageServerId,
2615        watchers: impl Iterator<Item = &'a FileSystemWatcher>,
2616        cx: &mut Context<LspStore>,
2617    ) -> LanguageServerWatchedPathsBuilder {
2618        let worktrees = self
2619            .worktree_store
2620            .read(cx)
2621            .worktrees()
2622            .filter_map(|worktree| {
2623                self.language_servers_for_worktree(worktree.read(cx).id())
2624                    .find(|server| server.server_id() == language_server_id)
2625                    .map(|_| worktree)
2626            })
2627            .collect::<Vec<_>>();
2628
2629        let mut worktree_globs = HashMap::default();
2630        let mut abs_globs = HashMap::default();
2631        log::trace!(
2632            "Processing new watcher paths for language server with id {}",
2633            language_server_id
2634        );
2635
2636        enum PathToWatch {
2637            Worktree {
2638                literal_prefix: Arc<Path>,
2639                pattern: String,
2640            },
2641            Absolute {
2642                path: Arc<Path>,
2643                pattern: String,
2644            },
2645        }
2646        for watcher in watchers {
2647            let mut found_host = false;
2648            for worktree in &worktrees {
2649                let glob_is_inside_worktree = worktree.update(cx, |tree, _| {
2650                    let worktree_root_path = tree.abs_path();
2651                    let path_to_watch = match &watcher.glob_pattern {
2652                        lsp::GlobPattern::String(s) => {
2653                            let watcher_path = SanitizedPath::from(s);
2654                            match watcher_path.as_path().strip_prefix(&worktree_root_path) {
2655                                Ok(relative) => {
2656                                    let pattern = relative.to_string_lossy().to_string();
2657                                    let literal_prefix = glob_literal_prefix(relative).into();
2658
2659                                    PathToWatch::Worktree {
2660                                        literal_prefix,
2661                                        pattern,
2662                                    }
2663                                }
2664                                Err(_) => {
2665                                    let path = glob_literal_prefix(watcher_path.as_path());
2666                                    let pattern = watcher_path
2667                                        .as_path()
2668                                        .strip_prefix(&path)
2669                                        .map(|p| p.to_string_lossy().to_string())
2670                                        .unwrap_or_else(|e| {
2671                                            debug_panic!(
2672                                                "Failed to strip prefix for string pattern: {}, with prefix: {}, with error: {}",
2673                                                s,
2674                                                path.display(),
2675                                                e
2676                                            );
2677                                            watcher_path.as_path().to_string_lossy().to_string()
2678                                        });
2679                                    let path = if path.components().next().is_none() {
2680                                        worktree_root_path.clone()
2681                                    } else {
2682                                        path.into()
2683                                    };
2684
2685                                    PathToWatch::Absolute { path, pattern }
2686                                }
2687                            }
2688                        }
2689                        lsp::GlobPattern::Relative(rp) => {
2690                            let Ok(mut base_uri) = match &rp.base_uri {
2691                                lsp::OneOf::Left(workspace_folder) => &workspace_folder.uri,
2692                                lsp::OneOf::Right(base_uri) => base_uri,
2693                            }
2694                            .to_file_path() else {
2695                                return false;
2696                            };
2697
2698                            match base_uri.strip_prefix(&worktree_root_path) {
2699                                Ok(relative) => {
2700                                    let mut literal_prefix = relative.to_owned();
2701                                    literal_prefix
2702                                        .push(glob_literal_prefix(Path::new(&rp.pattern)));
2703
2704                                    PathToWatch::Worktree {
2705                                        literal_prefix: literal_prefix.into(),
2706                                        pattern: rp.pattern.clone(),
2707                                    }
2708                                }
2709                                Err(_) => {
2710                                    let path = glob_literal_prefix(Path::new(&rp.pattern));
2711                                    let pattern = Path::new(&rp.pattern)
2712                                        .strip_prefix(&path)
2713                                        .map(|p| p.to_string_lossy().to_string())
2714                                        .unwrap_or_else(|e| {
2715                                            debug_panic!(
2716                                                "Failed to strip prefix for relative pattern: {}, with prefix: {}, with error: {}",
2717                                                rp.pattern,
2718                                                path.display(),
2719                                                e
2720                                            );
2721                                            rp.pattern.clone()
2722                                        });
2723                                    base_uri.push(path);
2724
2725                                    let path = if base_uri.components().next().is_none() {
2726                                        debug_panic!("base_uri is empty, {}", base_uri.display());
2727                                        worktree_root_path.clone()
2728                                    } else {
2729                                        base_uri.into()
2730                                    };
2731                                    PathToWatch::Absolute { path, pattern }
2732                                }
2733                            }
2734                        }
2735                    };
2736                    match path_to_watch {
2737                        PathToWatch::Worktree {
2738                            literal_prefix,
2739                            pattern,
2740                        } => {
2741                            if let Some((tree, glob)) =
2742                                tree.as_local_mut().zip(Glob::new(&pattern).log_err())
2743                            {
2744                                tree.add_path_prefix_to_scan(literal_prefix);
2745                                worktree_globs
2746                                    .entry(tree.id())
2747                                    .or_insert_with(GlobSetBuilder::new)
2748                                    .add(glob);
2749                            } else {
2750                                return false;
2751                            }
2752                        }
2753                        PathToWatch::Absolute { path, pattern } => {
2754                            if let Some(glob) = Glob::new(&pattern).log_err() {
2755                                abs_globs
2756                                    .entry(path)
2757                                    .or_insert_with(GlobSetBuilder::new)
2758                                    .add(glob);
2759                            }
2760                        }
2761                    }
2762                    true
2763                });
2764                if glob_is_inside_worktree {
2765                    log::trace!(
2766                        "Watcher pattern `{}` has been attached to the worktree at `{}`",
2767                        serde_json::to_string(&watcher.glob_pattern).unwrap(),
2768                        worktree.read(cx).abs_path().display()
2769                    );
2770                    found_host = true;
2771                }
2772            }
2773            if !found_host {
2774                log::error!(
2775                    "Watcher pattern `{}` has not been attached to any worktree or absolute path",
2776                    serde_json::to_string(&watcher.glob_pattern).unwrap()
2777                )
2778            }
2779        }
2780
2781        let mut watch_builder = LanguageServerWatchedPathsBuilder::default();
2782        for (worktree_id, builder) in worktree_globs {
2783            if let Ok(globset) = builder.build() {
2784                watch_builder.watch_worktree(worktree_id, globset);
2785            }
2786        }
2787        for (abs_path, builder) in abs_globs {
2788            if let Ok(globset) = builder.build() {
2789                watch_builder.watch_abs_path(abs_path, globset);
2790            }
2791        }
2792        watch_builder
2793    }
2794
2795    fn rebuild_watched_paths(
2796        &mut self,
2797        language_server_id: LanguageServerId,
2798        cx: &mut Context<LspStore>,
2799    ) {
2800        let Some(watchers) = self
2801            .language_server_watcher_registrations
2802            .get(&language_server_id)
2803        else {
2804            return;
2805        };
2806
2807        let watch_builder =
2808            self.rebuild_watched_paths_inner(language_server_id, watchers.values().flatten(), cx);
2809        let watcher = watch_builder.build(self.fs.clone(), language_server_id, cx);
2810        self.language_server_watched_paths
2811            .insert(language_server_id, watcher);
2812
2813        cx.notify();
2814    }
2815
2816    fn on_lsp_did_change_watched_files(
2817        &mut self,
2818        language_server_id: LanguageServerId,
2819        registration_id: &str,
2820        params: DidChangeWatchedFilesRegistrationOptions,
2821        cx: &mut Context<LspStore>,
2822    ) {
2823        let registrations = self
2824            .language_server_watcher_registrations
2825            .entry(language_server_id)
2826            .or_default();
2827
2828        registrations.insert(registration_id.to_string(), params.watchers);
2829
2830        self.rebuild_watched_paths(language_server_id, cx);
2831    }
2832
2833    fn on_lsp_unregister_did_change_watched_files(
2834        &mut self,
2835        language_server_id: LanguageServerId,
2836        registration_id: &str,
2837        cx: &mut Context<LspStore>,
2838    ) {
2839        let registrations = self
2840            .language_server_watcher_registrations
2841            .entry(language_server_id)
2842            .or_default();
2843
2844        if registrations.remove(registration_id).is_some() {
2845            log::info!(
2846                    "language server {}: unregistered workspace/DidChangeWatchedFiles capability with id {}",
2847                    language_server_id,
2848                    registration_id
2849                );
2850        } else {
2851            log::warn!(
2852                    "language server {}: failed to unregister workspace/DidChangeWatchedFiles capability with id {}. not registered.",
2853                    language_server_id,
2854                    registration_id
2855                );
2856        }
2857
2858        self.rebuild_watched_paths(language_server_id, cx);
2859    }
2860}
2861
2862#[derive(Debug)]
2863pub struct FormattableBuffer {
2864    handle: Entity<Buffer>,
2865    abs_path: Option<PathBuf>,
2866    env: Option<HashMap<String, String>>,
2867    ranges: Option<Vec<Range<Anchor>>>,
2868}
2869
2870pub struct RemoteLspStore {
2871    upstream_client: Option<AnyProtoClient>,
2872    upstream_project_id: u64,
2873}
2874
2875#[allow(clippy::large_enum_variant)]
2876pub(crate) enum LspStoreMode {
2877    Local(LocalLspStore),   // ssh host and collab host
2878    Remote(RemoteLspStore), // collab guest
2879}
2880
2881impl LspStoreMode {
2882    fn is_local(&self) -> bool {
2883        matches!(self, LspStoreMode::Local(_))
2884    }
2885}
2886
2887pub struct LspStore {
2888    mode: LspStoreMode,
2889    last_formatting_failure: Option<String>,
2890    downstream_client: Option<(AnyProtoClient, u64)>,
2891    nonce: u128,
2892    buffer_store: Entity<BufferStore>,
2893    worktree_store: Entity<WorktreeStore>,
2894    toolchain_store: Option<Entity<ToolchainStore>>,
2895    pub languages: Arc<LanguageRegistry>,
2896    pub language_server_statuses: BTreeMap<LanguageServerId, LanguageServerStatus>,
2897    active_entry: Option<ProjectEntryId>,
2898    _maintain_workspace_config: (Task<Result<()>>, watch::Sender<()>),
2899    _maintain_buffer_languages: Task<()>,
2900    diagnostic_summaries:
2901        HashMap<WorktreeId, HashMap<Arc<Path>, HashMap<LanguageServerId, DiagnosticSummary>>>,
2902}
2903
2904pub enum LspStoreEvent {
2905    LanguageServerAdded(LanguageServerId, LanguageServerName, Option<WorktreeId>),
2906    LanguageServerRemoved(LanguageServerId),
2907    LanguageServerUpdate {
2908        language_server_id: LanguageServerId,
2909        message: proto::update_language_server::Variant,
2910    },
2911    LanguageServerLog(LanguageServerId, LanguageServerLogType, String),
2912    LanguageServerPrompt(LanguageServerPromptRequest),
2913    LanguageDetected {
2914        buffer: Entity<Buffer>,
2915        new_language: Option<Arc<Language>>,
2916    },
2917    Notification(String),
2918    RefreshInlayHints,
2919    RefreshCodeLens,
2920    DiagnosticsUpdated {
2921        language_server_id: LanguageServerId,
2922        path: ProjectPath,
2923    },
2924    DiskBasedDiagnosticsStarted {
2925        language_server_id: LanguageServerId,
2926    },
2927    DiskBasedDiagnosticsFinished {
2928        language_server_id: LanguageServerId,
2929    },
2930    SnippetEdit {
2931        buffer_id: BufferId,
2932        edits: Vec<(lsp::Range, Snippet)>,
2933        most_recent_edit: clock::Lamport,
2934    },
2935}
2936
2937#[derive(Clone, Debug, Serialize)]
2938pub struct LanguageServerStatus {
2939    pub name: String,
2940    pub pending_work: BTreeMap<String, LanguageServerProgress>,
2941    pub has_pending_diagnostic_updates: bool,
2942    progress_tokens: HashSet<String>,
2943}
2944
2945#[derive(Clone, Debug)]
2946struct CoreSymbol {
2947    pub language_server_name: LanguageServerName,
2948    pub source_worktree_id: WorktreeId,
2949    pub source_language_server_id: LanguageServerId,
2950    pub path: ProjectPath,
2951    pub name: String,
2952    pub kind: lsp::SymbolKind,
2953    pub range: Range<Unclipped<PointUtf16>>,
2954    pub signature: [u8; 32],
2955}
2956
2957impl LspStore {
2958    pub fn init(client: &AnyProtoClient) {
2959        client.add_entity_request_handler(Self::handle_multi_lsp_query);
2960        client.add_entity_request_handler(Self::handle_restart_language_servers);
2961        client.add_entity_request_handler(Self::handle_cancel_language_server_work);
2962        client.add_entity_message_handler(Self::handle_start_language_server);
2963        client.add_entity_message_handler(Self::handle_update_language_server);
2964        client.add_entity_message_handler(Self::handle_language_server_log);
2965        client.add_entity_message_handler(Self::handle_update_diagnostic_summary);
2966        client.add_entity_request_handler(Self::handle_format_buffers);
2967        client.add_entity_request_handler(Self::handle_apply_code_action_kind);
2968        client.add_entity_request_handler(Self::handle_resolve_completion_documentation);
2969        client.add_entity_request_handler(Self::handle_apply_code_action);
2970        client.add_entity_request_handler(Self::handle_inlay_hints);
2971        client.add_entity_request_handler(Self::handle_get_project_symbols);
2972        client.add_entity_request_handler(Self::handle_resolve_inlay_hint);
2973        client.add_entity_request_handler(Self::handle_open_buffer_for_symbol);
2974        client.add_entity_request_handler(Self::handle_refresh_inlay_hints);
2975        client.add_entity_request_handler(Self::handle_refresh_code_lens);
2976        client.add_entity_request_handler(Self::handle_on_type_formatting);
2977        client.add_entity_request_handler(Self::handle_apply_additional_edits_for_completion);
2978        client.add_entity_request_handler(Self::handle_register_buffer_with_language_servers);
2979        client.add_entity_request_handler(Self::handle_rename_project_entry);
2980        client.add_entity_request_handler(Self::handle_lsp_command::<GetCodeActions>);
2981        client.add_entity_request_handler(Self::handle_lsp_command::<GetCompletions>);
2982        client.add_entity_request_handler(Self::handle_lsp_command::<GetHover>);
2983        client.add_entity_request_handler(Self::handle_lsp_command::<GetDefinition>);
2984        client.add_entity_request_handler(Self::handle_lsp_command::<GetDeclaration>);
2985        client.add_entity_request_handler(Self::handle_lsp_command::<GetTypeDefinition>);
2986        client.add_entity_request_handler(Self::handle_lsp_command::<GetDocumentHighlights>);
2987        client.add_entity_request_handler(Self::handle_lsp_command::<GetReferences>);
2988        client.add_entity_request_handler(Self::handle_lsp_command::<PrepareRename>);
2989        client.add_entity_request_handler(Self::handle_lsp_command::<PerformRename>);
2990        client.add_entity_request_handler(Self::handle_lsp_command::<lsp_ext_command::ExpandMacro>);
2991        client.add_entity_request_handler(Self::handle_lsp_command::<LinkedEditingRange>);
2992    }
2993
2994    pub fn as_remote(&self) -> Option<&RemoteLspStore> {
2995        match &self.mode {
2996            LspStoreMode::Remote(remote_lsp_store) => Some(remote_lsp_store),
2997            _ => None,
2998        }
2999    }
3000
3001    pub fn as_local(&self) -> Option<&LocalLspStore> {
3002        match &self.mode {
3003            LspStoreMode::Local(local_lsp_store) => Some(local_lsp_store),
3004            _ => None,
3005        }
3006    }
3007
3008    pub fn as_local_mut(&mut self) -> Option<&mut LocalLspStore> {
3009        match &mut self.mode {
3010            LspStoreMode::Local(local_lsp_store) => Some(local_lsp_store),
3011            _ => None,
3012        }
3013    }
3014
3015    pub fn upstream_client(&self) -> Option<(AnyProtoClient, u64)> {
3016        match &self.mode {
3017            LspStoreMode::Remote(RemoteLspStore {
3018                upstream_client: Some(upstream_client),
3019                upstream_project_id,
3020                ..
3021            }) => Some((upstream_client.clone(), *upstream_project_id)),
3022
3023            LspStoreMode::Remote(RemoteLspStore {
3024                upstream_client: None,
3025                ..
3026            }) => None,
3027            LspStoreMode::Local(_) => None,
3028        }
3029    }
3030
3031    pub fn new_local(
3032        buffer_store: Entity<BufferStore>,
3033        worktree_store: Entity<WorktreeStore>,
3034        prettier_store: Entity<PrettierStore>,
3035        toolchain_store: Entity<ToolchainStore>,
3036        environment: Entity<ProjectEnvironment>,
3037        languages: Arc<LanguageRegistry>,
3038        http_client: Arc<dyn HttpClient>,
3039        fs: Arc<dyn Fs>,
3040        cx: &mut Context<Self>,
3041    ) -> Self {
3042        let yarn = YarnPathStore::new(fs.clone(), cx);
3043        cx.subscribe(&buffer_store, Self::on_buffer_store_event)
3044            .detach();
3045        cx.subscribe(&worktree_store, Self::on_worktree_store_event)
3046            .detach();
3047        cx.subscribe(&prettier_store, Self::on_prettier_store_event)
3048            .detach();
3049        cx.subscribe(&toolchain_store, Self::on_toolchain_store_event)
3050            .detach();
3051        if let Some(extension_events) = extension::ExtensionEvents::try_global(cx).as_ref() {
3052            cx.subscribe(
3053                extension_events,
3054                Self::reload_zed_json_schemas_on_extensions_changed,
3055            )
3056            .detach();
3057        } else {
3058            log::info!("No extension events global found. Skipping JSON schema auto-reload setup");
3059        }
3060        cx.observe_global::<SettingsStore>(Self::on_settings_changed)
3061            .detach();
3062
3063        let _maintain_workspace_config = {
3064            let (sender, receiver) = watch::channel();
3065            (
3066                Self::maintain_workspace_config(fs.clone(), receiver, cx),
3067                sender,
3068            )
3069        };
3070        let project_tree = ProjectTree::new(worktree_store.clone(), cx);
3071        Self {
3072            mode: LspStoreMode::Local(LocalLspStore {
3073                weak: cx.weak_entity(),
3074                worktree_store: worktree_store.clone(),
3075                toolchain_store: toolchain_store.clone(),
3076                supplementary_language_servers: Default::default(),
3077                languages: languages.clone(),
3078                language_server_ids: Default::default(),
3079                language_servers: Default::default(),
3080                last_workspace_edits_by_language_server: Default::default(),
3081                language_server_watched_paths: Default::default(),
3082                language_server_paths_watched_for_rename: Default::default(),
3083                language_server_watcher_registrations: Default::default(),
3084                buffers_being_formatted: Default::default(),
3085                buffer_snapshots: Default::default(),
3086                prettier_store,
3087                environment,
3088                http_client,
3089                fs,
3090                yarn,
3091                next_diagnostic_group_id: Default::default(),
3092                diagnostics: Default::default(),
3093                _subscription: cx.on_app_quit(|this, cx| {
3094                    this.as_local_mut().unwrap().shutdown_language_servers(cx)
3095                }),
3096                lsp_tree: LanguageServerTree::new(project_tree, languages.clone(), cx),
3097                registered_buffers: Default::default(),
3098            }),
3099            last_formatting_failure: None,
3100            downstream_client: None,
3101            buffer_store,
3102            worktree_store,
3103            toolchain_store: Some(toolchain_store),
3104            languages: languages.clone(),
3105            language_server_statuses: Default::default(),
3106            nonce: StdRng::from_entropy().gen(),
3107            diagnostic_summaries: Default::default(),
3108            active_entry: None,
3109
3110            _maintain_workspace_config,
3111            _maintain_buffer_languages: Self::maintain_buffer_languages(languages, cx),
3112        }
3113    }
3114
3115    fn send_lsp_proto_request<R: LspCommand>(
3116        &self,
3117        buffer: Entity<Buffer>,
3118        client: AnyProtoClient,
3119        upstream_project_id: u64,
3120        request: R,
3121        cx: &mut Context<'_, LspStore>,
3122    ) -> Task<anyhow::Result<<R as LspCommand>::Response>> {
3123        let message = request.to_proto(upstream_project_id, buffer.read(cx));
3124        cx.spawn(async move |this, cx| {
3125            let response = client.request(message).await?;
3126            let this = this.upgrade().context("project dropped")?;
3127            request
3128                .response_from_proto(response, this, buffer, cx.clone())
3129                .await
3130        })
3131    }
3132
3133    pub(super) fn new_remote(
3134        buffer_store: Entity<BufferStore>,
3135        worktree_store: Entity<WorktreeStore>,
3136        toolchain_store: Option<Entity<ToolchainStore>>,
3137        languages: Arc<LanguageRegistry>,
3138        upstream_client: AnyProtoClient,
3139        project_id: u64,
3140        fs: Arc<dyn Fs>,
3141        cx: &mut Context<Self>,
3142    ) -> Self {
3143        cx.subscribe(&buffer_store, Self::on_buffer_store_event)
3144            .detach();
3145        cx.subscribe(&worktree_store, Self::on_worktree_store_event)
3146            .detach();
3147        let _maintain_workspace_config = {
3148            let (sender, receiver) = watch::channel();
3149            (Self::maintain_workspace_config(fs, receiver, cx), sender)
3150        };
3151        Self {
3152            mode: LspStoreMode::Remote(RemoteLspStore {
3153                upstream_client: Some(upstream_client),
3154                upstream_project_id: project_id,
3155            }),
3156            downstream_client: None,
3157            last_formatting_failure: None,
3158            buffer_store,
3159            worktree_store,
3160            languages: languages.clone(),
3161            language_server_statuses: Default::default(),
3162            nonce: StdRng::from_entropy().gen(),
3163            diagnostic_summaries: Default::default(),
3164            active_entry: None,
3165            toolchain_store,
3166            _maintain_workspace_config,
3167            _maintain_buffer_languages: Self::maintain_buffer_languages(languages.clone(), cx),
3168        }
3169    }
3170
3171    fn on_buffer_store_event(
3172        &mut self,
3173        _: Entity<BufferStore>,
3174        event: &BufferStoreEvent,
3175        cx: &mut Context<Self>,
3176    ) {
3177        match event {
3178            BufferStoreEvent::BufferAdded(buffer) => {
3179                self.on_buffer_added(buffer, cx).log_err();
3180            }
3181            BufferStoreEvent::BufferChangedFilePath { buffer, old_file } => {
3182                let buffer_id = buffer.read(cx).remote_id();
3183                if let Some(local) = self.as_local_mut() {
3184                    if let Some(old_file) = File::from_dyn(old_file.as_ref()) {
3185                        local.reset_buffer(buffer, old_file, cx);
3186
3187                        if local.registered_buffers.contains_key(&buffer_id) {
3188                            local.unregister_old_buffer_from_language_servers(buffer, old_file, cx);
3189                        }
3190                    }
3191                }
3192
3193                self.detect_language_for_buffer(buffer, cx);
3194                if let Some(local) = self.as_local_mut() {
3195                    local.initialize_buffer(buffer, cx);
3196                    if local.registered_buffers.contains_key(&buffer_id) {
3197                        local.register_buffer_with_language_servers(buffer, cx);
3198                    }
3199                }
3200            }
3201            _ => {}
3202        }
3203    }
3204
3205    fn on_worktree_store_event(
3206        &mut self,
3207        _: Entity<WorktreeStore>,
3208        event: &WorktreeStoreEvent,
3209        cx: &mut Context<Self>,
3210    ) {
3211        match event {
3212            WorktreeStoreEvent::WorktreeAdded(worktree) => {
3213                if !worktree.read(cx).is_local() {
3214                    return;
3215                }
3216                cx.subscribe(worktree, |this, worktree, event, cx| match event {
3217                    worktree::Event::UpdatedEntries(changes) => {
3218                        this.update_local_worktree_language_servers(&worktree, changes, cx);
3219                    }
3220                    worktree::Event::UpdatedGitRepositories(_)
3221                    | worktree::Event::DeletedEntry(_) => {}
3222                })
3223                .detach()
3224            }
3225            WorktreeStoreEvent::WorktreeRemoved(_, id) => self.remove_worktree(*id, cx),
3226            WorktreeStoreEvent::WorktreeUpdateSent(worktree) => {
3227                worktree.update(cx, |worktree, _cx| self.send_diagnostic_summaries(worktree));
3228            }
3229            WorktreeStoreEvent::WorktreeReleased(..)
3230            | WorktreeStoreEvent::WorktreeOrderChanged
3231            | WorktreeStoreEvent::WorktreeUpdatedEntries(..)
3232            | WorktreeStoreEvent::WorktreeUpdatedGitRepositories(..)
3233            | WorktreeStoreEvent::WorktreeDeletedEntry(..) => {}
3234        }
3235    }
3236
3237    fn on_prettier_store_event(
3238        &mut self,
3239        _: Entity<PrettierStore>,
3240        event: &PrettierStoreEvent,
3241        cx: &mut Context<Self>,
3242    ) {
3243        match event {
3244            PrettierStoreEvent::LanguageServerRemoved(prettier_server_id) => {
3245                self.unregister_supplementary_language_server(*prettier_server_id, cx);
3246            }
3247            PrettierStoreEvent::LanguageServerAdded {
3248                new_server_id,
3249                name,
3250                prettier_server,
3251            } => {
3252                self.register_supplementary_language_server(
3253                    *new_server_id,
3254                    name.clone(),
3255                    prettier_server.clone(),
3256                    cx,
3257                );
3258            }
3259        }
3260    }
3261
3262    fn on_toolchain_store_event(
3263        &mut self,
3264        _: Entity<ToolchainStore>,
3265        event: &ToolchainStoreEvent,
3266        _: &mut Context<Self>,
3267    ) {
3268        match event {
3269            ToolchainStoreEvent::ToolchainActivated { .. } => {
3270                self.request_workspace_config_refresh()
3271            }
3272        }
3273    }
3274
3275    fn request_workspace_config_refresh(&mut self) {
3276        *self._maintain_workspace_config.1.borrow_mut() = ();
3277    }
3278
3279    pub fn prettier_store(&self) -> Option<Entity<PrettierStore>> {
3280        self.as_local().map(|local| local.prettier_store.clone())
3281    }
3282
3283    fn on_buffer_event(
3284        &mut self,
3285        buffer: Entity<Buffer>,
3286        event: &language::BufferEvent,
3287        cx: &mut Context<Self>,
3288    ) {
3289        match event {
3290            language::BufferEvent::Edited { .. } => {
3291                self.on_buffer_edited(buffer, cx);
3292            }
3293
3294            language::BufferEvent::Saved => {
3295                self.on_buffer_saved(buffer, cx);
3296            }
3297
3298            _ => {}
3299        }
3300    }
3301
3302    fn on_buffer_added(&mut self, buffer: &Entity<Buffer>, cx: &mut Context<Self>) -> Result<()> {
3303        buffer.update(cx, |buffer, _| {
3304            buffer.set_language_registry(self.languages.clone())
3305        });
3306
3307        cx.subscribe(buffer, |this, buffer, event, cx| {
3308            this.on_buffer_event(buffer, event, cx);
3309        })
3310        .detach();
3311
3312        self.detect_language_for_buffer(buffer, cx);
3313        if let Some(local) = self.as_local_mut() {
3314            local.initialize_buffer(buffer, cx);
3315        }
3316
3317        Ok(())
3318    }
3319
3320    pub fn reload_zed_json_schemas_on_extensions_changed(
3321        &mut self,
3322        _: Entity<extension::ExtensionEvents>,
3323        evt: &extension::Event,
3324        cx: &mut Context<Self>,
3325    ) {
3326        #[expect(
3327            irrefutable_let_patterns,
3328            reason = "Make sure to handle new event types in extension properly"
3329        )]
3330        let extension::Event::ExtensionsInstalledChanged = evt
3331        else {
3332            return;
3333        };
3334        if self.as_local().is_none() {
3335            return;
3336        }
3337        cx.spawn(async move |this, cx| {
3338            let weak_ref = this.clone();
3339
3340            let servers = this
3341                .update(cx, |this, cx| {
3342                    let local = this.as_local()?;
3343
3344                    let mut servers = Vec::new();
3345                    for ((worktree_id, _), server_ids) in &local.language_server_ids {
3346                        for server_id in server_ids {
3347                            let Some(states) = local.language_servers.get(server_id) else {
3348                                continue;
3349                            };
3350                            let (json_adapter, json_server) = match states {
3351                                LanguageServerState::Running {
3352                                    adapter, server, ..
3353                                } if adapter.adapter.is_primary_zed_json_schema_adapter() => {
3354                                    (adapter.adapter.clone(), server.clone())
3355                                }
3356                                _ => continue,
3357                            };
3358
3359                            let Some(worktree) = this
3360                                .worktree_store
3361                                .read(cx)
3362                                .worktree_for_id(*worktree_id, cx)
3363                            else {
3364                                continue;
3365                            };
3366                            let json_delegate: Arc<dyn LspAdapterDelegate> =
3367                                LocalLspAdapterDelegate::new(
3368                                    local.languages.clone(),
3369                                    &local.environment,
3370                                    weak_ref.clone(),
3371                                    &worktree,
3372                                    local.http_client.clone(),
3373                                    local.fs.clone(),
3374                                    cx,
3375                                );
3376
3377                            servers.push((json_adapter, json_server, json_delegate));
3378                        }
3379                    }
3380                    return Some(servers);
3381                })
3382                .ok()
3383                .flatten();
3384
3385            let Some(servers) = servers else {
3386                return;
3387            };
3388
3389            let Ok(Some((fs, toolchain_store))) = this.read_with(cx, |this, cx| {
3390                let local = this.as_local()?;
3391                let toolchain_store = this.toolchain_store(cx);
3392                return Some((local.fs.clone(), toolchain_store));
3393            }) else {
3394                return;
3395            };
3396            for (adapter, server, delegate) in servers {
3397                adapter.clear_zed_json_schema_cache().await;
3398
3399                let Some(json_workspace_config) = adapter
3400                    .workspace_configuration(
3401                        fs.as_ref(),
3402                        &delegate,
3403                        toolchain_store.clone(),
3404                        cx,
3405                    )
3406                    .await
3407                    .context("generate new workspace configuration for JSON language server while trying to refresh JSON Schemas")
3408                    .ok()
3409                else {
3410                    continue;
3411                };
3412                server
3413                    .notify::<lsp::notification::DidChangeConfiguration>(
3414                        &lsp::DidChangeConfigurationParams {
3415                            settings: json_workspace_config,
3416                        },
3417                    )
3418                    .ok();
3419            }
3420        })
3421        .detach();
3422    }
3423
3424    pub(crate) fn register_buffer_with_language_servers(
3425        &mut self,
3426        buffer: &Entity<Buffer>,
3427        ignore_refcounts: bool,
3428        cx: &mut Context<Self>,
3429    ) -> OpenLspBufferHandle {
3430        let buffer_id = buffer.read(cx).remote_id();
3431        let handle = cx.new(|_| buffer.clone());
3432        if let Some(local) = self.as_local_mut() {
3433            let Some(file) = File::from_dyn(buffer.read(cx).file()) else {
3434                return handle;
3435            };
3436            if !file.is_local() {
3437                return handle;
3438            }
3439
3440            let refcount = local.registered_buffers.entry(buffer_id).or_insert(0);
3441            if !ignore_refcounts {
3442                *refcount += 1;
3443            }
3444
3445            if !ignore_refcounts || *refcount == 1 {
3446                local.register_buffer_with_language_servers(buffer, cx);
3447            }
3448            if !ignore_refcounts {
3449                cx.observe_release(&handle, move |this, buffer, cx| {
3450                    let local = this.as_local_mut().unwrap();
3451                    let Some(refcount) = local.registered_buffers.get_mut(&buffer_id) else {
3452                        debug_panic!("bad refcounting");
3453                        return;
3454                    };
3455
3456                    *refcount -= 1;
3457                    if *refcount == 0 {
3458                        local.registered_buffers.remove(&buffer_id);
3459                        if let Some(file) = File::from_dyn(buffer.read(cx).file()).cloned() {
3460                            local.unregister_old_buffer_from_language_servers(&buffer, &file, cx);
3461                        }
3462                    }
3463                })
3464                .detach();
3465            }
3466        } else if let Some((upstream_client, upstream_project_id)) = self.upstream_client() {
3467            let buffer_id = buffer.read(cx).remote_id().to_proto();
3468            cx.background_spawn(async move {
3469                upstream_client
3470                    .request(proto::RegisterBufferWithLanguageServers {
3471                        project_id: upstream_project_id,
3472                        buffer_id,
3473                    })
3474                    .await
3475            })
3476            .detach();
3477        } else {
3478            panic!("oops!");
3479        }
3480        handle
3481    }
3482
3483    fn maintain_buffer_languages(
3484        languages: Arc<LanguageRegistry>,
3485        cx: &mut Context<Self>,
3486    ) -> Task<()> {
3487        let mut subscription = languages.subscribe();
3488        let mut prev_reload_count = languages.reload_count();
3489        cx.spawn(async move |this, cx| {
3490            while let Some(()) = subscription.next().await {
3491                if let Some(this) = this.upgrade() {
3492                    // If the language registry has been reloaded, then remove and
3493                    // re-assign the languages on all open buffers.
3494                    let reload_count = languages.reload_count();
3495                    if reload_count > prev_reload_count {
3496                        prev_reload_count = reload_count;
3497                        this.update(cx, |this, cx| {
3498                            this.buffer_store.clone().update(cx, |buffer_store, cx| {
3499                                for buffer in buffer_store.buffers() {
3500                                    if let Some(f) = File::from_dyn(buffer.read(cx).file()).cloned()
3501                                    {
3502                                        buffer
3503                                            .update(cx, |buffer, cx| buffer.set_language(None, cx));
3504                                        if let Some(local) = this.as_local_mut() {
3505                                            local.reset_buffer(&buffer, &f, cx);
3506
3507                                            if local
3508                                                .registered_buffers
3509                                                .contains_key(&buffer.read(cx).remote_id())
3510                                            {
3511                                                if let Some(file_url) =
3512                                                    lsp::Url::from_file_path(&f.abs_path(cx))
3513                                                        .log_err()
3514                                                {
3515                                                    local.unregister_buffer_from_language_servers(
3516                                                        &buffer, &file_url, cx,
3517                                                    );
3518                                                }
3519                                            }
3520                                        }
3521                                    }
3522                                }
3523                            });
3524                        })
3525                        .ok();
3526                    }
3527
3528                    this.update(cx, |this, cx| {
3529                        let mut plain_text_buffers = Vec::new();
3530                        let mut buffers_with_unknown_injections = Vec::new();
3531                        for handle in this.buffer_store.read(cx).buffers() {
3532                            let buffer = handle.read(cx);
3533                            if buffer.language().is_none()
3534                                || buffer.language() == Some(&*language::PLAIN_TEXT)
3535                            {
3536                                plain_text_buffers.push(handle);
3537                            } else if buffer.contains_unknown_injections() {
3538                                buffers_with_unknown_injections.push(handle);
3539                            }
3540                        }
3541                        for buffer in plain_text_buffers {
3542                            this.detect_language_for_buffer(&buffer, cx);
3543                            if let Some(local) = this.as_local_mut() {
3544                                local.initialize_buffer(&buffer, cx);
3545                                if local
3546                                    .registered_buffers
3547                                    .contains_key(&buffer.read(cx).remote_id())
3548                                {
3549                                    local.register_buffer_with_language_servers(&buffer, cx);
3550                                }
3551                            }
3552                        }
3553
3554                        for buffer in buffers_with_unknown_injections {
3555                            buffer.update(cx, |buffer, cx| buffer.reparse(cx));
3556                        }
3557                    })
3558                    .ok();
3559                }
3560            }
3561        })
3562    }
3563
3564    fn detect_language_for_buffer(
3565        &mut self,
3566        buffer_handle: &Entity<Buffer>,
3567        cx: &mut Context<Self>,
3568    ) -> Option<language::AvailableLanguage> {
3569        // If the buffer has a language, set it and start the language server if we haven't already.
3570        let buffer = buffer_handle.read(cx);
3571        let file = buffer.file()?;
3572
3573        let content = buffer.as_rope();
3574        let available_language = self.languages.language_for_file(file, Some(content), cx);
3575        if let Some(available_language) = &available_language {
3576            if let Some(Ok(Ok(new_language))) = self
3577                .languages
3578                .load_language(available_language)
3579                .now_or_never()
3580            {
3581                self.set_language_for_buffer(buffer_handle, new_language, cx);
3582            }
3583        } else {
3584            cx.emit(LspStoreEvent::LanguageDetected {
3585                buffer: buffer_handle.clone(),
3586                new_language: None,
3587            });
3588        }
3589
3590        available_language
3591    }
3592
3593    pub(crate) fn set_language_for_buffer(
3594        &mut self,
3595        buffer_entity: &Entity<Buffer>,
3596        new_language: Arc<Language>,
3597        cx: &mut Context<Self>,
3598    ) {
3599        let buffer = buffer_entity.read(cx);
3600        let buffer_file = buffer.file().cloned();
3601        let buffer_id = buffer.remote_id();
3602        if let Some(local_store) = self.as_local_mut() {
3603            if local_store.registered_buffers.contains_key(&buffer_id) {
3604                if let Some(abs_path) =
3605                    File::from_dyn(buffer_file.as_ref()).map(|file| file.abs_path(cx))
3606                {
3607                    if let Some(file_url) = lsp::Url::from_file_path(&abs_path).log_err() {
3608                        local_store.unregister_buffer_from_language_servers(
3609                            buffer_entity,
3610                            &file_url,
3611                            cx,
3612                        );
3613                    }
3614                }
3615            }
3616        }
3617        buffer_entity.update(cx, |buffer, cx| {
3618            if buffer.language().map_or(true, |old_language| {
3619                !Arc::ptr_eq(old_language, &new_language)
3620            }) {
3621                buffer.set_language(Some(new_language.clone()), cx);
3622            }
3623        });
3624
3625        let settings =
3626            language_settings(Some(new_language.name()), buffer_file.as_ref(), cx).into_owned();
3627        let buffer_file = File::from_dyn(buffer_file.as_ref());
3628
3629        let worktree_id = if let Some(file) = buffer_file {
3630            let worktree = file.worktree.clone();
3631
3632            if let Some(local) = self.as_local_mut() {
3633                if local.registered_buffers.contains_key(&buffer_id) {
3634                    local.register_buffer_with_language_servers(buffer_entity, cx);
3635                }
3636            }
3637            Some(worktree.read(cx).id())
3638        } else {
3639            None
3640        };
3641
3642        if settings.prettier.allowed {
3643            if let Some(prettier_plugins) = prettier_store::prettier_plugins_for_language(&settings)
3644            {
3645                let prettier_store = self.as_local().map(|s| s.prettier_store.clone());
3646                if let Some(prettier_store) = prettier_store {
3647                    prettier_store.update(cx, |prettier_store, cx| {
3648                        prettier_store.install_default_prettier(
3649                            worktree_id,
3650                            prettier_plugins.iter().map(|s| Arc::from(s.as_str())),
3651                            cx,
3652                        )
3653                    })
3654                }
3655            }
3656        }
3657
3658        cx.emit(LspStoreEvent::LanguageDetected {
3659            buffer: buffer_entity.clone(),
3660            new_language: Some(new_language),
3661        })
3662    }
3663
3664    pub fn buffer_store(&self) -> Entity<BufferStore> {
3665        self.buffer_store.clone()
3666    }
3667
3668    pub fn set_active_entry(&mut self, active_entry: Option<ProjectEntryId>) {
3669        self.active_entry = active_entry;
3670    }
3671
3672    pub(crate) fn send_diagnostic_summaries(&self, worktree: &mut Worktree) {
3673        if let Some((client, downstream_project_id)) = self.downstream_client.clone() {
3674            if let Some(summaries) = self.diagnostic_summaries.get(&worktree.id()) {
3675                for (path, summaries) in summaries {
3676                    for (&server_id, summary) in summaries {
3677                        client
3678                            .send(proto::UpdateDiagnosticSummary {
3679                                project_id: downstream_project_id,
3680                                worktree_id: worktree.id().to_proto(),
3681                                summary: Some(summary.to_proto(server_id, path)),
3682                            })
3683                            .log_err();
3684                    }
3685                }
3686            }
3687        }
3688    }
3689
3690    pub fn request_lsp<R: LspCommand>(
3691        &mut self,
3692        buffer_handle: Entity<Buffer>,
3693        server: LanguageServerToQuery,
3694        request: R,
3695        cx: &mut Context<Self>,
3696    ) -> Task<Result<R::Response>>
3697    where
3698        <R::LspRequest as lsp::request::Request>::Result: Send,
3699        <R::LspRequest as lsp::request::Request>::Params: Send,
3700    {
3701        if let Some((upstream_client, upstream_project_id)) = self.upstream_client() {
3702            return self.send_lsp_proto_request(
3703                buffer_handle,
3704                upstream_client,
3705                upstream_project_id,
3706                request,
3707                cx,
3708            );
3709        }
3710
3711        let Some(language_server) = buffer_handle.update(cx, |buffer, cx| match server {
3712            LanguageServerToQuery::FirstCapable => self.as_local().and_then(|local| {
3713                local
3714                    .language_servers_for_buffer(buffer, cx)
3715                    .find(|(_, server)| {
3716                        request.check_capabilities(server.adapter_server_capabilities())
3717                    })
3718                    .map(|(_, server)| server.clone())
3719            }),
3720            LanguageServerToQuery::Other(id) => self
3721                .language_server_for_local_buffer(buffer, id, cx)
3722                .and_then(|(_, server)| {
3723                    request
3724                        .check_capabilities(server.adapter_server_capabilities())
3725                        .then(|| Arc::clone(server))
3726                }),
3727        }) else {
3728            return Task::ready(Ok(Default::default()));
3729        };
3730
3731        let buffer = buffer_handle.read(cx);
3732        let file = File::from_dyn(buffer.file()).and_then(File::as_local);
3733
3734        let Some(file) = file else {
3735            return Task::ready(Ok(Default::default()));
3736        };
3737
3738        let lsp_params = match request.to_lsp_params_or_response(
3739            &file.abs_path(cx),
3740            buffer,
3741            &language_server,
3742            cx,
3743        ) {
3744            Ok(LspParamsOrResponse::Params(lsp_params)) => lsp_params,
3745            Ok(LspParamsOrResponse::Response(response)) => return Task::ready(Ok(response)),
3746
3747            Err(err) => {
3748                let message = format!(
3749                    "{} via {} failed: {}",
3750                    request.display_name(),
3751                    language_server.name(),
3752                    err
3753                );
3754                log::warn!("{}", message);
3755                return Task::ready(Err(anyhow!(message)));
3756            }
3757        };
3758
3759        let status = request.status();
3760        if !request.check_capabilities(language_server.adapter_server_capabilities()) {
3761            return Task::ready(Ok(Default::default()));
3762        }
3763        return cx.spawn(async move |this, cx| {
3764            let lsp_request = language_server.request::<R::LspRequest>(lsp_params);
3765
3766            let id = lsp_request.id();
3767            let _cleanup = if status.is_some() {
3768                cx.update(|cx| {
3769                    this.update(cx, |this, cx| {
3770                        this.on_lsp_work_start(
3771                            language_server.server_id(),
3772                            id.to_string(),
3773                            LanguageServerProgress {
3774                                is_disk_based_diagnostics_progress: false,
3775                                is_cancellable: false,
3776                                title: None,
3777                                message: status.clone(),
3778                                percentage: None,
3779                                last_update_at: cx.background_executor().now(),
3780                            },
3781                            cx,
3782                        );
3783                    })
3784                })
3785                .log_err();
3786
3787                Some(defer(|| {
3788                    cx.update(|cx| {
3789                        this.update(cx, |this, cx| {
3790                            this.on_lsp_work_end(language_server.server_id(), id.to_string(), cx);
3791                        })
3792                    })
3793                    .log_err();
3794                }))
3795            } else {
3796                None
3797            };
3798
3799            let result = lsp_request.await;
3800
3801            let response = result.map_err(|err| {
3802                let message = format!(
3803                    "{} via {} failed: {}",
3804                    request.display_name(),
3805                    language_server.name(),
3806                    err
3807                );
3808                log::warn!("{}", message);
3809                anyhow!(message)
3810            })?;
3811
3812            let response = request
3813                .response_from_lsp(
3814                    response,
3815                    this.upgrade().ok_or_else(|| anyhow!("no app context"))?,
3816                    buffer_handle,
3817                    language_server.server_id(),
3818                    cx.clone(),
3819                )
3820                .await;
3821            response
3822        });
3823    }
3824
3825    fn on_settings_changed(&mut self, cx: &mut Context<Self>) {
3826        let mut language_formatters_to_check = Vec::new();
3827        for buffer in self.buffer_store.read(cx).buffers() {
3828            let buffer = buffer.read(cx);
3829            let buffer_file = File::from_dyn(buffer.file());
3830            let buffer_language = buffer.language();
3831            let settings = language_settings(buffer_language.map(|l| l.name()), buffer.file(), cx);
3832            if buffer_language.is_some() {
3833                language_formatters_to_check.push((
3834                    buffer_file.map(|f| f.worktree_id(cx)),
3835                    settings.into_owned(),
3836                ));
3837            }
3838        }
3839
3840        self.refresh_server_tree(cx);
3841
3842        if let Some(prettier_store) = self.as_local().map(|s| s.prettier_store.clone()) {
3843            prettier_store.update(cx, |prettier_store, cx| {
3844                prettier_store.on_settings_changed(language_formatters_to_check, cx)
3845            })
3846        }
3847
3848        cx.notify();
3849    }
3850
3851    fn refresh_server_tree(&mut self, cx: &mut Context<'_, Self>) {
3852        let buffer_store = self.buffer_store.clone();
3853        if let Some(local) = self.as_local_mut() {
3854            let mut adapters = BTreeMap::default();
3855            let to_stop = local.lsp_tree.clone().update(cx, |lsp_tree, cx| {
3856                let get_adapter = {
3857                    let languages = local.languages.clone();
3858                    let environment = local.environment.clone();
3859                    let weak = local.weak.clone();
3860                    let worktree_store = local.worktree_store.clone();
3861                    let http_client = local.http_client.clone();
3862                    let fs = local.fs.clone();
3863                    move |worktree_id, cx: &mut App| {
3864                        let worktree = worktree_store.read(cx).worktree_for_id(worktree_id, cx)?;
3865                        Some(LocalLspAdapterDelegate::new(
3866                            languages.clone(),
3867                            &environment,
3868                            weak.clone(),
3869                            &worktree,
3870                            http_client.clone(),
3871                            fs.clone(),
3872                            cx,
3873                        ))
3874                    }
3875                };
3876
3877                let mut rebase = lsp_tree.rebase();
3878                for buffer in buffer_store.read(cx).buffers().collect::<Vec<_>>() {
3879                    let buffer = buffer.read(cx);
3880                    if !local.registered_buffers.contains_key(&buffer.remote_id()) {
3881                        continue;
3882                    }
3883                    if let Some((file, language)) = File::from_dyn(buffer.file())
3884                        .cloned()
3885                        .zip(buffer.language().map(|l| l.name()))
3886                    {
3887                        let worktree_id = file.worktree_id(cx);
3888                        let Some(worktree) = local
3889                            .worktree_store
3890                            .read(cx)
3891                            .worktree_for_id(worktree_id, cx)
3892                        else {
3893                            continue;
3894                        };
3895                        let path: Arc<Path> = file
3896                            .path()
3897                            .parent()
3898                            .map(Arc::from)
3899                            .unwrap_or_else(|| file.path().clone());
3900                        let worktree_path = ProjectPath { worktree_id, path };
3901
3902                        let Some(delegate) = adapters
3903                            .entry(worktree_id)
3904                            .or_insert_with(|| get_adapter(worktree_id, cx))
3905                            .clone()
3906                        else {
3907                            continue;
3908                        };
3909                        let nodes = rebase.get(
3910                            worktree_path,
3911                            AdapterQuery::Language(&language),
3912                            delegate.clone(),
3913                            cx,
3914                        );
3915                        for node in nodes {
3916                            node.server_id_or_init(
3917                                |LaunchDisposition {
3918                                     server_name,
3919                                     attach,
3920                                     path,
3921                                     settings,
3922                                 }| match attach {
3923                                    language::Attach::InstancePerRoot => {
3924                                        // todo: handle instance per root proper.
3925                                        if let Some(server_ids) = local
3926                                            .language_server_ids
3927                                            .get(&(worktree_id, server_name.clone()))
3928                                        {
3929                                            server_ids.iter().cloned().next().unwrap()
3930                                        } else {
3931                                            local.start_language_server(
3932                                                &worktree,
3933                                                delegate.clone(),
3934                                                local
3935                                                    .languages
3936                                                    .lsp_adapters(&language)
3937                                                    .into_iter()
3938                                                    .find(|adapter| &adapter.name() == server_name)
3939                                                    .expect("To find LSP adapter"),
3940                                                settings,
3941                                                cx,
3942                                            )
3943                                        }
3944                                    }
3945                                    language::Attach::Shared => {
3946                                        let uri = Url::from_file_path(
3947                                            worktree.read(cx).abs_path().join(&path.path),
3948                                        );
3949                                        let key = (worktree_id, server_name.clone());
3950                                        local.language_server_ids.remove(&key);
3951
3952                                        let server_id = local.start_language_server(
3953                                            &worktree,
3954                                            delegate.clone(),
3955                                            local
3956                                                .languages
3957                                                .lsp_adapters(&language)
3958                                                .into_iter()
3959                                                .find(|adapter| &adapter.name() == server_name)
3960                                                .expect("To find LSP adapter"),
3961                                            settings,
3962                                            cx,
3963                                        );
3964                                        if let Some(state) = local.language_servers.get(&server_id)
3965                                        {
3966                                            if let Ok(uri) = uri {
3967                                                state.add_workspace_folder(uri);
3968                                            };
3969                                        }
3970                                        server_id
3971                                    }
3972                                },
3973                            );
3974                        }
3975                    }
3976                }
3977                rebase.finish()
3978            });
3979            for (id, name) in to_stop {
3980                self.stop_local_language_server(id, name, cx).detach();
3981            }
3982        }
3983    }
3984
3985    pub fn apply_code_action(
3986        &self,
3987        buffer_handle: Entity<Buffer>,
3988        mut action: CodeAction,
3989        push_to_history: bool,
3990        cx: &mut Context<Self>,
3991    ) -> Task<Result<ProjectTransaction>> {
3992        if let Some((upstream_client, project_id)) = self.upstream_client() {
3993            let request = proto::ApplyCodeAction {
3994                project_id,
3995                buffer_id: buffer_handle.read(cx).remote_id().into(),
3996                action: Some(Self::serialize_code_action(&action)),
3997            };
3998            let buffer_store = self.buffer_store();
3999            cx.spawn(async move |_, cx| {
4000                let response = upstream_client
4001                    .request(request)
4002                    .await?
4003                    .transaction
4004                    .ok_or_else(|| anyhow!("missing transaction"))?;
4005
4006                buffer_store
4007                    .update(cx, |buffer_store, cx| {
4008                        buffer_store.deserialize_project_transaction(response, push_to_history, cx)
4009                    })?
4010                    .await
4011            })
4012        } else if self.mode.is_local() {
4013            let Some((lsp_adapter, lang_server)) = buffer_handle.update(cx, |buffer, cx| {
4014                self.language_server_for_local_buffer(buffer, action.server_id, cx)
4015                    .map(|(adapter, server)| (adapter.clone(), server.clone()))
4016            }) else {
4017                return Task::ready(Ok(ProjectTransaction::default()));
4018            };
4019            cx.spawn(async move |this,  cx| {
4020                LocalLspStore::try_resolve_code_action(&lang_server, &mut action)
4021                    .await
4022                    .context("resolving a code action")?;
4023                if let Some(edit) = action.lsp_action.edit() {
4024                    if edit.changes.is_some() || edit.document_changes.is_some() {
4025                        return LocalLspStore::deserialize_workspace_edit(
4026                            this.upgrade().ok_or_else(|| anyhow!("no app present"))?,
4027                            edit.clone(),
4028                            push_to_history,
4029                            lsp_adapter.clone(),
4030                            lang_server.clone(),
4031                            cx,
4032                        )
4033                        .await;
4034                    }
4035                }
4036
4037                if let Some(command) = action.lsp_action.command() {
4038                    let server_capabilities = lang_server.capabilities();
4039                    let available_commands = server_capabilities
4040                        .execute_command_provider
4041                        .as_ref()
4042                        .map(|options| options.commands.as_slice())
4043                        .unwrap_or_default();
4044                    if available_commands.contains(&command.command) {
4045                        this.update(cx, |this, _| {
4046                            this.as_local_mut()
4047                                .unwrap()
4048                                .last_workspace_edits_by_language_server
4049                                .remove(&lang_server.server_id());
4050                        })?;
4051
4052                        let result = lang_server
4053                            .request::<lsp::request::ExecuteCommand>(lsp::ExecuteCommandParams {
4054                                command: command.command.clone(),
4055                                arguments: command.arguments.clone().unwrap_or_default(),
4056                                ..Default::default()
4057                            })
4058                            .await;
4059
4060                        result?;
4061
4062                        return this.update(cx, |this, _| {
4063                            this.as_local_mut()
4064                                .unwrap()
4065                                .last_workspace_edits_by_language_server
4066                                .remove(&lang_server.server_id())
4067                                .unwrap_or_default()
4068                        });
4069                    } else {
4070                        log::warn!("Cannot execute a command {} not listed in the language server capabilities", command.command);
4071                    }
4072                }
4073
4074                Ok(ProjectTransaction::default())
4075            })
4076        } else {
4077            Task::ready(Err(anyhow!("no upstream client and not local")))
4078        }
4079    }
4080
4081    pub fn apply_code_action_kind(
4082        &mut self,
4083        buffers: HashSet<Entity<Buffer>>,
4084        kind: CodeActionKind,
4085        push_to_history: bool,
4086        cx: &mut Context<Self>,
4087    ) -> Task<anyhow::Result<ProjectTransaction>> {
4088        if let Some(_) = self.as_local() {
4089            cx.spawn(async move |lsp_store, cx| {
4090                let buffers = buffers.into_iter().collect::<Vec<_>>();
4091                let result = LocalLspStore::execute_code_action_kind_locally(
4092                    lsp_store.clone(),
4093                    buffers,
4094                    kind,
4095                    push_to_history,
4096                    cx,
4097                )
4098                .await;
4099                lsp_store.update(cx, |lsp_store, _| {
4100                    lsp_store.update_last_formatting_failure(&result);
4101                })?;
4102                result
4103            })
4104        } else if let Some((client, project_id)) = self.upstream_client() {
4105            let buffer_store = self.buffer_store();
4106            cx.spawn(async move |lsp_store, cx| {
4107                let result = client
4108                    .request(proto::ApplyCodeActionKind {
4109                        project_id,
4110                        kind: kind.as_str().to_owned(),
4111                        buffer_ids: buffers
4112                            .iter()
4113                            .map(|buffer| buffer.update(cx, |buffer, _| buffer.remote_id().into()))
4114                            .collect::<Result<_>>()?,
4115                    })
4116                    .await
4117                    .and_then(|result| result.transaction.context("missing transaction"));
4118                lsp_store.update(cx, |lsp_store, _| {
4119                    lsp_store.update_last_formatting_failure(&result);
4120                })?;
4121
4122                let transaction_response = result?;
4123                buffer_store
4124                    .update(cx, |buffer_store, cx| {
4125                        buffer_store.deserialize_project_transaction(
4126                            transaction_response,
4127                            push_to_history,
4128                            cx,
4129                        )
4130                    })?
4131                    .await
4132            })
4133        } else {
4134            Task::ready(Ok(ProjectTransaction::default()))
4135        }
4136    }
4137
4138    pub fn resolve_inlay_hint(
4139        &self,
4140        hint: InlayHint,
4141        buffer_handle: Entity<Buffer>,
4142        server_id: LanguageServerId,
4143        cx: &mut Context<Self>,
4144    ) -> Task<anyhow::Result<InlayHint>> {
4145        if let Some((upstream_client, project_id)) = self.upstream_client() {
4146            let request = proto::ResolveInlayHint {
4147                project_id,
4148                buffer_id: buffer_handle.read(cx).remote_id().into(),
4149                language_server_id: server_id.0 as u64,
4150                hint: Some(InlayHints::project_to_proto_hint(hint.clone())),
4151            };
4152            cx.spawn(async move |_, _| {
4153                let response = upstream_client
4154                    .request(request)
4155                    .await
4156                    .context("inlay hints proto request")?;
4157                match response.hint {
4158                    Some(resolved_hint) => InlayHints::proto_to_project_hint(resolved_hint)
4159                        .context("inlay hints proto resolve response conversion"),
4160                    None => Ok(hint),
4161                }
4162            })
4163        } else {
4164            let Some(lang_server) = buffer_handle.update(cx, |buffer, cx| {
4165                self.language_server_for_local_buffer(buffer, server_id, cx)
4166                    .map(|(_, server)| server.clone())
4167            }) else {
4168                return Task::ready(Ok(hint));
4169            };
4170            if !InlayHints::can_resolve_inlays(&lang_server.capabilities()) {
4171                return Task::ready(Ok(hint));
4172            }
4173            let buffer_snapshot = buffer_handle.read(cx).snapshot();
4174            cx.spawn(async move |_, cx| {
4175                let resolve_task = lang_server.request::<lsp::request::InlayHintResolveRequest>(
4176                    InlayHints::project_to_lsp_hint(hint, &buffer_snapshot),
4177                );
4178                let resolved_hint = resolve_task
4179                    .await
4180                    .context("inlay hint resolve LSP request")?;
4181                let resolved_hint = InlayHints::lsp_to_project_hint(
4182                    resolved_hint,
4183                    &buffer_handle,
4184                    server_id,
4185                    ResolveState::Resolved,
4186                    false,
4187                    cx,
4188                )
4189                .await?;
4190                Ok(resolved_hint)
4191            })
4192        }
4193    }
4194
4195    pub(crate) fn linked_edit(
4196        &mut self,
4197        buffer: &Entity<Buffer>,
4198        position: Anchor,
4199        cx: &mut Context<Self>,
4200    ) -> Task<Result<Vec<Range<Anchor>>>> {
4201        let snapshot = buffer.read(cx).snapshot();
4202        let scope = snapshot.language_scope_at(position);
4203        let Some(server_id) = self
4204            .as_local()
4205            .and_then(|local| {
4206                buffer.update(cx, |buffer, cx| {
4207                    local
4208                        .language_servers_for_buffer(buffer, cx)
4209                        .filter(|(_, server)| {
4210                            server
4211                                .capabilities()
4212                                .linked_editing_range_provider
4213                                .is_some()
4214                        })
4215                        .filter(|(adapter, _)| {
4216                            scope
4217                                .as_ref()
4218                                .map(|scope| scope.language_allowed(&adapter.name))
4219                                .unwrap_or(true)
4220                        })
4221                        .map(|(_, server)| LanguageServerToQuery::Other(server.server_id()))
4222                        .next()
4223                })
4224            })
4225            .or_else(|| {
4226                self.upstream_client()
4227                    .is_some()
4228                    .then_some(LanguageServerToQuery::FirstCapable)
4229            })
4230            .filter(|_| {
4231                maybe!({
4232                    let language = buffer.read(cx).language_at(position)?;
4233                    Some(
4234                        language_settings(Some(language.name()), buffer.read(cx).file(), cx)
4235                            .linked_edits,
4236                    )
4237                }) == Some(true)
4238            })
4239        else {
4240            return Task::ready(Ok(vec![]));
4241        };
4242
4243        self.request_lsp(
4244            buffer.clone(),
4245            server_id,
4246            LinkedEditingRange { position },
4247            cx,
4248        )
4249    }
4250
4251    fn apply_on_type_formatting(
4252        &mut self,
4253        buffer: Entity<Buffer>,
4254        position: Anchor,
4255        trigger: String,
4256        cx: &mut Context<Self>,
4257    ) -> Task<Result<Option<Transaction>>> {
4258        if let Some((client, project_id)) = self.upstream_client() {
4259            let request = proto::OnTypeFormatting {
4260                project_id,
4261                buffer_id: buffer.read(cx).remote_id().into(),
4262                position: Some(serialize_anchor(&position)),
4263                trigger,
4264                version: serialize_version(&buffer.read(cx).version()),
4265            };
4266            cx.spawn(async move |_, _| {
4267                client
4268                    .request(request)
4269                    .await?
4270                    .transaction
4271                    .map(language::proto::deserialize_transaction)
4272                    .transpose()
4273            })
4274        } else if let Some(local) = self.as_local_mut() {
4275            let buffer_id = buffer.read(cx).remote_id();
4276            local.buffers_being_formatted.insert(buffer_id);
4277            cx.spawn(async move |this, cx| {
4278                let _cleanup = defer({
4279                    let this = this.clone();
4280                    let mut cx = cx.clone();
4281                    move || {
4282                        this.update(&mut cx, |this, _| {
4283                            if let Some(local) = this.as_local_mut() {
4284                                local.buffers_being_formatted.remove(&buffer_id);
4285                            }
4286                        })
4287                        .ok();
4288                    }
4289                });
4290
4291                buffer
4292                    .update(cx, |buffer, _| {
4293                        buffer.wait_for_edits(Some(position.timestamp))
4294                    })?
4295                    .await?;
4296                this.update(cx, |this, cx| {
4297                    let position = position.to_point_utf16(buffer.read(cx));
4298                    this.on_type_format(buffer, position, trigger, false, cx)
4299                })?
4300                .await
4301            })
4302        } else {
4303            Task::ready(Err(anyhow!("No upstream client or local language server")))
4304        }
4305    }
4306
4307    pub fn on_type_format<T: ToPointUtf16>(
4308        &mut self,
4309        buffer: Entity<Buffer>,
4310        position: T,
4311        trigger: String,
4312        push_to_history: bool,
4313        cx: &mut Context<Self>,
4314    ) -> Task<Result<Option<Transaction>>> {
4315        let position = position.to_point_utf16(buffer.read(cx));
4316        self.on_type_format_impl(buffer, position, trigger, push_to_history, cx)
4317    }
4318
4319    fn on_type_format_impl(
4320        &mut self,
4321        buffer: Entity<Buffer>,
4322        position: PointUtf16,
4323        trigger: String,
4324        push_to_history: bool,
4325        cx: &mut Context<Self>,
4326    ) -> Task<Result<Option<Transaction>>> {
4327        let options = buffer.update(cx, |buffer, cx| {
4328            lsp_command::lsp_formatting_options(
4329                language_settings(
4330                    buffer.language_at(position).map(|l| l.name()),
4331                    buffer.file(),
4332                    cx,
4333                )
4334                .as_ref(),
4335            )
4336        });
4337        self.request_lsp(
4338            buffer.clone(),
4339            LanguageServerToQuery::FirstCapable,
4340            OnTypeFormatting {
4341                position,
4342                trigger,
4343                options,
4344                push_to_history,
4345            },
4346            cx,
4347        )
4348    }
4349
4350    pub fn code_actions(
4351        &mut self,
4352        buffer_handle: &Entity<Buffer>,
4353        range: Range<Anchor>,
4354        kinds: Option<Vec<CodeActionKind>>,
4355        cx: &mut Context<Self>,
4356    ) -> Task<Result<Vec<CodeAction>>> {
4357        if let Some((upstream_client, project_id)) = self.upstream_client() {
4358            let request_task = upstream_client.request(proto::MultiLspQuery {
4359                buffer_id: buffer_handle.read(cx).remote_id().into(),
4360                version: serialize_version(&buffer_handle.read(cx).version()),
4361                project_id,
4362                strategy: Some(proto::multi_lsp_query::Strategy::All(
4363                    proto::AllLanguageServers {},
4364                )),
4365                request: Some(proto::multi_lsp_query::Request::GetCodeActions(
4366                    GetCodeActions {
4367                        range: range.clone(),
4368                        kinds: kinds.clone(),
4369                    }
4370                    .to_proto(project_id, buffer_handle.read(cx)),
4371                )),
4372            });
4373            let buffer = buffer_handle.clone();
4374            cx.spawn(async move |weak_project, cx| {
4375                let Some(project) = weak_project.upgrade() else {
4376                    return Ok(Vec::new());
4377                };
4378                let responses = request_task.await?.responses;
4379                let actions = join_all(
4380                    responses
4381                        .into_iter()
4382                        .filter_map(|lsp_response| match lsp_response.response? {
4383                            proto::lsp_response::Response::GetCodeActionsResponse(response) => {
4384                                Some(response)
4385                            }
4386                            unexpected => {
4387                                debug_panic!("Unexpected response: {unexpected:?}");
4388                                None
4389                            }
4390                        })
4391                        .map(|code_actions_response| {
4392                            GetCodeActions {
4393                                range: range.clone(),
4394                                kinds: kinds.clone(),
4395                            }
4396                            .response_from_proto(
4397                                code_actions_response,
4398                                project.clone(),
4399                                buffer.clone(),
4400                                cx.clone(),
4401                            )
4402                        }),
4403                )
4404                .await;
4405
4406                Ok(actions
4407                    .into_iter()
4408                    .collect::<Result<Vec<Vec<_>>>>()?
4409                    .into_iter()
4410                    .flatten()
4411                    .collect())
4412            })
4413        } else {
4414            let all_actions_task = self.request_multiple_lsp_locally(
4415                buffer_handle,
4416                Some(range.start),
4417                GetCodeActions {
4418                    range: range.clone(),
4419                    kinds: kinds.clone(),
4420                },
4421                cx,
4422            );
4423            cx.spawn(async move |_, _| Ok(all_actions_task.await.into_iter().flatten().collect()))
4424        }
4425    }
4426
4427    pub fn code_lens(
4428        &mut self,
4429        buffer_handle: &Entity<Buffer>,
4430        cx: &mut Context<Self>,
4431    ) -> Task<Result<Vec<CodeAction>>> {
4432        if let Some((upstream_client, project_id)) = self.upstream_client() {
4433            let request_task = upstream_client.request(proto::MultiLspQuery {
4434                buffer_id: buffer_handle.read(cx).remote_id().into(),
4435                version: serialize_version(&buffer_handle.read(cx).version()),
4436                project_id,
4437                strategy: Some(proto::multi_lsp_query::Strategy::All(
4438                    proto::AllLanguageServers {},
4439                )),
4440                request: Some(proto::multi_lsp_query::Request::GetCodeLens(
4441                    GetCodeLens.to_proto(project_id, buffer_handle.read(cx)),
4442                )),
4443            });
4444            let buffer = buffer_handle.clone();
4445            cx.spawn(async move |weak_project, cx| {
4446                let Some(project) = weak_project.upgrade() else {
4447                    return Ok(Vec::new());
4448                };
4449                let responses = request_task.await?.responses;
4450                let code_lens = join_all(
4451                    responses
4452                        .into_iter()
4453                        .filter_map(|lsp_response| match lsp_response.response? {
4454                            proto::lsp_response::Response::GetCodeLensResponse(response) => {
4455                                Some(response)
4456                            }
4457                            unexpected => {
4458                                debug_panic!("Unexpected response: {unexpected:?}");
4459                                None
4460                            }
4461                        })
4462                        .map(|code_lens_response| {
4463                            GetCodeLens.response_from_proto(
4464                                code_lens_response,
4465                                project.clone(),
4466                                buffer.clone(),
4467                                cx.clone(),
4468                            )
4469                        }),
4470                )
4471                .await;
4472
4473                Ok(code_lens
4474                    .into_iter()
4475                    .collect::<Result<Vec<Vec<_>>>>()?
4476                    .into_iter()
4477                    .flatten()
4478                    .collect())
4479            })
4480        } else {
4481            let code_lens_task =
4482                self.request_multiple_lsp_locally(buffer_handle, None::<usize>, GetCodeLens, cx);
4483            cx.spawn(async move |_, _| Ok(code_lens_task.await.into_iter().flatten().collect()))
4484        }
4485    }
4486
4487    #[inline(never)]
4488    pub fn completions(
4489        &self,
4490        buffer: &Entity<Buffer>,
4491        position: PointUtf16,
4492        context: CompletionContext,
4493        cx: &mut Context<Self>,
4494    ) -> Task<Result<Option<Vec<Completion>>>> {
4495        let language_registry = self.languages.clone();
4496
4497        if let Some((upstream_client, project_id)) = self.upstream_client() {
4498            let task = self.send_lsp_proto_request(
4499                buffer.clone(),
4500                upstream_client,
4501                project_id,
4502                GetCompletions { position, context },
4503                cx,
4504            );
4505            let language = buffer.read(cx).language().cloned();
4506
4507            // In the future, we should provide project guests with the names of LSP adapters,
4508            // so that they can use the correct LSP adapter when computing labels. For now,
4509            // guests just use the first LSP adapter associated with the buffer's language.
4510            let lsp_adapter = language.as_ref().and_then(|language| {
4511                language_registry
4512                    .lsp_adapters(&language.name())
4513                    .first()
4514                    .cloned()
4515            });
4516
4517            cx.foreground_executor().spawn(async move {
4518                let completions = task.await?;
4519                let mut result = Vec::new();
4520                populate_labels_for_completions(completions, language, lsp_adapter, &mut result)
4521                    .await;
4522                Ok(Some(result))
4523            })
4524        } else if let Some(local) = self.as_local() {
4525            let snapshot = buffer.read(cx).snapshot();
4526            let offset = position.to_offset(&snapshot);
4527            let scope = snapshot.language_scope_at(offset);
4528            let language = snapshot.language().cloned();
4529            let completion_settings = language_settings(
4530                language.as_ref().map(|language| language.name()),
4531                buffer.read(cx).file(),
4532                cx,
4533            )
4534            .completions;
4535            if !completion_settings.lsp {
4536                return Task::ready(Ok(None));
4537            }
4538
4539            let server_ids: Vec<_> = buffer.update(cx, |buffer, cx| {
4540                local
4541                    .language_servers_for_buffer(buffer, cx)
4542                    .filter(|(_, server)| server.capabilities().completion_provider.is_some())
4543                    .filter(|(adapter, _)| {
4544                        scope
4545                            .as_ref()
4546                            .map(|scope| scope.language_allowed(&adapter.name))
4547                            .unwrap_or(true)
4548                    })
4549                    .map(|(_, server)| server.server_id())
4550                    .collect()
4551            });
4552
4553            let buffer = buffer.clone();
4554            let lsp_timeout = completion_settings.lsp_fetch_timeout_ms;
4555            let lsp_timeout = if lsp_timeout > 0 {
4556                Some(Duration::from_millis(lsp_timeout))
4557            } else {
4558                None
4559            };
4560            cx.spawn(async move |this,  cx| {
4561                let mut tasks = Vec::with_capacity(server_ids.len());
4562                this.update(cx, |lsp_store, cx| {
4563                    for server_id in server_ids {
4564                        let lsp_adapter = lsp_store.language_server_adapter_for_id(server_id);
4565                        let lsp_timeout = lsp_timeout
4566                            .map(|lsp_timeout| cx.background_executor().timer(lsp_timeout));
4567                        let mut timeout = cx.background_spawn(async move {
4568                            match lsp_timeout {
4569                                Some(lsp_timeout) => {
4570                                    lsp_timeout.await;
4571                                    true
4572                                },
4573                                None => false,
4574                            }
4575                        }).fuse();
4576                        let mut lsp_request = lsp_store.request_lsp(
4577                            buffer.clone(),
4578                            LanguageServerToQuery::Other(server_id),
4579                            GetCompletions {
4580                                position,
4581                                context: context.clone(),
4582                            },
4583                            cx,
4584                        ).fuse();
4585                        let new_task = cx.background_spawn(async move {
4586                            select_biased! {
4587                                response = lsp_request => anyhow::Ok(Some(response?)),
4588                                timeout_happened = timeout => {
4589                                    if timeout_happened {
4590                                        log::warn!("Fetching completions from server {server_id} timed out, timeout ms: {}", completion_settings.lsp_fetch_timeout_ms);
4591                                        Ok(None)
4592                                    } else {
4593                                        let completions = lsp_request.await?;
4594                                        Ok(Some(completions))
4595                                    }
4596                                },
4597                            }
4598                        });
4599                        tasks.push((lsp_adapter, new_task));
4600                    }
4601                })?;
4602
4603                let mut has_completions_returned = false;
4604                let mut completions = Vec::new();
4605                for (lsp_adapter, task) in tasks {
4606                    if let Ok(Some(new_completions)) = task.await {
4607                        has_completions_returned = true;
4608                        populate_labels_for_completions(
4609                            new_completions,
4610                            language.clone(),
4611                            lsp_adapter,
4612                            &mut completions,
4613                        )
4614                        .await;
4615                    }
4616                }
4617                if has_completions_returned {
4618                    Ok(Some(completions))
4619                } else {
4620                    Ok(None)
4621                }
4622            })
4623        } else {
4624            Task::ready(Err(anyhow!("No upstream client or local language server")))
4625        }
4626    }
4627
4628    pub fn resolve_completions(
4629        &self,
4630        buffer: Entity<Buffer>,
4631        completion_indices: Vec<usize>,
4632        completions: Rc<RefCell<Box<[Completion]>>>,
4633        cx: &mut Context<Self>,
4634    ) -> Task<Result<bool>> {
4635        let client = self.upstream_client();
4636
4637        let buffer_id = buffer.read(cx).remote_id();
4638        let buffer_snapshot = buffer.read(cx).snapshot();
4639
4640        cx.spawn(async move |this, cx| {
4641            let mut did_resolve = false;
4642            if let Some((client, project_id)) = client {
4643                for completion_index in completion_indices {
4644                    let server_id = {
4645                        let completion = &completions.borrow()[completion_index];
4646                        completion.source.server_id()
4647                    };
4648                    if let Some(server_id) = server_id {
4649                        if Self::resolve_completion_remote(
4650                            project_id,
4651                            server_id,
4652                            buffer_id,
4653                            completions.clone(),
4654                            completion_index,
4655                            client.clone(),
4656                        )
4657                        .await
4658                        .log_err()
4659                        .is_some()
4660                        {
4661                            did_resolve = true;
4662                        }
4663                    } else {
4664                        resolve_word_completion(
4665                            &buffer_snapshot,
4666                            &mut completions.borrow_mut()[completion_index],
4667                        );
4668                    }
4669                }
4670            } else {
4671                for completion_index in completion_indices {
4672                    let server_id = {
4673                        let completion = &completions.borrow()[completion_index];
4674                        completion.source.server_id()
4675                    };
4676                    if let Some(server_id) = server_id {
4677                        let server_and_adapter = this
4678                            .read_with(cx, |lsp_store, _| {
4679                                let server = lsp_store.language_server_for_id(server_id)?;
4680                                let adapter =
4681                                    lsp_store.language_server_adapter_for_id(server.server_id())?;
4682                                Some((server, adapter))
4683                            })
4684                            .ok()
4685                            .flatten();
4686                        let Some((server, adapter)) = server_and_adapter else {
4687                            continue;
4688                        };
4689
4690                        let resolved = Self::resolve_completion_local(
4691                            server,
4692                            &buffer_snapshot,
4693                            completions.clone(),
4694                            completion_index,
4695                        )
4696                        .await
4697                        .log_err()
4698                        .is_some();
4699                        if resolved {
4700                            Self::regenerate_completion_labels(
4701                                adapter,
4702                                &buffer_snapshot,
4703                                completions.clone(),
4704                                completion_index,
4705                            )
4706                            .await
4707                            .log_err();
4708                            did_resolve = true;
4709                        }
4710                    } else {
4711                        resolve_word_completion(
4712                            &buffer_snapshot,
4713                            &mut completions.borrow_mut()[completion_index],
4714                        );
4715                    }
4716                }
4717            }
4718
4719            Ok(did_resolve)
4720        })
4721    }
4722
4723    async fn resolve_completion_local(
4724        server: Arc<lsp::LanguageServer>,
4725        snapshot: &BufferSnapshot,
4726        completions: Rc<RefCell<Box<[Completion]>>>,
4727        completion_index: usize,
4728    ) -> Result<()> {
4729        let server_id = server.server_id();
4730        let can_resolve = server
4731            .capabilities()
4732            .completion_provider
4733            .as_ref()
4734            .and_then(|options| options.resolve_provider)
4735            .unwrap_or(false);
4736        if !can_resolve {
4737            return Ok(());
4738        }
4739
4740        let request = {
4741            let completion = &completions.borrow()[completion_index];
4742            match &completion.source {
4743                CompletionSource::Lsp {
4744                    lsp_completion,
4745                    resolved,
4746                    server_id: completion_server_id,
4747                    ..
4748                } => {
4749                    if *resolved {
4750                        return Ok(());
4751                    }
4752                    anyhow::ensure!(
4753                        server_id == *completion_server_id,
4754                        "server_id mismatch, querying completion resolve for {server_id} but completion server id is {completion_server_id}"
4755                    );
4756                    server.request::<lsp::request::ResolveCompletionItem>(*lsp_completion.clone())
4757                }
4758                CompletionSource::BufferWord { .. } | CompletionSource::Custom => {
4759                    return Ok(());
4760                }
4761            }
4762        };
4763        let resolved_completion = request.await?;
4764
4765        if let Some(text_edit) = resolved_completion.text_edit.as_ref() {
4766            // Technically we don't have to parse the whole `text_edit`, since the only
4767            // language server we currently use that does update `text_edit` in `completionItem/resolve`
4768            // is `typescript-language-server` and they only update `text_edit.new_text`.
4769            // But we should not rely on that.
4770            let edit = parse_completion_text_edit(text_edit, snapshot);
4771
4772            if let Some((old_range, mut new_text)) = edit {
4773                LineEnding::normalize(&mut new_text);
4774
4775                let mut completions = completions.borrow_mut();
4776                let completion = &mut completions[completion_index];
4777
4778                completion.new_text = new_text;
4779                completion.old_range = old_range;
4780            }
4781        }
4782
4783        let mut completions = completions.borrow_mut();
4784        let completion = &mut completions[completion_index];
4785        if let CompletionSource::Lsp {
4786            lsp_completion,
4787            resolved,
4788            server_id: completion_server_id,
4789            ..
4790        } = &mut completion.source
4791        {
4792            if *resolved {
4793                return Ok(());
4794            }
4795            anyhow::ensure!(
4796                server_id == *completion_server_id,
4797                "server_id mismatch, applying completion resolve for {server_id} but completion server id is {completion_server_id}"
4798            );
4799            *lsp_completion = Box::new(resolved_completion);
4800            *resolved = true;
4801        }
4802        Ok(())
4803    }
4804
4805    async fn regenerate_completion_labels(
4806        adapter: Arc<CachedLspAdapter>,
4807        snapshot: &BufferSnapshot,
4808        completions: Rc<RefCell<Box<[Completion]>>>,
4809        completion_index: usize,
4810    ) -> Result<()> {
4811        let completion_item = completions.borrow()[completion_index]
4812            .source
4813            .lsp_completion(true)
4814            .map(Cow::into_owned);
4815        if let Some(lsp_documentation) = completion_item
4816            .as_ref()
4817            .and_then(|completion_item| completion_item.documentation.clone())
4818        {
4819            let mut completions = completions.borrow_mut();
4820            let completion = &mut completions[completion_index];
4821            completion.documentation = Some(lsp_documentation.into());
4822        } else {
4823            let mut completions = completions.borrow_mut();
4824            let completion = &mut completions[completion_index];
4825            completion.documentation = Some(CompletionDocumentation::Undocumented);
4826        }
4827
4828        let mut new_label = match completion_item {
4829            Some(completion_item) => {
4830                // NB: Zed does not have `details` inside the completion resolve capabilities, but certain language servers violate the spec and do not return `details` immediately, e.g. https://github.com/yioneko/vtsls/issues/213
4831                // So we have to update the label here anyway...
4832                let language = snapshot.language();
4833                match language {
4834                    Some(language) => {
4835                        adapter
4836                            .labels_for_completions(&[completion_item.clone()], language)
4837                            .await?
4838                    }
4839                    None => Vec::new(),
4840                }
4841                .pop()
4842                .flatten()
4843                .unwrap_or_else(|| {
4844                    CodeLabel::fallback_for_completion(
4845                        &completion_item,
4846                        language.map(|language| language.as_ref()),
4847                    )
4848                })
4849            }
4850            None => CodeLabel::plain(
4851                completions.borrow()[completion_index].new_text.clone(),
4852                None,
4853            ),
4854        };
4855        ensure_uniform_list_compatible_label(&mut new_label);
4856
4857        let mut completions = completions.borrow_mut();
4858        let completion = &mut completions[completion_index];
4859        if completion.label.filter_text() == new_label.filter_text() {
4860            completion.label = new_label;
4861        } else {
4862            log::error!(
4863                "Resolved completion changed display label from {} to {}. \
4864                 Refusing to apply this because it changes the fuzzy match text from {} to {}",
4865                completion.label.text(),
4866                new_label.text(),
4867                completion.label.filter_text(),
4868                new_label.filter_text()
4869            );
4870        }
4871
4872        Ok(())
4873    }
4874
4875    async fn resolve_completion_remote(
4876        project_id: u64,
4877        server_id: LanguageServerId,
4878        buffer_id: BufferId,
4879        completions: Rc<RefCell<Box<[Completion]>>>,
4880        completion_index: usize,
4881        client: AnyProtoClient,
4882    ) -> Result<()> {
4883        let lsp_completion = {
4884            let completion = &completions.borrow()[completion_index];
4885            match &completion.source {
4886                CompletionSource::Lsp {
4887                    lsp_completion,
4888                    resolved,
4889                    server_id: completion_server_id,
4890                    ..
4891                } => {
4892                    anyhow::ensure!(
4893                        server_id == *completion_server_id,
4894                        "remote server_id mismatch, querying completion resolve for {server_id} but completion server id is {completion_server_id}"
4895                    );
4896                    if *resolved {
4897                        return Ok(());
4898                    }
4899                    serde_json::to_string(lsp_completion).unwrap().into_bytes()
4900                }
4901                CompletionSource::Custom | CompletionSource::BufferWord { .. } => {
4902                    return Ok(());
4903                }
4904            }
4905        };
4906        let request = proto::ResolveCompletionDocumentation {
4907            project_id,
4908            language_server_id: server_id.0 as u64,
4909            lsp_completion,
4910            buffer_id: buffer_id.into(),
4911        };
4912
4913        let response = client
4914            .request(request)
4915            .await
4916            .context("completion documentation resolve proto request")?;
4917        let resolved_lsp_completion = serde_json::from_slice(&response.lsp_completion)?;
4918
4919        let documentation = if response.documentation.is_empty() {
4920            CompletionDocumentation::Undocumented
4921        } else if response.documentation_is_markdown {
4922            CompletionDocumentation::MultiLineMarkdown(response.documentation.into())
4923        } else if response.documentation.lines().count() <= 1 {
4924            CompletionDocumentation::SingleLine(response.documentation.into())
4925        } else {
4926            CompletionDocumentation::MultiLinePlainText(response.documentation.into())
4927        };
4928
4929        let mut completions = completions.borrow_mut();
4930        let completion = &mut completions[completion_index];
4931        completion.documentation = Some(documentation);
4932        if let CompletionSource::Lsp {
4933            lsp_completion,
4934            resolved,
4935            server_id: completion_server_id,
4936            lsp_defaults: _,
4937        } = &mut completion.source
4938        {
4939            if *resolved {
4940                return Ok(());
4941            }
4942            anyhow::ensure!(
4943                server_id == *completion_server_id,
4944                "remote server_id mismatch, applying completion resolve for {server_id} but completion server id is {completion_server_id}"
4945            );
4946            *lsp_completion = Box::new(resolved_lsp_completion);
4947            *resolved = true;
4948        }
4949
4950        let old_range = response
4951            .old_start
4952            .and_then(deserialize_anchor)
4953            .zip(response.old_end.and_then(deserialize_anchor));
4954        if let Some((old_start, old_end)) = old_range {
4955            if !response.new_text.is_empty() {
4956                completion.new_text = response.new_text;
4957                completion.old_range = old_start..old_end;
4958            }
4959        }
4960
4961        Ok(())
4962    }
4963
4964    pub fn apply_additional_edits_for_completion(
4965        &self,
4966        buffer_handle: Entity<Buffer>,
4967        completions: Rc<RefCell<Box<[Completion]>>>,
4968        completion_index: usize,
4969        push_to_history: bool,
4970        cx: &mut Context<Self>,
4971    ) -> Task<Result<Option<Transaction>>> {
4972        if let Some((client, project_id)) = self.upstream_client() {
4973            let buffer = buffer_handle.read(cx);
4974            let buffer_id = buffer.remote_id();
4975            cx.spawn(async move |_, cx| {
4976                let request = {
4977                    let completion = completions.borrow()[completion_index].clone();
4978                    proto::ApplyCompletionAdditionalEdits {
4979                        project_id,
4980                        buffer_id: buffer_id.into(),
4981                        completion: Some(Self::serialize_completion(&CoreCompletion {
4982                            old_range: completion.old_range,
4983                            new_text: completion.new_text,
4984                            source: completion.source,
4985                        })),
4986                    }
4987                };
4988
4989                if let Some(transaction) = client.request(request).await?.transaction {
4990                    let transaction = language::proto::deserialize_transaction(transaction)?;
4991                    buffer_handle
4992                        .update(cx, |buffer, _| {
4993                            buffer.wait_for_edits(transaction.edit_ids.iter().copied())
4994                        })?
4995                        .await?;
4996                    if push_to_history {
4997                        buffer_handle.update(cx, |buffer, _| {
4998                            buffer.push_transaction(transaction.clone(), Instant::now());
4999                        })?;
5000                    }
5001                    Ok(Some(transaction))
5002                } else {
5003                    Ok(None)
5004                }
5005            })
5006        } else {
5007            let Some(server) = buffer_handle.update(cx, |buffer, cx| {
5008                let completion = &completions.borrow()[completion_index];
5009                let server_id = completion.source.server_id()?;
5010                Some(
5011                    self.language_server_for_local_buffer(buffer, server_id, cx)?
5012                        .1
5013                        .clone(),
5014                )
5015            }) else {
5016                return Task::ready(Ok(None));
5017            };
5018            let snapshot = buffer_handle.read(&cx).snapshot();
5019
5020            cx.spawn(async move |this, cx| {
5021                Self::resolve_completion_local(
5022                    server.clone(),
5023                    &snapshot,
5024                    completions.clone(),
5025                    completion_index,
5026                )
5027                .await
5028                .context("resolving completion")?;
5029                let completion = completions.borrow()[completion_index].clone();
5030                let additional_text_edits = completion
5031                    .source
5032                    .lsp_completion(true)
5033                    .as_ref()
5034                    .and_then(|lsp_completion| lsp_completion.additional_text_edits.clone());
5035                if let Some(edits) = additional_text_edits {
5036                    let edits = this
5037                        .update(cx, |this, cx| {
5038                            this.as_local_mut().unwrap().edits_from_lsp(
5039                                &buffer_handle,
5040                                edits,
5041                                server.server_id(),
5042                                None,
5043                                cx,
5044                            )
5045                        })?
5046                        .await?;
5047
5048                    buffer_handle.update(cx, |buffer, cx| {
5049                        buffer.finalize_last_transaction();
5050                        buffer.start_transaction();
5051
5052                        for (range, text) in edits {
5053                            let primary = &completion.old_range;
5054                            let start_within = primary.start.cmp(&range.start, buffer).is_le()
5055                                && primary.end.cmp(&range.start, buffer).is_ge();
5056                            let end_within = range.start.cmp(&primary.end, buffer).is_le()
5057                                && range.end.cmp(&primary.end, buffer).is_ge();
5058
5059                            //Skip additional edits which overlap with the primary completion edit
5060                            //https://github.com/zed-industries/zed/pull/1871
5061                            if !start_within && !end_within {
5062                                buffer.edit([(range, text)], None, cx);
5063                            }
5064                        }
5065
5066                        let transaction = if buffer.end_transaction(cx).is_some() {
5067                            let transaction = buffer.finalize_last_transaction().unwrap().clone();
5068                            if !push_to_history {
5069                                buffer.forget_transaction(transaction.id);
5070                            }
5071                            Some(transaction)
5072                        } else {
5073                            None
5074                        };
5075                        Ok(transaction)
5076                    })?
5077                } else {
5078                    Ok(None)
5079                }
5080            })
5081        }
5082    }
5083
5084    pub fn inlay_hints(
5085        &mut self,
5086        buffer_handle: Entity<Buffer>,
5087        range: Range<Anchor>,
5088        cx: &mut Context<Self>,
5089    ) -> Task<anyhow::Result<Vec<InlayHint>>> {
5090        let buffer = buffer_handle.read(cx);
5091        let range_start = range.start;
5092        let range_end = range.end;
5093        let buffer_id = buffer.remote_id().into();
5094        let lsp_request = InlayHints { range };
5095
5096        if let Some((client, project_id)) = self.upstream_client() {
5097            let request = proto::InlayHints {
5098                project_id,
5099                buffer_id,
5100                start: Some(serialize_anchor(&range_start)),
5101                end: Some(serialize_anchor(&range_end)),
5102                version: serialize_version(&buffer_handle.read(cx).version()),
5103            };
5104            cx.spawn(async move |project, cx| {
5105                let response = client
5106                    .request(request)
5107                    .await
5108                    .context("inlay hints proto request")?;
5109                LspCommand::response_from_proto(
5110                    lsp_request,
5111                    response,
5112                    project.upgrade().ok_or_else(|| anyhow!("No project"))?,
5113                    buffer_handle.clone(),
5114                    cx.clone(),
5115                )
5116                .await
5117                .context("inlay hints proto response conversion")
5118            })
5119        } else {
5120            let lsp_request_task = self.request_lsp(
5121                buffer_handle.clone(),
5122                LanguageServerToQuery::FirstCapable,
5123                lsp_request,
5124                cx,
5125            );
5126            cx.spawn(async move |_, cx| {
5127                buffer_handle
5128                    .update(cx, |buffer, _| {
5129                        buffer.wait_for_edits(vec![range_start.timestamp, range_end.timestamp])
5130                    })?
5131                    .await
5132                    .context("waiting for inlay hint request range edits")?;
5133                lsp_request_task.await.context("inlay hints LSP request")
5134            })
5135        }
5136    }
5137
5138    pub fn signature_help<T: ToPointUtf16>(
5139        &mut self,
5140        buffer: &Entity<Buffer>,
5141        position: T,
5142        cx: &mut Context<Self>,
5143    ) -> Task<Vec<SignatureHelp>> {
5144        let position = position.to_point_utf16(buffer.read(cx));
5145
5146        if let Some((client, upstream_project_id)) = self.upstream_client() {
5147            let request_task = client.request(proto::MultiLspQuery {
5148                buffer_id: buffer.read(cx).remote_id().into(),
5149                version: serialize_version(&buffer.read(cx).version()),
5150                project_id: upstream_project_id,
5151                strategy: Some(proto::multi_lsp_query::Strategy::All(
5152                    proto::AllLanguageServers {},
5153                )),
5154                request: Some(proto::multi_lsp_query::Request::GetSignatureHelp(
5155                    GetSignatureHelp { position }.to_proto(upstream_project_id, buffer.read(cx)),
5156                )),
5157            });
5158            let buffer = buffer.clone();
5159            cx.spawn(async move |weak_project, cx| {
5160                let Some(project) = weak_project.upgrade() else {
5161                    return Vec::new();
5162                };
5163                join_all(
5164                    request_task
5165                        .await
5166                        .log_err()
5167                        .map(|response| response.responses)
5168                        .unwrap_or_default()
5169                        .into_iter()
5170                        .filter_map(|lsp_response| match lsp_response.response? {
5171                            proto::lsp_response::Response::GetSignatureHelpResponse(response) => {
5172                                Some(response)
5173                            }
5174                            unexpected => {
5175                                debug_panic!("Unexpected response: {unexpected:?}");
5176                                None
5177                            }
5178                        })
5179                        .map(|signature_response| {
5180                            let response = GetSignatureHelp { position }.response_from_proto(
5181                                signature_response,
5182                                project.clone(),
5183                                buffer.clone(),
5184                                cx.clone(),
5185                            );
5186                            async move { response.await.log_err().flatten() }
5187                        }),
5188                )
5189                .await
5190                .into_iter()
5191                .flatten()
5192                .collect()
5193            })
5194        } else {
5195            let all_actions_task = self.request_multiple_lsp_locally(
5196                buffer,
5197                Some(position),
5198                GetSignatureHelp { position },
5199                cx,
5200            );
5201            cx.spawn(async move |_, _| {
5202                all_actions_task
5203                    .await
5204                    .into_iter()
5205                    .flatten()
5206                    .filter(|help| !help.label.is_empty())
5207                    .collect::<Vec<_>>()
5208            })
5209        }
5210    }
5211
5212    pub fn hover(
5213        &mut self,
5214        buffer: &Entity<Buffer>,
5215        position: PointUtf16,
5216        cx: &mut Context<Self>,
5217    ) -> Task<Vec<Hover>> {
5218        if let Some((client, upstream_project_id)) = self.upstream_client() {
5219            let request_task = client.request(proto::MultiLspQuery {
5220                buffer_id: buffer.read(cx).remote_id().into(),
5221                version: serialize_version(&buffer.read(cx).version()),
5222                project_id: upstream_project_id,
5223                strategy: Some(proto::multi_lsp_query::Strategy::All(
5224                    proto::AllLanguageServers {},
5225                )),
5226                request: Some(proto::multi_lsp_query::Request::GetHover(
5227                    GetHover { position }.to_proto(upstream_project_id, buffer.read(cx)),
5228                )),
5229            });
5230            let buffer = buffer.clone();
5231            cx.spawn(async move |weak_project, cx| {
5232                let Some(project) = weak_project.upgrade() else {
5233                    return Vec::new();
5234                };
5235                join_all(
5236                    request_task
5237                        .await
5238                        .log_err()
5239                        .map(|response| response.responses)
5240                        .unwrap_or_default()
5241                        .into_iter()
5242                        .filter_map(|lsp_response| match lsp_response.response? {
5243                            proto::lsp_response::Response::GetHoverResponse(response) => {
5244                                Some(response)
5245                            }
5246                            unexpected => {
5247                                debug_panic!("Unexpected response: {unexpected:?}");
5248                                None
5249                            }
5250                        })
5251                        .map(|hover_response| {
5252                            let response = GetHover { position }.response_from_proto(
5253                                hover_response,
5254                                project.clone(),
5255                                buffer.clone(),
5256                                cx.clone(),
5257                            );
5258                            async move {
5259                                response
5260                                    .await
5261                                    .log_err()
5262                                    .flatten()
5263                                    .and_then(remove_empty_hover_blocks)
5264                            }
5265                        }),
5266                )
5267                .await
5268                .into_iter()
5269                .flatten()
5270                .collect()
5271            })
5272        } else {
5273            let all_actions_task = self.request_multiple_lsp_locally(
5274                buffer,
5275                Some(position),
5276                GetHover { position },
5277                cx,
5278            );
5279            cx.spawn(async move |_, _| {
5280                all_actions_task
5281                    .await
5282                    .into_iter()
5283                    .filter_map(|hover| remove_empty_hover_blocks(hover?))
5284                    .collect::<Vec<Hover>>()
5285            })
5286        }
5287    }
5288
5289    pub fn symbols(&self, query: &str, cx: &mut Context<Self>) -> Task<Result<Vec<Symbol>>> {
5290        let language_registry = self.languages.clone();
5291
5292        if let Some((upstream_client, project_id)) = self.upstream_client().as_ref() {
5293            let request = upstream_client.request(proto::GetProjectSymbols {
5294                project_id: *project_id,
5295                query: query.to_string(),
5296            });
5297            cx.foreground_executor().spawn(async move {
5298                let response = request.await?;
5299                let mut symbols = Vec::new();
5300                let core_symbols = response
5301                    .symbols
5302                    .into_iter()
5303                    .filter_map(|symbol| Self::deserialize_symbol(symbol).log_err())
5304                    .collect::<Vec<_>>();
5305                populate_labels_for_symbols(core_symbols, &language_registry, None, &mut symbols)
5306                    .await;
5307                Ok(symbols)
5308            })
5309        } else if let Some(local) = self.as_local() {
5310            struct WorkspaceSymbolsResult {
5311                server_id: LanguageServerId,
5312                lsp_adapter: Arc<CachedLspAdapter>,
5313                worktree: WeakEntity<Worktree>,
5314                worktree_abs_path: Arc<Path>,
5315                lsp_symbols: Vec<(String, SymbolKind, lsp::Location)>,
5316            }
5317
5318            let mut requests = Vec::new();
5319            let mut requested_servers = BTreeSet::new();
5320            'next_server: for ((worktree_id, _), server_ids) in local.language_server_ids.iter() {
5321                let Some(worktree_handle) = self
5322                    .worktree_store
5323                    .read(cx)
5324                    .worktree_for_id(*worktree_id, cx)
5325                else {
5326                    continue;
5327                };
5328                let worktree = worktree_handle.read(cx);
5329                if !worktree.is_visible() {
5330                    continue;
5331                }
5332
5333                let mut servers_to_query = server_ids
5334                    .difference(&requested_servers)
5335                    .cloned()
5336                    .collect::<BTreeSet<_>>();
5337                for server_id in &servers_to_query {
5338                    let (lsp_adapter, server) = match local.language_servers.get(server_id) {
5339                        Some(LanguageServerState::Running {
5340                            adapter, server, ..
5341                        }) => (adapter.clone(), server),
5342
5343                        _ => continue 'next_server,
5344                    };
5345                    let worktree_abs_path = worktree.abs_path().clone();
5346                    let worktree_handle = worktree_handle.clone();
5347                    let server_id = server.server_id();
5348                    requests.push(
5349                            server
5350                                .request::<lsp::request::WorkspaceSymbolRequest>(
5351                                    lsp::WorkspaceSymbolParams {
5352                                        query: query.to_string(),
5353                                        ..Default::default()
5354                                    },
5355                                )
5356                                .log_err()
5357                                .map(move |response| {
5358                                    let lsp_symbols = response.flatten().map(|symbol_response| match symbol_response {
5359                                        lsp::WorkspaceSymbolResponse::Flat(flat_responses) => {
5360                                            flat_responses.into_iter().map(|lsp_symbol| {
5361                                            (lsp_symbol.name, lsp_symbol.kind, lsp_symbol.location)
5362                                            }).collect::<Vec<_>>()
5363                                        }
5364                                        lsp::WorkspaceSymbolResponse::Nested(nested_responses) => {
5365                                            nested_responses.into_iter().filter_map(|lsp_symbol| {
5366                                                let location = match lsp_symbol.location {
5367                                                    OneOf::Left(location) => location,
5368                                                    OneOf::Right(_) => {
5369                                                        log::error!("Unexpected: client capabilities forbid symbol resolutions in workspace.symbol.resolveSupport");
5370                                                        return None
5371                                                    }
5372                                                };
5373                                                Some((lsp_symbol.name, lsp_symbol.kind, location))
5374                                            }).collect::<Vec<_>>()
5375                                        }
5376                                    }).unwrap_or_default();
5377
5378                                    WorkspaceSymbolsResult {
5379                                        server_id,
5380                                        lsp_adapter,
5381                                        worktree: worktree_handle.downgrade(),
5382                                        worktree_abs_path,
5383                                        lsp_symbols,
5384                                    }
5385                                }),
5386                        );
5387                }
5388                requested_servers.append(&mut servers_to_query);
5389            }
5390
5391            cx.spawn(async move |this, cx| {
5392                let responses = futures::future::join_all(requests).await;
5393                let this = match this.upgrade() {
5394                    Some(this) => this,
5395                    None => return Ok(Vec::new()),
5396                };
5397
5398                let mut symbols = Vec::new();
5399                for result in responses {
5400                    let core_symbols = this.update(cx, |this, cx| {
5401                        result
5402                            .lsp_symbols
5403                            .into_iter()
5404                            .filter_map(|(symbol_name, symbol_kind, symbol_location)| {
5405                                let abs_path = symbol_location.uri.to_file_path().ok()?;
5406                                let source_worktree = result.worktree.upgrade()?;
5407                                let source_worktree_id = source_worktree.read(cx).id();
5408
5409                                let path;
5410                                let worktree;
5411                                if let Some((tree, rel_path)) =
5412                                    this.worktree_store.read(cx).find_worktree(&abs_path, cx)
5413                                {
5414                                    worktree = tree;
5415                                    path = rel_path;
5416                                } else {
5417                                    worktree = source_worktree.clone();
5418                                    path = relativize_path(&result.worktree_abs_path, &abs_path);
5419                                }
5420
5421                                let worktree_id = worktree.read(cx).id();
5422                                let project_path = ProjectPath {
5423                                    worktree_id,
5424                                    path: path.into(),
5425                                };
5426                                let signature = this.symbol_signature(&project_path);
5427                                Some(CoreSymbol {
5428                                    source_language_server_id: result.server_id,
5429                                    language_server_name: result.lsp_adapter.name.clone(),
5430                                    source_worktree_id,
5431                                    path: project_path,
5432                                    kind: symbol_kind,
5433                                    name: symbol_name,
5434                                    range: range_from_lsp(symbol_location.range),
5435                                    signature,
5436                                })
5437                            })
5438                            .collect()
5439                    })?;
5440
5441                    populate_labels_for_symbols(
5442                        core_symbols,
5443                        &language_registry,
5444                        Some(result.lsp_adapter),
5445                        &mut symbols,
5446                    )
5447                    .await;
5448                }
5449
5450                Ok(symbols)
5451            })
5452        } else {
5453            Task::ready(Err(anyhow!("No upstream client or local language server")))
5454        }
5455    }
5456
5457    pub fn diagnostic_summary(&self, include_ignored: bool, cx: &App) -> DiagnosticSummary {
5458        let mut summary = DiagnosticSummary::default();
5459        for (_, _, path_summary) in self.diagnostic_summaries(include_ignored, cx) {
5460            summary.error_count += path_summary.error_count;
5461            summary.warning_count += path_summary.warning_count;
5462        }
5463        summary
5464    }
5465
5466    pub fn diagnostic_summaries<'a>(
5467        &'a self,
5468        include_ignored: bool,
5469        cx: &'a App,
5470    ) -> impl Iterator<Item = (ProjectPath, LanguageServerId, DiagnosticSummary)> + 'a {
5471        self.worktree_store
5472            .read(cx)
5473            .visible_worktrees(cx)
5474            .filter_map(|worktree| {
5475                let worktree = worktree.read(cx);
5476                Some((worktree, self.diagnostic_summaries.get(&worktree.id())?))
5477            })
5478            .flat_map(move |(worktree, summaries)| {
5479                let worktree_id = worktree.id();
5480                summaries
5481                    .iter()
5482                    .filter(move |(path, _)| {
5483                        include_ignored
5484                            || worktree
5485                                .entry_for_path(path.as_ref())
5486                                .map_or(false, |entry| !entry.is_ignored)
5487                    })
5488                    .flat_map(move |(path, summaries)| {
5489                        summaries.iter().map(move |(server_id, summary)| {
5490                            (
5491                                ProjectPath {
5492                                    worktree_id,
5493                                    path: path.clone(),
5494                                },
5495                                *server_id,
5496                                *summary,
5497                            )
5498                        })
5499                    })
5500            })
5501    }
5502
5503    pub fn on_buffer_edited(
5504        &mut self,
5505        buffer: Entity<Buffer>,
5506        cx: &mut Context<Self>,
5507    ) -> Option<()> {
5508        let language_servers: Vec<_> = buffer.update(cx, |buffer, cx| {
5509            Some(
5510                self.as_local()?
5511                    .language_servers_for_buffer(buffer, cx)
5512                    .map(|i| i.1.clone())
5513                    .collect(),
5514            )
5515        })?;
5516
5517        let buffer = buffer.read(cx);
5518        let file = File::from_dyn(buffer.file())?;
5519        let abs_path = file.as_local()?.abs_path(cx);
5520        let uri = lsp::Url::from_file_path(abs_path).unwrap();
5521        let next_snapshot = buffer.text_snapshot();
5522        for language_server in language_servers {
5523            let language_server = language_server.clone();
5524
5525            let buffer_snapshots = self
5526                .as_local_mut()
5527                .unwrap()
5528                .buffer_snapshots
5529                .get_mut(&buffer.remote_id())
5530                .and_then(|m| m.get_mut(&language_server.server_id()))?;
5531            let previous_snapshot = buffer_snapshots.last()?;
5532
5533            let build_incremental_change = || {
5534                buffer
5535                    .edits_since::<(PointUtf16, usize)>(previous_snapshot.snapshot.version())
5536                    .map(|edit| {
5537                        let edit_start = edit.new.start.0;
5538                        let edit_end = edit_start + (edit.old.end.0 - edit.old.start.0);
5539                        let new_text = next_snapshot
5540                            .text_for_range(edit.new.start.1..edit.new.end.1)
5541                            .collect();
5542                        lsp::TextDocumentContentChangeEvent {
5543                            range: Some(lsp::Range::new(
5544                                point_to_lsp(edit_start),
5545                                point_to_lsp(edit_end),
5546                            )),
5547                            range_length: None,
5548                            text: new_text,
5549                        }
5550                    })
5551                    .collect()
5552            };
5553
5554            let document_sync_kind = language_server
5555                .capabilities()
5556                .text_document_sync
5557                .as_ref()
5558                .and_then(|sync| match sync {
5559                    lsp::TextDocumentSyncCapability::Kind(kind) => Some(*kind),
5560                    lsp::TextDocumentSyncCapability::Options(options) => options.change,
5561                });
5562
5563            let content_changes: Vec<_> = match document_sync_kind {
5564                Some(lsp::TextDocumentSyncKind::FULL) => {
5565                    vec![lsp::TextDocumentContentChangeEvent {
5566                        range: None,
5567                        range_length: None,
5568                        text: next_snapshot.text(),
5569                    }]
5570                }
5571                Some(lsp::TextDocumentSyncKind::INCREMENTAL) => build_incremental_change(),
5572                _ => {
5573                    #[cfg(any(test, feature = "test-support"))]
5574                    {
5575                        build_incremental_change()
5576                    }
5577
5578                    #[cfg(not(any(test, feature = "test-support")))]
5579                    {
5580                        continue;
5581                    }
5582                }
5583            };
5584
5585            let next_version = previous_snapshot.version + 1;
5586            buffer_snapshots.push(LspBufferSnapshot {
5587                version: next_version,
5588                snapshot: next_snapshot.clone(),
5589            });
5590
5591            language_server
5592                .notify::<lsp::notification::DidChangeTextDocument>(
5593                    &lsp::DidChangeTextDocumentParams {
5594                        text_document: lsp::VersionedTextDocumentIdentifier::new(
5595                            uri.clone(),
5596                            next_version,
5597                        ),
5598                        content_changes,
5599                    },
5600                )
5601                .log_err();
5602        }
5603
5604        None
5605    }
5606
5607    pub fn on_buffer_saved(
5608        &mut self,
5609        buffer: Entity<Buffer>,
5610        cx: &mut Context<Self>,
5611    ) -> Option<()> {
5612        let file = File::from_dyn(buffer.read(cx).file())?;
5613        let worktree_id = file.worktree_id(cx);
5614        let abs_path = file.as_local()?.abs_path(cx);
5615        let text_document = lsp::TextDocumentIdentifier {
5616            uri: lsp::Url::from_file_path(abs_path).log_err()?,
5617        };
5618        let local = self.as_local()?;
5619
5620        for server in local.language_servers_for_worktree(worktree_id) {
5621            if let Some(include_text) = include_text(server.as_ref()) {
5622                let text = if include_text {
5623                    Some(buffer.read(cx).text())
5624                } else {
5625                    None
5626                };
5627                server
5628                    .notify::<lsp::notification::DidSaveTextDocument>(
5629                        &lsp::DidSaveTextDocumentParams {
5630                            text_document: text_document.clone(),
5631                            text,
5632                        },
5633                    )
5634                    .log_err();
5635            }
5636        }
5637
5638        let language_servers = buffer.update(cx, |buffer, cx| {
5639            local.language_server_ids_for_buffer(buffer, cx)
5640        });
5641        for language_server_id in language_servers {
5642            self.simulate_disk_based_diagnostics_events_if_needed(language_server_id, cx);
5643        }
5644
5645        None
5646    }
5647
5648    pub(crate) async fn refresh_workspace_configurations(
5649        this: &WeakEntity<Self>,
5650        fs: Arc<dyn Fs>,
5651        cx: &mut AsyncApp,
5652    ) {
5653        maybe!(async move {
5654            let servers = this
5655                .update(cx, |this, cx| {
5656                    let Some(local) = this.as_local() else {
5657                        return Vec::default();
5658                    };
5659                    local
5660                        .language_server_ids
5661                        .iter()
5662                        .flat_map(|((worktree_id, _), server_ids)| {
5663                            let worktree = this
5664                                .worktree_store
5665                                .read(cx)
5666                                .worktree_for_id(*worktree_id, cx);
5667                            let delegate = worktree.map(|worktree| {
5668                                LocalLspAdapterDelegate::new(
5669                                    local.languages.clone(),
5670                                    &local.environment,
5671                                    cx.weak_entity(),
5672                                    &worktree,
5673                                    local.http_client.clone(),
5674                                    local.fs.clone(),
5675                                    cx,
5676                                )
5677                            });
5678
5679                            server_ids.iter().filter_map(move |server_id| {
5680                                let states = local.language_servers.get(server_id)?;
5681
5682                                match states {
5683                                    LanguageServerState::Starting { .. } => None,
5684                                    LanguageServerState::Running {
5685                                        adapter, server, ..
5686                                    } => Some((
5687                                        adapter.adapter.clone(),
5688                                        server.clone(),
5689                                        delegate.clone()? as Arc<dyn LspAdapterDelegate>,
5690                                    )),
5691                                }
5692                            })
5693                        })
5694                        .collect::<Vec<_>>()
5695                })
5696                .ok()?;
5697
5698            let toolchain_store = this.update(cx, |this, cx| this.toolchain_store(cx)).ok()?;
5699            for (adapter, server, delegate) in servers {
5700                let settings = adapter
5701                    .workspace_configuration(fs.as_ref(), &delegate, toolchain_store.clone(), cx)
5702                    .await
5703                    .ok()?;
5704
5705                server
5706                    .notify::<lsp::notification::DidChangeConfiguration>(
5707                        &lsp::DidChangeConfigurationParams { settings },
5708                    )
5709                    .ok();
5710            }
5711            Some(())
5712        })
5713        .await;
5714    }
5715
5716    fn toolchain_store(&self, cx: &App) -> Arc<dyn LanguageToolchainStore> {
5717        if let Some(toolchain_store) = self.toolchain_store.as_ref() {
5718            toolchain_store.read(cx).as_language_toolchain_store()
5719        } else {
5720            Arc::new(EmptyToolchainStore)
5721        }
5722    }
5723    fn maintain_workspace_config(
5724        fs: Arc<dyn Fs>,
5725        external_refresh_requests: watch::Receiver<()>,
5726        cx: &mut Context<Self>,
5727    ) -> Task<Result<()>> {
5728        let (mut settings_changed_tx, mut settings_changed_rx) = watch::channel();
5729        let _ = postage::stream::Stream::try_recv(&mut settings_changed_rx);
5730
5731        let settings_observation = cx.observe_global::<SettingsStore>(move |_, _| {
5732            *settings_changed_tx.borrow_mut() = ();
5733        });
5734
5735        let mut joint_future =
5736            futures::stream::select(settings_changed_rx, external_refresh_requests);
5737        cx.spawn(async move |this, cx| {
5738            while let Some(()) = joint_future.next().await {
5739                Self::refresh_workspace_configurations(&this, fs.clone(), cx).await;
5740            }
5741
5742            drop(settings_observation);
5743            anyhow::Ok(())
5744        })
5745    }
5746
5747    pub fn language_servers_for_local_buffer<'a>(
5748        &'a self,
5749        buffer: &Buffer,
5750        cx: &mut App,
5751    ) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
5752        let local = self.as_local();
5753        let language_server_ids = local
5754            .map(|local| local.language_server_ids_for_buffer(buffer, cx))
5755            .unwrap_or_default();
5756
5757        language_server_ids
5758            .into_iter()
5759            .filter_map(
5760                move |server_id| match local?.language_servers.get(&server_id)? {
5761                    LanguageServerState::Running {
5762                        adapter, server, ..
5763                    } => Some((adapter, server)),
5764                    _ => None,
5765                },
5766            )
5767    }
5768
5769    pub fn language_server_for_local_buffer<'a>(
5770        &'a self,
5771        buffer: &'a Buffer,
5772        server_id: LanguageServerId,
5773        cx: &'a mut App,
5774    ) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
5775        self.as_local()?
5776            .language_servers_for_buffer(buffer, cx)
5777            .find(|(_, s)| s.server_id() == server_id)
5778    }
5779
5780    fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut Context<Self>) {
5781        self.diagnostic_summaries.remove(&id_to_remove);
5782        if let Some(local) = self.as_local_mut() {
5783            let to_remove = local.remove_worktree(id_to_remove, cx);
5784            for server in to_remove {
5785                self.language_server_statuses.remove(&server);
5786            }
5787        }
5788    }
5789
5790    pub fn shared(
5791        &mut self,
5792        project_id: u64,
5793        downstream_client: AnyProtoClient,
5794        _: &mut Context<Self>,
5795    ) {
5796        self.downstream_client = Some((downstream_client.clone(), project_id));
5797
5798        for (server_id, status) in &self.language_server_statuses {
5799            downstream_client
5800                .send(proto::StartLanguageServer {
5801                    project_id,
5802                    server: Some(proto::LanguageServer {
5803                        id: server_id.0 as u64,
5804                        name: status.name.clone(),
5805                        worktree_id: None,
5806                    }),
5807                })
5808                .log_err();
5809        }
5810    }
5811
5812    pub fn disconnected_from_host(&mut self) {
5813        self.downstream_client.take();
5814    }
5815
5816    pub fn disconnected_from_ssh_remote(&mut self) {
5817        if let LspStoreMode::Remote(RemoteLspStore {
5818            upstream_client, ..
5819        }) = &mut self.mode
5820        {
5821            upstream_client.take();
5822        }
5823    }
5824
5825    pub(crate) fn set_language_server_statuses_from_proto(
5826        &mut self,
5827        language_servers: Vec<proto::LanguageServer>,
5828    ) {
5829        self.language_server_statuses = language_servers
5830            .into_iter()
5831            .map(|server| {
5832                (
5833                    LanguageServerId(server.id as usize),
5834                    LanguageServerStatus {
5835                        name: server.name,
5836                        pending_work: Default::default(),
5837                        has_pending_diagnostic_updates: false,
5838                        progress_tokens: Default::default(),
5839                    },
5840                )
5841            })
5842            .collect();
5843    }
5844
5845    fn register_local_language_server(
5846        &mut self,
5847        worktree: Entity<Worktree>,
5848        language_server_name: LanguageServerName,
5849        language_server_id: LanguageServerId,
5850        cx: &mut App,
5851    ) {
5852        let Some(local) = self.as_local_mut() else {
5853            return;
5854        };
5855        let worktree_id = worktree.read(cx).id();
5856        let path = ProjectPath {
5857            worktree_id,
5858            path: Arc::from("".as_ref()),
5859        };
5860        let delegate = LocalLspAdapterDelegate::from_local_lsp(local, &worktree, cx);
5861        local.lsp_tree.update(cx, |this, cx| {
5862            for node in this.get(
5863                path,
5864                AdapterQuery::Adapter(&language_server_name),
5865                delegate,
5866                cx,
5867            ) {
5868                node.server_id_or_init(|disposition| {
5869                    assert_eq!(disposition.server_name, &language_server_name);
5870
5871                    language_server_id
5872                });
5873            }
5874        });
5875        local
5876            .language_server_ids
5877            .entry((worktree_id, language_server_name))
5878            .or_default()
5879            .insert(language_server_id);
5880    }
5881
5882    pub fn update_diagnostic_entries(
5883        &mut self,
5884        server_id: LanguageServerId,
5885        abs_path: PathBuf,
5886        version: Option<i32>,
5887        diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
5888        cx: &mut Context<Self>,
5889    ) -> Result<(), anyhow::Error> {
5890        let Some((worktree, relative_path)) =
5891            self.worktree_store.read(cx).find_worktree(&abs_path, cx)
5892        else {
5893            log::warn!("skipping diagnostics update, no worktree found for path {abs_path:?}");
5894            return Ok(());
5895        };
5896
5897        let project_path = ProjectPath {
5898            worktree_id: worktree.read(cx).id(),
5899            path: relative_path.into(),
5900        };
5901
5902        if let Some(buffer) = self.buffer_store.read(cx).get_by_path(&project_path, cx) {
5903            self.as_local_mut().unwrap().update_buffer_diagnostics(
5904                &buffer,
5905                server_id,
5906                version,
5907                diagnostics.clone(),
5908                cx,
5909            )?;
5910        }
5911
5912        let updated = worktree.update(cx, |worktree, cx| {
5913            self.update_worktree_diagnostics(
5914                worktree.id(),
5915                server_id,
5916                project_path.path.clone(),
5917                diagnostics,
5918                cx,
5919            )
5920        })?;
5921        if updated {
5922            cx.emit(LspStoreEvent::DiagnosticsUpdated {
5923                language_server_id: server_id,
5924                path: project_path,
5925            })
5926        }
5927        Ok(())
5928    }
5929
5930    fn update_worktree_diagnostics(
5931        &mut self,
5932        worktree_id: WorktreeId,
5933        server_id: LanguageServerId,
5934        worktree_path: Arc<Path>,
5935        diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
5936        _: &mut Context<Worktree>,
5937    ) -> Result<bool> {
5938        let local = match &mut self.mode {
5939            LspStoreMode::Local(local_lsp_store) => local_lsp_store,
5940            _ => anyhow::bail!("update_worktree_diagnostics called on remote"),
5941        };
5942
5943        let summaries_for_tree = self.diagnostic_summaries.entry(worktree_id).or_default();
5944        let diagnostics_for_tree = local.diagnostics.entry(worktree_id).or_default();
5945        let summaries_by_server_id = summaries_for_tree.entry(worktree_path.clone()).or_default();
5946
5947        let old_summary = summaries_by_server_id
5948            .remove(&server_id)
5949            .unwrap_or_default();
5950
5951        let new_summary = DiagnosticSummary::new(&diagnostics);
5952        if new_summary.is_empty() {
5953            if let Some(diagnostics_by_server_id) = diagnostics_for_tree.get_mut(&worktree_path) {
5954                if let Ok(ix) = diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0) {
5955                    diagnostics_by_server_id.remove(ix);
5956                }
5957                if diagnostics_by_server_id.is_empty() {
5958                    diagnostics_for_tree.remove(&worktree_path);
5959                }
5960            }
5961        } else {
5962            summaries_by_server_id.insert(server_id, new_summary);
5963            let diagnostics_by_server_id = diagnostics_for_tree
5964                .entry(worktree_path.clone())
5965                .or_default();
5966            match diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0) {
5967                Ok(ix) => {
5968                    diagnostics_by_server_id[ix] = (server_id, diagnostics);
5969                }
5970                Err(ix) => {
5971                    diagnostics_by_server_id.insert(ix, (server_id, diagnostics));
5972                }
5973            }
5974        }
5975
5976        if !old_summary.is_empty() || !new_summary.is_empty() {
5977            if let Some((downstream_client, project_id)) = &self.downstream_client {
5978                downstream_client
5979                    .send(proto::UpdateDiagnosticSummary {
5980                        project_id: *project_id,
5981                        worktree_id: worktree_id.to_proto(),
5982                        summary: Some(proto::DiagnosticSummary {
5983                            path: worktree_path.to_proto(),
5984                            language_server_id: server_id.0 as u64,
5985                            error_count: new_summary.error_count as u32,
5986                            warning_count: new_summary.warning_count as u32,
5987                        }),
5988                    })
5989                    .log_err();
5990            }
5991        }
5992
5993        Ok(!old_summary.is_empty() || !new_summary.is_empty())
5994    }
5995
5996    pub fn open_buffer_for_symbol(
5997        &mut self,
5998        symbol: &Symbol,
5999        cx: &mut Context<Self>,
6000    ) -> Task<Result<Entity<Buffer>>> {
6001        if let Some((client, project_id)) = self.upstream_client() {
6002            let request = client.request(proto::OpenBufferForSymbol {
6003                project_id,
6004                symbol: Some(Self::serialize_symbol(symbol)),
6005            });
6006            cx.spawn(async move |this, cx| {
6007                let response = request.await?;
6008                let buffer_id = BufferId::new(response.buffer_id)?;
6009                this.update(cx, |this, cx| this.wait_for_remote_buffer(buffer_id, cx))?
6010                    .await
6011            })
6012        } else if let Some(local) = self.as_local() {
6013            let Some(language_server_id) = local
6014                .language_server_ids
6015                .get(&(
6016                    symbol.source_worktree_id,
6017                    symbol.language_server_name.clone(),
6018                ))
6019                .and_then(|ids| {
6020                    ids.contains(&symbol.source_language_server_id)
6021                        .then_some(symbol.source_language_server_id)
6022                })
6023            else {
6024                return Task::ready(Err(anyhow!(
6025                    "language server for worktree and language not found"
6026                )));
6027            };
6028
6029            let worktree_abs_path = if let Some(worktree_abs_path) = self
6030                .worktree_store
6031                .read(cx)
6032                .worktree_for_id(symbol.path.worktree_id, cx)
6033                .map(|worktree| worktree.read(cx).abs_path())
6034            {
6035                worktree_abs_path
6036            } else {
6037                return Task::ready(Err(anyhow!("worktree not found for symbol")));
6038            };
6039
6040            let symbol_abs_path = resolve_path(&worktree_abs_path, &symbol.path.path);
6041            let symbol_uri = if let Ok(uri) = lsp::Url::from_file_path(symbol_abs_path) {
6042                uri
6043            } else {
6044                return Task::ready(Err(anyhow!("invalid symbol path")));
6045            };
6046
6047            self.open_local_buffer_via_lsp(
6048                symbol_uri,
6049                language_server_id,
6050                symbol.language_server_name.clone(),
6051                cx,
6052            )
6053        } else {
6054            Task::ready(Err(anyhow!("no upstream client or local store")))
6055        }
6056    }
6057
6058    pub fn open_local_buffer_via_lsp(
6059        &mut self,
6060        mut abs_path: lsp::Url,
6061        language_server_id: LanguageServerId,
6062        language_server_name: LanguageServerName,
6063        cx: &mut Context<Self>,
6064    ) -> Task<Result<Entity<Buffer>>> {
6065        cx.spawn(async move |lsp_store, cx| {
6066            // Escape percent-encoded string.
6067            let current_scheme = abs_path.scheme().to_owned();
6068            let _ = abs_path.set_scheme("file");
6069
6070            let abs_path = abs_path
6071                .to_file_path()
6072                .map_err(|_| anyhow!("can't convert URI to path"))?;
6073            let p = abs_path.clone();
6074            let yarn_worktree = lsp_store
6075                .update(cx, move |lsp_store, cx| match lsp_store.as_local() {
6076                    Some(local_lsp_store) => local_lsp_store.yarn.update(cx, |_, cx| {
6077                        cx.spawn(async move |this, cx| {
6078                            let t = this
6079                                .update(cx, |this, cx| this.process_path(&p, &current_scheme, cx))
6080                                .ok()?;
6081                            t.await
6082                        })
6083                    }),
6084                    None => Task::ready(None),
6085                })?
6086                .await;
6087            let (worktree_root_target, known_relative_path) =
6088                if let Some((zip_root, relative_path)) = yarn_worktree {
6089                    (zip_root, Some(relative_path))
6090                } else {
6091                    (Arc::<Path>::from(abs_path.as_path()), None)
6092                };
6093            let (worktree, relative_path) = if let Some(result) =
6094                lsp_store.update(cx, |lsp_store, cx| {
6095                    lsp_store.worktree_store.update(cx, |worktree_store, cx| {
6096                        worktree_store.find_worktree(&worktree_root_target, cx)
6097                    })
6098                })? {
6099                let relative_path =
6100                    known_relative_path.unwrap_or_else(|| Arc::<Path>::from(result.1));
6101                (result.0, relative_path)
6102            } else {
6103                let worktree = lsp_store
6104                    .update(cx, |lsp_store, cx| {
6105                        lsp_store.worktree_store.update(cx, |worktree_store, cx| {
6106                            worktree_store.create_worktree(&worktree_root_target, false, cx)
6107                        })
6108                    })?
6109                    .await?;
6110                if worktree.update(cx, |worktree, _| worktree.is_local())? {
6111                    lsp_store
6112                        .update(cx, |lsp_store, cx| {
6113                            lsp_store.register_local_language_server(
6114                                worktree.clone(),
6115                                language_server_name,
6116                                language_server_id,
6117                                cx,
6118                            )
6119                        })
6120                        .ok();
6121                }
6122                let worktree_root = worktree.update(cx, |worktree, _| worktree.abs_path())?;
6123                let relative_path = if let Some(known_path) = known_relative_path {
6124                    known_path
6125                } else {
6126                    abs_path.strip_prefix(worktree_root)?.into()
6127                };
6128                (worktree, relative_path)
6129            };
6130            let project_path = ProjectPath {
6131                worktree_id: worktree.update(cx, |worktree, _| worktree.id())?,
6132                path: relative_path,
6133            };
6134            lsp_store
6135                .update(cx, |lsp_store, cx| {
6136                    lsp_store.buffer_store().update(cx, |buffer_store, cx| {
6137                        buffer_store.open_buffer(project_path, cx)
6138                    })
6139                })?
6140                .await
6141        })
6142    }
6143
6144    fn request_multiple_lsp_locally<P, R>(
6145        &mut self,
6146        buffer: &Entity<Buffer>,
6147        position: Option<P>,
6148        request: R,
6149        cx: &mut Context<'_, Self>,
6150    ) -> Task<Vec<R::Response>>
6151    where
6152        P: ToOffset,
6153        R: LspCommand + Clone,
6154        <R::LspRequest as lsp::request::Request>::Result: Send,
6155        <R::LspRequest as lsp::request::Request>::Params: Send,
6156    {
6157        let Some(local) = self.as_local() else {
6158            return Task::ready(Vec::new());
6159        };
6160
6161        let snapshot = buffer.read(cx).snapshot();
6162        let scope = position.and_then(|position| snapshot.language_scope_at(position));
6163
6164        let server_ids = buffer.update(cx, |buffer, cx| {
6165            local
6166                .language_servers_for_buffer(buffer, cx)
6167                .filter(|(adapter, _)| {
6168                    scope
6169                        .as_ref()
6170                        .map(|scope| scope.language_allowed(&adapter.name))
6171                        .unwrap_or(true)
6172                })
6173                .map(|(_, server)| server.server_id())
6174                .collect::<Vec<_>>()
6175        });
6176
6177        let mut response_results = server_ids
6178            .into_iter()
6179            .map(|server_id| {
6180                self.request_lsp(
6181                    buffer.clone(),
6182                    LanguageServerToQuery::Other(server_id),
6183                    request.clone(),
6184                    cx,
6185                )
6186            })
6187            .collect::<FuturesUnordered<_>>();
6188
6189        cx.spawn(async move |_, _| {
6190            let mut responses = Vec::with_capacity(response_results.len());
6191            while let Some(response_result) = response_results.next().await {
6192                if let Some(response) = response_result.log_err() {
6193                    responses.push(response);
6194                }
6195            }
6196            responses
6197        })
6198    }
6199
6200    async fn handle_lsp_command<T: LspCommand>(
6201        this: Entity<Self>,
6202        envelope: TypedEnvelope<T::ProtoRequest>,
6203        mut cx: AsyncApp,
6204    ) -> Result<<T::ProtoRequest as proto::RequestMessage>::Response>
6205    where
6206        <T::LspRequest as lsp::request::Request>::Params: Send,
6207        <T::LspRequest as lsp::request::Request>::Result: Send,
6208    {
6209        let sender_id = envelope.original_sender_id().unwrap_or_default();
6210        let buffer_id = T::buffer_id_from_proto(&envelope.payload)?;
6211        let buffer_handle = this.update(&mut cx, |this, cx| {
6212            this.buffer_store.read(cx).get_existing(buffer_id)
6213        })??;
6214        let request = T::from_proto(
6215            envelope.payload,
6216            this.clone(),
6217            buffer_handle.clone(),
6218            cx.clone(),
6219        )
6220        .await?;
6221        let response = this
6222            .update(&mut cx, |this, cx| {
6223                this.request_lsp(
6224                    buffer_handle.clone(),
6225                    LanguageServerToQuery::FirstCapable,
6226                    request,
6227                    cx,
6228                )
6229            })?
6230            .await?;
6231        this.update(&mut cx, |this, cx| {
6232            Ok(T::response_to_proto(
6233                response,
6234                this,
6235                sender_id,
6236                &buffer_handle.read(cx).version(),
6237                cx,
6238            ))
6239        })?
6240    }
6241
6242    async fn handle_multi_lsp_query(
6243        this: Entity<Self>,
6244        envelope: TypedEnvelope<proto::MultiLspQuery>,
6245        mut cx: AsyncApp,
6246    ) -> Result<proto::MultiLspQueryResponse> {
6247        let response_from_ssh = this.update(&mut cx, |this, _| {
6248            let (upstream_client, project_id) = this.upstream_client()?;
6249            let mut payload = envelope.payload.clone();
6250            payload.project_id = project_id;
6251
6252            Some(upstream_client.request(payload))
6253        })?;
6254        if let Some(response_from_ssh) = response_from_ssh {
6255            return response_from_ssh.await;
6256        }
6257
6258        let sender_id = envelope.original_sender_id().unwrap_or_default();
6259        let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
6260        let version = deserialize_version(&envelope.payload.version);
6261        let buffer = this.update(&mut cx, |this, cx| {
6262            this.buffer_store.read(cx).get_existing(buffer_id)
6263        })??;
6264        buffer
6265            .update(&mut cx, |buffer, _| {
6266                buffer.wait_for_version(version.clone())
6267            })?
6268            .await?;
6269        let buffer_version = buffer.update(&mut cx, |buffer, _| buffer.version())?;
6270        match envelope
6271            .payload
6272            .strategy
6273            .context("invalid request without the strategy")?
6274        {
6275            proto::multi_lsp_query::Strategy::All(_) => {
6276                // currently, there's only one multiple language servers query strategy,
6277                // so just ensure it's specified correctly
6278            }
6279        }
6280        match envelope.payload.request {
6281            Some(proto::multi_lsp_query::Request::GetHover(get_hover)) => {
6282                let get_hover =
6283                    GetHover::from_proto(get_hover, this.clone(), buffer.clone(), cx.clone())
6284                        .await?;
6285                let all_hovers = this
6286                    .update(&mut cx, |this, cx| {
6287                        this.request_multiple_lsp_locally(
6288                            &buffer,
6289                            Some(get_hover.position),
6290                            get_hover,
6291                            cx,
6292                        )
6293                    })?
6294                    .await
6295                    .into_iter()
6296                    .filter_map(|hover| remove_empty_hover_blocks(hover?));
6297                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
6298                    responses: all_hovers
6299                        .map(|hover| proto::LspResponse {
6300                            response: Some(proto::lsp_response::Response::GetHoverResponse(
6301                                GetHover::response_to_proto(
6302                                    Some(hover),
6303                                    project,
6304                                    sender_id,
6305                                    &buffer_version,
6306                                    cx,
6307                                ),
6308                            )),
6309                        })
6310                        .collect(),
6311                })
6312            }
6313            Some(proto::multi_lsp_query::Request::GetCodeActions(get_code_actions)) => {
6314                let get_code_actions = GetCodeActions::from_proto(
6315                    get_code_actions,
6316                    this.clone(),
6317                    buffer.clone(),
6318                    cx.clone(),
6319                )
6320                .await?;
6321
6322                let all_actions = this
6323                    .update(&mut cx, |project, cx| {
6324                        project.request_multiple_lsp_locally(
6325                            &buffer,
6326                            Some(get_code_actions.range.start),
6327                            get_code_actions,
6328                            cx,
6329                        )
6330                    })?
6331                    .await
6332                    .into_iter();
6333
6334                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
6335                    responses: all_actions
6336                        .map(|code_actions| proto::LspResponse {
6337                            response: Some(proto::lsp_response::Response::GetCodeActionsResponse(
6338                                GetCodeActions::response_to_proto(
6339                                    code_actions,
6340                                    project,
6341                                    sender_id,
6342                                    &buffer_version,
6343                                    cx,
6344                                ),
6345                            )),
6346                        })
6347                        .collect(),
6348                })
6349            }
6350            Some(proto::multi_lsp_query::Request::GetSignatureHelp(get_signature_help)) => {
6351                let get_signature_help = GetSignatureHelp::from_proto(
6352                    get_signature_help,
6353                    this.clone(),
6354                    buffer.clone(),
6355                    cx.clone(),
6356                )
6357                .await?;
6358
6359                let all_signatures = this
6360                    .update(&mut cx, |project, cx| {
6361                        project.request_multiple_lsp_locally(
6362                            &buffer,
6363                            Some(get_signature_help.position),
6364                            get_signature_help,
6365                            cx,
6366                        )
6367                    })?
6368                    .await
6369                    .into_iter();
6370
6371                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
6372                    responses: all_signatures
6373                        .map(|signature_help| proto::LspResponse {
6374                            response: Some(
6375                                proto::lsp_response::Response::GetSignatureHelpResponse(
6376                                    GetSignatureHelp::response_to_proto(
6377                                        signature_help,
6378                                        project,
6379                                        sender_id,
6380                                        &buffer_version,
6381                                        cx,
6382                                    ),
6383                                ),
6384                            ),
6385                        })
6386                        .collect(),
6387                })
6388            }
6389            Some(proto::multi_lsp_query::Request::GetCodeLens(get_code_lens)) => {
6390                let get_code_lens = GetCodeLens::from_proto(
6391                    get_code_lens,
6392                    this.clone(),
6393                    buffer.clone(),
6394                    cx.clone(),
6395                )
6396                .await?;
6397
6398                let code_lens_actions = this
6399                    .update(&mut cx, |project, cx| {
6400                        project.request_multiple_lsp_locally(
6401                            &buffer,
6402                            None::<usize>,
6403                            get_code_lens,
6404                            cx,
6405                        )
6406                    })?
6407                    .await
6408                    .into_iter();
6409
6410                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
6411                    responses: code_lens_actions
6412                        .map(|actions| proto::LspResponse {
6413                            response: Some(proto::lsp_response::Response::GetCodeLensResponse(
6414                                GetCodeLens::response_to_proto(
6415                                    actions,
6416                                    project,
6417                                    sender_id,
6418                                    &buffer_version,
6419                                    cx,
6420                                ),
6421                            )),
6422                        })
6423                        .collect(),
6424                })
6425            }
6426            None => anyhow::bail!("empty multi lsp query request"),
6427        }
6428    }
6429
6430    async fn handle_apply_code_action(
6431        this: Entity<Self>,
6432        envelope: TypedEnvelope<proto::ApplyCodeAction>,
6433        mut cx: AsyncApp,
6434    ) -> Result<proto::ApplyCodeActionResponse> {
6435        let sender_id = envelope.original_sender_id().unwrap_or_default();
6436        let action = Self::deserialize_code_action(
6437            envelope
6438                .payload
6439                .action
6440                .ok_or_else(|| anyhow!("invalid action"))?,
6441        )?;
6442        let apply_code_action = this.update(&mut cx, |this, cx| {
6443            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
6444            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
6445            anyhow::Ok(this.apply_code_action(buffer, action, false, cx))
6446        })??;
6447
6448        let project_transaction = apply_code_action.await?;
6449        let project_transaction = this.update(&mut cx, |this, cx| {
6450            this.buffer_store.update(cx, |buffer_store, cx| {
6451                buffer_store.serialize_project_transaction_for_peer(
6452                    project_transaction,
6453                    sender_id,
6454                    cx,
6455                )
6456            })
6457        })?;
6458        Ok(proto::ApplyCodeActionResponse {
6459            transaction: Some(project_transaction),
6460        })
6461    }
6462
6463    async fn handle_register_buffer_with_language_servers(
6464        this: Entity<Self>,
6465        envelope: TypedEnvelope<proto::RegisterBufferWithLanguageServers>,
6466        mut cx: AsyncApp,
6467    ) -> Result<proto::Ack> {
6468        let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
6469        let peer_id = envelope.original_sender_id.unwrap_or(envelope.sender_id);
6470        this.update(&mut cx, |this, cx| {
6471            if let Some((upstream_client, upstream_project_id)) = this.upstream_client() {
6472                return upstream_client.send(proto::RegisterBufferWithLanguageServers {
6473                    project_id: upstream_project_id,
6474                    buffer_id: buffer_id.to_proto(),
6475                });
6476            }
6477
6478            let Some(buffer) = this.buffer_store().read(cx).get(buffer_id) else {
6479                anyhow::bail!("buffer is not open");
6480            };
6481
6482            let handle = this.register_buffer_with_language_servers(&buffer, false, cx);
6483            this.buffer_store().update(cx, |buffer_store, _| {
6484                buffer_store.register_shared_lsp_handle(peer_id, buffer_id, handle);
6485            });
6486
6487            Ok(())
6488        })??;
6489        Ok(proto::Ack {})
6490    }
6491
6492    async fn handle_rename_project_entry(
6493        this: Entity<Self>,
6494        envelope: TypedEnvelope<proto::RenameProjectEntry>,
6495        mut cx: AsyncApp,
6496    ) -> Result<proto::ProjectEntryResponse> {
6497        let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id);
6498        let (worktree_id, worktree, old_path, is_dir) = this
6499            .update(&mut cx, |this, cx| {
6500                this.worktree_store
6501                    .read(cx)
6502                    .worktree_and_entry_for_id(entry_id, cx)
6503                    .map(|(worktree, entry)| {
6504                        (
6505                            worktree.read(cx).id(),
6506                            worktree,
6507                            entry.path.clone(),
6508                            entry.is_dir(),
6509                        )
6510                    })
6511            })?
6512            .ok_or_else(|| anyhow!("worktree not found"))?;
6513        let (old_abs_path, new_abs_path) = {
6514            let root_path = worktree.update(&mut cx, |this, _| this.abs_path())?;
6515            let new_path = PathBuf::from_proto(envelope.payload.new_path.clone());
6516            (root_path.join(&old_path), root_path.join(&new_path))
6517        };
6518
6519        Self::will_rename_entry(
6520            this.downgrade(),
6521            worktree_id,
6522            &old_abs_path,
6523            &new_abs_path,
6524            is_dir,
6525            cx.clone(),
6526        )
6527        .await;
6528        let response = Worktree::handle_rename_entry(worktree, envelope.payload, cx.clone()).await;
6529        this.update(&mut cx, |this, _| {
6530            this.did_rename_entry(worktree_id, &old_abs_path, &new_abs_path, is_dir);
6531        })
6532        .ok();
6533        response
6534    }
6535
6536    async fn handle_update_diagnostic_summary(
6537        this: Entity<Self>,
6538        envelope: TypedEnvelope<proto::UpdateDiagnosticSummary>,
6539        mut cx: AsyncApp,
6540    ) -> Result<()> {
6541        this.update(&mut cx, |this, cx| {
6542            let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
6543            if let Some(message) = envelope.payload.summary {
6544                let project_path = ProjectPath {
6545                    worktree_id,
6546                    path: Arc::<Path>::from_proto(message.path),
6547                };
6548                let path = project_path.path.clone();
6549                let server_id = LanguageServerId(message.language_server_id as usize);
6550                let summary = DiagnosticSummary {
6551                    error_count: message.error_count as usize,
6552                    warning_count: message.warning_count as usize,
6553                };
6554
6555                if summary.is_empty() {
6556                    if let Some(worktree_summaries) =
6557                        this.diagnostic_summaries.get_mut(&worktree_id)
6558                    {
6559                        if let Some(summaries) = worktree_summaries.get_mut(&path) {
6560                            summaries.remove(&server_id);
6561                            if summaries.is_empty() {
6562                                worktree_summaries.remove(&path);
6563                            }
6564                        }
6565                    }
6566                } else {
6567                    this.diagnostic_summaries
6568                        .entry(worktree_id)
6569                        .or_default()
6570                        .entry(path)
6571                        .or_default()
6572                        .insert(server_id, summary);
6573                }
6574                if let Some((downstream_client, project_id)) = &this.downstream_client {
6575                    downstream_client
6576                        .send(proto::UpdateDiagnosticSummary {
6577                            project_id: *project_id,
6578                            worktree_id: worktree_id.to_proto(),
6579                            summary: Some(proto::DiagnosticSummary {
6580                                path: project_path.path.as_ref().to_proto(),
6581                                language_server_id: server_id.0 as u64,
6582                                error_count: summary.error_count as u32,
6583                                warning_count: summary.warning_count as u32,
6584                            }),
6585                        })
6586                        .log_err();
6587                }
6588                cx.emit(LspStoreEvent::DiagnosticsUpdated {
6589                    language_server_id: LanguageServerId(message.language_server_id as usize),
6590                    path: project_path,
6591                });
6592            }
6593            Ok(())
6594        })?
6595    }
6596
6597    async fn handle_start_language_server(
6598        this: Entity<Self>,
6599        envelope: TypedEnvelope<proto::StartLanguageServer>,
6600        mut cx: AsyncApp,
6601    ) -> Result<()> {
6602        let server = envelope
6603            .payload
6604            .server
6605            .ok_or_else(|| anyhow!("invalid server"))?;
6606
6607        this.update(&mut cx, |this, cx| {
6608            let server_id = LanguageServerId(server.id as usize);
6609            this.language_server_statuses.insert(
6610                server_id,
6611                LanguageServerStatus {
6612                    name: server.name.clone(),
6613                    pending_work: Default::default(),
6614                    has_pending_diagnostic_updates: false,
6615                    progress_tokens: Default::default(),
6616                },
6617            );
6618            cx.emit(LspStoreEvent::LanguageServerAdded(
6619                server_id,
6620                LanguageServerName(server.name.into()),
6621                server.worktree_id.map(WorktreeId::from_proto),
6622            ));
6623            cx.notify();
6624        })?;
6625        Ok(())
6626    }
6627
6628    async fn handle_update_language_server(
6629        this: Entity<Self>,
6630        envelope: TypedEnvelope<proto::UpdateLanguageServer>,
6631        mut cx: AsyncApp,
6632    ) -> Result<()> {
6633        this.update(&mut cx, |this, cx| {
6634            let language_server_id = LanguageServerId(envelope.payload.language_server_id as usize);
6635
6636            match envelope
6637                .payload
6638                .variant
6639                .ok_or_else(|| anyhow!("invalid variant"))?
6640            {
6641                proto::update_language_server::Variant::WorkStart(payload) => {
6642                    this.on_lsp_work_start(
6643                        language_server_id,
6644                        payload.token,
6645                        LanguageServerProgress {
6646                            title: payload.title,
6647                            is_disk_based_diagnostics_progress: false,
6648                            is_cancellable: payload.is_cancellable.unwrap_or(false),
6649                            message: payload.message,
6650                            percentage: payload.percentage.map(|p| p as usize),
6651                            last_update_at: cx.background_executor().now(),
6652                        },
6653                        cx,
6654                    );
6655                }
6656
6657                proto::update_language_server::Variant::WorkProgress(payload) => {
6658                    this.on_lsp_work_progress(
6659                        language_server_id,
6660                        payload.token,
6661                        LanguageServerProgress {
6662                            title: None,
6663                            is_disk_based_diagnostics_progress: false,
6664                            is_cancellable: payload.is_cancellable.unwrap_or(false),
6665                            message: payload.message,
6666                            percentage: payload.percentage.map(|p| p as usize),
6667                            last_update_at: cx.background_executor().now(),
6668                        },
6669                        cx,
6670                    );
6671                }
6672
6673                proto::update_language_server::Variant::WorkEnd(payload) => {
6674                    this.on_lsp_work_end(language_server_id, payload.token, cx);
6675                }
6676
6677                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(_) => {
6678                    this.disk_based_diagnostics_started(language_server_id, cx);
6679                }
6680
6681                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(_) => {
6682                    this.disk_based_diagnostics_finished(language_server_id, cx)
6683                }
6684            }
6685
6686            Ok(())
6687        })?
6688    }
6689
6690    async fn handle_language_server_log(
6691        this: Entity<Self>,
6692        envelope: TypedEnvelope<proto::LanguageServerLog>,
6693        mut cx: AsyncApp,
6694    ) -> Result<()> {
6695        let language_server_id = LanguageServerId(envelope.payload.language_server_id as usize);
6696        let log_type = envelope
6697            .payload
6698            .log_type
6699            .map(LanguageServerLogType::from_proto)
6700            .context("invalid language server log type")?;
6701
6702        let message = envelope.payload.message;
6703
6704        this.update(&mut cx, |_, cx| {
6705            cx.emit(LspStoreEvent::LanguageServerLog(
6706                language_server_id,
6707                log_type,
6708                message,
6709            ));
6710        })
6711    }
6712
6713    pub fn disk_based_diagnostics_started(
6714        &mut self,
6715        language_server_id: LanguageServerId,
6716        cx: &mut Context<Self>,
6717    ) {
6718        if let Some(language_server_status) =
6719            self.language_server_statuses.get_mut(&language_server_id)
6720        {
6721            language_server_status.has_pending_diagnostic_updates = true;
6722        }
6723
6724        cx.emit(LspStoreEvent::DiskBasedDiagnosticsStarted { language_server_id });
6725        cx.emit(LspStoreEvent::LanguageServerUpdate {
6726            language_server_id,
6727            message: proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(
6728                Default::default(),
6729            ),
6730        })
6731    }
6732
6733    pub fn disk_based_diagnostics_finished(
6734        &mut self,
6735        language_server_id: LanguageServerId,
6736        cx: &mut Context<Self>,
6737    ) {
6738        if let Some(language_server_status) =
6739            self.language_server_statuses.get_mut(&language_server_id)
6740        {
6741            language_server_status.has_pending_diagnostic_updates = false;
6742        }
6743
6744        cx.emit(LspStoreEvent::DiskBasedDiagnosticsFinished { language_server_id });
6745        cx.emit(LspStoreEvent::LanguageServerUpdate {
6746            language_server_id,
6747            message: proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
6748                Default::default(),
6749            ),
6750        })
6751    }
6752
6753    // After saving a buffer using a language server that doesn't provide a disk-based progress token,
6754    // kick off a timer that will reset every time the buffer is saved. If the timer eventually fires,
6755    // simulate disk-based diagnostics being finished so that other pieces of UI (e.g., project
6756    // diagnostics view, diagnostic status bar) can update. We don't emit an event right away because
6757    // the language server might take some time to publish diagnostics.
6758    fn simulate_disk_based_diagnostics_events_if_needed(
6759        &mut self,
6760        language_server_id: LanguageServerId,
6761        cx: &mut Context<Self>,
6762    ) {
6763        const DISK_BASED_DIAGNOSTICS_DEBOUNCE: Duration = Duration::from_secs(1);
6764
6765        let Some(LanguageServerState::Running {
6766            simulate_disk_based_diagnostics_completion,
6767            adapter,
6768            ..
6769        }) = self
6770            .as_local_mut()
6771            .and_then(|local_store| local_store.language_servers.get_mut(&language_server_id))
6772        else {
6773            return;
6774        };
6775
6776        if adapter.disk_based_diagnostics_progress_token.is_some() {
6777            return;
6778        }
6779
6780        let prev_task =
6781            simulate_disk_based_diagnostics_completion.replace(cx.spawn(async move |this, cx| {
6782                cx.background_executor()
6783                    .timer(DISK_BASED_DIAGNOSTICS_DEBOUNCE)
6784                    .await;
6785
6786                this.update(cx, |this, cx| {
6787                    this.disk_based_diagnostics_finished(language_server_id, cx);
6788
6789                    if let Some(LanguageServerState::Running {
6790                        simulate_disk_based_diagnostics_completion,
6791                        ..
6792                    }) = this.as_local_mut().and_then(|local_store| {
6793                        local_store.language_servers.get_mut(&language_server_id)
6794                    }) {
6795                        *simulate_disk_based_diagnostics_completion = None;
6796                    }
6797                })
6798                .ok();
6799            }));
6800
6801        if prev_task.is_none() {
6802            self.disk_based_diagnostics_started(language_server_id, cx);
6803        }
6804    }
6805
6806    pub fn language_server_statuses(
6807        &self,
6808    ) -> impl DoubleEndedIterator<Item = (LanguageServerId, &LanguageServerStatus)> {
6809        self.language_server_statuses
6810            .iter()
6811            .map(|(key, value)| (*key, value))
6812    }
6813
6814    pub(super) fn did_rename_entry(
6815        &self,
6816        worktree_id: WorktreeId,
6817        old_path: &Path,
6818        new_path: &Path,
6819        is_dir: bool,
6820    ) {
6821        maybe!({
6822            let local_store = self.as_local()?;
6823
6824            let old_uri = lsp::Url::from_file_path(old_path).ok().map(String::from)?;
6825            let new_uri = lsp::Url::from_file_path(new_path).ok().map(String::from)?;
6826
6827            for language_server in local_store.language_servers_for_worktree(worktree_id) {
6828                let Some(filter) = local_store
6829                    .language_server_paths_watched_for_rename
6830                    .get(&language_server.server_id())
6831                else {
6832                    continue;
6833                };
6834
6835                if filter.should_send_did_rename(&old_uri, is_dir) {
6836                    language_server
6837                        .notify::<DidRenameFiles>(&RenameFilesParams {
6838                            files: vec![FileRename {
6839                                old_uri: old_uri.clone(),
6840                                new_uri: new_uri.clone(),
6841                            }],
6842                        })
6843                        .log_err();
6844                }
6845            }
6846            Some(())
6847        });
6848    }
6849
6850    pub(super) fn will_rename_entry(
6851        this: WeakEntity<Self>,
6852        worktree_id: WorktreeId,
6853        old_path: &Path,
6854        new_path: &Path,
6855        is_dir: bool,
6856        cx: AsyncApp,
6857    ) -> Task<()> {
6858        let old_uri = lsp::Url::from_file_path(old_path).ok().map(String::from);
6859        let new_uri = lsp::Url::from_file_path(new_path).ok().map(String::from);
6860        cx.spawn(async move |cx| {
6861            let mut tasks = vec![];
6862            this.update(cx, |this, cx| {
6863                let local_store = this.as_local()?;
6864                let old_uri = old_uri?;
6865                let new_uri = new_uri?;
6866                for language_server in local_store.language_servers_for_worktree(worktree_id) {
6867                    let Some(filter) = local_store
6868                        .language_server_paths_watched_for_rename
6869                        .get(&language_server.server_id())
6870                    else {
6871                        continue;
6872                    };
6873                    let Some(adapter) =
6874                        this.language_server_adapter_for_id(language_server.server_id())
6875                    else {
6876                        continue;
6877                    };
6878                    if filter.should_send_will_rename(&old_uri, is_dir) {
6879                        let apply_edit = cx.spawn({
6880                            let old_uri = old_uri.clone();
6881                            let new_uri = new_uri.clone();
6882                            let language_server = language_server.clone();
6883                            async move |this, cx| {
6884                                let edit = language_server
6885                                    .request::<WillRenameFiles>(RenameFilesParams {
6886                                        files: vec![FileRename { old_uri, new_uri }],
6887                                    })
6888                                    .log_err()
6889                                    .await
6890                                    .flatten()?;
6891
6892                                LocalLspStore::deserialize_workspace_edit(
6893                                    this.upgrade()?,
6894                                    edit,
6895                                    false,
6896                                    adapter.clone(),
6897                                    language_server.clone(),
6898                                    cx,
6899                                )
6900                                .await
6901                                .ok();
6902                                Some(())
6903                            }
6904                        });
6905                        tasks.push(apply_edit);
6906                    }
6907                }
6908                Some(())
6909            })
6910            .ok()
6911            .flatten();
6912            for task in tasks {
6913                // Await on tasks sequentially so that the order of application of edits is deterministic
6914                // (at least with regards to the order of registration of language servers)
6915                task.await;
6916            }
6917        })
6918    }
6919
6920    fn lsp_notify_abs_paths_changed(
6921        &mut self,
6922        server_id: LanguageServerId,
6923        changes: Vec<PathEvent>,
6924    ) {
6925        maybe!({
6926            let server = self.language_server_for_id(server_id)?;
6927            let changes = changes
6928                .into_iter()
6929                .filter_map(|event| {
6930                    let typ = match event.kind? {
6931                        PathEventKind::Created => lsp::FileChangeType::CREATED,
6932                        PathEventKind::Removed => lsp::FileChangeType::DELETED,
6933                        PathEventKind::Changed => lsp::FileChangeType::CHANGED,
6934                    };
6935                    Some(lsp::FileEvent {
6936                        uri: lsp::Url::from_file_path(&event.path).ok()?,
6937                        typ,
6938                    })
6939                })
6940                .collect::<Vec<_>>();
6941            if !changes.is_empty() {
6942                server
6943                    .notify::<lsp::notification::DidChangeWatchedFiles>(
6944                        &lsp::DidChangeWatchedFilesParams { changes },
6945                    )
6946                    .log_err();
6947            }
6948            Some(())
6949        });
6950    }
6951
6952    pub fn language_server_for_id(&self, id: LanguageServerId) -> Option<Arc<LanguageServer>> {
6953        let local_lsp_store = self.as_local()?;
6954        if let Some(LanguageServerState::Running { server, .. }) =
6955            local_lsp_store.language_servers.get(&id)
6956        {
6957            Some(server.clone())
6958        } else if let Some((_, server)) = local_lsp_store.supplementary_language_servers.get(&id) {
6959            Some(Arc::clone(server))
6960        } else {
6961            None
6962        }
6963    }
6964
6965    fn on_lsp_progress(
6966        &mut self,
6967        progress: lsp::ProgressParams,
6968        language_server_id: LanguageServerId,
6969        disk_based_diagnostics_progress_token: Option<String>,
6970        cx: &mut Context<Self>,
6971    ) {
6972        let token = match progress.token {
6973            lsp::NumberOrString::String(token) => token,
6974            lsp::NumberOrString::Number(token) => {
6975                log::info!("skipping numeric progress token {}", token);
6976                return;
6977            }
6978        };
6979
6980        let lsp::ProgressParamsValue::WorkDone(progress) = progress.value;
6981        let language_server_status =
6982            if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
6983                status
6984            } else {
6985                return;
6986            };
6987
6988        if !language_server_status.progress_tokens.contains(&token) {
6989            return;
6990        }
6991
6992        let is_disk_based_diagnostics_progress = disk_based_diagnostics_progress_token
6993            .as_ref()
6994            .map_or(false, |disk_based_token| {
6995                token.starts_with(disk_based_token)
6996            });
6997
6998        match progress {
6999            lsp::WorkDoneProgress::Begin(report) => {
7000                if is_disk_based_diagnostics_progress {
7001                    self.disk_based_diagnostics_started(language_server_id, cx);
7002                }
7003                self.on_lsp_work_start(
7004                    language_server_id,
7005                    token.clone(),
7006                    LanguageServerProgress {
7007                        title: Some(report.title),
7008                        is_disk_based_diagnostics_progress,
7009                        is_cancellable: report.cancellable.unwrap_or(false),
7010                        message: report.message.clone(),
7011                        percentage: report.percentage.map(|p| p as usize),
7012                        last_update_at: cx.background_executor().now(),
7013                    },
7014                    cx,
7015                );
7016            }
7017            lsp::WorkDoneProgress::Report(report) => self.on_lsp_work_progress(
7018                language_server_id,
7019                token,
7020                LanguageServerProgress {
7021                    title: None,
7022                    is_disk_based_diagnostics_progress,
7023                    is_cancellable: report.cancellable.unwrap_or(false),
7024                    message: report.message,
7025                    percentage: report.percentage.map(|p| p as usize),
7026                    last_update_at: cx.background_executor().now(),
7027                },
7028                cx,
7029            ),
7030            lsp::WorkDoneProgress::End(_) => {
7031                language_server_status.progress_tokens.remove(&token);
7032                self.on_lsp_work_end(language_server_id, token.clone(), cx);
7033                if is_disk_based_diagnostics_progress {
7034                    self.disk_based_diagnostics_finished(language_server_id, cx);
7035                }
7036            }
7037        }
7038    }
7039
7040    fn on_lsp_work_start(
7041        &mut self,
7042        language_server_id: LanguageServerId,
7043        token: String,
7044        progress: LanguageServerProgress,
7045        cx: &mut Context<Self>,
7046    ) {
7047        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
7048            status.pending_work.insert(token.clone(), progress.clone());
7049            cx.notify();
7050        }
7051        cx.emit(LspStoreEvent::LanguageServerUpdate {
7052            language_server_id,
7053            message: proto::update_language_server::Variant::WorkStart(proto::LspWorkStart {
7054                token,
7055                title: progress.title,
7056                message: progress.message,
7057                percentage: progress.percentage.map(|p| p as u32),
7058                is_cancellable: Some(progress.is_cancellable),
7059            }),
7060        })
7061    }
7062
7063    fn on_lsp_work_progress(
7064        &mut self,
7065        language_server_id: LanguageServerId,
7066        token: String,
7067        progress: LanguageServerProgress,
7068        cx: &mut Context<Self>,
7069    ) {
7070        let mut did_update = false;
7071        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
7072            match status.pending_work.entry(token.clone()) {
7073                btree_map::Entry::Vacant(entry) => {
7074                    entry.insert(progress.clone());
7075                    did_update = true;
7076                }
7077                btree_map::Entry::Occupied(mut entry) => {
7078                    let entry = entry.get_mut();
7079                    if (progress.last_update_at - entry.last_update_at)
7080                        >= SERVER_PROGRESS_THROTTLE_TIMEOUT
7081                    {
7082                        entry.last_update_at = progress.last_update_at;
7083                        if progress.message.is_some() {
7084                            entry.message = progress.message.clone();
7085                        }
7086                        if progress.percentage.is_some() {
7087                            entry.percentage = progress.percentage;
7088                        }
7089                        if progress.is_cancellable != entry.is_cancellable {
7090                            entry.is_cancellable = progress.is_cancellable;
7091                        }
7092                        did_update = true;
7093                    }
7094                }
7095            }
7096        }
7097
7098        if did_update {
7099            cx.emit(LspStoreEvent::LanguageServerUpdate {
7100                language_server_id,
7101                message: proto::update_language_server::Variant::WorkProgress(
7102                    proto::LspWorkProgress {
7103                        token,
7104                        message: progress.message,
7105                        percentage: progress.percentage.map(|p| p as u32),
7106                        is_cancellable: Some(progress.is_cancellable),
7107                    },
7108                ),
7109            })
7110        }
7111    }
7112
7113    fn on_lsp_work_end(
7114        &mut self,
7115        language_server_id: LanguageServerId,
7116        token: String,
7117        cx: &mut Context<Self>,
7118    ) {
7119        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
7120            if let Some(work) = status.pending_work.remove(&token) {
7121                if !work.is_disk_based_diagnostics_progress {
7122                    cx.emit(LspStoreEvent::RefreshInlayHints);
7123                }
7124            }
7125            cx.notify();
7126        }
7127
7128        cx.emit(LspStoreEvent::LanguageServerUpdate {
7129            language_server_id,
7130            message: proto::update_language_server::Variant::WorkEnd(proto::LspWorkEnd { token }),
7131        })
7132    }
7133
7134    pub async fn handle_resolve_completion_documentation(
7135        this: Entity<Self>,
7136        envelope: TypedEnvelope<proto::ResolveCompletionDocumentation>,
7137        mut cx: AsyncApp,
7138    ) -> Result<proto::ResolveCompletionDocumentationResponse> {
7139        let lsp_completion = serde_json::from_slice(&envelope.payload.lsp_completion)?;
7140
7141        let completion = this
7142            .read_with(&cx, |this, cx| {
7143                let id = LanguageServerId(envelope.payload.language_server_id as usize);
7144                let Some(server) = this.language_server_for_id(id) else {
7145                    return Err(anyhow!("No language server {id}"));
7146                };
7147
7148                Ok(cx.background_spawn(async move {
7149                    let can_resolve = server
7150                        .capabilities()
7151                        .completion_provider
7152                        .as_ref()
7153                        .and_then(|options| options.resolve_provider)
7154                        .unwrap_or(false);
7155                    if can_resolve {
7156                        server
7157                            .request::<lsp::request::ResolveCompletionItem>(lsp_completion)
7158                            .await
7159                    } else {
7160                        anyhow::Ok(lsp_completion)
7161                    }
7162                }))
7163            })??
7164            .await?;
7165
7166        let mut documentation_is_markdown = false;
7167        let lsp_completion = serde_json::to_string(&completion)?.into_bytes();
7168        let documentation = match completion.documentation {
7169            Some(lsp::Documentation::String(text)) => text,
7170
7171            Some(lsp::Documentation::MarkupContent(lsp::MarkupContent { kind, value })) => {
7172                documentation_is_markdown = kind == lsp::MarkupKind::Markdown;
7173                value
7174            }
7175
7176            _ => String::new(),
7177        };
7178
7179        // If we have a new buffer_id, that means we're talking to a new client
7180        // and want to check for new text_edits in the completion too.
7181        let mut old_start = None;
7182        let mut old_end = None;
7183        let mut new_text = String::default();
7184        if let Ok(buffer_id) = BufferId::new(envelope.payload.buffer_id) {
7185            let buffer_snapshot = this.update(&mut cx, |this, cx| {
7186                let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
7187                anyhow::Ok(buffer.read(cx).snapshot())
7188            })??;
7189
7190            if let Some(text_edit) = completion.text_edit.as_ref() {
7191                let edit = parse_completion_text_edit(text_edit, &buffer_snapshot);
7192
7193                if let Some((old_range, mut text_edit_new_text)) = edit {
7194                    LineEnding::normalize(&mut text_edit_new_text);
7195
7196                    new_text = text_edit_new_text;
7197                    old_start = Some(serialize_anchor(&old_range.start));
7198                    old_end = Some(serialize_anchor(&old_range.end));
7199                }
7200            }
7201        }
7202
7203        Ok(proto::ResolveCompletionDocumentationResponse {
7204            documentation,
7205            documentation_is_markdown,
7206            old_start,
7207            old_end,
7208            new_text,
7209            lsp_completion,
7210        })
7211    }
7212
7213    async fn handle_on_type_formatting(
7214        this: Entity<Self>,
7215        envelope: TypedEnvelope<proto::OnTypeFormatting>,
7216        mut cx: AsyncApp,
7217    ) -> Result<proto::OnTypeFormattingResponse> {
7218        let on_type_formatting = this.update(&mut cx, |this, cx| {
7219            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
7220            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
7221            let position = envelope
7222                .payload
7223                .position
7224                .and_then(deserialize_anchor)
7225                .ok_or_else(|| anyhow!("invalid position"))?;
7226            Ok::<_, anyhow::Error>(this.apply_on_type_formatting(
7227                buffer,
7228                position,
7229                envelope.payload.trigger.clone(),
7230                cx,
7231            ))
7232        })??;
7233
7234        let transaction = on_type_formatting
7235            .await?
7236            .as_ref()
7237            .map(language::proto::serialize_transaction);
7238        Ok(proto::OnTypeFormattingResponse { transaction })
7239    }
7240
7241    async fn handle_refresh_inlay_hints(
7242        this: Entity<Self>,
7243        _: TypedEnvelope<proto::RefreshInlayHints>,
7244        mut cx: AsyncApp,
7245    ) -> Result<proto::Ack> {
7246        this.update(&mut cx, |_, cx| {
7247            cx.emit(LspStoreEvent::RefreshInlayHints);
7248        })?;
7249        Ok(proto::Ack {})
7250    }
7251
7252    async fn handle_inlay_hints(
7253        this: Entity<Self>,
7254        envelope: TypedEnvelope<proto::InlayHints>,
7255        mut cx: AsyncApp,
7256    ) -> Result<proto::InlayHintsResponse> {
7257        let sender_id = envelope.original_sender_id().unwrap_or_default();
7258        let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
7259        let buffer = this.update(&mut cx, |this, cx| {
7260            this.buffer_store.read(cx).get_existing(buffer_id)
7261        })??;
7262        buffer
7263            .update(&mut cx, |buffer, _| {
7264                buffer.wait_for_version(deserialize_version(&envelope.payload.version))
7265            })?
7266            .await
7267            .with_context(|| format!("waiting for version for buffer {}", buffer.entity_id()))?;
7268
7269        let start = envelope
7270            .payload
7271            .start
7272            .and_then(deserialize_anchor)
7273            .context("missing range start")?;
7274        let end = envelope
7275            .payload
7276            .end
7277            .and_then(deserialize_anchor)
7278            .context("missing range end")?;
7279        let buffer_hints = this
7280            .update(&mut cx, |lsp_store, cx| {
7281                lsp_store.inlay_hints(buffer.clone(), start..end, cx)
7282            })?
7283            .await
7284            .context("inlay hints fetch")?;
7285
7286        this.update(&mut cx, |project, cx| {
7287            InlayHints::response_to_proto(
7288                buffer_hints,
7289                project,
7290                sender_id,
7291                &buffer.read(cx).version(),
7292                cx,
7293            )
7294        })
7295    }
7296
7297    async fn handle_resolve_inlay_hint(
7298        this: Entity<Self>,
7299        envelope: TypedEnvelope<proto::ResolveInlayHint>,
7300        mut cx: AsyncApp,
7301    ) -> Result<proto::ResolveInlayHintResponse> {
7302        let proto_hint = envelope
7303            .payload
7304            .hint
7305            .expect("incorrect protobuf resolve inlay hint message: missing the inlay hint");
7306        let hint = InlayHints::proto_to_project_hint(proto_hint)
7307            .context("resolved proto inlay hint conversion")?;
7308        let buffer = this.update(&mut cx, |this, cx| {
7309            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
7310            this.buffer_store.read(cx).get_existing(buffer_id)
7311        })??;
7312        let response_hint = this
7313            .update(&mut cx, |this, cx| {
7314                this.resolve_inlay_hint(
7315                    hint,
7316                    buffer,
7317                    LanguageServerId(envelope.payload.language_server_id as usize),
7318                    cx,
7319                )
7320            })?
7321            .await
7322            .context("inlay hints fetch")?;
7323        Ok(proto::ResolveInlayHintResponse {
7324            hint: Some(InlayHints::project_to_proto_hint(response_hint)),
7325        })
7326    }
7327
7328    async fn handle_refresh_code_lens(
7329        this: Entity<Self>,
7330        _: TypedEnvelope<proto::RefreshCodeLens>,
7331        mut cx: AsyncApp,
7332    ) -> Result<proto::Ack> {
7333        this.update(&mut cx, |_, cx| {
7334            cx.emit(LspStoreEvent::RefreshCodeLens);
7335        })?;
7336        Ok(proto::Ack {})
7337    }
7338
7339    async fn handle_open_buffer_for_symbol(
7340        this: Entity<Self>,
7341        envelope: TypedEnvelope<proto::OpenBufferForSymbol>,
7342        mut cx: AsyncApp,
7343    ) -> Result<proto::OpenBufferForSymbolResponse> {
7344        let peer_id = envelope.original_sender_id().unwrap_or_default();
7345        let symbol = envelope
7346            .payload
7347            .symbol
7348            .ok_or_else(|| anyhow!("invalid symbol"))?;
7349        let symbol = Self::deserialize_symbol(symbol)?;
7350        let symbol = this.update(&mut cx, |this, _| {
7351            let signature = this.symbol_signature(&symbol.path);
7352            if signature == symbol.signature {
7353                Ok(symbol)
7354            } else {
7355                Err(anyhow!("invalid symbol signature"))
7356            }
7357        })??;
7358        let buffer = this
7359            .update(&mut cx, |this, cx| {
7360                this.open_buffer_for_symbol(
7361                    &Symbol {
7362                        language_server_name: symbol.language_server_name,
7363                        source_worktree_id: symbol.source_worktree_id,
7364                        source_language_server_id: symbol.source_language_server_id,
7365                        path: symbol.path,
7366                        name: symbol.name,
7367                        kind: symbol.kind,
7368                        range: symbol.range,
7369                        signature: symbol.signature,
7370                        label: CodeLabel {
7371                            text: Default::default(),
7372                            runs: Default::default(),
7373                            filter_range: Default::default(),
7374                        },
7375                    },
7376                    cx,
7377                )
7378            })?
7379            .await?;
7380
7381        this.update(&mut cx, |this, cx| {
7382            let is_private = buffer
7383                .read(cx)
7384                .file()
7385                .map(|f| f.is_private())
7386                .unwrap_or_default();
7387            if is_private {
7388                Err(anyhow!(rpc::ErrorCode::UnsharedItem))
7389            } else {
7390                this.buffer_store
7391                    .update(cx, |buffer_store, cx| {
7392                        buffer_store.create_buffer_for_peer(&buffer, peer_id, cx)
7393                    })
7394                    .detach_and_log_err(cx);
7395                let buffer_id = buffer.read(cx).remote_id().to_proto();
7396                Ok(proto::OpenBufferForSymbolResponse { buffer_id })
7397            }
7398        })?
7399    }
7400
7401    fn symbol_signature(&self, project_path: &ProjectPath) -> [u8; 32] {
7402        let mut hasher = Sha256::new();
7403        hasher.update(project_path.worktree_id.to_proto().to_be_bytes());
7404        hasher.update(project_path.path.to_string_lossy().as_bytes());
7405        hasher.update(self.nonce.to_be_bytes());
7406        hasher.finalize().as_slice().try_into().unwrap()
7407    }
7408
7409    pub async fn handle_get_project_symbols(
7410        this: Entity<Self>,
7411        envelope: TypedEnvelope<proto::GetProjectSymbols>,
7412        mut cx: AsyncApp,
7413    ) -> Result<proto::GetProjectSymbolsResponse> {
7414        let symbols = this
7415            .update(&mut cx, |this, cx| {
7416                this.symbols(&envelope.payload.query, cx)
7417            })?
7418            .await?;
7419
7420        Ok(proto::GetProjectSymbolsResponse {
7421            symbols: symbols.iter().map(Self::serialize_symbol).collect(),
7422        })
7423    }
7424
7425    pub async fn handle_restart_language_servers(
7426        this: Entity<Self>,
7427        envelope: TypedEnvelope<proto::RestartLanguageServers>,
7428        mut cx: AsyncApp,
7429    ) -> Result<proto::Ack> {
7430        this.update(&mut cx, |this, cx| {
7431            let buffers = this.buffer_ids_to_buffers(envelope.payload.buffer_ids.into_iter(), cx);
7432            this.restart_language_servers_for_buffers(buffers, cx);
7433        })?;
7434
7435        Ok(proto::Ack {})
7436    }
7437
7438    pub async fn handle_cancel_language_server_work(
7439        this: Entity<Self>,
7440        envelope: TypedEnvelope<proto::CancelLanguageServerWork>,
7441        mut cx: AsyncApp,
7442    ) -> Result<proto::Ack> {
7443        this.update(&mut cx, |this, cx| {
7444            if let Some(work) = envelope.payload.work {
7445                match work {
7446                    proto::cancel_language_server_work::Work::Buffers(buffers) => {
7447                        let buffers =
7448                            this.buffer_ids_to_buffers(buffers.buffer_ids.into_iter(), cx);
7449                        this.cancel_language_server_work_for_buffers(buffers, cx);
7450                    }
7451                    proto::cancel_language_server_work::Work::LanguageServerWork(work) => {
7452                        let server_id = LanguageServerId::from_proto(work.language_server_id);
7453                        this.cancel_language_server_work(server_id, work.token, cx);
7454                    }
7455                }
7456            }
7457        })?;
7458
7459        Ok(proto::Ack {})
7460    }
7461
7462    fn buffer_ids_to_buffers(
7463        &mut self,
7464        buffer_ids: impl Iterator<Item = u64>,
7465        cx: &mut Context<Self>,
7466    ) -> Vec<Entity<Buffer>> {
7467        buffer_ids
7468            .into_iter()
7469            .flat_map(|buffer_id| {
7470                self.buffer_store
7471                    .read(cx)
7472                    .get(BufferId::new(buffer_id).log_err()?)
7473            })
7474            .collect::<Vec<_>>()
7475    }
7476
7477    async fn handle_apply_additional_edits_for_completion(
7478        this: Entity<Self>,
7479        envelope: TypedEnvelope<proto::ApplyCompletionAdditionalEdits>,
7480        mut cx: AsyncApp,
7481    ) -> Result<proto::ApplyCompletionAdditionalEditsResponse> {
7482        let (buffer, completion) = this.update(&mut cx, |this, cx| {
7483            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
7484            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
7485            let completion = Self::deserialize_completion(
7486                envelope
7487                    .payload
7488                    .completion
7489                    .ok_or_else(|| anyhow!("invalid completion"))?,
7490            )?;
7491            anyhow::Ok((buffer, completion))
7492        })??;
7493
7494        let apply_additional_edits = this.update(&mut cx, |this, cx| {
7495            this.apply_additional_edits_for_completion(
7496                buffer,
7497                Rc::new(RefCell::new(Box::new([Completion {
7498                    old_range: completion.old_range,
7499                    new_text: completion.new_text,
7500                    source: completion.source,
7501                    documentation: None,
7502                    label: CodeLabel {
7503                        text: Default::default(),
7504                        runs: Default::default(),
7505                        filter_range: Default::default(),
7506                    },
7507                    confirm: None,
7508                }]))),
7509                0,
7510                false,
7511                cx,
7512            )
7513        })?;
7514
7515        Ok(proto::ApplyCompletionAdditionalEditsResponse {
7516            transaction: apply_additional_edits
7517                .await?
7518                .as_ref()
7519                .map(language::proto::serialize_transaction),
7520        })
7521    }
7522
7523    pub fn last_formatting_failure(&self) -> Option<&str> {
7524        self.last_formatting_failure.as_deref()
7525    }
7526
7527    pub fn reset_last_formatting_failure(&mut self) {
7528        self.last_formatting_failure = None;
7529    }
7530
7531    pub fn environment_for_buffer(
7532        &self,
7533        buffer: &Entity<Buffer>,
7534        cx: &mut Context<Self>,
7535    ) -> Shared<Task<Option<HashMap<String, String>>>> {
7536        let worktree_id = buffer.read(cx).file().map(|file| file.worktree_id(cx));
7537        let worktree_abs_path = worktree_id.and_then(|worktree_id| {
7538            self.worktree_store
7539                .read(cx)
7540                .worktree_for_id(worktree_id, cx)
7541                .map(|entry| entry.read(cx).abs_path().clone())
7542        });
7543
7544        if let Some(environment) = &self.as_local().map(|local| local.environment.clone()) {
7545            environment.update(cx, |env, cx| {
7546                env.get_environment(worktree_id, worktree_abs_path, cx)
7547            })
7548        } else {
7549            Task::ready(None).shared()
7550        }
7551    }
7552
7553    pub fn format(
7554        &mut self,
7555        buffers: HashSet<Entity<Buffer>>,
7556        target: LspFormatTarget,
7557        push_to_history: bool,
7558        trigger: FormatTrigger,
7559        cx: &mut Context<Self>,
7560    ) -> Task<anyhow::Result<ProjectTransaction>> {
7561        if let Some(_) = self.as_local() {
7562            let buffers = buffers
7563                .into_iter()
7564                .map(|buffer_handle| {
7565                    let buffer = buffer_handle.read(cx);
7566                    let buffer_abs_path = File::from_dyn(buffer.file())
7567                        .and_then(|file| file.as_local().map(|f| f.abs_path(cx)));
7568
7569                    (buffer_handle, buffer_abs_path, buffer.remote_id())
7570                })
7571                .collect::<Vec<_>>();
7572
7573            cx.spawn(async move |lsp_store, cx| {
7574                let mut formattable_buffers = Vec::with_capacity(buffers.len());
7575
7576                for (handle, abs_path, id) in buffers {
7577                    let env = lsp_store
7578                        .update(cx, |lsp_store, cx| {
7579                            lsp_store.environment_for_buffer(&handle, cx)
7580                        })?
7581                        .await;
7582
7583                    let ranges = match &target {
7584                        LspFormatTarget::Buffers => None,
7585                        LspFormatTarget::Ranges(ranges) => {
7586                            let Some(ranges) = ranges.get(&id) else {
7587                                return Err(anyhow!("No format ranges provided for buffer"));
7588                            };
7589                            Some(ranges.clone())
7590                        }
7591                    };
7592
7593                    formattable_buffers.push(FormattableBuffer {
7594                        handle,
7595                        abs_path,
7596                        env,
7597                        ranges,
7598                    });
7599                }
7600
7601                let result = LocalLspStore::format_locally(
7602                    lsp_store.clone(),
7603                    formattable_buffers,
7604                    push_to_history,
7605                    trigger,
7606                    cx,
7607                )
7608                .await;
7609                lsp_store.update(cx, |lsp_store, _| {
7610                    lsp_store.update_last_formatting_failure(&result);
7611                })?;
7612
7613                result
7614            })
7615        } else if let Some((client, project_id)) = self.upstream_client() {
7616            // Don't support formatting ranges via remote
7617            match target {
7618                LspFormatTarget::Buffers => {}
7619                LspFormatTarget::Ranges(_) => {
7620                    return Task::ready(Ok(ProjectTransaction::default()));
7621                }
7622            }
7623
7624            let buffer_store = self.buffer_store();
7625            cx.spawn(async move |lsp_store, cx| {
7626                let result = client
7627                    .request(proto::FormatBuffers {
7628                        project_id,
7629                        trigger: trigger as i32,
7630                        buffer_ids: buffers
7631                            .iter()
7632                            .map(|buffer| buffer.update(cx, |buffer, _| buffer.remote_id().into()))
7633                            .collect::<Result<_>>()?,
7634                    })
7635                    .await
7636                    .and_then(|result| result.transaction.context("missing transaction"));
7637
7638                lsp_store.update(cx, |lsp_store, _| {
7639                    lsp_store.update_last_formatting_failure(&result);
7640                })?;
7641
7642                let transaction_response = result?;
7643                buffer_store
7644                    .update(cx, |buffer_store, cx| {
7645                        buffer_store.deserialize_project_transaction(
7646                            transaction_response,
7647                            push_to_history,
7648                            cx,
7649                        )
7650                    })?
7651                    .await
7652            })
7653        } else {
7654            Task::ready(Ok(ProjectTransaction::default()))
7655        }
7656    }
7657
7658    async fn handle_format_buffers(
7659        this: Entity<Self>,
7660        envelope: TypedEnvelope<proto::FormatBuffers>,
7661        mut cx: AsyncApp,
7662    ) -> Result<proto::FormatBuffersResponse> {
7663        let sender_id = envelope.original_sender_id().unwrap_or_default();
7664        let format = this.update(&mut cx, |this, cx| {
7665            let mut buffers = HashSet::default();
7666            for buffer_id in &envelope.payload.buffer_ids {
7667                let buffer_id = BufferId::new(*buffer_id)?;
7668                buffers.insert(this.buffer_store.read(cx).get_existing(buffer_id)?);
7669            }
7670            let trigger = FormatTrigger::from_proto(envelope.payload.trigger);
7671            anyhow::Ok(this.format(buffers, LspFormatTarget::Buffers, false, trigger, cx))
7672        })??;
7673
7674        let project_transaction = format.await?;
7675        let project_transaction = this.update(&mut cx, |this, cx| {
7676            this.buffer_store.update(cx, |buffer_store, cx| {
7677                buffer_store.serialize_project_transaction_for_peer(
7678                    project_transaction,
7679                    sender_id,
7680                    cx,
7681                )
7682            })
7683        })?;
7684        Ok(proto::FormatBuffersResponse {
7685            transaction: Some(project_transaction),
7686        })
7687    }
7688
7689    async fn handle_apply_code_action_kind(
7690        this: Entity<Self>,
7691        envelope: TypedEnvelope<proto::ApplyCodeActionKind>,
7692        mut cx: AsyncApp,
7693    ) -> Result<proto::ApplyCodeActionKindResponse> {
7694        let sender_id = envelope.original_sender_id().unwrap_or_default();
7695        let format = this.update(&mut cx, |this, cx| {
7696            let mut buffers = HashSet::default();
7697            for buffer_id in &envelope.payload.buffer_ids {
7698                let buffer_id = BufferId::new(*buffer_id)?;
7699                buffers.insert(this.buffer_store.read(cx).get_existing(buffer_id)?);
7700            }
7701            let kind = match envelope.payload.kind.as_str() {
7702                "" => Ok(CodeActionKind::EMPTY),
7703                "quickfix" => Ok(CodeActionKind::QUICKFIX),
7704                "refactor" => Ok(CodeActionKind::REFACTOR),
7705                "refactor.extract" => Ok(CodeActionKind::REFACTOR_EXTRACT),
7706                "refactor.inline" => Ok(CodeActionKind::REFACTOR_INLINE),
7707                "refactor.rewrite" => Ok(CodeActionKind::REFACTOR_REWRITE),
7708                "source" => Ok(CodeActionKind::SOURCE),
7709                "source.organizeImports" => Ok(CodeActionKind::SOURCE_ORGANIZE_IMPORTS),
7710                "source.fixAll" => Ok(CodeActionKind::SOURCE_FIX_ALL),
7711                _ => Err(anyhow!("Invalid code action kind")),
7712            }?;
7713            anyhow::Ok(this.apply_code_action_kind(buffers, kind, false, cx))
7714        })??;
7715
7716        let project_transaction = format.await?;
7717        let project_transaction = this.update(&mut cx, |this, cx| {
7718            this.buffer_store.update(cx, |buffer_store, cx| {
7719                buffer_store.serialize_project_transaction_for_peer(
7720                    project_transaction,
7721                    sender_id,
7722                    cx,
7723                )
7724            })
7725        })?;
7726        Ok(proto::ApplyCodeActionKindResponse {
7727            transaction: Some(project_transaction),
7728        })
7729    }
7730
7731    async fn shutdown_language_server(
7732        server_state: Option<LanguageServerState>,
7733        name: LanguageServerName,
7734        cx: &mut AsyncApp,
7735    ) {
7736        let server = match server_state {
7737            Some(LanguageServerState::Starting { startup, .. }) => {
7738                let mut timer = cx
7739                    .background_executor()
7740                    .timer(SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT)
7741                    .fuse();
7742
7743                select! {
7744                    server = startup.fuse() => server,
7745                    _ = timer => {
7746                        log::info!(
7747                            "timeout waiting for language server {} to finish launching before stopping",
7748                            name
7749                        );
7750                        None
7751                    },
7752                }
7753            }
7754
7755            Some(LanguageServerState::Running { server, .. }) => Some(server),
7756
7757            None => None,
7758        };
7759
7760        if let Some(server) = server {
7761            if let Some(shutdown) = server.shutdown() {
7762                shutdown.await;
7763            }
7764        }
7765    }
7766
7767    // Returns a list of all of the worktrees which no longer have a language server and the root path
7768    // for the stopped server
7769    fn stop_local_language_server(
7770        &mut self,
7771        server_id: LanguageServerId,
7772        name: LanguageServerName,
7773        cx: &mut Context<Self>,
7774    ) -> Task<Vec<WorktreeId>> {
7775        let local = match &mut self.mode {
7776            LspStoreMode::Local(local) => local,
7777            _ => {
7778                return Task::ready(Vec::new());
7779            }
7780        };
7781
7782        let mut orphaned_worktrees = vec![];
7783        // Remove this server ID from all entries in the given worktree.
7784        local.language_server_ids.retain(|(worktree, _), ids| {
7785            if !ids.remove(&server_id) {
7786                return true;
7787            }
7788
7789            if ids.is_empty() {
7790                orphaned_worktrees.push(*worktree);
7791                false
7792            } else {
7793                true
7794            }
7795        });
7796        let _ = self.language_server_statuses.remove(&server_id);
7797        log::info!("stopping language server {name}");
7798        self.buffer_store.update(cx, |buffer_store, cx| {
7799            for buffer in buffer_store.buffers() {
7800                buffer.update(cx, |buffer, cx| {
7801                    buffer.update_diagnostics(server_id, DiagnosticSet::new([], buffer), cx);
7802                    buffer.set_completion_triggers(server_id, Default::default(), cx);
7803                });
7804            }
7805        });
7806
7807        for (worktree_id, summaries) in self.diagnostic_summaries.iter_mut() {
7808            summaries.retain(|path, summaries_by_server_id| {
7809                if summaries_by_server_id.remove(&server_id).is_some() {
7810                    if let Some((client, project_id)) = self.downstream_client.clone() {
7811                        client
7812                            .send(proto::UpdateDiagnosticSummary {
7813                                project_id,
7814                                worktree_id: worktree_id.to_proto(),
7815                                summary: Some(proto::DiagnosticSummary {
7816                                    path: path.as_ref().to_proto(),
7817                                    language_server_id: server_id.0 as u64,
7818                                    error_count: 0,
7819                                    warning_count: 0,
7820                                }),
7821                            })
7822                            .log_err();
7823                    }
7824                    !summaries_by_server_id.is_empty()
7825                } else {
7826                    true
7827                }
7828            });
7829        }
7830
7831        let local = self.as_local_mut().unwrap();
7832        for diagnostics in local.diagnostics.values_mut() {
7833            diagnostics.retain(|_, diagnostics_by_server_id| {
7834                if let Ok(ix) = diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0) {
7835                    diagnostics_by_server_id.remove(ix);
7836                    !diagnostics_by_server_id.is_empty()
7837                } else {
7838                    true
7839                }
7840            });
7841        }
7842        local.language_server_watched_paths.remove(&server_id);
7843        let server_state = local.language_servers.remove(&server_id);
7844        cx.notify();
7845        cx.emit(LspStoreEvent::LanguageServerRemoved(server_id));
7846        cx.spawn(async move |_, cx| {
7847            Self::shutdown_language_server(server_state, name, cx).await;
7848            orphaned_worktrees
7849        })
7850    }
7851
7852    pub fn restart_language_servers_for_buffers(
7853        &mut self,
7854        buffers: Vec<Entity<Buffer>>,
7855        cx: &mut Context<Self>,
7856    ) {
7857        if let Some((client, project_id)) = self.upstream_client() {
7858            let request = client.request(proto::RestartLanguageServers {
7859                project_id,
7860                buffer_ids: buffers
7861                    .into_iter()
7862                    .map(|b| b.read(cx).remote_id().to_proto())
7863                    .collect(),
7864            });
7865            cx.background_spawn(request).detach_and_log_err(cx);
7866        } else {
7867            let Some(local) = self.as_local_mut() else {
7868                return;
7869            };
7870            let language_servers_to_stop = buffers
7871                .iter()
7872                .flat_map(|buffer| {
7873                    buffer.update(cx, |buffer, cx| {
7874                        local.language_server_ids_for_buffer(buffer, cx)
7875                    })
7876                })
7877                .collect::<BTreeSet<_>>();
7878            local.lsp_tree.update(cx, |this, _| {
7879                this.remove_nodes(&language_servers_to_stop);
7880            });
7881            let tasks = language_servers_to_stop
7882                .into_iter()
7883                .map(|server| {
7884                    let name = self
7885                        .language_server_statuses
7886                        .get(&server)
7887                        .map(|state| state.name.as_str().into())
7888                        .unwrap_or_else(|| LanguageServerName::from("Unknown"));
7889                    self.stop_local_language_server(server, name, cx)
7890                })
7891                .collect::<Vec<_>>();
7892
7893            cx.spawn(async move |this, cx| {
7894                cx.background_spawn(futures::future::join_all(tasks)).await;
7895                this.update(cx, |this, cx| {
7896                    for buffer in buffers {
7897                        this.register_buffer_with_language_servers(&buffer, true, cx);
7898                    }
7899                })
7900                .ok()
7901            })
7902            .detach();
7903        }
7904    }
7905
7906    pub fn update_diagnostics(
7907        &mut self,
7908        language_server_id: LanguageServerId,
7909        mut params: lsp::PublishDiagnosticsParams,
7910        disk_based_sources: &[String],
7911        cx: &mut Context<Self>,
7912    ) -> Result<()> {
7913        if !self.mode.is_local() {
7914            anyhow::bail!("called update_diagnostics on remote");
7915        }
7916        let abs_path = params
7917            .uri
7918            .to_file_path()
7919            .map_err(|_| anyhow!("URI is not a file"))?;
7920        let mut diagnostics = Vec::default();
7921        let mut primary_diagnostic_group_ids = HashMap::default();
7922        let mut sources_by_group_id = HashMap::default();
7923        let mut supporting_diagnostics = HashMap::default();
7924
7925        // Ensure that primary diagnostics are always the most severe
7926        params.diagnostics.sort_by_key(|item| item.severity);
7927
7928        for diagnostic in &params.diagnostics {
7929            let source = diagnostic.source.as_ref();
7930            let range = range_from_lsp(diagnostic.range);
7931            let is_supporting = diagnostic
7932                .related_information
7933                .as_ref()
7934                .map_or(false, |infos| {
7935                    infos.iter().any(|info| {
7936                        primary_diagnostic_group_ids.contains_key(&(
7937                            source,
7938                            diagnostic.code.clone(),
7939                            range_from_lsp(info.location.range),
7940                        ))
7941                    })
7942                });
7943
7944            let is_unnecessary = diagnostic.tags.as_ref().map_or(false, |tags| {
7945                tags.iter().any(|tag| *tag == DiagnosticTag::UNNECESSARY)
7946            });
7947
7948            if is_supporting {
7949                supporting_diagnostics.insert(
7950                    (source, diagnostic.code.clone(), range),
7951                    (diagnostic.severity, is_unnecessary),
7952                );
7953            } else {
7954                let group_id = post_inc(&mut self.as_local_mut().unwrap().next_diagnostic_group_id);
7955                let is_disk_based =
7956                    source.map_or(false, |source| disk_based_sources.contains(source));
7957
7958                sources_by_group_id.insert(group_id, source);
7959                primary_diagnostic_group_ids
7960                    .insert((source, diagnostic.code.clone(), range.clone()), group_id);
7961
7962                diagnostics.push(DiagnosticEntry {
7963                    range,
7964                    diagnostic: Diagnostic {
7965                        source: diagnostic.source.clone(),
7966                        code: diagnostic.code.clone(),
7967                        severity: diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR),
7968                        message: diagnostic.message.trim().to_string(),
7969                        group_id,
7970                        is_primary: true,
7971                        is_disk_based,
7972                        is_unnecessary,
7973                        data: diagnostic.data.clone(),
7974                    },
7975                });
7976                if let Some(infos) = &diagnostic.related_information {
7977                    for info in infos {
7978                        if info.location.uri == params.uri && !info.message.is_empty() {
7979                            let range = range_from_lsp(info.location.range);
7980                            diagnostics.push(DiagnosticEntry {
7981                                range,
7982                                diagnostic: Diagnostic {
7983                                    source: diagnostic.source.clone(),
7984                                    code: diagnostic.code.clone(),
7985                                    severity: DiagnosticSeverity::INFORMATION,
7986                                    message: info.message.trim().to_string(),
7987                                    group_id,
7988                                    is_primary: false,
7989                                    is_disk_based,
7990                                    is_unnecessary: false,
7991                                    data: diagnostic.data.clone(),
7992                                },
7993                            });
7994                        }
7995                    }
7996                }
7997            }
7998        }
7999
8000        for entry in &mut diagnostics {
8001            let diagnostic = &mut entry.diagnostic;
8002            if !diagnostic.is_primary {
8003                let source = *sources_by_group_id.get(&diagnostic.group_id).unwrap();
8004                if let Some(&(severity, is_unnecessary)) = supporting_diagnostics.get(&(
8005                    source,
8006                    diagnostic.code.clone(),
8007                    entry.range.clone(),
8008                )) {
8009                    if let Some(severity) = severity {
8010                        diagnostic.severity = severity;
8011                    }
8012                    diagnostic.is_unnecessary = is_unnecessary;
8013                }
8014            }
8015        }
8016
8017        self.update_diagnostic_entries(
8018            language_server_id,
8019            abs_path,
8020            params.version,
8021            diagnostics,
8022            cx,
8023        )?;
8024        Ok(())
8025    }
8026
8027    fn insert_newly_running_language_server(
8028        &mut self,
8029        adapter: Arc<CachedLspAdapter>,
8030        language_server: Arc<LanguageServer>,
8031        server_id: LanguageServerId,
8032        key: (WorktreeId, LanguageServerName),
8033        workspace_folders: Arc<Mutex<BTreeSet<Url>>>,
8034        cx: &mut Context<Self>,
8035    ) {
8036        let Some(local) = self.as_local_mut() else {
8037            return;
8038        };
8039        // If the language server for this key doesn't match the server id, don't store the
8040        // server. Which will cause it to be dropped, killing the process
8041        if local
8042            .language_server_ids
8043            .get(&key)
8044            .map(|ids| !ids.contains(&server_id))
8045            .unwrap_or(false)
8046        {
8047            return;
8048        }
8049
8050        // Update language_servers collection with Running variant of LanguageServerState
8051        // indicating that the server is up and running and ready
8052        let workspace_folders = workspace_folders.lock().clone();
8053        local.language_servers.insert(
8054            server_id,
8055            LanguageServerState::running(
8056                workspace_folders,
8057                adapter.clone(),
8058                language_server.clone(),
8059                None,
8060            ),
8061        );
8062        if let Some(file_ops_caps) = language_server
8063            .capabilities()
8064            .workspace
8065            .as_ref()
8066            .and_then(|ws| ws.file_operations.as_ref())
8067        {
8068            let did_rename_caps = file_ops_caps.did_rename.as_ref();
8069            let will_rename_caps = file_ops_caps.will_rename.as_ref();
8070            if did_rename_caps.or(will_rename_caps).is_some() {
8071                let watcher = RenamePathsWatchedForServer::default()
8072                    .with_did_rename_patterns(did_rename_caps)
8073                    .with_will_rename_patterns(will_rename_caps);
8074                local
8075                    .language_server_paths_watched_for_rename
8076                    .insert(server_id, watcher);
8077            }
8078        }
8079
8080        self.language_server_statuses.insert(
8081            server_id,
8082            LanguageServerStatus {
8083                name: language_server.name().to_string(),
8084                pending_work: Default::default(),
8085                has_pending_diagnostic_updates: false,
8086                progress_tokens: Default::default(),
8087            },
8088        );
8089
8090        cx.emit(LspStoreEvent::LanguageServerAdded(
8091            server_id,
8092            language_server.name(),
8093            Some(key.0),
8094        ));
8095        cx.emit(LspStoreEvent::RefreshInlayHints);
8096
8097        if let Some((downstream_client, project_id)) = self.downstream_client.as_ref() {
8098            downstream_client
8099                .send(proto::StartLanguageServer {
8100                    project_id: *project_id,
8101                    server: Some(proto::LanguageServer {
8102                        id: server_id.0 as u64,
8103                        name: language_server.name().to_string(),
8104                        worktree_id: Some(key.0.to_proto()),
8105                    }),
8106                })
8107                .log_err();
8108        }
8109
8110        // Tell the language server about every open buffer in the worktree that matches the language.
8111        self.buffer_store.clone().update(cx, |buffer_store, cx| {
8112            for buffer_handle in buffer_store.buffers() {
8113                let buffer = buffer_handle.read(cx);
8114                let file = match File::from_dyn(buffer.file()) {
8115                    Some(file) => file,
8116                    None => continue,
8117                };
8118                let language = match buffer.language() {
8119                    Some(language) => language,
8120                    None => continue,
8121                };
8122
8123                if file.worktree.read(cx).id() != key.0
8124                    || !self
8125                        .languages
8126                        .lsp_adapters(&language.name())
8127                        .iter()
8128                        .any(|a| a.name == key.1)
8129                {
8130                    continue;
8131                }
8132                // didOpen
8133                let file = match file.as_local() {
8134                    Some(file) => file,
8135                    None => continue,
8136                };
8137
8138                let local = self.as_local_mut().unwrap();
8139
8140                if local.registered_buffers.contains_key(&buffer.remote_id()) {
8141                    let versions = local
8142                        .buffer_snapshots
8143                        .entry(buffer.remote_id())
8144                        .or_default()
8145                        .entry(server_id)
8146                        .and_modify(|_| {
8147                            assert!(
8148                            false,
8149                            "There should not be an existing snapshot for a newly inserted buffer"
8150                        )
8151                        })
8152                        .or_insert_with(|| {
8153                            vec![LspBufferSnapshot {
8154                                version: 0,
8155                                snapshot: buffer.text_snapshot(),
8156                            }]
8157                        });
8158
8159                    let snapshot = versions.last().unwrap();
8160                    let version = snapshot.version;
8161                    let initial_snapshot = &snapshot.snapshot;
8162                    let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap();
8163                    language_server.register_buffer(
8164                        uri,
8165                        adapter.language_id(&language.name()),
8166                        version,
8167                        initial_snapshot.text(),
8168                    );
8169                }
8170                buffer_handle.update(cx, |buffer, cx| {
8171                    buffer.set_completion_triggers(
8172                        server_id,
8173                        language_server
8174                            .capabilities()
8175                            .completion_provider
8176                            .as_ref()
8177                            .and_then(|provider| {
8178                                provider
8179                                    .trigger_characters
8180                                    .as_ref()
8181                                    .map(|characters| characters.iter().cloned().collect())
8182                            })
8183                            .unwrap_or_default(),
8184                        cx,
8185                    )
8186                });
8187            }
8188        });
8189
8190        cx.notify();
8191    }
8192
8193    pub fn language_servers_running_disk_based_diagnostics(
8194        &self,
8195    ) -> impl Iterator<Item = LanguageServerId> + '_ {
8196        self.language_server_statuses
8197            .iter()
8198            .filter_map(|(id, status)| {
8199                if status.has_pending_diagnostic_updates {
8200                    Some(*id)
8201                } else {
8202                    None
8203                }
8204            })
8205    }
8206
8207    pub(crate) fn cancel_language_server_work_for_buffers(
8208        &mut self,
8209        buffers: impl IntoIterator<Item = Entity<Buffer>>,
8210        cx: &mut Context<Self>,
8211    ) {
8212        if let Some((client, project_id)) = self.upstream_client() {
8213            let request = client.request(proto::CancelLanguageServerWork {
8214                project_id,
8215                work: Some(proto::cancel_language_server_work::Work::Buffers(
8216                    proto::cancel_language_server_work::Buffers {
8217                        buffer_ids: buffers
8218                            .into_iter()
8219                            .map(|b| b.read(cx).remote_id().to_proto())
8220                            .collect(),
8221                    },
8222                )),
8223            });
8224            cx.background_spawn(request).detach_and_log_err(cx);
8225        } else if let Some(local) = self.as_local() {
8226            let servers = buffers
8227                .into_iter()
8228                .flat_map(|buffer| {
8229                    buffer.update(cx, |buffer, cx| {
8230                        local.language_server_ids_for_buffer(buffer, cx).into_iter()
8231                    })
8232                })
8233                .collect::<HashSet<_>>();
8234            for server_id in servers {
8235                self.cancel_language_server_work(server_id, None, cx);
8236            }
8237        }
8238    }
8239
8240    pub(crate) fn cancel_language_server_work(
8241        &mut self,
8242        server_id: LanguageServerId,
8243        token_to_cancel: Option<String>,
8244        cx: &mut Context<Self>,
8245    ) {
8246        if let Some(local) = self.as_local() {
8247            let status = self.language_server_statuses.get(&server_id);
8248            let server = local.language_servers.get(&server_id);
8249            if let Some((LanguageServerState::Running { server, .. }, status)) = server.zip(status)
8250            {
8251                for (token, progress) in &status.pending_work {
8252                    if let Some(token_to_cancel) = token_to_cancel.as_ref() {
8253                        if token != token_to_cancel {
8254                            continue;
8255                        }
8256                    }
8257                    if progress.is_cancellable {
8258                        server
8259                            .notify::<lsp::notification::WorkDoneProgressCancel>(
8260                                &WorkDoneProgressCancelParams {
8261                                    token: lsp::NumberOrString::String(token.clone()),
8262                                },
8263                            )
8264                            .ok();
8265                    }
8266                }
8267            }
8268        } else if let Some((client, project_id)) = self.upstream_client() {
8269            let request = client.request(proto::CancelLanguageServerWork {
8270                project_id,
8271                work: Some(
8272                    proto::cancel_language_server_work::Work::LanguageServerWork(
8273                        proto::cancel_language_server_work::LanguageServerWork {
8274                            language_server_id: server_id.to_proto(),
8275                            token: token_to_cancel,
8276                        },
8277                    ),
8278                ),
8279            });
8280            cx.background_spawn(request).detach_and_log_err(cx);
8281        }
8282    }
8283
8284    fn register_supplementary_language_server(
8285        &mut self,
8286        id: LanguageServerId,
8287        name: LanguageServerName,
8288        server: Arc<LanguageServer>,
8289        cx: &mut Context<Self>,
8290    ) {
8291        if let Some(local) = self.as_local_mut() {
8292            local
8293                .supplementary_language_servers
8294                .insert(id, (name.clone(), server));
8295            cx.emit(LspStoreEvent::LanguageServerAdded(id, name, None));
8296        }
8297    }
8298
8299    fn unregister_supplementary_language_server(
8300        &mut self,
8301        id: LanguageServerId,
8302        cx: &mut Context<Self>,
8303    ) {
8304        if let Some(local) = self.as_local_mut() {
8305            local.supplementary_language_servers.remove(&id);
8306            cx.emit(LspStoreEvent::LanguageServerRemoved(id));
8307        }
8308    }
8309
8310    pub(crate) fn supplementary_language_servers(
8311        &self,
8312    ) -> impl '_ + Iterator<Item = (LanguageServerId, LanguageServerName)> {
8313        self.as_local().into_iter().flat_map(|local| {
8314            local
8315                .supplementary_language_servers
8316                .iter()
8317                .map(|(id, (name, _))| (*id, name.clone()))
8318        })
8319    }
8320
8321    pub fn language_server_adapter_for_id(
8322        &self,
8323        id: LanguageServerId,
8324    ) -> Option<Arc<CachedLspAdapter>> {
8325        self.as_local()
8326            .and_then(|local| local.language_servers.get(&id))
8327            .and_then(|language_server_state| match language_server_state {
8328                LanguageServerState::Running { adapter, .. } => Some(adapter.clone()),
8329                _ => None,
8330            })
8331    }
8332
8333    pub(super) fn update_local_worktree_language_servers(
8334        &mut self,
8335        worktree_handle: &Entity<Worktree>,
8336        changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
8337        cx: &mut Context<Self>,
8338    ) {
8339        if changes.is_empty() {
8340            return;
8341        }
8342
8343        let Some(local) = self.as_local() else { return };
8344
8345        local.prettier_store.update(cx, |prettier_store, cx| {
8346            prettier_store.update_prettier_settings(&worktree_handle, changes, cx)
8347        });
8348
8349        let worktree_id = worktree_handle.read(cx).id();
8350        let mut language_server_ids = local
8351            .language_server_ids
8352            .iter()
8353            .flat_map(|((server_worktree, _), server_ids)| {
8354                server_ids
8355                    .iter()
8356                    .filter_map(|server_id| server_worktree.eq(&worktree_id).then(|| *server_id))
8357            })
8358            .collect::<Vec<_>>();
8359        language_server_ids.sort();
8360        language_server_ids.dedup();
8361
8362        let abs_path = worktree_handle.read(cx).abs_path();
8363        for server_id in &language_server_ids {
8364            if let Some(LanguageServerState::Running { server, .. }) =
8365                local.language_servers.get(server_id)
8366            {
8367                if let Some(watched_paths) = local
8368                    .language_server_watched_paths
8369                    .get(server_id)
8370                    .and_then(|paths| paths.worktree_paths.get(&worktree_id))
8371                {
8372                    let params = lsp::DidChangeWatchedFilesParams {
8373                        changes: changes
8374                            .iter()
8375                            .filter_map(|(path, _, change)| {
8376                                if !watched_paths.is_match(path) {
8377                                    return None;
8378                                }
8379                                let typ = match change {
8380                                    PathChange::Loaded => return None,
8381                                    PathChange::Added => lsp::FileChangeType::CREATED,
8382                                    PathChange::Removed => lsp::FileChangeType::DELETED,
8383                                    PathChange::Updated => lsp::FileChangeType::CHANGED,
8384                                    PathChange::AddedOrUpdated => lsp::FileChangeType::CHANGED,
8385                                };
8386                                Some(lsp::FileEvent {
8387                                    uri: lsp::Url::from_file_path(abs_path.join(path)).unwrap(),
8388                                    typ,
8389                                })
8390                            })
8391                            .collect(),
8392                    };
8393                    if !params.changes.is_empty() {
8394                        server
8395                            .notify::<lsp::notification::DidChangeWatchedFiles>(&params)
8396                            .log_err();
8397                    }
8398                }
8399            }
8400        }
8401    }
8402
8403    pub fn wait_for_remote_buffer(
8404        &mut self,
8405        id: BufferId,
8406        cx: &mut Context<Self>,
8407    ) -> Task<Result<Entity<Buffer>>> {
8408        self.buffer_store.update(cx, |buffer_store, cx| {
8409            buffer_store.wait_for_remote_buffer(id, cx)
8410        })
8411    }
8412
8413    fn serialize_symbol(symbol: &Symbol) -> proto::Symbol {
8414        proto::Symbol {
8415            language_server_name: symbol.language_server_name.0.to_string(),
8416            source_worktree_id: symbol.source_worktree_id.to_proto(),
8417            language_server_id: symbol.source_language_server_id.to_proto(),
8418            worktree_id: symbol.path.worktree_id.to_proto(),
8419            path: symbol.path.path.as_ref().to_proto(),
8420            name: symbol.name.clone(),
8421            kind: unsafe { mem::transmute::<lsp::SymbolKind, i32>(symbol.kind) },
8422            start: Some(proto::PointUtf16 {
8423                row: symbol.range.start.0.row,
8424                column: symbol.range.start.0.column,
8425            }),
8426            end: Some(proto::PointUtf16 {
8427                row: symbol.range.end.0.row,
8428                column: symbol.range.end.0.column,
8429            }),
8430            signature: symbol.signature.to_vec(),
8431        }
8432    }
8433
8434    fn deserialize_symbol(serialized_symbol: proto::Symbol) -> Result<CoreSymbol> {
8435        let source_worktree_id = WorktreeId::from_proto(serialized_symbol.source_worktree_id);
8436        let worktree_id = WorktreeId::from_proto(serialized_symbol.worktree_id);
8437        let kind = unsafe { mem::transmute::<i32, lsp::SymbolKind>(serialized_symbol.kind) };
8438        let path = ProjectPath {
8439            worktree_id,
8440            path: Arc::<Path>::from_proto(serialized_symbol.path),
8441        };
8442
8443        let start = serialized_symbol
8444            .start
8445            .ok_or_else(|| anyhow!("invalid start"))?;
8446        let end = serialized_symbol
8447            .end
8448            .ok_or_else(|| anyhow!("invalid end"))?;
8449        Ok(CoreSymbol {
8450            language_server_name: LanguageServerName(serialized_symbol.language_server_name.into()),
8451            source_worktree_id,
8452            source_language_server_id: LanguageServerId::from_proto(
8453                serialized_symbol.language_server_id,
8454            ),
8455            path,
8456            name: serialized_symbol.name,
8457            range: Unclipped(PointUtf16::new(start.row, start.column))
8458                ..Unclipped(PointUtf16::new(end.row, end.column)),
8459            kind,
8460            signature: serialized_symbol
8461                .signature
8462                .try_into()
8463                .map_err(|_| anyhow!("invalid signature"))?,
8464        })
8465    }
8466
8467    pub(crate) fn serialize_completion(completion: &CoreCompletion) -> proto::Completion {
8468        let mut serialized_completion = proto::Completion {
8469            old_start: Some(serialize_anchor(&completion.old_range.start)),
8470            old_end: Some(serialize_anchor(&completion.old_range.end)),
8471            new_text: completion.new_text.clone(),
8472            ..proto::Completion::default()
8473        };
8474        match &completion.source {
8475            CompletionSource::Lsp {
8476                server_id,
8477                lsp_completion,
8478                lsp_defaults,
8479                resolved,
8480            } => {
8481                serialized_completion.source = proto::completion::Source::Lsp as i32;
8482                serialized_completion.server_id = server_id.0 as u64;
8483                serialized_completion.lsp_completion = serde_json::to_vec(lsp_completion).unwrap();
8484                serialized_completion.lsp_defaults = lsp_defaults
8485                    .as_deref()
8486                    .map(|lsp_defaults| serde_json::to_vec(lsp_defaults).unwrap());
8487                serialized_completion.resolved = *resolved;
8488            }
8489            CompletionSource::BufferWord {
8490                word_range,
8491                resolved,
8492            } => {
8493                serialized_completion.source = proto::completion::Source::BufferWord as i32;
8494                serialized_completion.buffer_word_start = Some(serialize_anchor(&word_range.start));
8495                serialized_completion.buffer_word_end = Some(serialize_anchor(&word_range.end));
8496                serialized_completion.resolved = *resolved;
8497            }
8498            CompletionSource::Custom => {
8499                serialized_completion.source = proto::completion::Source::Custom as i32;
8500                serialized_completion.resolved = true;
8501            }
8502        }
8503
8504        serialized_completion
8505    }
8506
8507    pub(crate) fn deserialize_completion(completion: proto::Completion) -> Result<CoreCompletion> {
8508        let old_start = completion
8509            .old_start
8510            .and_then(deserialize_anchor)
8511            .context("invalid old start")?;
8512        let old_end = completion
8513            .old_end
8514            .and_then(deserialize_anchor)
8515            .context("invalid old end")?;
8516        Ok(CoreCompletion {
8517            old_range: old_start..old_end,
8518            new_text: completion.new_text,
8519            source: match proto::completion::Source::from_i32(completion.source) {
8520                Some(proto::completion::Source::Custom) => CompletionSource::Custom,
8521                Some(proto::completion::Source::Lsp) => CompletionSource::Lsp {
8522                    server_id: LanguageServerId::from_proto(completion.server_id),
8523                    lsp_completion: serde_json::from_slice(&completion.lsp_completion)?,
8524                    lsp_defaults: completion
8525                        .lsp_defaults
8526                        .as_deref()
8527                        .map(serde_json::from_slice)
8528                        .transpose()?,
8529                    resolved: completion.resolved,
8530                },
8531                Some(proto::completion::Source::BufferWord) => {
8532                    let word_range = completion
8533                        .buffer_word_start
8534                        .and_then(deserialize_anchor)
8535                        .context("invalid buffer word start")?
8536                        ..completion
8537                            .buffer_word_end
8538                            .and_then(deserialize_anchor)
8539                            .context("invalid buffer word end")?;
8540                    CompletionSource::BufferWord {
8541                        word_range,
8542                        resolved: completion.resolved,
8543                    }
8544                }
8545                _ => anyhow::bail!("Unexpected completion source {}", completion.source),
8546            },
8547        })
8548    }
8549
8550    pub(crate) fn serialize_code_action(action: &CodeAction) -> proto::CodeAction {
8551        let (kind, lsp_action) = match &action.lsp_action {
8552            LspAction::Action(code_action) => (
8553                proto::code_action::Kind::Action as i32,
8554                serde_json::to_vec(code_action).unwrap(),
8555            ),
8556            LspAction::Command(command) => (
8557                proto::code_action::Kind::Command as i32,
8558                serde_json::to_vec(command).unwrap(),
8559            ),
8560            LspAction::CodeLens(code_lens) => (
8561                proto::code_action::Kind::CodeLens as i32,
8562                serde_json::to_vec(code_lens).unwrap(),
8563            ),
8564        };
8565
8566        proto::CodeAction {
8567            server_id: action.server_id.0 as u64,
8568            start: Some(serialize_anchor(&action.range.start)),
8569            end: Some(serialize_anchor(&action.range.end)),
8570            lsp_action,
8571            kind,
8572            resolved: action.resolved,
8573        }
8574    }
8575
8576    pub(crate) fn deserialize_code_action(action: proto::CodeAction) -> Result<CodeAction> {
8577        let start = action
8578            .start
8579            .and_then(deserialize_anchor)
8580            .context("invalid start")?;
8581        let end = action
8582            .end
8583            .and_then(deserialize_anchor)
8584            .context("invalid end")?;
8585        let lsp_action = match proto::code_action::Kind::from_i32(action.kind) {
8586            Some(proto::code_action::Kind::Action) => {
8587                LspAction::Action(serde_json::from_slice(&action.lsp_action)?)
8588            }
8589            Some(proto::code_action::Kind::Command) => {
8590                LspAction::Command(serde_json::from_slice(&action.lsp_action)?)
8591            }
8592            Some(proto::code_action::Kind::CodeLens) => {
8593                LspAction::CodeLens(serde_json::from_slice(&action.lsp_action)?)
8594            }
8595            None => anyhow::bail!("Unknown action kind {}", action.kind),
8596        };
8597        Ok(CodeAction {
8598            server_id: LanguageServerId(action.server_id as usize),
8599            range: start..end,
8600            resolved: action.resolved,
8601            lsp_action,
8602        })
8603    }
8604
8605    fn update_last_formatting_failure<T>(&mut self, formatting_result: &anyhow::Result<T>) {
8606        match &formatting_result {
8607            Ok(_) => self.last_formatting_failure = None,
8608            Err(error) => {
8609                let error_string = format!("{error:#}");
8610                log::error!("Formatting failed: {error_string}");
8611                self.last_formatting_failure
8612                    .replace(error_string.lines().join(" "));
8613            }
8614        }
8615    }
8616}
8617
8618fn resolve_word_completion(snapshot: &BufferSnapshot, completion: &mut Completion) {
8619    let CompletionSource::BufferWord {
8620        word_range,
8621        resolved,
8622    } = &mut completion.source
8623    else {
8624        return;
8625    };
8626    if *resolved {
8627        return;
8628    }
8629
8630    if completion.new_text
8631        != snapshot
8632            .text_for_range(word_range.clone())
8633            .collect::<String>()
8634    {
8635        return;
8636    }
8637
8638    let mut offset = 0;
8639    for chunk in snapshot.chunks(word_range.clone(), true) {
8640        let end_offset = offset + chunk.text.len();
8641        if let Some(highlight_id) = chunk.syntax_highlight_id {
8642            completion
8643                .label
8644                .runs
8645                .push((offset..end_offset, highlight_id));
8646        }
8647        offset = end_offset;
8648    }
8649    *resolved = true;
8650}
8651
8652impl EventEmitter<LspStoreEvent> for LspStore {}
8653
8654fn remove_empty_hover_blocks(mut hover: Hover) -> Option<Hover> {
8655    hover
8656        .contents
8657        .retain(|hover_block| !hover_block.text.trim().is_empty());
8658    if hover.contents.is_empty() {
8659        None
8660    } else {
8661        Some(hover)
8662    }
8663}
8664
8665async fn populate_labels_for_completions(
8666    new_completions: Vec<CoreCompletion>,
8667    language: Option<Arc<Language>>,
8668    lsp_adapter: Option<Arc<CachedLspAdapter>>,
8669    completions: &mut Vec<Completion>,
8670) {
8671    let lsp_completions = new_completions
8672        .iter()
8673        .filter_map(|new_completion| {
8674            if let Some(lsp_completion) = new_completion.source.lsp_completion(true) {
8675                Some(lsp_completion.into_owned())
8676            } else {
8677                None
8678            }
8679        })
8680        .collect::<Vec<_>>();
8681
8682    let mut labels = if let Some((language, lsp_adapter)) = language.as_ref().zip(lsp_adapter) {
8683        lsp_adapter
8684            .labels_for_completions(&lsp_completions, language)
8685            .await
8686            .log_err()
8687            .unwrap_or_default()
8688    } else {
8689        Vec::new()
8690    }
8691    .into_iter()
8692    .fuse();
8693
8694    for completion in new_completions {
8695        match completion.source.lsp_completion(true) {
8696            Some(lsp_completion) => {
8697                let documentation = if let Some(docs) = lsp_completion.documentation.clone() {
8698                    Some(docs.into())
8699                } else {
8700                    None
8701                };
8702
8703                let mut label = labels.next().flatten().unwrap_or_else(|| {
8704                    CodeLabel::fallback_for_completion(&lsp_completion, language.as_deref())
8705                });
8706                ensure_uniform_list_compatible_label(&mut label);
8707                completions.push(Completion {
8708                    label,
8709                    documentation,
8710                    old_range: completion.old_range,
8711                    new_text: completion.new_text,
8712                    source: completion.source,
8713                    confirm: None,
8714                });
8715            }
8716            None => {
8717                let mut label = CodeLabel::plain(completion.new_text.clone(), None);
8718                ensure_uniform_list_compatible_label(&mut label);
8719                completions.push(Completion {
8720                    label,
8721                    documentation: None,
8722                    old_range: completion.old_range,
8723                    new_text: completion.new_text,
8724                    source: completion.source,
8725                    confirm: None,
8726                });
8727            }
8728        }
8729    }
8730}
8731
8732#[derive(Debug)]
8733pub enum LanguageServerToQuery {
8734    /// Query language servers in order of users preference, up until one capable of handling the request is found.
8735    FirstCapable,
8736    /// Query a specific language server.
8737    Other(LanguageServerId),
8738}
8739
8740#[derive(Default)]
8741struct RenamePathsWatchedForServer {
8742    did_rename: Vec<RenameActionPredicate>,
8743    will_rename: Vec<RenameActionPredicate>,
8744}
8745
8746impl RenamePathsWatchedForServer {
8747    fn with_did_rename_patterns(
8748        mut self,
8749        did_rename: Option<&FileOperationRegistrationOptions>,
8750    ) -> Self {
8751        if let Some(did_rename) = did_rename {
8752            self.did_rename = did_rename
8753                .filters
8754                .iter()
8755                .filter_map(|filter| filter.try_into().log_err())
8756                .collect();
8757        }
8758        self
8759    }
8760    fn with_will_rename_patterns(
8761        mut self,
8762        will_rename: Option<&FileOperationRegistrationOptions>,
8763    ) -> Self {
8764        if let Some(will_rename) = will_rename {
8765            self.will_rename = will_rename
8766                .filters
8767                .iter()
8768                .filter_map(|filter| filter.try_into().log_err())
8769                .collect();
8770        }
8771        self
8772    }
8773
8774    fn should_send_did_rename(&self, path: &str, is_dir: bool) -> bool {
8775        self.did_rename.iter().any(|pred| pred.eval(path, is_dir))
8776    }
8777    fn should_send_will_rename(&self, path: &str, is_dir: bool) -> bool {
8778        self.will_rename.iter().any(|pred| pred.eval(path, is_dir))
8779    }
8780}
8781
8782impl TryFrom<&FileOperationFilter> for RenameActionPredicate {
8783    type Error = globset::Error;
8784    fn try_from(ops: &FileOperationFilter) -> Result<Self, globset::Error> {
8785        Ok(Self {
8786            kind: ops.pattern.matches.clone(),
8787            glob: GlobBuilder::new(&ops.pattern.glob)
8788                .case_insensitive(
8789                    ops.pattern
8790                        .options
8791                        .as_ref()
8792                        .map_or(false, |ops| ops.ignore_case.unwrap_or(false)),
8793                )
8794                .build()?
8795                .compile_matcher(),
8796        })
8797    }
8798}
8799struct RenameActionPredicate {
8800    glob: GlobMatcher,
8801    kind: Option<FileOperationPatternKind>,
8802}
8803
8804impl RenameActionPredicate {
8805    // Returns true if language server should be notified
8806    fn eval(&self, path: &str, is_dir: bool) -> bool {
8807        self.kind.as_ref().map_or(true, |kind| {
8808            let expected_kind = if is_dir {
8809                FileOperationPatternKind::Folder
8810            } else {
8811                FileOperationPatternKind::File
8812            };
8813            kind == &expected_kind
8814        }) && self.glob.is_match(path)
8815    }
8816}
8817
8818#[derive(Default)]
8819struct LanguageServerWatchedPaths {
8820    worktree_paths: HashMap<WorktreeId, GlobSet>,
8821    abs_paths: HashMap<Arc<Path>, (GlobSet, Task<()>)>,
8822}
8823
8824#[derive(Default)]
8825struct LanguageServerWatchedPathsBuilder {
8826    worktree_paths: HashMap<WorktreeId, GlobSet>,
8827    abs_paths: HashMap<Arc<Path>, GlobSet>,
8828}
8829
8830impl LanguageServerWatchedPathsBuilder {
8831    fn watch_worktree(&mut self, worktree_id: WorktreeId, glob_set: GlobSet) {
8832        self.worktree_paths.insert(worktree_id, glob_set);
8833    }
8834    fn watch_abs_path(&mut self, path: Arc<Path>, glob_set: GlobSet) {
8835        self.abs_paths.insert(path, glob_set);
8836    }
8837    fn build(
8838        self,
8839        fs: Arc<dyn Fs>,
8840        language_server_id: LanguageServerId,
8841        cx: &mut Context<LspStore>,
8842    ) -> LanguageServerWatchedPaths {
8843        let project = cx.weak_entity();
8844
8845        const LSP_ABS_PATH_OBSERVE: Duration = Duration::from_millis(100);
8846        let abs_paths = self
8847            .abs_paths
8848            .into_iter()
8849            .map(|(abs_path, globset)| {
8850                let task = cx.spawn({
8851                    let abs_path = abs_path.clone();
8852                    let fs = fs.clone();
8853
8854                    let lsp_store = project.clone();
8855                    async move |_, cx| {
8856                        maybe!(async move {
8857                            let mut push_updates = fs.watch(&abs_path, LSP_ABS_PATH_OBSERVE).await;
8858                            while let Some(update) = push_updates.0.next().await {
8859                                let action = lsp_store
8860                                    .update(cx, |this, _| {
8861                                        let Some(local) = this.as_local() else {
8862                                            return ControlFlow::Break(());
8863                                        };
8864                                        let Some(watcher) = local
8865                                            .language_server_watched_paths
8866                                            .get(&language_server_id)
8867                                        else {
8868                                            return ControlFlow::Break(());
8869                                        };
8870                                        let (globs, _) = watcher.abs_paths.get(&abs_path).expect(
8871                                            "Watched abs path is not registered with a watcher",
8872                                        );
8873                                        let matching_entries = update
8874                                            .into_iter()
8875                                            .filter(|event| globs.is_match(&event.path))
8876                                            .collect::<Vec<_>>();
8877                                        this.lsp_notify_abs_paths_changed(
8878                                            language_server_id,
8879                                            matching_entries,
8880                                        );
8881                                        ControlFlow::Continue(())
8882                                    })
8883                                    .ok()?;
8884
8885                                if action.is_break() {
8886                                    break;
8887                                }
8888                            }
8889                            Some(())
8890                        })
8891                        .await;
8892                    }
8893                });
8894                (abs_path, (globset, task))
8895            })
8896            .collect();
8897        LanguageServerWatchedPaths {
8898            worktree_paths: self.worktree_paths,
8899            abs_paths,
8900        }
8901    }
8902}
8903
8904struct LspBufferSnapshot {
8905    version: i32,
8906    snapshot: TextBufferSnapshot,
8907}
8908
8909/// A prompt requested by LSP server.
8910#[derive(Clone, Debug)]
8911pub struct LanguageServerPromptRequest {
8912    pub level: PromptLevel,
8913    pub message: String,
8914    pub actions: Vec<MessageActionItem>,
8915    pub lsp_name: String,
8916    pub(crate) response_channel: Sender<MessageActionItem>,
8917}
8918
8919impl LanguageServerPromptRequest {
8920    pub async fn respond(self, index: usize) -> Option<()> {
8921        if let Some(response) = self.actions.into_iter().nth(index) {
8922            self.response_channel.send(response).await.ok()
8923        } else {
8924            None
8925        }
8926    }
8927}
8928impl PartialEq for LanguageServerPromptRequest {
8929    fn eq(&self, other: &Self) -> bool {
8930        self.message == other.message && self.actions == other.actions
8931    }
8932}
8933
8934#[derive(Clone, Debug, PartialEq)]
8935pub enum LanguageServerLogType {
8936    Log(MessageType),
8937    Trace(Option<String>),
8938}
8939
8940impl LanguageServerLogType {
8941    pub fn to_proto(&self) -> proto::language_server_log::LogType {
8942        match self {
8943            Self::Log(log_type) => {
8944                let message_type = match *log_type {
8945                    MessageType::ERROR => 1,
8946                    MessageType::WARNING => 2,
8947                    MessageType::INFO => 3,
8948                    MessageType::LOG => 4,
8949                    other => {
8950                        log::warn!("Unknown lsp log message type: {:?}", other);
8951                        4
8952                    }
8953                };
8954                proto::language_server_log::LogType::LogMessageType(message_type)
8955            }
8956            Self::Trace(message) => {
8957                proto::language_server_log::LogType::LogTrace(proto::LspLogTrace {
8958                    message: message.clone(),
8959                })
8960            }
8961        }
8962    }
8963
8964    pub fn from_proto(log_type: proto::language_server_log::LogType) -> Self {
8965        match log_type {
8966            proto::language_server_log::LogType::LogMessageType(message_type) => {
8967                Self::Log(match message_type {
8968                    1 => MessageType::ERROR,
8969                    2 => MessageType::WARNING,
8970                    3 => MessageType::INFO,
8971                    4 => MessageType::LOG,
8972                    _ => MessageType::LOG,
8973                })
8974            }
8975            proto::language_server_log::LogType::LogTrace(trace) => Self::Trace(trace.message),
8976        }
8977    }
8978}
8979
8980pub enum LanguageServerState {
8981    Starting {
8982        startup: Task<Option<Arc<LanguageServer>>>,
8983        /// List of language servers that will be added to the workspace once it's initialization completes.
8984        pending_workspace_folders: Arc<Mutex<BTreeSet<Url>>>,
8985    },
8986
8987    Running {
8988        adapter: Arc<CachedLspAdapter>,
8989        server: Arc<LanguageServer>,
8990        simulate_disk_based_diagnostics_completion: Option<Task<()>>,
8991    },
8992}
8993
8994impl LanguageServerState {
8995    fn add_workspace_folder(&self, uri: Url) {
8996        match self {
8997            LanguageServerState::Starting {
8998                pending_workspace_folders,
8999                ..
9000            } => {
9001                pending_workspace_folders.lock().insert(uri);
9002            }
9003            LanguageServerState::Running { server, .. } => {
9004                server.add_workspace_folder(uri);
9005            }
9006        }
9007    }
9008    fn _remove_workspace_folder(&self, uri: Url) {
9009        match self {
9010            LanguageServerState::Starting {
9011                pending_workspace_folders,
9012                ..
9013            } => {
9014                pending_workspace_folders.lock().remove(&uri);
9015            }
9016            LanguageServerState::Running { server, .. } => server.remove_workspace_folder(uri),
9017        }
9018    }
9019    fn running(
9020        workspace_folders: BTreeSet<Url>,
9021        adapter: Arc<CachedLspAdapter>,
9022        server: Arc<LanguageServer>,
9023        simulate_disk_based_diagnostics_completion: Option<Task<()>>,
9024    ) -> Self {
9025        server.set_workspace_folders(workspace_folders);
9026        Self::Running {
9027            adapter,
9028            server,
9029            simulate_disk_based_diagnostics_completion,
9030        }
9031    }
9032}
9033
9034impl std::fmt::Debug for LanguageServerState {
9035    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9036        match self {
9037            LanguageServerState::Starting { .. } => {
9038                f.debug_struct("LanguageServerState::Starting").finish()
9039            }
9040            LanguageServerState::Running { .. } => {
9041                f.debug_struct("LanguageServerState::Running").finish()
9042            }
9043        }
9044    }
9045}
9046
9047#[derive(Clone, Debug, Serialize)]
9048pub struct LanguageServerProgress {
9049    pub is_disk_based_diagnostics_progress: bool,
9050    pub is_cancellable: bool,
9051    pub title: Option<String>,
9052    pub message: Option<String>,
9053    pub percentage: Option<usize>,
9054    #[serde(skip_serializing)]
9055    pub last_update_at: Instant,
9056}
9057
9058#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize)]
9059pub struct DiagnosticSummary {
9060    pub error_count: usize,
9061    pub warning_count: usize,
9062}
9063
9064impl DiagnosticSummary {
9065    pub fn new<'a, T: 'a>(diagnostics: impl IntoIterator<Item = &'a DiagnosticEntry<T>>) -> Self {
9066        let mut this = Self {
9067            error_count: 0,
9068            warning_count: 0,
9069        };
9070
9071        for entry in diagnostics {
9072            if entry.diagnostic.is_primary {
9073                match entry.diagnostic.severity {
9074                    DiagnosticSeverity::ERROR => this.error_count += 1,
9075                    DiagnosticSeverity::WARNING => this.warning_count += 1,
9076                    _ => {}
9077                }
9078            }
9079        }
9080
9081        this
9082    }
9083
9084    pub fn is_empty(&self) -> bool {
9085        self.error_count == 0 && self.warning_count == 0
9086    }
9087
9088    pub fn to_proto(
9089        &self,
9090        language_server_id: LanguageServerId,
9091        path: &Path,
9092    ) -> proto::DiagnosticSummary {
9093        proto::DiagnosticSummary {
9094            path: path.to_proto(),
9095            language_server_id: language_server_id.0 as u64,
9096            error_count: self.error_count as u32,
9097            warning_count: self.warning_count as u32,
9098        }
9099    }
9100}
9101
9102#[derive(Clone, Debug)]
9103pub enum CompletionDocumentation {
9104    /// There is no documentation for this completion.
9105    Undocumented,
9106    /// A single line of documentation.
9107    SingleLine(SharedString),
9108    /// Multiple lines of plain text documentation.
9109    MultiLinePlainText(SharedString),
9110    /// Markdown documentation.
9111    MultiLineMarkdown(SharedString),
9112}
9113
9114impl From<lsp::Documentation> for CompletionDocumentation {
9115    fn from(docs: lsp::Documentation) -> Self {
9116        match docs {
9117            lsp::Documentation::String(text) => {
9118                if text.lines().count() <= 1 {
9119                    CompletionDocumentation::SingleLine(text.into())
9120                } else {
9121                    CompletionDocumentation::MultiLinePlainText(text.into())
9122                }
9123            }
9124
9125            lsp::Documentation::MarkupContent(lsp::MarkupContent { kind, value }) => match kind {
9126                lsp::MarkupKind::PlainText => {
9127                    if value.lines().count() <= 1 {
9128                        CompletionDocumentation::SingleLine(value.into())
9129                    } else {
9130                        CompletionDocumentation::MultiLinePlainText(value.into())
9131                    }
9132                }
9133
9134                lsp::MarkupKind::Markdown => {
9135                    CompletionDocumentation::MultiLineMarkdown(value.into())
9136                }
9137            },
9138        }
9139    }
9140}
9141
9142fn glob_literal_prefix(glob: &Path) -> PathBuf {
9143    glob.components()
9144        .take_while(|component| match component {
9145            path::Component::Normal(part) => !part.to_string_lossy().contains(['*', '?', '{', '}']),
9146            _ => true,
9147        })
9148        .collect()
9149}
9150
9151pub struct SshLspAdapter {
9152    name: LanguageServerName,
9153    binary: LanguageServerBinary,
9154    initialization_options: Option<String>,
9155    code_action_kinds: Option<Vec<CodeActionKind>>,
9156}
9157
9158impl SshLspAdapter {
9159    pub fn new(
9160        name: LanguageServerName,
9161        binary: LanguageServerBinary,
9162        initialization_options: Option<String>,
9163        code_action_kinds: Option<String>,
9164    ) -> Self {
9165        Self {
9166            name,
9167            binary,
9168            initialization_options,
9169            code_action_kinds: code_action_kinds
9170                .as_ref()
9171                .and_then(|c| serde_json::from_str(c).ok()),
9172        }
9173    }
9174}
9175
9176#[async_trait(?Send)]
9177impl LspAdapter for SshLspAdapter {
9178    fn name(&self) -> LanguageServerName {
9179        self.name.clone()
9180    }
9181
9182    async fn initialization_options(
9183        self: Arc<Self>,
9184        _: &dyn Fs,
9185        _: &Arc<dyn LspAdapterDelegate>,
9186    ) -> Result<Option<serde_json::Value>> {
9187        let Some(options) = &self.initialization_options else {
9188            return Ok(None);
9189        };
9190        let result = serde_json::from_str(options)?;
9191        Ok(result)
9192    }
9193
9194    fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
9195        self.code_action_kinds.clone()
9196    }
9197
9198    async fn check_if_user_installed(
9199        &self,
9200        _: &dyn LspAdapterDelegate,
9201        _: Arc<dyn LanguageToolchainStore>,
9202        _: &AsyncApp,
9203    ) -> Option<LanguageServerBinary> {
9204        Some(self.binary.clone())
9205    }
9206
9207    async fn cached_server_binary(
9208        &self,
9209        _: PathBuf,
9210        _: &dyn LspAdapterDelegate,
9211    ) -> Option<LanguageServerBinary> {
9212        None
9213    }
9214
9215    async fn fetch_latest_server_version(
9216        &self,
9217        _: &dyn LspAdapterDelegate,
9218    ) -> Result<Box<dyn 'static + Send + Any>> {
9219        anyhow::bail!("SshLspAdapter does not support fetch_latest_server_version")
9220    }
9221
9222    async fn fetch_server_binary(
9223        &self,
9224        _: Box<dyn 'static + Send + Any>,
9225        _: PathBuf,
9226        _: &dyn LspAdapterDelegate,
9227    ) -> Result<LanguageServerBinary> {
9228        anyhow::bail!("SshLspAdapter does not support fetch_server_binary")
9229    }
9230}
9231
9232pub fn language_server_settings<'a>(
9233    delegate: &'a dyn LspAdapterDelegate,
9234    language: &LanguageServerName,
9235    cx: &'a App,
9236) -> Option<&'a LspSettings> {
9237    language_server_settings_for(
9238        SettingsLocation {
9239            worktree_id: delegate.worktree_id(),
9240            path: delegate.worktree_root_path(),
9241        },
9242        language,
9243        cx,
9244    )
9245}
9246
9247pub(crate) fn language_server_settings_for<'a>(
9248    location: SettingsLocation<'a>,
9249    language: &LanguageServerName,
9250    cx: &'a App,
9251) -> Option<&'a LspSettings> {
9252    ProjectSettings::get(Some(location), cx).lsp.get(language)
9253}
9254
9255pub struct LocalLspAdapterDelegate {
9256    lsp_store: WeakEntity<LspStore>,
9257    worktree: worktree::Snapshot,
9258    fs: Arc<dyn Fs>,
9259    http_client: Arc<dyn HttpClient>,
9260    language_registry: Arc<LanguageRegistry>,
9261    load_shell_env_task: Shared<Task<Option<HashMap<String, String>>>>,
9262}
9263
9264impl LocalLspAdapterDelegate {
9265    pub fn new(
9266        language_registry: Arc<LanguageRegistry>,
9267        environment: &Entity<ProjectEnvironment>,
9268        lsp_store: WeakEntity<LspStore>,
9269        worktree: &Entity<Worktree>,
9270        http_client: Arc<dyn HttpClient>,
9271        fs: Arc<dyn Fs>,
9272        cx: &mut App,
9273    ) -> Arc<Self> {
9274        let (worktree_id, worktree_abs_path) = {
9275            let worktree = worktree.read(cx);
9276            (worktree.id(), worktree.abs_path())
9277        };
9278
9279        let load_shell_env_task = environment.update(cx, |env, cx| {
9280            env.get_environment(Some(worktree_id), Some(worktree_abs_path), cx)
9281        });
9282
9283        Arc::new(Self {
9284            lsp_store,
9285            worktree: worktree.read(cx).snapshot(),
9286            fs,
9287            http_client,
9288            language_registry,
9289            load_shell_env_task,
9290        })
9291    }
9292
9293    fn from_local_lsp(
9294        local: &LocalLspStore,
9295        worktree: &Entity<Worktree>,
9296        cx: &mut App,
9297    ) -> Arc<Self> {
9298        Self::new(
9299            local.languages.clone(),
9300            &local.environment,
9301            local.weak.clone(),
9302            worktree,
9303            local.http_client.clone(),
9304            local.fs.clone(),
9305            cx,
9306        )
9307    }
9308}
9309
9310#[async_trait]
9311impl LspAdapterDelegate for LocalLspAdapterDelegate {
9312    fn show_notification(&self, message: &str, cx: &mut App) {
9313        self.lsp_store
9314            .update(cx, |_, cx| {
9315                cx.emit(LspStoreEvent::Notification(message.to_owned()))
9316            })
9317            .ok();
9318    }
9319
9320    fn http_client(&self) -> Arc<dyn HttpClient> {
9321        self.http_client.clone()
9322    }
9323
9324    fn worktree_id(&self) -> WorktreeId {
9325        self.worktree.id()
9326    }
9327
9328    fn exists(&self, path: &Path, is_dir: Option<bool>) -> bool {
9329        self.worktree.entry_for_path(path).map_or(false, |entry| {
9330            is_dir.map_or(true, |is_required_to_be_dir| {
9331                is_required_to_be_dir == entry.is_dir()
9332            })
9333        })
9334    }
9335
9336    fn worktree_root_path(&self) -> &Path {
9337        self.worktree.abs_path().as_ref()
9338    }
9339
9340    async fn shell_env(&self) -> HashMap<String, String> {
9341        let task = self.load_shell_env_task.clone();
9342        task.await.unwrap_or_default()
9343    }
9344
9345    async fn npm_package_installed_version(
9346        &self,
9347        package_name: &str,
9348    ) -> Result<Option<(PathBuf, String)>> {
9349        let local_package_directory = self.worktree_root_path();
9350        let node_modules_directory = local_package_directory.join("node_modules");
9351
9352        if let Some(version) =
9353            read_package_installed_version(node_modules_directory.clone(), package_name).await?
9354        {
9355            return Ok(Some((node_modules_directory, version)));
9356        }
9357        let Some(npm) = self.which("npm".as_ref()).await else {
9358            log::warn!(
9359                "Failed to find npm executable for {:?}",
9360                local_package_directory
9361            );
9362            return Ok(None);
9363        };
9364
9365        let env = self.shell_env().await;
9366        let output = util::command::new_smol_command(&npm)
9367            .args(["root", "-g"])
9368            .envs(env)
9369            .current_dir(local_package_directory)
9370            .output()
9371            .await?;
9372        let global_node_modules =
9373            PathBuf::from(String::from_utf8_lossy(&output.stdout).to_string());
9374
9375        if let Some(version) =
9376            read_package_installed_version(global_node_modules.clone(), package_name).await?
9377        {
9378            return Ok(Some((global_node_modules, version)));
9379        }
9380        return Ok(None);
9381    }
9382
9383    #[cfg(not(target_os = "windows"))]
9384    async fn which(&self, command: &OsStr) -> Option<PathBuf> {
9385        let worktree_abs_path = self.worktree.abs_path();
9386        let shell_path = self.shell_env().await.get("PATH").cloned();
9387        which::which_in(command, shell_path.as_ref(), worktree_abs_path).ok()
9388    }
9389
9390    #[cfg(target_os = "windows")]
9391    async fn which(&self, command: &OsStr) -> Option<PathBuf> {
9392        // todo(windows) Getting the shell env variables in a current directory on Windows is more complicated than other platforms
9393        //               there isn't a 'default shell' necessarily. The closest would be the default profile on the windows terminal
9394        //               SEE: https://learn.microsoft.com/en-us/windows/terminal/customize-settings/startup
9395        which::which(command).ok()
9396    }
9397
9398    async fn try_exec(&self, command: LanguageServerBinary) -> Result<()> {
9399        let working_dir = self.worktree_root_path();
9400        let output = util::command::new_smol_command(&command.path)
9401            .args(command.arguments)
9402            .envs(command.env.clone().unwrap_or_default())
9403            .current_dir(working_dir)
9404            .output()
9405            .await?;
9406
9407        if output.status.success() {
9408            return Ok(());
9409        }
9410        Err(anyhow!(
9411            "{}, stdout: {:?}, stderr: {:?}",
9412            output.status,
9413            String::from_utf8_lossy(&output.stdout),
9414            String::from_utf8_lossy(&output.stderr)
9415        ))
9416    }
9417
9418    fn update_status(&self, server_name: LanguageServerName, status: language::BinaryStatus) {
9419        self.language_registry
9420            .update_lsp_status(server_name, status);
9421    }
9422
9423    async fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>> {
9424        let dir = self.language_registry.language_server_download_dir(name)?;
9425
9426        if !dir.exists() {
9427            smol::fs::create_dir_all(&dir)
9428                .await
9429                .context("failed to create container directory")
9430                .log_err()?;
9431        }
9432
9433        Some(dir)
9434    }
9435
9436    async fn read_text_file(&self, path: PathBuf) -> Result<String> {
9437        let entry = self
9438            .worktree
9439            .entry_for_path(&path)
9440            .with_context(|| format!("no worktree entry for path {path:?}"))?;
9441        let abs_path = self
9442            .worktree
9443            .absolutize(&entry.path)
9444            .with_context(|| format!("cannot absolutize path {path:?}"))?;
9445
9446        self.fs.load(&abs_path).await
9447    }
9448}
9449
9450async fn populate_labels_for_symbols(
9451    symbols: Vec<CoreSymbol>,
9452    language_registry: &Arc<LanguageRegistry>,
9453    lsp_adapter: Option<Arc<CachedLspAdapter>>,
9454    output: &mut Vec<Symbol>,
9455) {
9456    #[allow(clippy::mutable_key_type)]
9457    let mut symbols_by_language = HashMap::<Option<Arc<Language>>, Vec<CoreSymbol>>::default();
9458
9459    let mut unknown_paths = BTreeSet::new();
9460    for symbol in symbols {
9461        let language = language_registry
9462            .language_for_file_path(&symbol.path.path)
9463            .await
9464            .ok()
9465            .or_else(|| {
9466                unknown_paths.insert(symbol.path.path.clone());
9467                None
9468            });
9469        symbols_by_language
9470            .entry(language)
9471            .or_default()
9472            .push(symbol);
9473    }
9474
9475    for unknown_path in unknown_paths {
9476        log::info!(
9477            "no language found for symbol path {}",
9478            unknown_path.display()
9479        );
9480    }
9481
9482    let mut label_params = Vec::new();
9483    for (language, mut symbols) in symbols_by_language {
9484        label_params.clear();
9485        label_params.extend(
9486            symbols
9487                .iter_mut()
9488                .map(|symbol| (mem::take(&mut symbol.name), symbol.kind)),
9489        );
9490
9491        let mut labels = Vec::new();
9492        if let Some(language) = language {
9493            let lsp_adapter = lsp_adapter.clone().or_else(|| {
9494                language_registry
9495                    .lsp_adapters(&language.name())
9496                    .first()
9497                    .cloned()
9498            });
9499            if let Some(lsp_adapter) = lsp_adapter {
9500                labels = lsp_adapter
9501                    .labels_for_symbols(&label_params, &language)
9502                    .await
9503                    .log_err()
9504                    .unwrap_or_default();
9505            }
9506        }
9507
9508        for ((symbol, (name, _)), label) in symbols
9509            .into_iter()
9510            .zip(label_params.drain(..))
9511            .zip(labels.into_iter().chain(iter::repeat(None)))
9512        {
9513            output.push(Symbol {
9514                language_server_name: symbol.language_server_name,
9515                source_worktree_id: symbol.source_worktree_id,
9516                source_language_server_id: symbol.source_language_server_id,
9517                path: symbol.path,
9518                label: label.unwrap_or_else(|| CodeLabel::plain(name.clone(), None)),
9519                name,
9520                kind: symbol.kind,
9521                range: symbol.range,
9522                signature: symbol.signature,
9523            });
9524        }
9525    }
9526}
9527
9528fn include_text(server: &lsp::LanguageServer) -> Option<bool> {
9529    match server.capabilities().text_document_sync.as_ref()? {
9530        lsp::TextDocumentSyncCapability::Kind(kind) => match *kind {
9531            lsp::TextDocumentSyncKind::NONE => None,
9532            lsp::TextDocumentSyncKind::FULL => Some(true),
9533            lsp::TextDocumentSyncKind::INCREMENTAL => Some(false),
9534            _ => None,
9535        },
9536        lsp::TextDocumentSyncCapability::Options(options) => match options.save.as_ref()? {
9537            lsp::TextDocumentSyncSaveOptions::Supported(supported) => {
9538                if *supported {
9539                    Some(true)
9540                } else {
9541                    None
9542                }
9543            }
9544            lsp::TextDocumentSyncSaveOptions::SaveOptions(save_options) => {
9545                Some(save_options.include_text.unwrap_or(false))
9546            }
9547        },
9548    }
9549}
9550
9551/// Completion items are displayed in a `UniformList`.
9552/// Usually, those items are single-line strings, but in LSP responses,
9553/// completion items `label`, `detail` and `label_details.description` may contain newlines or long spaces.
9554/// Many language plugins construct these items by joining these parts together, and we may use `CodeLabel::fallback_for_completion` that uses `label` at least.
9555/// All that may lead to a newline being inserted into resulting `CodeLabel.text`, which will force `UniformList` to bloat each entry to occupy more space,
9556/// breaking the completions menu presentation.
9557///
9558/// Sanitize the text to ensure there are no newlines, or, if there are some, remove them and also remove long space sequences if there were newlines.
9559fn ensure_uniform_list_compatible_label(label: &mut CodeLabel) {
9560    let mut new_text = String::with_capacity(label.text.len());
9561    let mut offset_map = vec![0; label.text.len() + 1];
9562    let mut last_char_was_space = false;
9563    let mut new_idx = 0;
9564    let mut chars = label.text.char_indices().fuse();
9565    let mut newlines_removed = false;
9566
9567    while let Some((idx, c)) = chars.next() {
9568        offset_map[idx] = new_idx;
9569
9570        match c {
9571            '\n' if last_char_was_space => {
9572                newlines_removed = true;
9573            }
9574            '\t' | ' ' if last_char_was_space => {}
9575            '\n' if !last_char_was_space => {
9576                new_text.push(' ');
9577                new_idx += 1;
9578                last_char_was_space = true;
9579                newlines_removed = true;
9580            }
9581            ' ' | '\t' => {
9582                new_text.push(' ');
9583                new_idx += 1;
9584                last_char_was_space = true;
9585            }
9586            _ => {
9587                new_text.push(c);
9588                new_idx += c.len_utf8();
9589                last_char_was_space = false;
9590            }
9591        }
9592    }
9593    offset_map[label.text.len()] = new_idx;
9594
9595    // Only modify the label if newlines were removed.
9596    if !newlines_removed {
9597        return;
9598    }
9599
9600    let last_index = new_idx;
9601    let mut run_ranges_errors = Vec::new();
9602    label.runs.retain_mut(|(range, _)| {
9603        match offset_map.get(range.start) {
9604            Some(&start) => range.start = start,
9605            None => {
9606                run_ranges_errors.push(range.clone());
9607                return false;
9608            }
9609        }
9610
9611        match offset_map.get(range.end) {
9612            Some(&end) => range.end = end,
9613            None => {
9614                run_ranges_errors.push(range.clone());
9615                range.end = last_index;
9616            }
9617        }
9618        true
9619    });
9620    if !run_ranges_errors.is_empty() {
9621        log::error!(
9622            "Completion label has errors in its run ranges: {run_ranges_errors:?}, label text: {}",
9623            label.text
9624        );
9625    }
9626
9627    let mut wrong_filter_range = None;
9628    if label.filter_range == (0..label.text.len()) {
9629        label.filter_range = 0..new_text.len();
9630    } else {
9631        let mut original_filter_range = Some(label.filter_range.clone());
9632        match offset_map.get(label.filter_range.start) {
9633            Some(&start) => label.filter_range.start = start,
9634            None => {
9635                wrong_filter_range = original_filter_range.take();
9636                label.filter_range.start = last_index;
9637            }
9638        }
9639
9640        match offset_map.get(label.filter_range.end) {
9641            Some(&end) => label.filter_range.end = end,
9642            None => {
9643                wrong_filter_range = original_filter_range.take();
9644                label.filter_range.end = last_index;
9645            }
9646        }
9647    }
9648    if let Some(wrong_filter_range) = wrong_filter_range {
9649        log::error!(
9650            "Completion label has an invalid filter range: {wrong_filter_range:?}, label text: {}",
9651            label.text
9652        );
9653    }
9654
9655    label.text = new_text;
9656}
9657
9658#[cfg(test)]
9659mod tests {
9660    use language::HighlightId;
9661
9662    use super::*;
9663
9664    #[test]
9665    fn test_glob_literal_prefix() {
9666        assert_eq!(glob_literal_prefix(Path::new("**/*.js")), Path::new(""));
9667        assert_eq!(
9668            glob_literal_prefix(Path::new("node_modules/**/*.js")),
9669            Path::new("node_modules")
9670        );
9671        assert_eq!(
9672            glob_literal_prefix(Path::new("foo/{bar,baz}.js")),
9673            Path::new("foo")
9674        );
9675        assert_eq!(
9676            glob_literal_prefix(Path::new("foo/bar/baz.js")),
9677            Path::new("foo/bar/baz.js")
9678        );
9679
9680        #[cfg(target_os = "windows")]
9681        {
9682            assert_eq!(glob_literal_prefix(Path::new("**\\*.js")), Path::new(""));
9683            assert_eq!(
9684                glob_literal_prefix(Path::new("node_modules\\**/*.js")),
9685                Path::new("node_modules")
9686            );
9687            assert_eq!(
9688                glob_literal_prefix(Path::new("foo/{bar,baz}.js")),
9689                Path::new("foo")
9690            );
9691            assert_eq!(
9692                glob_literal_prefix(Path::new("foo\\bar\\baz.js")),
9693                Path::new("foo/bar/baz.js")
9694            );
9695        }
9696    }
9697
9698    #[test]
9699    fn test_multi_len_chars_normalization() {
9700        let mut label = CodeLabel {
9701            text: "myElˇ (parameter) myElˇ: {\n    foo: string;\n}".to_string(),
9702            runs: vec![(0..6, HighlightId(1))],
9703            filter_range: 0..6,
9704        };
9705        ensure_uniform_list_compatible_label(&mut label);
9706        assert_eq!(
9707            label,
9708            CodeLabel {
9709                text: "myElˇ (parameter) myElˇ: { foo: string; }".to_string(),
9710                runs: vec![(0..6, HighlightId(1))],
9711                filter_range: 0..6,
9712            }
9713        );
9714    }
9715}