lsp_store.rs

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