lsp_store.rs

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