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