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