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