lsp_store.rs

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