lsp_store.rs

   1use crate::{
   2    buffer_store::{BufferStore, BufferStoreEvent},
   3    deserialize_code_actions,
   4    environment::ProjectEnvironment,
   5    lsp_command::{self, *},
   6    lsp_ext_command,
   7    prettier_store::{self, PrettierStore, PrettierStoreEvent},
   8    project_settings::{LspSettings, ProjectSettings},
   9    project_tree::{AdapterQuery, LanguageServerTree, LaunchDisposition, ProjectTree},
  10    relativize_path, resolve_path,
  11    toolchain_store::{EmptyToolchainStore, ToolchainStoreEvent},
  12    worktree_store::{WorktreeStore, WorktreeStoreEvent},
  13    yarn::YarnPathStore,
  14    CodeAction, Completion, CoreCompletion, Hover, InlayHint, ProjectItem as _, ProjectPath,
  15    ProjectTransaction, ResolveState, Symbol, ToolchainStore,
  16};
  17use anyhow::{anyhow, Context as _, Result};
  18use async_trait::async_trait;
  19use client::{proto, TypedEnvelope};
  20use collections::{btree_map, BTreeMap, BTreeSet, HashMap, HashSet};
  21use futures::{
  22    future::{join_all, Shared},
  23    select,
  24    stream::FuturesUnordered,
  25    AsyncWriteExt, Future, FutureExt, StreamExt,
  26};
  27use globset::{Glob, GlobBuilder, GlobMatcher, GlobSet, GlobSetBuilder};
  28use gpui::{
  29    App, AppContext as _, AsyncApp, Context, Entity, EventEmitter, PromptLevel, SharedString, Task,
  30    WeakEntity,
  31};
  32use http_client::HttpClient;
  33use itertools::Itertools as _;
  34use language::{
  35    language_settings::{
  36        language_settings, FormatOnSave, Formatter, LanguageSettings, SelectedFormatter,
  37    },
  38    point_to_lsp,
  39    proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
  40    range_from_lsp, range_to_lsp, Bias, Buffer, BufferSnapshot, CachedLspAdapter, CodeLabel,
  41    Diagnostic, DiagnosticEntry, DiagnosticSet, Diff, File as _, Language, LanguageRegistry,
  42    LanguageServerBinaryStatus, LanguageToolchainStore, LocalFile, LspAdapter, LspAdapterDelegate,
  43    Patch, PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction, Unclipped,
  44};
  45use lsp::{
  46    notification::DidRenameFiles, CodeActionKind, CompletionContext, DiagnosticSeverity,
  47    DiagnosticTag, DidChangeWatchedFilesRegistrationOptions, Edit, FileOperationFilter,
  48    FileOperationPatternKind, FileOperationRegistrationOptions, FileRename, FileSystemWatcher,
  49    InsertTextFormat, LanguageServer, LanguageServerBinary, LanguageServerBinaryOptions,
  50    LanguageServerId, LanguageServerName, LspRequestFuture, MessageActionItem, MessageType, OneOf,
  51    RenameFilesParams, ServerHealthStatus, ServerStatus, SymbolKind, TextEdit, WillRenameFiles,
  52    WorkDoneProgressCancelParams, WorkspaceFolder,
  53};
  54use node_runtime::read_package_installed_version;
  55use parking_lot::Mutex;
  56use postage::watch;
  57use rand::prelude::*;
  58
  59use rpc::{
  60    proto::{FromProto, ToProto},
  61    AnyProtoClient,
  62};
  63use serde::Serialize;
  64use settings::{Settings, SettingsLocation, SettingsStore};
  65use sha2::{Digest, Sha256};
  66use similar::{ChangeTag, TextDiff};
  67use smol::channel::Sender;
  68use snippet::Snippet;
  69use std::{
  70    any::Any,
  71    cell::RefCell,
  72    cmp::Ordering,
  73    convert::TryInto,
  74    ffi::OsStr,
  75    iter, mem,
  76    ops::{ControlFlow, Range},
  77    path::{self, Path, PathBuf},
  78    rc::Rc,
  79    str,
  80    sync::Arc,
  81    time::{Duration, Instant},
  82};
  83use text::{Anchor, BufferId, LineEnding, OffsetRangeExt, TransactionId};
  84use url::Url;
  85use util::{
  86    debug_panic, defer, maybe, merge_json_value_into, paths::SanitizedPath, post_inc, ResultExt,
  87    TryFutureExt as _,
  88};
  89
  90pub use fs::*;
  91pub use language::Location;
  92#[cfg(any(test, feature = "test-support"))]
  93pub use prettier::FORMAT_SUFFIX as TEST_PRETTIER_FORMAT_SUFFIX;
  94pub use worktree::{
  95    Entry, EntryKind, File, LocalWorktree, PathChange, ProjectEntryId, UpdatedEntriesSet,
  96    UpdatedGitRepositoriesSet, Worktree, WorktreeId, WorktreeSettings, FS_WATCH_LATENCY,
  97};
  98
  99const SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
 100pub const SERVER_PROGRESS_THROTTLE_TIMEOUT: Duration = Duration::from_millis(100);
 101
 102#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 103pub enum FormatTrigger {
 104    Save,
 105    Manual,
 106}
 107
 108pub enum LspFormatTarget {
 109    Buffers,
 110    Ranges(BTreeMap<BufferId, Vec<Range<Anchor>>>),
 111}
 112
 113// proto::RegisterBufferWithLanguageServer {}
 114
 115pub type OpenLspBufferHandle = Entity<Entity<Buffer>>;
 116
 117// Currently, formatting operations are represented differently depending on
 118// whether they come from a language server or an external command.
 119#[derive(Debug)]
 120pub enum FormatOperation {
 121    Lsp(Vec<(Range<Anchor>, String)>),
 122    External(Diff),
 123    Prettier(Diff),
 124}
 125
 126impl FormatTrigger {
 127    fn from_proto(value: i32) -> FormatTrigger {
 128        match value {
 129            0 => FormatTrigger::Save,
 130            1 => FormatTrigger::Manual,
 131            _ => FormatTrigger::Save,
 132        }
 133    }
 134}
 135
 136pub struct LocalLspStore {
 137    weak: WeakEntity<LspStore>,
 138    worktree_store: Entity<WorktreeStore>,
 139    toolchain_store: Entity<ToolchainStore>,
 140    http_client: Arc<dyn HttpClient>,
 141    environment: Entity<ProjectEnvironment>,
 142    fs: Arc<dyn Fs>,
 143    languages: Arc<LanguageRegistry>,
 144    language_server_ids: HashMap<(WorktreeId, LanguageServerName), BTreeSet<LanguageServerId>>,
 145    yarn: Entity<YarnPathStore>,
 146    pub language_servers: HashMap<LanguageServerId, LanguageServerState>,
 147    buffers_being_formatted: HashSet<BufferId>,
 148    last_workspace_edits_by_language_server: HashMap<LanguageServerId, ProjectTransaction>,
 149    language_server_watched_paths: HashMap<LanguageServerId, LanguageServerWatchedPaths>,
 150    language_server_paths_watched_for_rename:
 151        HashMap<LanguageServerId, RenamePathsWatchedForServer>,
 152    language_server_watcher_registrations:
 153        HashMap<LanguageServerId, HashMap<String, Vec<FileSystemWatcher>>>,
 154    supplementary_language_servers:
 155        HashMap<LanguageServerId, (LanguageServerName, Arc<LanguageServer>)>,
 156    prettier_store: Entity<PrettierStore>,
 157    next_diagnostic_group_id: usize,
 158    diagnostics: HashMap<
 159        WorktreeId,
 160        HashMap<
 161            Arc<Path>,
 162            Vec<(
 163                LanguageServerId,
 164                Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
 165            )>,
 166        >,
 167    >,
 168    buffer_snapshots: HashMap<BufferId, HashMap<LanguageServerId, Vec<LspBufferSnapshot>>>, // buffer_id -> server_id -> vec of snapshots
 169    _subscription: gpui::Subscription,
 170    lsp_tree: Entity<LanguageServerTree>,
 171    registered_buffers: HashMap<BufferId, usize>,
 172}
 173
 174impl LocalLspStore {
 175    /// Returns the running language server for the given ID. Note if the language server is starting, it will not be returned.
 176    pub fn running_language_server_for_id(
 177        &self,
 178        id: LanguageServerId,
 179    ) -> Option<&Arc<LanguageServer>> {
 180        let language_server_state = self.language_servers.get(&id)?;
 181
 182        match language_server_state {
 183            LanguageServerState::Running { server, .. } => Some(server),
 184            LanguageServerState::Starting { .. } => None,
 185        }
 186    }
 187
 188    fn start_language_server(
 189        &mut self,
 190        worktree_handle: &Entity<Worktree>,
 191        delegate: Arc<LocalLspAdapterDelegate>,
 192        adapter: Arc<CachedLspAdapter>,
 193        settings: Arc<LspSettings>,
 194        cx: &mut App,
 195    ) -> LanguageServerId {
 196        let worktree = worktree_handle.read(cx);
 197        let worktree_id = worktree.id();
 198        let root_path = worktree.abs_path();
 199        let key = (worktree_id, adapter.name.clone());
 200
 201        let override_options = settings.initialization_options.clone();
 202
 203        let stderr_capture = Arc::new(Mutex::new(Some(String::new())));
 204
 205        let server_id = self.languages.next_language_server_id();
 206        log::info!(
 207            "attempting to start language server {:?}, path: {root_path:?}, id: {server_id}",
 208            adapter.name.0
 209        );
 210
 211        let binary = self.get_language_server_binary(adapter.clone(), delegate.clone(), true, cx);
 212
 213        let pending_server = cx.spawn({
 214            let adapter = adapter.clone();
 215            let server_name = adapter.name.clone();
 216            let stderr_capture = stderr_capture.clone();
 217            #[cfg(any(test, feature = "test-support"))]
 218            let lsp_store = self.weak.clone();
 219
 220            move |cx| async move {
 221                let binary = binary.await?;
 222                #[cfg(any(test, feature = "test-support"))]
 223                if let Some(server) = lsp_store
 224                    .update(&mut cx.clone(), |this, cx| {
 225                        this.languages.create_fake_language_server(
 226                            server_id,
 227                            &server_name,
 228                            binary.clone(),
 229                            cx.to_async(),
 230                        )
 231                    })
 232                    .ok()
 233                    .flatten()
 234                {
 235                    return Ok(server);
 236                }
 237
 238                lsp::LanguageServer::new(
 239                    stderr_capture,
 240                    server_id,
 241                    server_name,
 242                    binary,
 243                    &root_path,
 244                    adapter.code_action_kinds(),
 245                    cx,
 246                )
 247            }
 248        });
 249
 250        let pending_workspace_folders: Arc<Mutex<BTreeSet<Url>>> = Default::default();
 251        let startup = {
 252            let server_name = adapter.name.0.clone();
 253            let delegate = delegate as Arc<dyn LspAdapterDelegate>;
 254            let key = key.clone();
 255            let adapter = adapter.clone();
 256            let this = self.weak.clone();
 257            let pending_workspace_folders = pending_workspace_folders.clone();
 258            let fs = self.fs.clone();
 259            cx.spawn(move |mut cx| async move {
 260                let result = {
 261                    let delegate = delegate.clone();
 262                    let adapter = adapter.clone();
 263                    let this = this.clone();
 264                    let toolchains = this
 265                        .update(&mut cx, |this, cx| this.toolchain_store(cx))
 266                        .ok()?;
 267                    let mut cx = cx.clone();
 268                    async move {
 269                        let language_server = pending_server.await?;
 270
 271                        let workspace_config = adapter
 272                            .adapter
 273                            .clone()
 274                            .workspace_configuration(
 275                                fs.as_ref(),
 276                                &delegate,
 277                                toolchains.clone(),
 278                                &mut cx,
 279                            )
 280                            .await?;
 281
 282                        let mut initialization_options = adapter
 283                            .adapter
 284                            .clone()
 285                            .initialization_options(fs.as_ref(), &(delegate))
 286                            .await?;
 287
 288                        match (&mut initialization_options, override_options) {
 289                            (Some(initialization_options), Some(override_options)) => {
 290                                merge_json_value_into(override_options, initialization_options);
 291                            }
 292                            (None, override_options) => initialization_options = override_options,
 293                            _ => {}
 294                        }
 295
 296                        let initialization_params = cx.update(|cx| {
 297                            let mut params = language_server.default_initialize_params(cx);
 298                            params.initialization_options = initialization_options;
 299                            adapter.adapter.prepare_initialize_params(params)
 300                        })??;
 301
 302                        Self::setup_lsp_messages(
 303                            this.clone(),
 304                            fs,
 305                            &language_server,
 306                            delegate,
 307                            adapter,
 308                        );
 309
 310                        let did_change_configuration_params =
 311                            Arc::new(lsp::DidChangeConfigurationParams {
 312                                settings: workspace_config,
 313                            });
 314                        let language_server = cx
 315                            .update(|cx| {
 316                                language_server.initialize(
 317                                    initialization_params,
 318                                    did_change_configuration_params.clone(),
 319                                    cx,
 320                                )
 321                            })?
 322                            .await
 323                            .inspect_err(|_| {
 324                                if let Some(this) = this.upgrade() {
 325                                    this.update(&mut cx, |_, cx| {
 326                                        cx.emit(LspStoreEvent::LanguageServerRemoved(server_id))
 327                                    })
 328                                    .ok();
 329                                }
 330                            })?;
 331
 332                        language_server
 333                            .notify::<lsp::notification::DidChangeConfiguration>(
 334                                &did_change_configuration_params,
 335                            )
 336                            .ok();
 337
 338                        anyhow::Ok(language_server)
 339                    }
 340                }
 341                .await;
 342
 343                match result {
 344                    Ok(server) => {
 345                        this.update(&mut cx, |this, mut cx| {
 346                            this.insert_newly_running_language_server(
 347                                adapter,
 348                                server.clone(),
 349                                server_id,
 350                                key,
 351                                pending_workspace_folders,
 352                                &mut cx,
 353                            );
 354                        })
 355                        .ok();
 356                        stderr_capture.lock().take();
 357                        Some(server)
 358                    }
 359
 360                    Err(err) => {
 361                        let log = stderr_capture.lock().take().unwrap_or_default();
 362                        delegate.update_status(
 363                            adapter.name(),
 364                            LanguageServerBinaryStatus::Failed {
 365                                error: format!("{err}\n-- stderr--\n{}", log),
 366                            },
 367                        );
 368                        log::error!("Failed to start language server {server_name:?}: {err}");
 369                        log::error!("server stderr: {:?}", log);
 370                        None
 371                    }
 372                }
 373            })
 374        };
 375        let state = LanguageServerState::Starting {
 376            startup,
 377            pending_workspace_folders,
 378        };
 379
 380        self.language_servers.insert(server_id, state);
 381        self.language_server_ids
 382            .entry(key)
 383            .or_default()
 384            .insert(server_id);
 385        server_id
 386    }
 387
 388    fn get_language_server_binary(
 389        &self,
 390        adapter: Arc<CachedLspAdapter>,
 391        delegate: Arc<dyn LspAdapterDelegate>,
 392        allow_binary_download: bool,
 393        cx: &mut App,
 394    ) -> Task<Result<LanguageServerBinary>> {
 395        let settings = ProjectSettings::get(
 396            Some(SettingsLocation {
 397                worktree_id: delegate.worktree_id(),
 398                path: Path::new(""),
 399            }),
 400            cx,
 401        )
 402        .lsp
 403        .get(&adapter.name)
 404        .and_then(|s| s.binary.clone());
 405
 406        if settings.as_ref().is_some_and(|b| b.path.is_some()) {
 407            let settings = settings.unwrap();
 408            return cx.spawn(|_| async move {
 409                Ok(LanguageServerBinary {
 410                    path: PathBuf::from(&settings.path.unwrap()),
 411                    env: Some(delegate.shell_env().await),
 412                    arguments: settings
 413                        .arguments
 414                        .unwrap_or_default()
 415                        .iter()
 416                        .map(Into::into)
 417                        .collect(),
 418                })
 419            });
 420        }
 421        let lsp_binary_options = LanguageServerBinaryOptions {
 422            allow_path_lookup: !settings
 423                .as_ref()
 424                .and_then(|b| b.ignore_system_version)
 425                .unwrap_or_default(),
 426            allow_binary_download,
 427        };
 428        let toolchains = self.toolchain_store.read(cx).as_language_toolchain_store();
 429        cx.spawn(|mut cx| async move {
 430            let binary_result = adapter
 431                .clone()
 432                .get_language_server_command(
 433                    delegate.clone(),
 434                    toolchains,
 435                    lsp_binary_options,
 436                    &mut cx,
 437                )
 438                .await;
 439
 440            delegate.update_status(adapter.name.clone(), LanguageServerBinaryStatus::None);
 441
 442            let mut binary = binary_result?;
 443            if let Some(arguments) = settings.and_then(|b| b.arguments) {
 444                binary.arguments = arguments.into_iter().map(Into::into).collect();
 445            }
 446
 447            let mut shell_env = delegate.shell_env().await;
 448            shell_env.extend(binary.env.unwrap_or_default());
 449            binary.env = Some(shell_env);
 450            Ok(binary)
 451        })
 452    }
 453
 454    fn setup_lsp_messages(
 455        this: WeakEntity<LspStore>,
 456        fs: Arc<dyn Fs>,
 457        language_server: &LanguageServer,
 458        delegate: Arc<dyn LspAdapterDelegate>,
 459        adapter: Arc<CachedLspAdapter>,
 460    ) {
 461        let name = language_server.name();
 462        let server_id = language_server.server_id();
 463        language_server
 464            .on_notification::<lsp::notification::PublishDiagnostics, _>({
 465                let adapter = adapter.clone();
 466                let this = this.clone();
 467                move |mut params, mut cx| {
 468                    let adapter = adapter.clone();
 469                    if let Some(this) = this.upgrade() {
 470                        adapter.process_diagnostics(&mut params);
 471                        this.update(&mut cx, |this, cx| {
 472                            this.update_diagnostics(
 473                                server_id,
 474                                params,
 475                                &adapter.disk_based_diagnostic_sources,
 476                                cx,
 477                            )
 478                            .log_err();
 479                        })
 480                        .ok();
 481                    }
 482                }
 483            })
 484            .detach();
 485        language_server
 486            .on_request::<lsp::request::WorkspaceConfiguration, _, _>({
 487                let adapter = adapter.adapter.clone();
 488                let delegate = delegate.clone();
 489                let this = this.clone();
 490                let fs = fs.clone();
 491                move |params, mut cx| {
 492                    let adapter = adapter.clone();
 493                    let delegate = delegate.clone();
 494                    let this = this.clone();
 495                    let fs = fs.clone();
 496                    async move {
 497                        let toolchains =
 498                            this.update(&mut cx, |this, cx| this.toolchain_store(cx))?;
 499                        let workspace_config = adapter
 500                            .workspace_configuration(fs.as_ref(), &delegate, toolchains, &mut cx)
 501                            .await?;
 502                        Ok(params
 503                            .items
 504                            .into_iter()
 505                            .map(|item| {
 506                                if let Some(section) = &item.section {
 507                                    workspace_config
 508                                        .get(section)
 509                                        .cloned()
 510                                        .unwrap_or(serde_json::Value::Null)
 511                                } else {
 512                                    workspace_config.clone()
 513                                }
 514                            })
 515                            .collect())
 516                    }
 517                }
 518            })
 519            .detach();
 520
 521        language_server
 522            .on_request::<lsp::request::WorkspaceFoldersRequest, _, _>({
 523                let this = this.clone();
 524                move |_, mut cx| {
 525                    let this = this.clone();
 526                    async move {
 527                        let Some(server) =
 528                            this.update(&mut cx, |this, _| this.language_server_for_id(server_id))?
 529                        else {
 530                            return Ok(None);
 531                        };
 532                        let root = server.workspace_folders();
 533                        Ok(Some(
 534                            root.iter()
 535                                .cloned()
 536                                .map(|uri| WorkspaceFolder {
 537                                    uri,
 538                                    name: Default::default(),
 539                                })
 540                                .collect(),
 541                        ))
 542                    }
 543                }
 544            })
 545            .detach();
 546        // Even though we don't have handling for these requests, respond to them to
 547        // avoid stalling any language server like `gopls` which waits for a response
 548        // to these requests when initializing.
 549        language_server
 550            .on_request::<lsp::request::WorkDoneProgressCreate, _, _>({
 551                let this = this.clone();
 552                move |params, mut cx| {
 553                    let this = this.clone();
 554                    async move {
 555                        this.update(&mut cx, |this, _| {
 556                            if let Some(status) = this.language_server_statuses.get_mut(&server_id)
 557                            {
 558                                if let lsp::NumberOrString::String(token) = params.token {
 559                                    status.progress_tokens.insert(token);
 560                                }
 561                            }
 562                        })?;
 563
 564                        Ok(())
 565                    }
 566                }
 567            })
 568            .detach();
 569
 570        language_server
 571            .on_request::<lsp::request::RegisterCapability, _, _>({
 572                let this = this.clone();
 573                move |params, mut cx| {
 574                    let this = this.clone();
 575                    async move {
 576                        for reg in params.registrations {
 577                            match reg.method.as_str() {
 578                                "workspace/didChangeWatchedFiles" => {
 579                                    if let Some(options) = reg.register_options {
 580                                        let options = serde_json::from_value(options)?;
 581                                        this.update(&mut cx, |this, cx| {
 582                                            this.as_local_mut()?.on_lsp_did_change_watched_files(
 583                                                server_id, &reg.id, options, cx,
 584                                            );
 585                                            Some(())
 586                                        })?;
 587                                    }
 588                                }
 589                                "textDocument/rangeFormatting" => {
 590                                    this.update(&mut cx, |this, _| {
 591                                        if let Some(server) = this.language_server_for_id(server_id)
 592                                        {
 593                                            let options = reg
 594                                                .register_options
 595                                                .map(|options| {
 596                                                    serde_json::from_value::<
 597                                                        lsp::DocumentRangeFormattingOptions,
 598                                                    >(
 599                                                        options
 600                                                    )
 601                                                })
 602                                                .transpose()?;
 603                                            let provider = match options {
 604                                                None => OneOf::Left(true),
 605                                                Some(options) => OneOf::Right(options),
 606                                            };
 607                                            server.update_capabilities(|capabilities| {
 608                                                capabilities.document_range_formatting_provider =
 609                                                    Some(provider);
 610                                            })
 611                                        }
 612                                        anyhow::Ok(())
 613                                    })??;
 614                                }
 615                                "textDocument/onTypeFormatting" => {
 616                                    this.update(&mut cx, |this, _| {
 617                                        if let Some(server) = this.language_server_for_id(server_id)
 618                                        {
 619                                            let options = reg
 620                                                .register_options
 621                                                .map(|options| {
 622                                                    serde_json::from_value::<
 623                                                        lsp::DocumentOnTypeFormattingOptions,
 624                                                    >(
 625                                                        options
 626                                                    )
 627                                                })
 628                                                .transpose()?;
 629                                            if let Some(options) = options {
 630                                                server.update_capabilities(|capabilities| {
 631                                                    capabilities
 632                                                        .document_on_type_formatting_provider =
 633                                                        Some(options);
 634                                                })
 635                                            }
 636                                        }
 637                                        anyhow::Ok(())
 638                                    })??;
 639                                }
 640                                "textDocument/formatting" => {
 641                                    this.update(&mut cx, |this, _| {
 642                                        if let Some(server) = this.language_server_for_id(server_id)
 643                                        {
 644                                            let options = reg
 645                                                .register_options
 646                                                .map(|options| {
 647                                                    serde_json::from_value::<
 648                                                        lsp::DocumentFormattingOptions,
 649                                                    >(
 650                                                        options
 651                                                    )
 652                                                })
 653                                                .transpose()?;
 654                                            let provider = match options {
 655                                                None => OneOf::Left(true),
 656                                                Some(options) => OneOf::Right(options),
 657                                            };
 658                                            server.update_capabilities(|capabilities| {
 659                                                capabilities.document_formatting_provider =
 660                                                    Some(provider);
 661                                            })
 662                                        }
 663                                        anyhow::Ok(())
 664                                    })??;
 665                                }
 666                                "workspace/didChangeConfiguration" => {
 667                                    // Ignore payload since we notify clients of setting changes unconditionally, relying on them pulling the latest settings.
 668                                }
 669                                _ => log::warn!("unhandled capability registration: {reg:?}"),
 670                            }
 671                        }
 672                        Ok(())
 673                    }
 674                }
 675            })
 676            .detach();
 677
 678        language_server
 679            .on_request::<lsp::request::UnregisterCapability, _, _>({
 680                let this = this.clone();
 681                move |params, mut cx| {
 682                    let this = this.clone();
 683                    async move {
 684                        for unreg in params.unregisterations.iter() {
 685                            match unreg.method.as_str() {
 686                                "workspace/didChangeWatchedFiles" => {
 687                                    this.update(&mut cx, |this, cx| {
 688                                        this.as_local_mut()?
 689                                            .on_lsp_unregister_did_change_watched_files(
 690                                                server_id, &unreg.id, cx,
 691                                            );
 692                                        Some(())
 693                                    })?;
 694                                }
 695                                "textDocument/rename" => {
 696                                    this.update(&mut cx, |this, _| {
 697                                        if let Some(server) = this.language_server_for_id(server_id)
 698                                        {
 699                                            server.update_capabilities(|capabilities| {
 700                                                capabilities.rename_provider = None
 701                                            })
 702                                        }
 703                                    })?;
 704                                }
 705                                "textDocument/rangeFormatting" => {
 706                                    this.update(&mut cx, |this, _| {
 707                                        if let Some(server) = this.language_server_for_id(server_id)
 708                                        {
 709                                            server.update_capabilities(|capabilities| {
 710                                                capabilities.document_range_formatting_provider =
 711                                                    None
 712                                            })
 713                                        }
 714                                    })?;
 715                                }
 716                                "textDocument/onTypeFormatting" => {
 717                                    this.update(&mut cx, |this, _| {
 718                                        if let Some(server) = this.language_server_for_id(server_id)
 719                                        {
 720                                            server.update_capabilities(|capabilities| {
 721                                                capabilities.document_on_type_formatting_provider =
 722                                                    None;
 723                                            })
 724                                        }
 725                                    })?;
 726                                }
 727                                "textDocument/formatting" => {
 728                                    this.update(&mut cx, |this, _| {
 729                                        if let Some(server) = this.language_server_for_id(server_id)
 730                                        {
 731                                            server.update_capabilities(|capabilities| {
 732                                                capabilities.document_formatting_provider = None;
 733                                            })
 734                                        }
 735                                    })?;
 736                                }
 737                                _ => log::warn!("unhandled capability unregistration: {unreg:?}"),
 738                            }
 739                        }
 740                        Ok(())
 741                    }
 742                }
 743            })
 744            .detach();
 745
 746        language_server
 747            .on_request::<lsp::request::ApplyWorkspaceEdit, _, _>({
 748                let adapter = adapter.clone();
 749                let this = this.clone();
 750                move |params, cx| {
 751                    LocalLspStore::on_lsp_workspace_edit(
 752                        this.clone(),
 753                        params,
 754                        server_id,
 755                        adapter.clone(),
 756                        cx,
 757                    )
 758                }
 759            })
 760            .detach();
 761
 762        language_server
 763            .on_request::<lsp::request::InlayHintRefreshRequest, _, _>({
 764                let this = this.clone();
 765                move |(), mut cx| {
 766                    let this = this.clone();
 767                    async move {
 768                        this.update(&mut cx, |this, cx| {
 769                            cx.emit(LspStoreEvent::RefreshInlayHints);
 770                            this.downstream_client.as_ref().map(|(client, project_id)| {
 771                                client.send(proto::RefreshInlayHints {
 772                                    project_id: *project_id,
 773                                })
 774                            })
 775                        })?
 776                        .transpose()?;
 777                        Ok(())
 778                    }
 779                }
 780            })
 781            .detach();
 782
 783        language_server
 784            .on_request::<lsp::request::ShowMessageRequest, _, _>({
 785                let this = this.clone();
 786                let name = name.to_string();
 787                move |params, mut cx| {
 788                    let this = this.clone();
 789                    let name = name.to_string();
 790                    async move {
 791                        let actions = params.actions.unwrap_or_default();
 792                        let (tx, rx) = smol::channel::bounded(1);
 793                        let request = LanguageServerPromptRequest {
 794                            level: match params.typ {
 795                                lsp::MessageType::ERROR => PromptLevel::Critical,
 796                                lsp::MessageType::WARNING => PromptLevel::Warning,
 797                                _ => PromptLevel::Info,
 798                            },
 799                            message: params.message,
 800                            actions,
 801                            response_channel: tx,
 802                            lsp_name: name.clone(),
 803                        };
 804
 805                        let did_update = this
 806                            .update(&mut cx, |_, cx| {
 807                                cx.emit(LspStoreEvent::LanguageServerPrompt(request));
 808                            })
 809                            .is_ok();
 810                        if did_update {
 811                            let response = rx.recv().await.ok();
 812                            Ok(response)
 813                        } else {
 814                            Ok(None)
 815                        }
 816                    }
 817                }
 818            })
 819            .detach();
 820
 821        language_server
 822            .on_notification::<ServerStatus, _>({
 823                let this = this.clone();
 824                let name = name.to_string();
 825                move |params, mut cx| {
 826                    let this = this.clone();
 827                    let name = name.to_string();
 828                    if let Some(ref message) = params.message {
 829                        let message = message.trim();
 830                        if !message.is_empty() {
 831                            let formatted_message = format!(
 832                                "Language server {name} (id {server_id}) status update: {message}"
 833                            );
 834                            match params.health {
 835                                ServerHealthStatus::Ok => log::info!("{}", formatted_message),
 836                                ServerHealthStatus::Warning => log::warn!("{}", formatted_message),
 837                                ServerHealthStatus::Error => {
 838                                    log::error!("{}", formatted_message);
 839                                    let (tx, _rx) = smol::channel::bounded(1);
 840                                    let request = LanguageServerPromptRequest {
 841                                        level: PromptLevel::Critical,
 842                                        message: params.message.unwrap_or_default(),
 843                                        actions: Vec::new(),
 844                                        response_channel: tx,
 845                                        lsp_name: name.clone(),
 846                                    };
 847                                    let _ = this
 848                                        .update(&mut cx, |_, cx| {
 849                                            cx.emit(LspStoreEvent::LanguageServerPrompt(request));
 850                                        })
 851                                        .ok();
 852                                }
 853                                ServerHealthStatus::Other(status) => {
 854                                    log::info!(
 855                                        "Unknown server health: {status}\n{formatted_message}"
 856                                    )
 857                                }
 858                            }
 859                        }
 860                    }
 861                }
 862            })
 863            .detach();
 864        language_server
 865            .on_notification::<lsp::notification::ShowMessage, _>({
 866                let this = this.clone();
 867                let name = name.to_string();
 868                move |params, mut cx| {
 869                    let this = this.clone();
 870                    let name = name.to_string();
 871
 872                    let (tx, _) = smol::channel::bounded(1);
 873                    let request = LanguageServerPromptRequest {
 874                        level: match params.typ {
 875                            lsp::MessageType::ERROR => PromptLevel::Critical,
 876                            lsp::MessageType::WARNING => PromptLevel::Warning,
 877                            _ => PromptLevel::Info,
 878                        },
 879                        message: params.message,
 880                        actions: vec![],
 881                        response_channel: tx,
 882                        lsp_name: name.clone(),
 883                    };
 884
 885                    let _ = this.update(&mut cx, |_, cx| {
 886                        cx.emit(LspStoreEvent::LanguageServerPrompt(request));
 887                    });
 888                }
 889            })
 890            .detach();
 891
 892        let disk_based_diagnostics_progress_token =
 893            adapter.disk_based_diagnostics_progress_token.clone();
 894
 895        language_server
 896            .on_notification::<lsp::notification::Progress, _>({
 897                let this = this.clone();
 898                move |params, mut cx| {
 899                    if let Some(this) = this.upgrade() {
 900                        this.update(&mut cx, |this, cx| {
 901                            this.on_lsp_progress(
 902                                params,
 903                                server_id,
 904                                disk_based_diagnostics_progress_token.clone(),
 905                                cx,
 906                            );
 907                        })
 908                        .ok();
 909                    }
 910                }
 911            })
 912            .detach();
 913
 914        language_server
 915            .on_notification::<lsp::notification::LogMessage, _>({
 916                let this = this.clone();
 917                move |params, mut cx| {
 918                    if let Some(this) = this.upgrade() {
 919                        this.update(&mut cx, |_, cx| {
 920                            cx.emit(LspStoreEvent::LanguageServerLog(
 921                                server_id,
 922                                LanguageServerLogType::Log(params.typ),
 923                                params.message,
 924                            ));
 925                        })
 926                        .ok();
 927                    }
 928                }
 929            })
 930            .detach();
 931
 932        language_server
 933            .on_notification::<lsp::notification::LogTrace, _>({
 934                let this = this.clone();
 935                move |params, mut cx| {
 936                    if let Some(this) = this.upgrade() {
 937                        this.update(&mut cx, |_, cx| {
 938                            cx.emit(LspStoreEvent::LanguageServerLog(
 939                                server_id,
 940                                LanguageServerLogType::Trace(params.verbose),
 941                                params.message,
 942                            ));
 943                        })
 944                        .ok();
 945                    }
 946                }
 947            })
 948            .detach();
 949    }
 950
 951    fn shutdown_language_servers(
 952        &mut self,
 953        _cx: &mut Context<LspStore>,
 954    ) -> impl Future<Output = ()> {
 955        let shutdown_futures = self
 956            .language_servers
 957            .drain()
 958            .map(|(_, server_state)| async {
 959                use LanguageServerState::*;
 960                match server_state {
 961                    Running { server, .. } => server.shutdown()?.await,
 962                    Starting { startup, .. } => startup.await?.shutdown()?.await,
 963                }
 964            })
 965            .collect::<Vec<_>>();
 966
 967        async move {
 968            futures::future::join_all(shutdown_futures).await;
 969        }
 970    }
 971
 972    fn language_servers_for_worktree(
 973        &self,
 974        worktree_id: WorktreeId,
 975    ) -> impl Iterator<Item = &Arc<LanguageServer>> {
 976        self.language_server_ids
 977            .iter()
 978            .flat_map(move |((language_server_path, _), ids)| {
 979                ids.iter().filter_map(move |id| {
 980                    if *language_server_path != worktree_id {
 981                        return None;
 982                    }
 983                    if let Some(LanguageServerState::Running { server, .. }) =
 984                        self.language_servers.get(id)
 985                    {
 986                        return Some(server);
 987                    } else {
 988                        None
 989                    }
 990                })
 991            })
 992    }
 993
 994    fn language_server_ids_for_project_path(
 995        &self,
 996        project_path: ProjectPath,
 997        language: &Language,
 998        cx: &mut App,
 999    ) -> Vec<LanguageServerId> {
1000        let Some(worktree) = self
1001            .worktree_store
1002            .read(cx)
1003            .worktree_for_id(project_path.worktree_id, cx)
1004        else {
1005            return vec![];
1006        };
1007        let delegate = LocalLspAdapterDelegate::from_local_lsp(self, &worktree, cx);
1008        let root = self.lsp_tree.update(cx, |this, cx| {
1009            this.get(
1010                project_path,
1011                AdapterQuery::Language(&language.name()),
1012                delegate,
1013                cx,
1014            )
1015            .filter_map(|node| node.server_id())
1016            .collect::<Vec<_>>()
1017        });
1018
1019        root
1020    }
1021
1022    fn language_server_ids_for_buffer(
1023        &self,
1024        buffer: &Buffer,
1025        cx: &mut App,
1026    ) -> Vec<LanguageServerId> {
1027        if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) {
1028            let worktree_id = file.worktree_id(cx);
1029
1030            let path: Arc<Path> = file
1031                .path()
1032                .parent()
1033                .map(Arc::from)
1034                .unwrap_or_else(|| file.path().clone());
1035            let worktree_path = ProjectPath { worktree_id, path };
1036            self.language_server_ids_for_project_path(worktree_path, language, cx)
1037        } else {
1038            Vec::new()
1039        }
1040    }
1041
1042    fn language_servers_for_buffer<'a>(
1043        &'a self,
1044        buffer: &'a Buffer,
1045        cx: &'a mut App,
1046    ) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
1047        self.language_server_ids_for_buffer(buffer, cx)
1048            .into_iter()
1049            .filter_map(|server_id| match self.language_servers.get(&server_id)? {
1050                LanguageServerState::Running {
1051                    adapter, server, ..
1052                } => Some((adapter, server)),
1053                _ => None,
1054            })
1055    }
1056
1057    fn primary_language_server_for_buffer<'a>(
1058        &'a self,
1059        buffer: &'a Buffer,
1060        cx: &'a mut App,
1061    ) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
1062        // The list of language servers is ordered based on the `language_servers` setting
1063        // for each language, thus we can consider the first one in the list to be the
1064        // primary one.
1065        self.language_servers_for_buffer(buffer, cx).next()
1066    }
1067
1068    async fn format_locally(
1069        lsp_store: WeakEntity<LspStore>,
1070        mut buffers: Vec<FormattableBuffer>,
1071        push_to_history: bool,
1072        trigger: FormatTrigger,
1073        mut cx: AsyncApp,
1074    ) -> anyhow::Result<ProjectTransaction> {
1075        // Do not allow multiple concurrent formatting requests for the
1076        // same buffer.
1077        lsp_store.update(&mut cx, |this, cx| {
1078            let this = this.as_local_mut().unwrap();
1079            buffers.retain(|buffer| {
1080                this.buffers_being_formatted
1081                    .insert(buffer.handle.read(cx).remote_id())
1082            });
1083        })?;
1084
1085        let _cleanup = defer({
1086            let this = lsp_store.clone();
1087            let mut cx = cx.clone();
1088            let buffers = &buffers;
1089            move || {
1090                this.update(&mut cx, |this, cx| {
1091                    let this = this.as_local_mut().unwrap();
1092                    for buffer in buffers {
1093                        this.buffers_being_formatted
1094                            .remove(&buffer.handle.read(cx).remote_id());
1095                    }
1096                })
1097                .ok();
1098            }
1099        });
1100
1101        let mut project_transaction = ProjectTransaction::default();
1102        for buffer in &buffers {
1103            let adapters_and_servers = lsp_store.update(&mut cx, |lsp_store, cx| {
1104                buffer.handle.update(cx, |buffer, cx| {
1105                    lsp_store
1106                        .as_local()
1107                        .unwrap()
1108                        .language_servers_for_buffer(buffer, cx)
1109                        .map(|(adapter, lsp)| (adapter.clone(), lsp.clone()))
1110                        .collect::<Vec<_>>()
1111                })
1112            })?;
1113
1114            let settings = buffer.handle.update(&mut cx, |buffer, cx| {
1115                language_settings(buffer.language().map(|l| l.name()), buffer.file(), cx)
1116                    .into_owned()
1117            })?;
1118
1119            let remove_trailing_whitespace = settings.remove_trailing_whitespace_on_save;
1120            let ensure_final_newline = settings.ensure_final_newline_on_save;
1121
1122            // First, format buffer's whitespace according to the settings.
1123            let trailing_whitespace_diff = if remove_trailing_whitespace {
1124                Some(
1125                    buffer
1126                        .handle
1127                        .update(&mut cx, |b, cx| b.remove_trailing_whitespace(cx))?
1128                        .await,
1129                )
1130            } else {
1131                None
1132            };
1133            let whitespace_transaction_id = buffer.handle.update(&mut cx, |buffer, cx| {
1134                buffer.finalize_last_transaction();
1135                buffer.start_transaction();
1136                if let Some(diff) = trailing_whitespace_diff {
1137                    buffer.apply_diff(diff, cx);
1138                }
1139                if ensure_final_newline {
1140                    buffer.ensure_final_newline(cx);
1141                }
1142                buffer.end_transaction(cx)
1143            })?;
1144
1145            let initial_transaction_id = whitespace_transaction_id;
1146
1147            // Apply the `code_actions_on_format` before we run the formatter.
1148            let code_actions = deserialize_code_actions(&settings.code_actions_on_format);
1149            #[allow(clippy::nonminimal_bool)]
1150            if !code_actions.is_empty()
1151                && !(trigger == FormatTrigger::Save && settings.format_on_save == FormatOnSave::Off)
1152            {
1153                Self::execute_code_actions_on_servers(
1154                    &lsp_store,
1155                    &adapters_and_servers,
1156                    code_actions,
1157                    &buffer.handle,
1158                    push_to_history,
1159                    &mut project_transaction,
1160                    &mut cx,
1161                )
1162                .await?;
1163            }
1164
1165            let prettier_settings = buffer.handle.read_with(&cx, |buffer, cx| {
1166                language_settings(buffer.language().map(|l| l.name()), buffer.file(), cx)
1167                    .prettier
1168                    .clone()
1169            })?;
1170
1171            let formatters = match (trigger, &settings.format_on_save) {
1172                (FormatTrigger::Save, FormatOnSave::Off) => &[],
1173                (FormatTrigger::Save, FormatOnSave::List(formatters)) => formatters.as_ref(),
1174                (FormatTrigger::Manual, _) | (FormatTrigger::Save, FormatOnSave::On) => {
1175                    match &settings.formatter {
1176                        SelectedFormatter::Auto => {
1177                            if prettier_settings.allowed {
1178                                std::slice::from_ref(&Formatter::Prettier)
1179                            } else {
1180                                std::slice::from_ref(&Formatter::LanguageServer { name: None })
1181                            }
1182                        }
1183                        SelectedFormatter::List(formatter_list) => formatter_list.as_ref(),
1184                    }
1185                }
1186            };
1187            Self::execute_formatters(
1188                lsp_store.clone(),
1189                formatters,
1190                buffer,
1191                &settings,
1192                &adapters_and_servers,
1193                push_to_history,
1194                initial_transaction_id,
1195                &mut project_transaction,
1196                &mut cx,
1197            )
1198            .await?;
1199        }
1200
1201        Ok(project_transaction)
1202    }
1203
1204    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(completions, language, lsp_adapter, &mut result)
4208                    .await;
4209                Ok(result)
4210            })
4211        } else if let Some(local) = self.as_local() {
4212            let snapshot = buffer.read(cx).snapshot();
4213            let offset = position.to_offset(&snapshot);
4214            let scope = snapshot.language_scope_at(offset);
4215            let language = snapshot.language().cloned();
4216
4217            let server_ids: Vec<_> = buffer.update(cx, |buffer, cx| {
4218                local
4219                    .language_servers_for_buffer(buffer, cx)
4220                    .filter(|(_, server)| server.capabilities().completion_provider.is_some())
4221                    .filter(|(adapter, _)| {
4222                        scope
4223                            .as_ref()
4224                            .map(|scope| scope.language_allowed(&adapter.name))
4225                            .unwrap_or(true)
4226                    })
4227                    .map(|(_, server)| server.server_id())
4228                    .collect()
4229            });
4230
4231            let buffer = buffer.clone();
4232            cx.spawn(move |this, mut cx| async move {
4233                let mut tasks = Vec::with_capacity(server_ids.len());
4234                this.update(&mut cx, |this, cx| {
4235                    for server_id in server_ids {
4236                        let lsp_adapter = this.language_server_adapter_for_id(server_id);
4237                        tasks.push((
4238                            lsp_adapter,
4239                            this.request_lsp(
4240                                buffer.clone(),
4241                                LanguageServerToQuery::Other(server_id),
4242                                GetCompletions {
4243                                    position,
4244                                    context: context.clone(),
4245                                },
4246                                cx,
4247                            ),
4248                        ));
4249                    }
4250                })?;
4251
4252                let mut completions = Vec::new();
4253                for (lsp_adapter, task) in tasks {
4254                    if let Ok(new_completions) = task.await {
4255                        populate_labels_for_completions(
4256                            new_completions,
4257                            language.clone(),
4258                            lsp_adapter,
4259                            &mut completions,
4260                        )
4261                        .await;
4262                    }
4263                }
4264
4265                Ok(completions)
4266            })
4267        } else {
4268            Task::ready(Err(anyhow!("No upstream client or local language server")))
4269        }
4270    }
4271
4272    pub fn resolve_completions(
4273        &self,
4274        buffer: Entity<Buffer>,
4275        completion_indices: Vec<usize>,
4276        completions: Rc<RefCell<Box<[Completion]>>>,
4277        cx: &mut Context<Self>,
4278    ) -> Task<Result<bool>> {
4279        let client = self.upstream_client();
4280
4281        let buffer_id = buffer.read(cx).remote_id();
4282        let buffer_snapshot = buffer.read(cx).snapshot();
4283
4284        cx.spawn(move |this, cx| async move {
4285            let mut did_resolve = false;
4286            if let Some((client, project_id)) = client {
4287                for completion_index in completion_indices {
4288                    let server_id = completions.borrow()[completion_index].server_id;
4289
4290                    if Self::resolve_completion_remote(
4291                        project_id,
4292                        server_id,
4293                        buffer_id,
4294                        completions.clone(),
4295                        completion_index,
4296                        client.clone(),
4297                    )
4298                    .await
4299                    .log_err()
4300                    .is_some()
4301                    {
4302                        did_resolve = true;
4303                    }
4304                }
4305            } else {
4306                for completion_index in completion_indices {
4307                    let server_id = completions.borrow()[completion_index].server_id;
4308
4309                    let server_and_adapter = this
4310                        .read_with(&cx, |lsp_store, _| {
4311                            let server = lsp_store.language_server_for_id(server_id)?;
4312                            let adapter =
4313                                lsp_store.language_server_adapter_for_id(server.server_id())?;
4314                            Some((server, adapter))
4315                        })
4316                        .ok()
4317                        .flatten();
4318                    let Some((server, adapter)) = server_and_adapter else {
4319                        continue;
4320                    };
4321
4322                    let resolved = Self::resolve_completion_local(
4323                        server,
4324                        &buffer_snapshot,
4325                        completions.clone(),
4326                        completion_index,
4327                    )
4328                    .await
4329                    .log_err()
4330                    .is_some();
4331                    if resolved {
4332                        Self::regenerate_completion_labels(
4333                            adapter,
4334                            &buffer_snapshot,
4335                            completions.clone(),
4336                            completion_index,
4337                        )
4338                        .await
4339                        .log_err();
4340                        did_resolve = true;
4341                    }
4342                }
4343            }
4344
4345            Ok(did_resolve)
4346        })
4347    }
4348
4349    async fn resolve_completion_local(
4350        server: Arc<lsp::LanguageServer>,
4351        snapshot: &BufferSnapshot,
4352        completions: Rc<RefCell<Box<[Completion]>>>,
4353        completion_index: usize,
4354    ) -> Result<()> {
4355        let can_resolve = server
4356            .capabilities()
4357            .completion_provider
4358            .as_ref()
4359            .and_then(|options| options.resolve_provider)
4360            .unwrap_or(false);
4361        if !can_resolve {
4362            return Ok(());
4363        }
4364
4365        let request = {
4366            let completion = &completions.borrow()[completion_index];
4367            if completion.resolved {
4368                return Ok(());
4369            }
4370            server.request::<lsp::request::ResolveCompletionItem>(completion.lsp_completion.clone())
4371        };
4372        let completion_item = request.await?;
4373
4374        if let Some(text_edit) = completion_item.text_edit.as_ref() {
4375            // Technically we don't have to parse the whole `text_edit`, since the only
4376            // language server we currently use that does update `text_edit` in `completionItem/resolve`
4377            // is `typescript-language-server` and they only update `text_edit.new_text`.
4378            // But we should not rely on that.
4379            let edit = parse_completion_text_edit(text_edit, snapshot);
4380
4381            if let Some((old_range, mut new_text)) = edit {
4382                LineEnding::normalize(&mut new_text);
4383
4384                let mut completions = completions.borrow_mut();
4385                let completion = &mut completions[completion_index];
4386
4387                completion.new_text = new_text;
4388                completion.old_range = old_range;
4389            }
4390        }
4391        if completion_item.insert_text_format == Some(InsertTextFormat::SNIPPET) {
4392            // vtsls might change the type of completion after resolution.
4393            let mut completions = completions.borrow_mut();
4394            let completion = &mut completions[completion_index];
4395            if completion_item.insert_text_format != completion.lsp_completion.insert_text_format {
4396                completion.lsp_completion.insert_text_format = completion_item.insert_text_format;
4397            }
4398        }
4399
4400        let mut completions = completions.borrow_mut();
4401        let completion = &mut completions[completion_index];
4402        completion.lsp_completion = completion_item;
4403        completion.resolved = true;
4404        Ok(())
4405    }
4406
4407    async fn regenerate_completion_labels(
4408        adapter: Arc<CachedLspAdapter>,
4409        snapshot: &BufferSnapshot,
4410        completions: Rc<RefCell<Box<[Completion]>>>,
4411        completion_index: usize,
4412    ) -> Result<()> {
4413        let completion_item = completions.borrow()[completion_index]
4414            .lsp_completion
4415            .clone();
4416        if let Some(lsp_documentation) = completion_item.documentation.clone() {
4417            let mut completions = completions.borrow_mut();
4418            let completion = &mut completions[completion_index];
4419            completion.documentation = Some(lsp_documentation.into());
4420        } else {
4421            let mut completions = completions.borrow_mut();
4422            let completion = &mut completions[completion_index];
4423            completion.documentation = Some(CompletionDocumentation::Undocumented);
4424        }
4425
4426        // 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
4427        // So we have to update the label here anyway...
4428        let language = snapshot.language();
4429        let mut new_label = match language {
4430            Some(language) => {
4431                adapter
4432                    .labels_for_completions(&[completion_item.clone()], language)
4433                    .await?
4434            }
4435            None => Vec::new(),
4436        }
4437        .pop()
4438        .flatten()
4439        .unwrap_or_else(|| {
4440            CodeLabel::fallback_for_completion(
4441                &completion_item,
4442                language.map(|language| language.as_ref()),
4443            )
4444        });
4445        ensure_uniform_list_compatible_label(&mut new_label);
4446
4447        let mut completions = completions.borrow_mut();
4448        let completion = &mut completions[completion_index];
4449        if completion.label.filter_text() == new_label.filter_text() {
4450            completion.label = new_label;
4451        } else {
4452            log::error!(
4453                "Resolved completion changed display label from {} to {}. \
4454                 Refusing to apply this because it changes the fuzzy match text from {} to {}",
4455                completion.label.text(),
4456                new_label.text(),
4457                completion.label.filter_text(),
4458                new_label.filter_text()
4459            );
4460        }
4461
4462        Ok(())
4463    }
4464
4465    async fn resolve_completion_remote(
4466        project_id: u64,
4467        server_id: LanguageServerId,
4468        buffer_id: BufferId,
4469        completions: Rc<RefCell<Box<[Completion]>>>,
4470        completion_index: usize,
4471        client: AnyProtoClient,
4472    ) -> Result<()> {
4473        let lsp_completion = {
4474            let completion = &completions.borrow()[completion_index];
4475            if completion.resolved {
4476                return Ok(());
4477            }
4478            serde_json::to_string(&completion.lsp_completion)
4479                .unwrap()
4480                .into_bytes()
4481        };
4482        let request = proto::ResolveCompletionDocumentation {
4483            project_id,
4484            language_server_id: server_id.0 as u64,
4485            lsp_completion,
4486            buffer_id: buffer_id.into(),
4487        };
4488
4489        let response = client
4490            .request(request)
4491            .await
4492            .context("completion documentation resolve proto request")?;
4493        let lsp_completion = serde_json::from_slice(&response.lsp_completion)?;
4494
4495        let documentation = if response.documentation.is_empty() {
4496            CompletionDocumentation::Undocumented
4497        } else if response.documentation_is_markdown {
4498            CompletionDocumentation::MultiLineMarkdown(response.documentation.into())
4499        } else if response.documentation.lines().count() <= 1 {
4500            CompletionDocumentation::SingleLine(response.documentation.into())
4501        } else {
4502            CompletionDocumentation::MultiLinePlainText(response.documentation.into())
4503        };
4504
4505        let mut completions = completions.borrow_mut();
4506        let completion = &mut completions[completion_index];
4507        completion.documentation = Some(documentation);
4508        completion.lsp_completion = lsp_completion;
4509        completion.resolved = true;
4510
4511        let old_range = response
4512            .old_start
4513            .and_then(deserialize_anchor)
4514            .zip(response.old_end.and_then(deserialize_anchor));
4515        if let Some((old_start, old_end)) = old_range {
4516            if !response.new_text.is_empty() {
4517                completion.new_text = response.new_text;
4518                completion.old_range = old_start..old_end;
4519            }
4520        }
4521
4522        Ok(())
4523    }
4524
4525    pub fn apply_additional_edits_for_completion(
4526        &self,
4527        buffer_handle: Entity<Buffer>,
4528        completions: Rc<RefCell<Box<[Completion]>>>,
4529        completion_index: usize,
4530        push_to_history: bool,
4531        cx: &mut Context<Self>,
4532    ) -> Task<Result<Option<Transaction>>> {
4533        if let Some((client, project_id)) = self.upstream_client() {
4534            let buffer = buffer_handle.read(cx);
4535            let buffer_id = buffer.remote_id();
4536            cx.spawn(move |_, mut cx| async move {
4537                let request = {
4538                    let completion = completions.borrow()[completion_index].clone();
4539                    proto::ApplyCompletionAdditionalEdits {
4540                        project_id,
4541                        buffer_id: buffer_id.into(),
4542                        completion: Some(Self::serialize_completion(&CoreCompletion {
4543                            old_range: completion.old_range,
4544                            new_text: completion.new_text,
4545                            server_id: completion.server_id,
4546                            lsp_completion: completion.lsp_completion,
4547                            resolved: completion.resolved,
4548                        })),
4549                    }
4550                };
4551
4552                let response = client.request(request).await?;
4553                completions.borrow_mut()[completion_index].resolved = true;
4554
4555                if let Some(transaction) = response.transaction {
4556                    let transaction = language::proto::deserialize_transaction(transaction)?;
4557                    buffer_handle
4558                        .update(&mut cx, |buffer, _| {
4559                            buffer.wait_for_edits(transaction.edit_ids.iter().copied())
4560                        })?
4561                        .await?;
4562                    if push_to_history {
4563                        buffer_handle.update(&mut cx, |buffer, _| {
4564                            buffer.push_transaction(transaction.clone(), Instant::now());
4565                        })?;
4566                    }
4567                    Ok(Some(transaction))
4568                } else {
4569                    Ok(None)
4570                }
4571            })
4572        } else {
4573            let server_id = completions.borrow()[completion_index].server_id;
4574            let Some(server) = buffer_handle.update(cx, |buffer, cx| {
4575                Some(
4576                    self.language_server_for_local_buffer(buffer, server_id, cx)?
4577                        .1
4578                        .clone(),
4579                )
4580            }) else {
4581                return Task::ready(Ok(None));
4582            };
4583            let snapshot = buffer_handle.read(&cx).snapshot();
4584
4585            cx.spawn(move |this, mut cx| async move {
4586                Self::resolve_completion_local(
4587                    server.clone(),
4588                    &snapshot,
4589                    completions.clone(),
4590                    completion_index,
4591                )
4592                .await
4593                .context("resolving completion")?;
4594                let completion = completions.borrow()[completion_index].clone();
4595                let additional_text_edits = completion.lsp_completion.additional_text_edits;
4596                if let Some(edits) = additional_text_edits {
4597                    let edits = this
4598                        .update(&mut cx, |this, cx| {
4599                            this.as_local_mut().unwrap().edits_from_lsp(
4600                                &buffer_handle,
4601                                edits,
4602                                server.server_id(),
4603                                None,
4604                                cx,
4605                            )
4606                        })?
4607                        .await?;
4608
4609                    buffer_handle.update(&mut cx, |buffer, cx| {
4610                        buffer.finalize_last_transaction();
4611                        buffer.start_transaction();
4612
4613                        for (range, text) in edits {
4614                            let primary = &completion.old_range;
4615                            let start_within = primary.start.cmp(&range.start, buffer).is_le()
4616                                && primary.end.cmp(&range.start, buffer).is_ge();
4617                            let end_within = range.start.cmp(&primary.end, buffer).is_le()
4618                                && range.end.cmp(&primary.end, buffer).is_ge();
4619
4620                            //Skip additional edits which overlap with the primary completion edit
4621                            //https://github.com/zed-industries/zed/pull/1871
4622                            if !start_within && !end_within {
4623                                buffer.edit([(range, text)], None, cx);
4624                            }
4625                        }
4626
4627                        let transaction = if buffer.end_transaction(cx).is_some() {
4628                            let transaction = buffer.finalize_last_transaction().unwrap().clone();
4629                            if !push_to_history {
4630                                buffer.forget_transaction(transaction.id);
4631                            }
4632                            Some(transaction)
4633                        } else {
4634                            None
4635                        };
4636                        Ok(transaction)
4637                    })?
4638                } else {
4639                    Ok(None)
4640                }
4641            })
4642        }
4643    }
4644
4645    pub fn inlay_hints(
4646        &mut self,
4647        buffer_handle: Entity<Buffer>,
4648        range: Range<Anchor>,
4649        cx: &mut Context<Self>,
4650    ) -> Task<anyhow::Result<Vec<InlayHint>>> {
4651        let buffer = buffer_handle.read(cx);
4652        let range_start = range.start;
4653        let range_end = range.end;
4654        let buffer_id = buffer.remote_id().into();
4655        let lsp_request = InlayHints { range };
4656
4657        if let Some((client, project_id)) = self.upstream_client() {
4658            let request = proto::InlayHints {
4659                project_id,
4660                buffer_id,
4661                start: Some(serialize_anchor(&range_start)),
4662                end: Some(serialize_anchor(&range_end)),
4663                version: serialize_version(&buffer_handle.read(cx).version()),
4664            };
4665            cx.spawn(move |project, cx| async move {
4666                let response = client
4667                    .request(request)
4668                    .await
4669                    .context("inlay hints proto request")?;
4670                LspCommand::response_from_proto(
4671                    lsp_request,
4672                    response,
4673                    project.upgrade().ok_or_else(|| anyhow!("No project"))?,
4674                    buffer_handle.clone(),
4675                    cx.clone(),
4676                )
4677                .await
4678                .context("inlay hints proto response conversion")
4679            })
4680        } else {
4681            let lsp_request_task = self.request_lsp(
4682                buffer_handle.clone(),
4683                LanguageServerToQuery::Primary,
4684                lsp_request,
4685                cx,
4686            );
4687            cx.spawn(move |_, mut cx| async move {
4688                buffer_handle
4689                    .update(&mut cx, |buffer, _| {
4690                        buffer.wait_for_edits(vec![range_start.timestamp, range_end.timestamp])
4691                    })?
4692                    .await
4693                    .context("waiting for inlay hint request range edits")?;
4694                lsp_request_task.await.context("inlay hints LSP request")
4695            })
4696        }
4697    }
4698
4699    pub fn signature_help<T: ToPointUtf16>(
4700        &mut self,
4701        buffer: &Entity<Buffer>,
4702        position: T,
4703        cx: &mut Context<Self>,
4704    ) -> Task<Vec<SignatureHelp>> {
4705        let position = position.to_point_utf16(buffer.read(cx));
4706
4707        if let Some((client, upstream_project_id)) = self.upstream_client() {
4708            let request_task = client.request(proto::MultiLspQuery {
4709                buffer_id: buffer.read(cx).remote_id().into(),
4710                version: serialize_version(&buffer.read(cx).version()),
4711                project_id: upstream_project_id,
4712                strategy: Some(proto::multi_lsp_query::Strategy::All(
4713                    proto::AllLanguageServers {},
4714                )),
4715                request: Some(proto::multi_lsp_query::Request::GetSignatureHelp(
4716                    GetSignatureHelp { position }.to_proto(upstream_project_id, buffer.read(cx)),
4717                )),
4718            });
4719            let buffer = buffer.clone();
4720            cx.spawn(|weak_project, cx| async move {
4721                let Some(project) = weak_project.upgrade() else {
4722                    return Vec::new();
4723                };
4724                join_all(
4725                    request_task
4726                        .await
4727                        .log_err()
4728                        .map(|response| response.responses)
4729                        .unwrap_or_default()
4730                        .into_iter()
4731                        .filter_map(|lsp_response| match lsp_response.response? {
4732                            proto::lsp_response::Response::GetSignatureHelpResponse(response) => {
4733                                Some(response)
4734                            }
4735                            unexpected => {
4736                                debug_panic!("Unexpected response: {unexpected:?}");
4737                                None
4738                            }
4739                        })
4740                        .map(|signature_response| {
4741                            let response = GetSignatureHelp { position }.response_from_proto(
4742                                signature_response,
4743                                project.clone(),
4744                                buffer.clone(),
4745                                cx.clone(),
4746                            );
4747                            async move { response.await.log_err().flatten() }
4748                        }),
4749                )
4750                .await
4751                .into_iter()
4752                .flatten()
4753                .collect()
4754            })
4755        } else {
4756            let all_actions_task = self.request_multiple_lsp_locally(
4757                buffer,
4758                Some(position),
4759                GetSignatureHelp { position },
4760                cx,
4761            );
4762            cx.spawn(|_, _| async move {
4763                all_actions_task
4764                    .await
4765                    .into_iter()
4766                    .flatten()
4767                    .filter(|help| !help.markdown.is_empty())
4768                    .collect::<Vec<_>>()
4769            })
4770        }
4771    }
4772
4773    pub fn hover(
4774        &mut self,
4775        buffer: &Entity<Buffer>,
4776        position: PointUtf16,
4777        cx: &mut Context<Self>,
4778    ) -> Task<Vec<Hover>> {
4779        if let Some((client, upstream_project_id)) = self.upstream_client() {
4780            let request_task = client.request(proto::MultiLspQuery {
4781                buffer_id: buffer.read(cx).remote_id().into(),
4782                version: serialize_version(&buffer.read(cx).version()),
4783                project_id: upstream_project_id,
4784                strategy: Some(proto::multi_lsp_query::Strategy::All(
4785                    proto::AllLanguageServers {},
4786                )),
4787                request: Some(proto::multi_lsp_query::Request::GetHover(
4788                    GetHover { position }.to_proto(upstream_project_id, buffer.read(cx)),
4789                )),
4790            });
4791            let buffer = buffer.clone();
4792            cx.spawn(|weak_project, cx| async move {
4793                let Some(project) = weak_project.upgrade() else {
4794                    return Vec::new();
4795                };
4796                join_all(
4797                    request_task
4798                        .await
4799                        .log_err()
4800                        .map(|response| response.responses)
4801                        .unwrap_or_default()
4802                        .into_iter()
4803                        .filter_map(|lsp_response| match lsp_response.response? {
4804                            proto::lsp_response::Response::GetHoverResponse(response) => {
4805                                Some(response)
4806                            }
4807                            unexpected => {
4808                                debug_panic!("Unexpected response: {unexpected:?}");
4809                                None
4810                            }
4811                        })
4812                        .map(|hover_response| {
4813                            let response = GetHover { position }.response_from_proto(
4814                                hover_response,
4815                                project.clone(),
4816                                buffer.clone(),
4817                                cx.clone(),
4818                            );
4819                            async move {
4820                                response
4821                                    .await
4822                                    .log_err()
4823                                    .flatten()
4824                                    .and_then(remove_empty_hover_blocks)
4825                            }
4826                        }),
4827                )
4828                .await
4829                .into_iter()
4830                .flatten()
4831                .collect()
4832            })
4833        } else {
4834            let all_actions_task = self.request_multiple_lsp_locally(
4835                buffer,
4836                Some(position),
4837                GetHover { position },
4838                cx,
4839            );
4840            cx.spawn(|_, _| async move {
4841                all_actions_task
4842                    .await
4843                    .into_iter()
4844                    .filter_map(|hover| remove_empty_hover_blocks(hover?))
4845                    .collect::<Vec<Hover>>()
4846            })
4847        }
4848    }
4849
4850    pub fn symbols(&self, query: &str, cx: &mut Context<Self>) -> Task<Result<Vec<Symbol>>> {
4851        let language_registry = self.languages.clone();
4852
4853        if let Some((upstream_client, project_id)) = self.upstream_client().as_ref() {
4854            let request = upstream_client.request(proto::GetProjectSymbols {
4855                project_id: *project_id,
4856                query: query.to_string(),
4857            });
4858            cx.foreground_executor().spawn(async move {
4859                let response = request.await?;
4860                let mut symbols = Vec::new();
4861                let core_symbols = response
4862                    .symbols
4863                    .into_iter()
4864                    .filter_map(|symbol| Self::deserialize_symbol(symbol).log_err())
4865                    .collect::<Vec<_>>();
4866                populate_labels_for_symbols(core_symbols, &language_registry, None, &mut symbols)
4867                    .await;
4868                Ok(symbols)
4869            })
4870        } else if let Some(local) = self.as_local() {
4871            struct WorkspaceSymbolsResult {
4872                server_id: LanguageServerId,
4873                lsp_adapter: Arc<CachedLspAdapter>,
4874                worktree: WeakEntity<Worktree>,
4875                worktree_abs_path: Arc<Path>,
4876                lsp_symbols: Vec<(String, SymbolKind, lsp::Location)>,
4877            }
4878
4879            let mut requests = Vec::new();
4880            let mut requested_servers = BTreeSet::new();
4881            'next_server: for ((worktree_id, _), server_ids) in local.language_server_ids.iter() {
4882                let Some(worktree_handle) = self
4883                    .worktree_store
4884                    .read(cx)
4885                    .worktree_for_id(*worktree_id, cx)
4886                else {
4887                    continue;
4888                };
4889                let worktree = worktree_handle.read(cx);
4890                if !worktree.is_visible() {
4891                    continue;
4892                }
4893
4894                let mut servers_to_query = server_ids
4895                    .difference(&requested_servers)
4896                    .cloned()
4897                    .collect::<BTreeSet<_>>();
4898                for server_id in &servers_to_query {
4899                    let (lsp_adapter, server) = match local.language_servers.get(server_id) {
4900                        Some(LanguageServerState::Running {
4901                            adapter, server, ..
4902                        }) => (adapter.clone(), server),
4903
4904                        _ => continue 'next_server,
4905                    };
4906                    let worktree_abs_path = worktree.abs_path().clone();
4907                    let worktree_handle = worktree_handle.clone();
4908                    let server_id = server.server_id();
4909                    requests.push(
4910                            server
4911                                .request::<lsp::request::WorkspaceSymbolRequest>(
4912                                    lsp::WorkspaceSymbolParams {
4913                                        query: query.to_string(),
4914                                        ..Default::default()
4915                                    },
4916                                )
4917                                .log_err()
4918                                .map(move |response| {
4919                                    let lsp_symbols = response.flatten().map(|symbol_response| match symbol_response {
4920                                        lsp::WorkspaceSymbolResponse::Flat(flat_responses) => {
4921                                            flat_responses.into_iter().map(|lsp_symbol| {
4922                                            (lsp_symbol.name, lsp_symbol.kind, lsp_symbol.location)
4923                                            }).collect::<Vec<_>>()
4924                                        }
4925                                        lsp::WorkspaceSymbolResponse::Nested(nested_responses) => {
4926                                            nested_responses.into_iter().filter_map(|lsp_symbol| {
4927                                                let location = match lsp_symbol.location {
4928                                                    OneOf::Left(location) => location,
4929                                                    OneOf::Right(_) => {
4930                                                        log::error!("Unexpected: client capabilities forbid symbol resolutions in workspace.symbol.resolveSupport");
4931                                                        return None
4932                                                    }
4933                                                };
4934                                                Some((lsp_symbol.name, lsp_symbol.kind, location))
4935                                            }).collect::<Vec<_>>()
4936                                        }
4937                                    }).unwrap_or_default();
4938
4939                                    WorkspaceSymbolsResult {
4940                                        server_id,
4941                                        lsp_adapter,
4942                                        worktree: worktree_handle.downgrade(),
4943                                        worktree_abs_path,
4944                                        lsp_symbols,
4945                                    }
4946                                }),
4947                        );
4948                }
4949                requested_servers.append(&mut servers_to_query);
4950            }
4951
4952            cx.spawn(move |this, mut cx| async move {
4953                let responses = futures::future::join_all(requests).await;
4954                let this = match this.upgrade() {
4955                    Some(this) => this,
4956                    None => return Ok(Vec::new()),
4957                };
4958
4959                let mut symbols = Vec::new();
4960                for result in responses {
4961                    let core_symbols = this.update(&mut cx, |this, cx| {
4962                        result
4963                            .lsp_symbols
4964                            .into_iter()
4965                            .filter_map(|(symbol_name, symbol_kind, symbol_location)| {
4966                                let abs_path = symbol_location.uri.to_file_path().ok()?;
4967                                let source_worktree = result.worktree.upgrade()?;
4968                                let source_worktree_id = source_worktree.read(cx).id();
4969
4970                                let path;
4971                                let worktree;
4972                                if let Some((tree, rel_path)) =
4973                                    this.worktree_store.read(cx).find_worktree(&abs_path, cx)
4974                                {
4975                                    worktree = tree;
4976                                    path = rel_path;
4977                                } else {
4978                                    worktree = source_worktree.clone();
4979                                    path = relativize_path(&result.worktree_abs_path, &abs_path);
4980                                }
4981
4982                                let worktree_id = worktree.read(cx).id();
4983                                let project_path = ProjectPath {
4984                                    worktree_id,
4985                                    path: path.into(),
4986                                };
4987                                let signature = this.symbol_signature(&project_path);
4988                                Some(CoreSymbol {
4989                                    source_language_server_id: result.server_id,
4990                                    language_server_name: result.lsp_adapter.name.clone(),
4991                                    source_worktree_id,
4992                                    path: project_path,
4993                                    kind: symbol_kind,
4994                                    name: symbol_name,
4995                                    range: range_from_lsp(symbol_location.range),
4996                                    signature,
4997                                })
4998                            })
4999                            .collect()
5000                    })?;
5001
5002                    populate_labels_for_symbols(
5003                        core_symbols,
5004                        &language_registry,
5005                        Some(result.lsp_adapter),
5006                        &mut symbols,
5007                    )
5008                    .await;
5009                }
5010
5011                Ok(symbols)
5012            })
5013        } else {
5014            Task::ready(Err(anyhow!("No upstream client or local language server")))
5015        }
5016    }
5017
5018    pub fn diagnostic_summary(&self, include_ignored: bool, cx: &App) -> DiagnosticSummary {
5019        let mut summary = DiagnosticSummary::default();
5020        for (_, _, path_summary) in self.diagnostic_summaries(include_ignored, cx) {
5021            summary.error_count += path_summary.error_count;
5022            summary.warning_count += path_summary.warning_count;
5023        }
5024        summary
5025    }
5026
5027    pub fn diagnostic_summaries<'a>(
5028        &'a self,
5029        include_ignored: bool,
5030        cx: &'a App,
5031    ) -> impl Iterator<Item = (ProjectPath, LanguageServerId, DiagnosticSummary)> + 'a {
5032        self.worktree_store
5033            .read(cx)
5034            .visible_worktrees(cx)
5035            .filter_map(|worktree| {
5036                let worktree = worktree.read(cx);
5037                Some((worktree, self.diagnostic_summaries.get(&worktree.id())?))
5038            })
5039            .flat_map(move |(worktree, summaries)| {
5040                let worktree_id = worktree.id();
5041                summaries
5042                    .iter()
5043                    .filter(move |(path, _)| {
5044                        include_ignored
5045                            || worktree
5046                                .entry_for_path(path.as_ref())
5047                                .map_or(false, |entry| !entry.is_ignored)
5048                    })
5049                    .flat_map(move |(path, summaries)| {
5050                        summaries.iter().map(move |(server_id, summary)| {
5051                            (
5052                                ProjectPath {
5053                                    worktree_id,
5054                                    path: path.clone(),
5055                                },
5056                                *server_id,
5057                                *summary,
5058                            )
5059                        })
5060                    })
5061            })
5062    }
5063
5064    pub fn on_buffer_edited(
5065        &mut self,
5066        buffer: Entity<Buffer>,
5067        cx: &mut Context<Self>,
5068    ) -> Option<()> {
5069        let language_servers: Vec<_> = buffer.update(cx, |buffer, cx| {
5070            Some(
5071                self.as_local()?
5072                    .language_servers_for_buffer(buffer, cx)
5073                    .map(|i| i.1.clone())
5074                    .collect(),
5075            )
5076        })?;
5077
5078        let buffer = buffer.read(cx);
5079        let file = File::from_dyn(buffer.file())?;
5080        let abs_path = file.as_local()?.abs_path(cx);
5081        let uri = lsp::Url::from_file_path(abs_path).unwrap();
5082        let next_snapshot = buffer.text_snapshot();
5083        for language_server in language_servers {
5084            let language_server = language_server.clone();
5085
5086            let buffer_snapshots = self
5087                .as_local_mut()
5088                .unwrap()
5089                .buffer_snapshots
5090                .get_mut(&buffer.remote_id())
5091                .and_then(|m| m.get_mut(&language_server.server_id()))?;
5092            let previous_snapshot = buffer_snapshots.last()?;
5093
5094            let build_incremental_change = || {
5095                buffer
5096                    .edits_since::<(PointUtf16, usize)>(previous_snapshot.snapshot.version())
5097                    .map(|edit| {
5098                        let edit_start = edit.new.start.0;
5099                        let edit_end = edit_start + (edit.old.end.0 - edit.old.start.0);
5100                        let new_text = next_snapshot
5101                            .text_for_range(edit.new.start.1..edit.new.end.1)
5102                            .collect();
5103                        lsp::TextDocumentContentChangeEvent {
5104                            range: Some(lsp::Range::new(
5105                                point_to_lsp(edit_start),
5106                                point_to_lsp(edit_end),
5107                            )),
5108                            range_length: None,
5109                            text: new_text,
5110                        }
5111                    })
5112                    .collect()
5113            };
5114
5115            let document_sync_kind = language_server
5116                .capabilities()
5117                .text_document_sync
5118                .as_ref()
5119                .and_then(|sync| match sync {
5120                    lsp::TextDocumentSyncCapability::Kind(kind) => Some(*kind),
5121                    lsp::TextDocumentSyncCapability::Options(options) => options.change,
5122                });
5123
5124            let content_changes: Vec<_> = match document_sync_kind {
5125                Some(lsp::TextDocumentSyncKind::FULL) => {
5126                    vec![lsp::TextDocumentContentChangeEvent {
5127                        range: None,
5128                        range_length: None,
5129                        text: next_snapshot.text(),
5130                    }]
5131                }
5132                Some(lsp::TextDocumentSyncKind::INCREMENTAL) => build_incremental_change(),
5133                _ => {
5134                    #[cfg(any(test, feature = "test-support"))]
5135                    {
5136                        build_incremental_change()
5137                    }
5138
5139                    #[cfg(not(any(test, feature = "test-support")))]
5140                    {
5141                        continue;
5142                    }
5143                }
5144            };
5145
5146            let next_version = previous_snapshot.version + 1;
5147            buffer_snapshots.push(LspBufferSnapshot {
5148                version: next_version,
5149                snapshot: next_snapshot.clone(),
5150            });
5151
5152            language_server
5153                .notify::<lsp::notification::DidChangeTextDocument>(
5154                    &lsp::DidChangeTextDocumentParams {
5155                        text_document: lsp::VersionedTextDocumentIdentifier::new(
5156                            uri.clone(),
5157                            next_version,
5158                        ),
5159                        content_changes,
5160                    },
5161                )
5162                .log_err();
5163        }
5164
5165        None
5166    }
5167
5168    pub fn on_buffer_saved(
5169        &mut self,
5170        buffer: Entity<Buffer>,
5171        cx: &mut Context<Self>,
5172    ) -> Option<()> {
5173        let file = File::from_dyn(buffer.read(cx).file())?;
5174        let worktree_id = file.worktree_id(cx);
5175        let abs_path = file.as_local()?.abs_path(cx);
5176        let text_document = lsp::TextDocumentIdentifier {
5177            uri: lsp::Url::from_file_path(abs_path).log_err()?,
5178        };
5179        let local = self.as_local()?;
5180
5181        for server in local.language_servers_for_worktree(worktree_id) {
5182            if let Some(include_text) = include_text(server.as_ref()) {
5183                let text = if include_text {
5184                    Some(buffer.read(cx).text())
5185                } else {
5186                    None
5187                };
5188                server
5189                    .notify::<lsp::notification::DidSaveTextDocument>(
5190                        &lsp::DidSaveTextDocumentParams {
5191                            text_document: text_document.clone(),
5192                            text,
5193                        },
5194                    )
5195                    .log_err();
5196            }
5197        }
5198
5199        let language_servers = buffer.update(cx, |buffer, cx| {
5200            local.language_server_ids_for_buffer(buffer, cx)
5201        });
5202        for language_server_id in language_servers {
5203            self.simulate_disk_based_diagnostics_events_if_needed(language_server_id, cx);
5204        }
5205
5206        None
5207    }
5208
5209    pub(crate) async fn refresh_workspace_configurations(
5210        this: &WeakEntity<Self>,
5211        fs: Arc<dyn Fs>,
5212        mut cx: AsyncApp,
5213    ) {
5214        maybe!(async move {
5215            let servers = this
5216                .update(&mut cx, |this, cx| {
5217                    let Some(local) = this.as_local() else {
5218                        return Vec::default();
5219                    };
5220                    local
5221                        .language_server_ids
5222                        .iter()
5223                        .flat_map(|((worktree_id, _), server_ids)| {
5224                            let worktree = this
5225                                .worktree_store
5226                                .read(cx)
5227                                .worktree_for_id(*worktree_id, cx);
5228                            let delegate = worktree.map(|worktree| {
5229                                LocalLspAdapterDelegate::new(
5230                                    local.languages.clone(),
5231                                    &local.environment,
5232                                    cx.weak_entity(),
5233                                    &worktree,
5234                                    local.http_client.clone(),
5235                                    local.fs.clone(),
5236                                    cx,
5237                                )
5238                            });
5239
5240                            server_ids.iter().filter_map(move |server_id| {
5241                                let states = local.language_servers.get(server_id)?;
5242
5243                                match states {
5244                                    LanguageServerState::Starting { .. } => None,
5245                                    LanguageServerState::Running {
5246                                        adapter, server, ..
5247                                    } => Some((
5248                                        adapter.adapter.clone(),
5249                                        server.clone(),
5250                                        delegate.clone()? as Arc<dyn LspAdapterDelegate>,
5251                                    )),
5252                                }
5253                            })
5254                        })
5255                        .collect::<Vec<_>>()
5256                })
5257                .ok()?;
5258
5259            let toolchain_store = this
5260                .update(&mut cx, |this, cx| this.toolchain_store(cx))
5261                .ok()?;
5262            for (adapter, server, delegate) in servers {
5263                let settings = adapter
5264                    .workspace_configuration(
5265                        fs.as_ref(),
5266                        &delegate,
5267                        toolchain_store.clone(),
5268                        &mut cx,
5269                    )
5270                    .await
5271                    .ok()?;
5272
5273                server
5274                    .notify::<lsp::notification::DidChangeConfiguration>(
5275                        &lsp::DidChangeConfigurationParams { settings },
5276                    )
5277                    .ok();
5278            }
5279            Some(())
5280        })
5281        .await;
5282    }
5283
5284    fn toolchain_store(&self, cx: &App) -> Arc<dyn LanguageToolchainStore> {
5285        if let Some(toolchain_store) = self.toolchain_store.as_ref() {
5286            toolchain_store.read(cx).as_language_toolchain_store()
5287        } else {
5288            Arc::new(EmptyToolchainStore)
5289        }
5290    }
5291    fn maintain_workspace_config(
5292        fs: Arc<dyn Fs>,
5293        external_refresh_requests: watch::Receiver<()>,
5294        cx: &mut Context<Self>,
5295    ) -> Task<Result<()>> {
5296        let (mut settings_changed_tx, mut settings_changed_rx) = watch::channel();
5297        let _ = postage::stream::Stream::try_recv(&mut settings_changed_rx);
5298
5299        let settings_observation = cx.observe_global::<SettingsStore>(move |_, _| {
5300            *settings_changed_tx.borrow_mut() = ();
5301        });
5302
5303        let mut joint_future =
5304            futures::stream::select(settings_changed_rx, external_refresh_requests);
5305        cx.spawn(move |this, cx| async move {
5306            while let Some(()) = joint_future.next().await {
5307                Self::refresh_workspace_configurations(&this, fs.clone(), cx.clone()).await;
5308            }
5309
5310            drop(settings_observation);
5311            anyhow::Ok(())
5312        })
5313    }
5314
5315    pub fn language_servers_for_local_buffer<'a>(
5316        &'a self,
5317        buffer: &Buffer,
5318        cx: &mut App,
5319    ) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
5320        let local = self.as_local();
5321        let language_server_ids = local
5322            .map(|local| local.language_server_ids_for_buffer(buffer, cx))
5323            .unwrap_or_default();
5324
5325        language_server_ids
5326            .into_iter()
5327            .filter_map(
5328                move |server_id| match local?.language_servers.get(&server_id)? {
5329                    LanguageServerState::Running {
5330                        adapter, server, ..
5331                    } => Some((adapter, server)),
5332                    _ => None,
5333                },
5334            )
5335    }
5336
5337    pub fn language_server_for_local_buffer<'a>(
5338        &'a self,
5339        buffer: &'a Buffer,
5340        server_id: LanguageServerId,
5341        cx: &'a mut App,
5342    ) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
5343        self.as_local()?
5344            .language_servers_for_buffer(buffer, cx)
5345            .find(|(_, s)| s.server_id() == server_id)
5346    }
5347
5348    fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut Context<Self>) {
5349        self.diagnostic_summaries.remove(&id_to_remove);
5350        if let Some(local) = self.as_local_mut() {
5351            let to_remove = local.remove_worktree(id_to_remove, cx);
5352            for server in to_remove {
5353                self.language_server_statuses.remove(&server);
5354            }
5355        }
5356    }
5357
5358    pub fn shared(
5359        &mut self,
5360        project_id: u64,
5361        downstream_client: AnyProtoClient,
5362        _: &mut Context<Self>,
5363    ) {
5364        self.downstream_client = Some((downstream_client.clone(), project_id));
5365
5366        for (server_id, status) in &self.language_server_statuses {
5367            downstream_client
5368                .send(proto::StartLanguageServer {
5369                    project_id,
5370                    server: Some(proto::LanguageServer {
5371                        id: server_id.0 as u64,
5372                        name: status.name.clone(),
5373                        worktree_id: None,
5374                    }),
5375                })
5376                .log_err();
5377        }
5378    }
5379
5380    pub fn disconnected_from_host(&mut self) {
5381        self.downstream_client.take();
5382    }
5383
5384    pub fn disconnected_from_ssh_remote(&mut self) {
5385        if let LspStoreMode::Remote(RemoteLspStore {
5386            upstream_client, ..
5387        }) = &mut self.mode
5388        {
5389            upstream_client.take();
5390        }
5391    }
5392
5393    pub(crate) fn set_language_server_statuses_from_proto(
5394        &mut self,
5395        language_servers: Vec<proto::LanguageServer>,
5396    ) {
5397        self.language_server_statuses = language_servers
5398            .into_iter()
5399            .map(|server| {
5400                (
5401                    LanguageServerId(server.id as usize),
5402                    LanguageServerStatus {
5403                        name: server.name,
5404                        pending_work: Default::default(),
5405                        has_pending_diagnostic_updates: false,
5406                        progress_tokens: Default::default(),
5407                    },
5408                )
5409            })
5410            .collect();
5411    }
5412
5413    fn register_local_language_server(
5414        &mut self,
5415        worktree: Entity<Worktree>,
5416        language_server_name: LanguageServerName,
5417        language_server_id: LanguageServerId,
5418        cx: &mut App,
5419    ) {
5420        let Some(local) = self.as_local_mut() else {
5421            return;
5422        };
5423        let worktree_id = worktree.read(cx).id();
5424        let path = ProjectPath {
5425            worktree_id,
5426            path: Arc::from("".as_ref()),
5427        };
5428        let delegate = LocalLspAdapterDelegate::from_local_lsp(local, &worktree, cx);
5429        local.lsp_tree.update(cx, |this, cx| {
5430            for node in this.get(
5431                path,
5432                AdapterQuery::Adapter(&language_server_name),
5433                delegate,
5434                cx,
5435            ) {
5436                node.server_id_or_init(|disposition| {
5437                    assert_eq!(disposition.server_name, &language_server_name);
5438
5439                    language_server_id
5440                });
5441            }
5442        });
5443        local
5444            .language_server_ids
5445            .entry((worktree_id, language_server_name))
5446            .or_default()
5447            .insert(language_server_id);
5448    }
5449
5450    pub fn update_diagnostic_entries(
5451        &mut self,
5452        server_id: LanguageServerId,
5453        abs_path: PathBuf,
5454        version: Option<i32>,
5455        diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
5456        cx: &mut Context<Self>,
5457    ) -> Result<(), anyhow::Error> {
5458        let Some((worktree, relative_path)) =
5459            self.worktree_store.read(cx).find_worktree(&abs_path, cx)
5460        else {
5461            log::warn!("skipping diagnostics update, no worktree found for path {abs_path:?}");
5462            return Ok(());
5463        };
5464
5465        let project_path = ProjectPath {
5466            worktree_id: worktree.read(cx).id(),
5467            path: relative_path.into(),
5468        };
5469
5470        if let Some(buffer) = self.buffer_store.read(cx).get_by_path(&project_path, cx) {
5471            self.as_local_mut().unwrap().update_buffer_diagnostics(
5472                &buffer,
5473                server_id,
5474                version,
5475                diagnostics.clone(),
5476                cx,
5477            )?;
5478        }
5479
5480        let updated = worktree.update(cx, |worktree, cx| {
5481            self.update_worktree_diagnostics(
5482                worktree.id(),
5483                server_id,
5484                project_path.path.clone(),
5485                diagnostics,
5486                cx,
5487            )
5488        })?;
5489        if updated {
5490            cx.emit(LspStoreEvent::DiagnosticsUpdated {
5491                language_server_id: server_id,
5492                path: project_path,
5493            })
5494        }
5495        Ok(())
5496    }
5497
5498    fn update_worktree_diagnostics(
5499        &mut self,
5500        worktree_id: WorktreeId,
5501        server_id: LanguageServerId,
5502        worktree_path: Arc<Path>,
5503        diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
5504        _: &mut Context<Worktree>,
5505    ) -> Result<bool> {
5506        let local = match &mut self.mode {
5507            LspStoreMode::Local(local_lsp_store) => local_lsp_store,
5508            _ => anyhow::bail!("update_worktree_diagnostics called on remote"),
5509        };
5510
5511        let summaries_for_tree = self.diagnostic_summaries.entry(worktree_id).or_default();
5512        let diagnostics_for_tree = local.diagnostics.entry(worktree_id).or_default();
5513        let summaries_by_server_id = summaries_for_tree.entry(worktree_path.clone()).or_default();
5514
5515        let old_summary = summaries_by_server_id
5516            .remove(&server_id)
5517            .unwrap_or_default();
5518
5519        let new_summary = DiagnosticSummary::new(&diagnostics);
5520        if new_summary.is_empty() {
5521            if let Some(diagnostics_by_server_id) = diagnostics_for_tree.get_mut(&worktree_path) {
5522                if let Ok(ix) = diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0) {
5523                    diagnostics_by_server_id.remove(ix);
5524                }
5525                if diagnostics_by_server_id.is_empty() {
5526                    diagnostics_for_tree.remove(&worktree_path);
5527                }
5528            }
5529        } else {
5530            summaries_by_server_id.insert(server_id, new_summary);
5531            let diagnostics_by_server_id = diagnostics_for_tree
5532                .entry(worktree_path.clone())
5533                .or_default();
5534            match diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0) {
5535                Ok(ix) => {
5536                    diagnostics_by_server_id[ix] = (server_id, diagnostics);
5537                }
5538                Err(ix) => {
5539                    diagnostics_by_server_id.insert(ix, (server_id, diagnostics));
5540                }
5541            }
5542        }
5543
5544        if !old_summary.is_empty() || !new_summary.is_empty() {
5545            if let Some((downstream_client, project_id)) = &self.downstream_client {
5546                downstream_client
5547                    .send(proto::UpdateDiagnosticSummary {
5548                        project_id: *project_id,
5549                        worktree_id: worktree_id.to_proto(),
5550                        summary: Some(proto::DiagnosticSummary {
5551                            path: worktree_path.to_proto(),
5552                            language_server_id: server_id.0 as u64,
5553                            error_count: new_summary.error_count as u32,
5554                            warning_count: new_summary.warning_count as u32,
5555                        }),
5556                    })
5557                    .log_err();
5558            }
5559        }
5560
5561        Ok(!old_summary.is_empty() || !new_summary.is_empty())
5562    }
5563
5564    pub fn open_buffer_for_symbol(
5565        &mut self,
5566        symbol: &Symbol,
5567        cx: &mut Context<Self>,
5568    ) -> Task<Result<Entity<Buffer>>> {
5569        if let Some((client, project_id)) = self.upstream_client() {
5570            let request = client.request(proto::OpenBufferForSymbol {
5571                project_id,
5572                symbol: Some(Self::serialize_symbol(symbol)),
5573            });
5574            cx.spawn(move |this, mut cx| async move {
5575                let response = request.await?;
5576                let buffer_id = BufferId::new(response.buffer_id)?;
5577                this.update(&mut cx, |this, cx| {
5578                    this.wait_for_remote_buffer(buffer_id, cx)
5579                })?
5580                .await
5581            })
5582        } else if let Some(local) = self.as_local() {
5583            let Some(language_server_id) = local
5584                .language_server_ids
5585                .get(&(
5586                    symbol.source_worktree_id,
5587                    symbol.language_server_name.clone(),
5588                ))
5589                .and_then(|ids| {
5590                    ids.contains(&symbol.source_language_server_id)
5591                        .then_some(symbol.source_language_server_id)
5592                })
5593            else {
5594                return Task::ready(Err(anyhow!(
5595                    "language server for worktree and language not found"
5596                )));
5597            };
5598
5599            let worktree_abs_path = if let Some(worktree_abs_path) = self
5600                .worktree_store
5601                .read(cx)
5602                .worktree_for_id(symbol.path.worktree_id, cx)
5603                .map(|worktree| worktree.read(cx).abs_path())
5604            {
5605                worktree_abs_path
5606            } else {
5607                return Task::ready(Err(anyhow!("worktree not found for symbol")));
5608            };
5609
5610            let symbol_abs_path = resolve_path(&worktree_abs_path, &symbol.path.path);
5611            let symbol_uri = if let Ok(uri) = lsp::Url::from_file_path(symbol_abs_path) {
5612                uri
5613            } else {
5614                return Task::ready(Err(anyhow!("invalid symbol path")));
5615            };
5616
5617            self.open_local_buffer_via_lsp(
5618                symbol_uri,
5619                language_server_id,
5620                symbol.language_server_name.clone(),
5621                cx,
5622            )
5623        } else {
5624            Task::ready(Err(anyhow!("no upstream client or local store")))
5625        }
5626    }
5627
5628    pub fn open_local_buffer_via_lsp(
5629        &mut self,
5630        mut abs_path: lsp::Url,
5631        language_server_id: LanguageServerId,
5632        language_server_name: LanguageServerName,
5633        cx: &mut Context<Self>,
5634    ) -> Task<Result<Entity<Buffer>>> {
5635        cx.spawn(move |lsp_store, mut cx| async move {
5636            // Escape percent-encoded string.
5637            let current_scheme = abs_path.scheme().to_owned();
5638            let _ = abs_path.set_scheme("file");
5639
5640            let abs_path = abs_path
5641                .to_file_path()
5642                .map_err(|_| anyhow!("can't convert URI to path"))?;
5643            let p = abs_path.clone();
5644            let yarn_worktree = lsp_store
5645                .update(&mut cx, move |lsp_store, cx| match lsp_store.as_local() {
5646                    Some(local_lsp_store) => local_lsp_store.yarn.update(cx, |_, cx| {
5647                        cx.spawn(|this, mut cx| async move {
5648                            let t = this
5649                                .update(&mut cx, |this, cx| {
5650                                    this.process_path(&p, &current_scheme, cx)
5651                                })
5652                                .ok()?;
5653                            t.await
5654                        })
5655                    }),
5656                    None => Task::ready(None),
5657                })?
5658                .await;
5659            let (worktree_root_target, known_relative_path) =
5660                if let Some((zip_root, relative_path)) = yarn_worktree {
5661                    (zip_root, Some(relative_path))
5662                } else {
5663                    (Arc::<Path>::from(abs_path.as_path()), None)
5664                };
5665            let (worktree, relative_path) = if let Some(result) =
5666                lsp_store.update(&mut cx, |lsp_store, cx| {
5667                    lsp_store.worktree_store.update(cx, |worktree_store, cx| {
5668                        worktree_store.find_worktree(&worktree_root_target, cx)
5669                    })
5670                })? {
5671                let relative_path =
5672                    known_relative_path.unwrap_or_else(|| Arc::<Path>::from(result.1));
5673                (result.0, relative_path)
5674            } else {
5675                let worktree = lsp_store
5676                    .update(&mut cx, |lsp_store, cx| {
5677                        lsp_store.worktree_store.update(cx, |worktree_store, cx| {
5678                            worktree_store.create_worktree(&worktree_root_target, false, cx)
5679                        })
5680                    })?
5681                    .await?;
5682                if worktree.update(&mut cx, |worktree, _| worktree.is_local())? {
5683                    lsp_store
5684                        .update(&mut cx, |lsp_store, cx| {
5685                            lsp_store.register_local_language_server(
5686                                worktree.clone(),
5687                                language_server_name,
5688                                language_server_id,
5689                                cx,
5690                            )
5691                        })
5692                        .ok();
5693                }
5694                let worktree_root = worktree.update(&mut cx, |worktree, _| worktree.abs_path())?;
5695                let relative_path = if let Some(known_path) = known_relative_path {
5696                    known_path
5697                } else {
5698                    abs_path.strip_prefix(worktree_root)?.into()
5699                };
5700                (worktree, relative_path)
5701            };
5702            let project_path = ProjectPath {
5703                worktree_id: worktree.update(&mut cx, |worktree, _| worktree.id())?,
5704                path: relative_path,
5705            };
5706            lsp_store
5707                .update(&mut cx, |lsp_store, cx| {
5708                    lsp_store.buffer_store().update(cx, |buffer_store, cx| {
5709                        buffer_store.open_buffer(project_path, cx)
5710                    })
5711                })?
5712                .await
5713        })
5714    }
5715
5716    fn request_multiple_lsp_locally<P, R>(
5717        &mut self,
5718        buffer: &Entity<Buffer>,
5719        position: Option<P>,
5720        request: R,
5721        cx: &mut Context<'_, Self>,
5722    ) -> Task<Vec<R::Response>>
5723    where
5724        P: ToOffset,
5725        R: LspCommand + Clone,
5726        <R::LspRequest as lsp::request::Request>::Result: Send,
5727        <R::LspRequest as lsp::request::Request>::Params: Send,
5728    {
5729        let Some(local) = self.as_local() else {
5730            return Task::ready(Vec::new());
5731        };
5732
5733        let snapshot = buffer.read(cx).snapshot();
5734        let scope = position.and_then(|position| snapshot.language_scope_at(position));
5735
5736        let server_ids = buffer.update(cx, |buffer, cx| {
5737            local
5738                .language_servers_for_buffer(buffer, cx)
5739                .filter(|(adapter, _)| {
5740                    scope
5741                        .as_ref()
5742                        .map(|scope| scope.language_allowed(&adapter.name))
5743                        .unwrap_or(true)
5744                })
5745                .map(|(_, server)| server.server_id())
5746                .collect::<Vec<_>>()
5747        });
5748
5749        let mut response_results = server_ids
5750            .into_iter()
5751            .map(|server_id| {
5752                self.request_lsp(
5753                    buffer.clone(),
5754                    LanguageServerToQuery::Other(server_id),
5755                    request.clone(),
5756                    cx,
5757                )
5758            })
5759            .collect::<FuturesUnordered<_>>();
5760
5761        cx.spawn(|_, _| async move {
5762            let mut responses = Vec::with_capacity(response_results.len());
5763            while let Some(response_result) = response_results.next().await {
5764                if let Some(response) = response_result.log_err() {
5765                    responses.push(response);
5766                }
5767            }
5768            responses
5769        })
5770    }
5771
5772    async fn handle_lsp_command<T: LspCommand>(
5773        this: Entity<Self>,
5774        envelope: TypedEnvelope<T::ProtoRequest>,
5775        mut cx: AsyncApp,
5776    ) -> Result<<T::ProtoRequest as proto::RequestMessage>::Response>
5777    where
5778        <T::LspRequest as lsp::request::Request>::Params: Send,
5779        <T::LspRequest as lsp::request::Request>::Result: Send,
5780    {
5781        let sender_id = envelope.original_sender_id().unwrap_or_default();
5782        let buffer_id = T::buffer_id_from_proto(&envelope.payload)?;
5783        let buffer_handle = this.update(&mut cx, |this, cx| {
5784            this.buffer_store.read(cx).get_existing(buffer_id)
5785        })??;
5786        let request = T::from_proto(
5787            envelope.payload,
5788            this.clone(),
5789            buffer_handle.clone(),
5790            cx.clone(),
5791        )
5792        .await?;
5793        let response = this
5794            .update(&mut cx, |this, cx| {
5795                this.request_lsp(
5796                    buffer_handle.clone(),
5797                    LanguageServerToQuery::Primary,
5798                    request,
5799                    cx,
5800                )
5801            })?
5802            .await?;
5803        this.update(&mut cx, |this, cx| {
5804            Ok(T::response_to_proto(
5805                response,
5806                this,
5807                sender_id,
5808                &buffer_handle.read(cx).version(),
5809                cx,
5810            ))
5811        })?
5812    }
5813
5814    async fn handle_multi_lsp_query(
5815        this: Entity<Self>,
5816        envelope: TypedEnvelope<proto::MultiLspQuery>,
5817        mut cx: AsyncApp,
5818    ) -> Result<proto::MultiLspQueryResponse> {
5819        let response_from_ssh = this.update(&mut cx, |this, _| {
5820            let (upstream_client, project_id) = this.upstream_client()?;
5821            let mut payload = envelope.payload.clone();
5822            payload.project_id = project_id;
5823
5824            Some(upstream_client.request(payload))
5825        })?;
5826        if let Some(response_from_ssh) = response_from_ssh {
5827            return response_from_ssh.await;
5828        }
5829
5830        let sender_id = envelope.original_sender_id().unwrap_or_default();
5831        let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
5832        let version = deserialize_version(&envelope.payload.version);
5833        let buffer = this.update(&mut cx, |this, cx| {
5834            this.buffer_store.read(cx).get_existing(buffer_id)
5835        })??;
5836        buffer
5837            .update(&mut cx, |buffer, _| {
5838                buffer.wait_for_version(version.clone())
5839            })?
5840            .await?;
5841        let buffer_version = buffer.update(&mut cx, |buffer, _| buffer.version())?;
5842        match envelope
5843            .payload
5844            .strategy
5845            .context("invalid request without the strategy")?
5846        {
5847            proto::multi_lsp_query::Strategy::All(_) => {
5848                // currently, there's only one multiple language servers query strategy,
5849                // so just ensure it's specified correctly
5850            }
5851        }
5852        match envelope.payload.request {
5853            Some(proto::multi_lsp_query::Request::GetHover(get_hover)) => {
5854                let get_hover =
5855                    GetHover::from_proto(get_hover, this.clone(), buffer.clone(), cx.clone())
5856                        .await?;
5857                let all_hovers = this
5858                    .update(&mut cx, |this, cx| {
5859                        this.request_multiple_lsp_locally(
5860                            &buffer,
5861                            Some(get_hover.position),
5862                            get_hover,
5863                            cx,
5864                        )
5865                    })?
5866                    .await
5867                    .into_iter()
5868                    .filter_map(|hover| remove_empty_hover_blocks(hover?));
5869                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
5870                    responses: all_hovers
5871                        .map(|hover| proto::LspResponse {
5872                            response: Some(proto::lsp_response::Response::GetHoverResponse(
5873                                GetHover::response_to_proto(
5874                                    Some(hover),
5875                                    project,
5876                                    sender_id,
5877                                    &buffer_version,
5878                                    cx,
5879                                ),
5880                            )),
5881                        })
5882                        .collect(),
5883                })
5884            }
5885            Some(proto::multi_lsp_query::Request::GetCodeActions(get_code_actions)) => {
5886                let get_code_actions = GetCodeActions::from_proto(
5887                    get_code_actions,
5888                    this.clone(),
5889                    buffer.clone(),
5890                    cx.clone(),
5891                )
5892                .await?;
5893
5894                let all_actions = this
5895                    .update(&mut cx, |project, cx| {
5896                        project.request_multiple_lsp_locally(
5897                            &buffer,
5898                            Some(get_code_actions.range.start),
5899                            get_code_actions,
5900                            cx,
5901                        )
5902                    })?
5903                    .await
5904                    .into_iter();
5905
5906                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
5907                    responses: all_actions
5908                        .map(|code_actions| proto::LspResponse {
5909                            response: Some(proto::lsp_response::Response::GetCodeActionsResponse(
5910                                GetCodeActions::response_to_proto(
5911                                    code_actions,
5912                                    project,
5913                                    sender_id,
5914                                    &buffer_version,
5915                                    cx,
5916                                ),
5917                            )),
5918                        })
5919                        .collect(),
5920                })
5921            }
5922            Some(proto::multi_lsp_query::Request::GetSignatureHelp(get_signature_help)) => {
5923                let get_signature_help = GetSignatureHelp::from_proto(
5924                    get_signature_help,
5925                    this.clone(),
5926                    buffer.clone(),
5927                    cx.clone(),
5928                )
5929                .await?;
5930
5931                let all_signatures = this
5932                    .update(&mut cx, |project, cx| {
5933                        project.request_multiple_lsp_locally(
5934                            &buffer,
5935                            Some(get_signature_help.position),
5936                            get_signature_help,
5937                            cx,
5938                        )
5939                    })?
5940                    .await
5941                    .into_iter();
5942
5943                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
5944                    responses: all_signatures
5945                        .map(|signature_help| proto::LspResponse {
5946                            response: Some(
5947                                proto::lsp_response::Response::GetSignatureHelpResponse(
5948                                    GetSignatureHelp::response_to_proto(
5949                                        signature_help,
5950                                        project,
5951                                        sender_id,
5952                                        &buffer_version,
5953                                        cx,
5954                                    ),
5955                                ),
5956                            ),
5957                        })
5958                        .collect(),
5959                })
5960            }
5961            None => anyhow::bail!("empty multi lsp query request"),
5962        }
5963    }
5964
5965    async fn handle_apply_code_action(
5966        this: Entity<Self>,
5967        envelope: TypedEnvelope<proto::ApplyCodeAction>,
5968        mut cx: AsyncApp,
5969    ) -> Result<proto::ApplyCodeActionResponse> {
5970        let sender_id = envelope.original_sender_id().unwrap_or_default();
5971        let action = Self::deserialize_code_action(
5972            envelope
5973                .payload
5974                .action
5975                .ok_or_else(|| anyhow!("invalid action"))?,
5976        )?;
5977        let apply_code_action = this.update(&mut cx, |this, cx| {
5978            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
5979            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
5980            anyhow::Ok(this.apply_code_action(buffer, action, false, cx))
5981        })??;
5982
5983        let project_transaction = apply_code_action.await?;
5984        let project_transaction = this.update(&mut cx, |this, cx| {
5985            this.buffer_store.update(cx, |buffer_store, cx| {
5986                buffer_store.serialize_project_transaction_for_peer(
5987                    project_transaction,
5988                    sender_id,
5989                    cx,
5990                )
5991            })
5992        })?;
5993        Ok(proto::ApplyCodeActionResponse {
5994            transaction: Some(project_transaction),
5995        })
5996    }
5997
5998    async fn handle_register_buffer_with_language_servers(
5999        this: Entity<Self>,
6000        envelope: TypedEnvelope<proto::RegisterBufferWithLanguageServers>,
6001        mut cx: AsyncApp,
6002    ) -> Result<proto::Ack> {
6003        let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
6004        let peer_id = envelope.original_sender_id.unwrap_or(envelope.sender_id);
6005        this.update(&mut cx, |this, cx| {
6006            if let Some((upstream_client, upstream_project_id)) = this.upstream_client() {
6007                return upstream_client.send(proto::RegisterBufferWithLanguageServers {
6008                    project_id: upstream_project_id,
6009                    buffer_id: buffer_id.to_proto(),
6010                });
6011            }
6012
6013            let Some(buffer) = this.buffer_store().read(cx).get(buffer_id) else {
6014                anyhow::bail!("buffer is not open");
6015            };
6016
6017            let handle = this.register_buffer_with_language_servers(&buffer, false, cx);
6018            this.buffer_store().update(cx, |buffer_store, _| {
6019                buffer_store.register_shared_lsp_handle(peer_id, buffer_id, handle);
6020            });
6021
6022            Ok(())
6023        })??;
6024        Ok(proto::Ack {})
6025    }
6026
6027    async fn handle_rename_project_entry(
6028        this: Entity<Self>,
6029        envelope: TypedEnvelope<proto::RenameProjectEntry>,
6030        mut cx: AsyncApp,
6031    ) -> Result<proto::ProjectEntryResponse> {
6032        let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id);
6033        let (worktree_id, worktree, old_path, is_dir) = this
6034            .update(&mut cx, |this, cx| {
6035                this.worktree_store
6036                    .read(cx)
6037                    .worktree_and_entry_for_id(entry_id, cx)
6038                    .map(|(worktree, entry)| {
6039                        (
6040                            worktree.read(cx).id(),
6041                            worktree,
6042                            entry.path.clone(),
6043                            entry.is_dir(),
6044                        )
6045                    })
6046            })?
6047            .ok_or_else(|| anyhow!("worktree not found"))?;
6048        let (old_abs_path, new_abs_path) = {
6049            let root_path = worktree.update(&mut cx, |this, _| this.abs_path())?;
6050            let new_path = PathBuf::from_proto(envelope.payload.new_path.clone());
6051            (root_path.join(&old_path), root_path.join(&new_path))
6052        };
6053
6054        Self::will_rename_entry(
6055            this.downgrade(),
6056            worktree_id,
6057            &old_abs_path,
6058            &new_abs_path,
6059            is_dir,
6060            cx.clone(),
6061        )
6062        .await;
6063        let response = Worktree::handle_rename_entry(worktree, envelope.payload, cx.clone()).await;
6064        this.update(&mut cx, |this, _| {
6065            this.did_rename_entry(worktree_id, &old_abs_path, &new_abs_path, is_dir);
6066        })
6067        .ok();
6068        response
6069    }
6070
6071    async fn handle_update_diagnostic_summary(
6072        this: Entity<Self>,
6073        envelope: TypedEnvelope<proto::UpdateDiagnosticSummary>,
6074        mut cx: AsyncApp,
6075    ) -> Result<()> {
6076        this.update(&mut cx, |this, cx| {
6077            let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
6078            if let Some(message) = envelope.payload.summary {
6079                let project_path = ProjectPath {
6080                    worktree_id,
6081                    path: Arc::<Path>::from_proto(message.path),
6082                };
6083                let path = project_path.path.clone();
6084                let server_id = LanguageServerId(message.language_server_id as usize);
6085                let summary = DiagnosticSummary {
6086                    error_count: message.error_count as usize,
6087                    warning_count: message.warning_count as usize,
6088                };
6089
6090                if summary.is_empty() {
6091                    if let Some(worktree_summaries) =
6092                        this.diagnostic_summaries.get_mut(&worktree_id)
6093                    {
6094                        if let Some(summaries) = worktree_summaries.get_mut(&path) {
6095                            summaries.remove(&server_id);
6096                            if summaries.is_empty() {
6097                                worktree_summaries.remove(&path);
6098                            }
6099                        }
6100                    }
6101                } else {
6102                    this.diagnostic_summaries
6103                        .entry(worktree_id)
6104                        .or_default()
6105                        .entry(path)
6106                        .or_default()
6107                        .insert(server_id, summary);
6108                }
6109                if let Some((downstream_client, project_id)) = &this.downstream_client {
6110                    downstream_client
6111                        .send(proto::UpdateDiagnosticSummary {
6112                            project_id: *project_id,
6113                            worktree_id: worktree_id.to_proto(),
6114                            summary: Some(proto::DiagnosticSummary {
6115                                path: project_path.path.as_ref().to_proto(),
6116                                language_server_id: server_id.0 as u64,
6117                                error_count: summary.error_count as u32,
6118                                warning_count: summary.warning_count as u32,
6119                            }),
6120                        })
6121                        .log_err();
6122                }
6123                cx.emit(LspStoreEvent::DiagnosticsUpdated {
6124                    language_server_id: LanguageServerId(message.language_server_id as usize),
6125                    path: project_path,
6126                });
6127            }
6128            Ok(())
6129        })?
6130    }
6131
6132    async fn handle_start_language_server(
6133        this: Entity<Self>,
6134        envelope: TypedEnvelope<proto::StartLanguageServer>,
6135        mut cx: AsyncApp,
6136    ) -> Result<()> {
6137        let server = envelope
6138            .payload
6139            .server
6140            .ok_or_else(|| anyhow!("invalid server"))?;
6141
6142        this.update(&mut cx, |this, cx| {
6143            let server_id = LanguageServerId(server.id as usize);
6144            this.language_server_statuses.insert(
6145                server_id,
6146                LanguageServerStatus {
6147                    name: server.name.clone(),
6148                    pending_work: Default::default(),
6149                    has_pending_diagnostic_updates: false,
6150                    progress_tokens: Default::default(),
6151                },
6152            );
6153            cx.emit(LspStoreEvent::LanguageServerAdded(
6154                server_id,
6155                LanguageServerName(server.name.into()),
6156                server.worktree_id.map(WorktreeId::from_proto),
6157            ));
6158            cx.notify();
6159        })?;
6160        Ok(())
6161    }
6162
6163    async fn handle_update_language_server(
6164        this: Entity<Self>,
6165        envelope: TypedEnvelope<proto::UpdateLanguageServer>,
6166        mut cx: AsyncApp,
6167    ) -> Result<()> {
6168        this.update(&mut cx, |this, cx| {
6169            let language_server_id = LanguageServerId(envelope.payload.language_server_id as usize);
6170
6171            match envelope
6172                .payload
6173                .variant
6174                .ok_or_else(|| anyhow!("invalid variant"))?
6175            {
6176                proto::update_language_server::Variant::WorkStart(payload) => {
6177                    this.on_lsp_work_start(
6178                        language_server_id,
6179                        payload.token,
6180                        LanguageServerProgress {
6181                            title: payload.title,
6182                            is_disk_based_diagnostics_progress: false,
6183                            is_cancellable: payload.is_cancellable.unwrap_or(false),
6184                            message: payload.message,
6185                            percentage: payload.percentage.map(|p| p as usize),
6186                            last_update_at: cx.background_executor().now(),
6187                        },
6188                        cx,
6189                    );
6190                }
6191
6192                proto::update_language_server::Variant::WorkProgress(payload) => {
6193                    this.on_lsp_work_progress(
6194                        language_server_id,
6195                        payload.token,
6196                        LanguageServerProgress {
6197                            title: None,
6198                            is_disk_based_diagnostics_progress: false,
6199                            is_cancellable: payload.is_cancellable.unwrap_or(false),
6200                            message: payload.message,
6201                            percentage: payload.percentage.map(|p| p as usize),
6202                            last_update_at: cx.background_executor().now(),
6203                        },
6204                        cx,
6205                    );
6206                }
6207
6208                proto::update_language_server::Variant::WorkEnd(payload) => {
6209                    this.on_lsp_work_end(language_server_id, payload.token, cx);
6210                }
6211
6212                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(_) => {
6213                    this.disk_based_diagnostics_started(language_server_id, cx);
6214                }
6215
6216                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(_) => {
6217                    this.disk_based_diagnostics_finished(language_server_id, cx)
6218                }
6219            }
6220
6221            Ok(())
6222        })?
6223    }
6224
6225    async fn handle_language_server_log(
6226        this: Entity<Self>,
6227        envelope: TypedEnvelope<proto::LanguageServerLog>,
6228        mut cx: AsyncApp,
6229    ) -> Result<()> {
6230        let language_server_id = LanguageServerId(envelope.payload.language_server_id as usize);
6231        let log_type = envelope
6232            .payload
6233            .log_type
6234            .map(LanguageServerLogType::from_proto)
6235            .context("invalid language server log type")?;
6236
6237        let message = envelope.payload.message;
6238
6239        this.update(&mut cx, |_, cx| {
6240            cx.emit(LspStoreEvent::LanguageServerLog(
6241                language_server_id,
6242                log_type,
6243                message,
6244            ));
6245        })
6246    }
6247
6248    pub fn disk_based_diagnostics_started(
6249        &mut self,
6250        language_server_id: LanguageServerId,
6251        cx: &mut Context<Self>,
6252    ) {
6253        if let Some(language_server_status) =
6254            self.language_server_statuses.get_mut(&language_server_id)
6255        {
6256            language_server_status.has_pending_diagnostic_updates = true;
6257        }
6258
6259        cx.emit(LspStoreEvent::DiskBasedDiagnosticsStarted { language_server_id });
6260        cx.emit(LspStoreEvent::LanguageServerUpdate {
6261            language_server_id,
6262            message: proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(
6263                Default::default(),
6264            ),
6265        })
6266    }
6267
6268    pub fn disk_based_diagnostics_finished(
6269        &mut self,
6270        language_server_id: LanguageServerId,
6271        cx: &mut Context<Self>,
6272    ) {
6273        if let Some(language_server_status) =
6274            self.language_server_statuses.get_mut(&language_server_id)
6275        {
6276            language_server_status.has_pending_diagnostic_updates = false;
6277        }
6278
6279        cx.emit(LspStoreEvent::DiskBasedDiagnosticsFinished { language_server_id });
6280        cx.emit(LspStoreEvent::LanguageServerUpdate {
6281            language_server_id,
6282            message: proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
6283                Default::default(),
6284            ),
6285        })
6286    }
6287
6288    // After saving a buffer using a language server that doesn't provide a disk-based progress token,
6289    // kick off a timer that will reset every time the buffer is saved. If the timer eventually fires,
6290    // simulate disk-based diagnostics being finished so that other pieces of UI (e.g., project
6291    // diagnostics view, diagnostic status bar) can update. We don't emit an event right away because
6292    // the language server might take some time to publish diagnostics.
6293    fn simulate_disk_based_diagnostics_events_if_needed(
6294        &mut self,
6295        language_server_id: LanguageServerId,
6296        cx: &mut Context<Self>,
6297    ) {
6298        const DISK_BASED_DIAGNOSTICS_DEBOUNCE: Duration = Duration::from_secs(1);
6299
6300        let Some(LanguageServerState::Running {
6301            simulate_disk_based_diagnostics_completion,
6302            adapter,
6303            ..
6304        }) = self
6305            .as_local_mut()
6306            .and_then(|local_store| local_store.language_servers.get_mut(&language_server_id))
6307        else {
6308            return;
6309        };
6310
6311        if adapter.disk_based_diagnostics_progress_token.is_some() {
6312            return;
6313        }
6314
6315        let prev_task = simulate_disk_based_diagnostics_completion.replace(cx.spawn(
6316            move |this, mut cx| async move {
6317                cx.background_executor()
6318                    .timer(DISK_BASED_DIAGNOSTICS_DEBOUNCE)
6319                    .await;
6320
6321                this.update(&mut cx, |this, cx| {
6322                    this.disk_based_diagnostics_finished(language_server_id, cx);
6323
6324                    if let Some(LanguageServerState::Running {
6325                        simulate_disk_based_diagnostics_completion,
6326                        ..
6327                    }) = this.as_local_mut().and_then(|local_store| {
6328                        local_store.language_servers.get_mut(&language_server_id)
6329                    }) {
6330                        *simulate_disk_based_diagnostics_completion = None;
6331                    }
6332                })
6333                .ok();
6334            },
6335        ));
6336
6337        if prev_task.is_none() {
6338            self.disk_based_diagnostics_started(language_server_id, cx);
6339        }
6340    }
6341
6342    pub fn language_server_statuses(
6343        &self,
6344    ) -> impl DoubleEndedIterator<Item = (LanguageServerId, &LanguageServerStatus)> {
6345        self.language_server_statuses
6346            .iter()
6347            .map(|(key, value)| (*key, value))
6348    }
6349
6350    pub(super) fn did_rename_entry(
6351        &self,
6352        worktree_id: WorktreeId,
6353        old_path: &Path,
6354        new_path: &Path,
6355        is_dir: bool,
6356    ) {
6357        maybe!({
6358            let local_store = self.as_local()?;
6359
6360            let old_uri = lsp::Url::from_file_path(old_path).ok().map(String::from)?;
6361            let new_uri = lsp::Url::from_file_path(new_path).ok().map(String::from)?;
6362
6363            for language_server in local_store.language_servers_for_worktree(worktree_id) {
6364                let Some(filter) = local_store
6365                    .language_server_paths_watched_for_rename
6366                    .get(&language_server.server_id())
6367                else {
6368                    continue;
6369                };
6370
6371                if filter.should_send_did_rename(&old_uri, is_dir) {
6372                    language_server
6373                        .notify::<DidRenameFiles>(&RenameFilesParams {
6374                            files: vec![FileRename {
6375                                old_uri: old_uri.clone(),
6376                                new_uri: new_uri.clone(),
6377                            }],
6378                        })
6379                        .log_err();
6380                }
6381            }
6382            Some(())
6383        });
6384    }
6385
6386    pub(super) fn will_rename_entry(
6387        this: WeakEntity<Self>,
6388        worktree_id: WorktreeId,
6389        old_path: &Path,
6390        new_path: &Path,
6391        is_dir: bool,
6392        cx: AsyncApp,
6393    ) -> Task<()> {
6394        let old_uri = lsp::Url::from_file_path(old_path).ok().map(String::from);
6395        let new_uri = lsp::Url::from_file_path(new_path).ok().map(String::from);
6396        cx.spawn(move |mut cx| async move {
6397            let mut tasks = vec![];
6398            this.update(&mut cx, |this, cx| {
6399                let local_store = this.as_local()?;
6400                let old_uri = old_uri?;
6401                let new_uri = new_uri?;
6402                for language_server in local_store.language_servers_for_worktree(worktree_id) {
6403                    let Some(filter) = local_store
6404                        .language_server_paths_watched_for_rename
6405                        .get(&language_server.server_id())
6406                    else {
6407                        continue;
6408                    };
6409                    let Some(adapter) =
6410                        this.language_server_adapter_for_id(language_server.server_id())
6411                    else {
6412                        continue;
6413                    };
6414                    if filter.should_send_will_rename(&old_uri, is_dir) {
6415                        let apply_edit = cx.spawn({
6416                            let old_uri = old_uri.clone();
6417                            let new_uri = new_uri.clone();
6418                            let language_server = language_server.clone();
6419                            |this, mut cx| async move {
6420                                let edit = language_server
6421                                    .request::<WillRenameFiles>(RenameFilesParams {
6422                                        files: vec![FileRename { old_uri, new_uri }],
6423                                    })
6424                                    .log_err()
6425                                    .await
6426                                    .flatten()?;
6427
6428                                LocalLspStore::deserialize_workspace_edit(
6429                                    this.upgrade()?,
6430                                    edit,
6431                                    false,
6432                                    adapter.clone(),
6433                                    language_server.clone(),
6434                                    &mut cx,
6435                                )
6436                                .await
6437                                .ok();
6438                                Some(())
6439                            }
6440                        });
6441                        tasks.push(apply_edit);
6442                    }
6443                }
6444                Some(())
6445            })
6446            .ok()
6447            .flatten();
6448            for task in tasks {
6449                // Await on tasks sequentially so that the order of application of edits is deterministic
6450                // (at least with regards to the order of registration of language servers)
6451                task.await;
6452            }
6453        })
6454    }
6455
6456    fn lsp_notify_abs_paths_changed(
6457        &mut self,
6458        server_id: LanguageServerId,
6459        changes: Vec<PathEvent>,
6460    ) {
6461        maybe!({
6462            let server = self.language_server_for_id(server_id)?;
6463            let changes = changes
6464                .into_iter()
6465                .filter_map(|event| {
6466                    let typ = match event.kind? {
6467                        PathEventKind::Created => lsp::FileChangeType::CREATED,
6468                        PathEventKind::Removed => lsp::FileChangeType::DELETED,
6469                        PathEventKind::Changed => lsp::FileChangeType::CHANGED,
6470                    };
6471                    Some(lsp::FileEvent {
6472                        uri: lsp::Url::from_file_path(&event.path).ok()?,
6473                        typ,
6474                    })
6475                })
6476                .collect::<Vec<_>>();
6477            if !changes.is_empty() {
6478                server
6479                    .notify::<lsp::notification::DidChangeWatchedFiles>(
6480                        &lsp::DidChangeWatchedFilesParams { changes },
6481                    )
6482                    .log_err();
6483            }
6484            Some(())
6485        });
6486    }
6487
6488    pub fn language_server_for_id(&self, id: LanguageServerId) -> Option<Arc<LanguageServer>> {
6489        let local_lsp_store = self.as_local()?;
6490        if let Some(LanguageServerState::Running { server, .. }) =
6491            local_lsp_store.language_servers.get(&id)
6492        {
6493            Some(server.clone())
6494        } else if let Some((_, server)) = local_lsp_store.supplementary_language_servers.get(&id) {
6495            Some(Arc::clone(server))
6496        } else {
6497            None
6498        }
6499    }
6500
6501    fn on_lsp_progress(
6502        &mut self,
6503        progress: lsp::ProgressParams,
6504        language_server_id: LanguageServerId,
6505        disk_based_diagnostics_progress_token: Option<String>,
6506        cx: &mut Context<Self>,
6507    ) {
6508        let token = match progress.token {
6509            lsp::NumberOrString::String(token) => token,
6510            lsp::NumberOrString::Number(token) => {
6511                log::info!("skipping numeric progress token {}", token);
6512                return;
6513            }
6514        };
6515
6516        let lsp::ProgressParamsValue::WorkDone(progress) = progress.value;
6517        let language_server_status =
6518            if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
6519                status
6520            } else {
6521                return;
6522            };
6523
6524        if !language_server_status.progress_tokens.contains(&token) {
6525            return;
6526        }
6527
6528        let is_disk_based_diagnostics_progress = disk_based_diagnostics_progress_token
6529            .as_ref()
6530            .map_or(false, |disk_based_token| {
6531                token.starts_with(disk_based_token)
6532            });
6533
6534        match progress {
6535            lsp::WorkDoneProgress::Begin(report) => {
6536                if is_disk_based_diagnostics_progress {
6537                    self.disk_based_diagnostics_started(language_server_id, cx);
6538                }
6539                self.on_lsp_work_start(
6540                    language_server_id,
6541                    token.clone(),
6542                    LanguageServerProgress {
6543                        title: Some(report.title),
6544                        is_disk_based_diagnostics_progress,
6545                        is_cancellable: report.cancellable.unwrap_or(false),
6546                        message: report.message.clone(),
6547                        percentage: report.percentage.map(|p| p as usize),
6548                        last_update_at: cx.background_executor().now(),
6549                    },
6550                    cx,
6551                );
6552            }
6553            lsp::WorkDoneProgress::Report(report) => {
6554                if self.on_lsp_work_progress(
6555                    language_server_id,
6556                    token.clone(),
6557                    LanguageServerProgress {
6558                        title: None,
6559                        is_disk_based_diagnostics_progress,
6560                        is_cancellable: report.cancellable.unwrap_or(false),
6561                        message: report.message.clone(),
6562                        percentage: report.percentage.map(|p| p as usize),
6563                        last_update_at: cx.background_executor().now(),
6564                    },
6565                    cx,
6566                ) {
6567                    cx.emit(LspStoreEvent::LanguageServerUpdate {
6568                        language_server_id,
6569                        message: proto::update_language_server::Variant::WorkProgress(
6570                            proto::LspWorkProgress {
6571                                token,
6572                                message: report.message,
6573                                percentage: report.percentage,
6574                                is_cancellable: report.cancellable,
6575                            },
6576                        ),
6577                    })
6578                }
6579            }
6580            lsp::WorkDoneProgress::End(_) => {
6581                language_server_status.progress_tokens.remove(&token);
6582                self.on_lsp_work_end(language_server_id, token.clone(), cx);
6583                if is_disk_based_diagnostics_progress {
6584                    self.disk_based_diagnostics_finished(language_server_id, cx);
6585                }
6586            }
6587        }
6588    }
6589
6590    fn on_lsp_work_start(
6591        &mut self,
6592        language_server_id: LanguageServerId,
6593        token: String,
6594        progress: LanguageServerProgress,
6595        cx: &mut Context<Self>,
6596    ) {
6597        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
6598            status.pending_work.insert(token.clone(), progress.clone());
6599            cx.notify();
6600        }
6601        cx.emit(LspStoreEvent::LanguageServerUpdate {
6602            language_server_id,
6603            message: proto::update_language_server::Variant::WorkStart(proto::LspWorkStart {
6604                token,
6605                title: progress.title,
6606                message: progress.message,
6607                percentage: progress.percentage.map(|p| p as u32),
6608                is_cancellable: Some(progress.is_cancellable),
6609            }),
6610        })
6611    }
6612
6613    fn on_lsp_work_progress(
6614        &mut self,
6615        language_server_id: LanguageServerId,
6616        token: String,
6617        progress: LanguageServerProgress,
6618        cx: &mut Context<Self>,
6619    ) -> bool {
6620        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
6621            match status.pending_work.entry(token) {
6622                btree_map::Entry::Vacant(entry) => {
6623                    entry.insert(progress);
6624                    cx.notify();
6625                    return true;
6626                }
6627                btree_map::Entry::Occupied(mut entry) => {
6628                    let entry = entry.get_mut();
6629                    if (progress.last_update_at - entry.last_update_at)
6630                        >= SERVER_PROGRESS_THROTTLE_TIMEOUT
6631                    {
6632                        entry.last_update_at = progress.last_update_at;
6633                        if progress.message.is_some() {
6634                            entry.message = progress.message;
6635                        }
6636                        if progress.percentage.is_some() {
6637                            entry.percentage = progress.percentage;
6638                        }
6639                        if progress.is_cancellable != entry.is_cancellable {
6640                            entry.is_cancellable = progress.is_cancellable;
6641                        }
6642                        cx.notify();
6643                        return true;
6644                    }
6645                }
6646            }
6647        }
6648
6649        false
6650    }
6651
6652    fn on_lsp_work_end(
6653        &mut self,
6654        language_server_id: LanguageServerId,
6655        token: String,
6656        cx: &mut Context<Self>,
6657    ) {
6658        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
6659            if let Some(work) = status.pending_work.remove(&token) {
6660                if !work.is_disk_based_diagnostics_progress {
6661                    cx.emit(LspStoreEvent::RefreshInlayHints);
6662                }
6663            }
6664            cx.notify();
6665        }
6666
6667        cx.emit(LspStoreEvent::LanguageServerUpdate {
6668            language_server_id,
6669            message: proto::update_language_server::Variant::WorkEnd(proto::LspWorkEnd { token }),
6670        })
6671    }
6672
6673    pub async fn handle_resolve_completion_documentation(
6674        this: Entity<Self>,
6675        envelope: TypedEnvelope<proto::ResolveCompletionDocumentation>,
6676        mut cx: AsyncApp,
6677    ) -> Result<proto::ResolveCompletionDocumentationResponse> {
6678        let lsp_completion = serde_json::from_slice(&envelope.payload.lsp_completion)?;
6679
6680        let completion = this
6681            .read_with(&cx, |this, cx| {
6682                let id = LanguageServerId(envelope.payload.language_server_id as usize);
6683                let Some(server) = this.language_server_for_id(id) else {
6684                    return Err(anyhow!("No language server {id}"));
6685                };
6686
6687                Ok(cx.background_spawn(async move {
6688                    let can_resolve = server
6689                        .capabilities()
6690                        .completion_provider
6691                        .as_ref()
6692                        .and_then(|options| options.resolve_provider)
6693                        .unwrap_or(false);
6694                    if can_resolve {
6695                        server
6696                            .request::<lsp::request::ResolveCompletionItem>(lsp_completion)
6697                            .await
6698                    } else {
6699                        anyhow::Ok(lsp_completion)
6700                    }
6701                }))
6702            })??
6703            .await?;
6704
6705        let mut documentation_is_markdown = false;
6706        let lsp_completion = serde_json::to_string(&completion)?.into_bytes();
6707        let documentation = match completion.documentation {
6708            Some(lsp::Documentation::String(text)) => text,
6709
6710            Some(lsp::Documentation::MarkupContent(lsp::MarkupContent { kind, value })) => {
6711                documentation_is_markdown = kind == lsp::MarkupKind::Markdown;
6712                value
6713            }
6714
6715            _ => String::new(),
6716        };
6717
6718        // If we have a new buffer_id, that means we're talking to a new client
6719        // and want to check for new text_edits in the completion too.
6720        let mut old_start = None;
6721        let mut old_end = None;
6722        let mut new_text = String::default();
6723        if let Ok(buffer_id) = BufferId::new(envelope.payload.buffer_id) {
6724            let buffer_snapshot = this.update(&mut cx, |this, cx| {
6725                let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
6726                anyhow::Ok(buffer.read(cx).snapshot())
6727            })??;
6728
6729            if let Some(text_edit) = completion.text_edit.as_ref() {
6730                let edit = parse_completion_text_edit(text_edit, &buffer_snapshot);
6731
6732                if let Some((old_range, mut text_edit_new_text)) = edit {
6733                    LineEnding::normalize(&mut text_edit_new_text);
6734
6735                    new_text = text_edit_new_text;
6736                    old_start = Some(serialize_anchor(&old_range.start));
6737                    old_end = Some(serialize_anchor(&old_range.end));
6738                }
6739            }
6740        }
6741
6742        Ok(proto::ResolveCompletionDocumentationResponse {
6743            documentation,
6744            documentation_is_markdown,
6745            old_start,
6746            old_end,
6747            new_text,
6748            lsp_completion,
6749        })
6750    }
6751
6752    async fn handle_on_type_formatting(
6753        this: Entity<Self>,
6754        envelope: TypedEnvelope<proto::OnTypeFormatting>,
6755        mut cx: AsyncApp,
6756    ) -> Result<proto::OnTypeFormattingResponse> {
6757        let on_type_formatting = this.update(&mut cx, |this, cx| {
6758            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
6759            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
6760            let position = envelope
6761                .payload
6762                .position
6763                .and_then(deserialize_anchor)
6764                .ok_or_else(|| anyhow!("invalid position"))?;
6765            Ok::<_, anyhow::Error>(this.apply_on_type_formatting(
6766                buffer,
6767                position,
6768                envelope.payload.trigger.clone(),
6769                cx,
6770            ))
6771        })??;
6772
6773        let transaction = on_type_formatting
6774            .await?
6775            .as_ref()
6776            .map(language::proto::serialize_transaction);
6777        Ok(proto::OnTypeFormattingResponse { transaction })
6778    }
6779
6780    async fn handle_refresh_inlay_hints(
6781        this: Entity<Self>,
6782        _: TypedEnvelope<proto::RefreshInlayHints>,
6783        mut cx: AsyncApp,
6784    ) -> Result<proto::Ack> {
6785        this.update(&mut cx, |_, cx| {
6786            cx.emit(LspStoreEvent::RefreshInlayHints);
6787        })?;
6788        Ok(proto::Ack {})
6789    }
6790
6791    async fn handle_inlay_hints(
6792        this: Entity<Self>,
6793        envelope: TypedEnvelope<proto::InlayHints>,
6794        mut cx: AsyncApp,
6795    ) -> Result<proto::InlayHintsResponse> {
6796        let sender_id = envelope.original_sender_id().unwrap_or_default();
6797        let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
6798        let buffer = this.update(&mut cx, |this, cx| {
6799            this.buffer_store.read(cx).get_existing(buffer_id)
6800        })??;
6801        buffer
6802            .update(&mut cx, |buffer, _| {
6803                buffer.wait_for_version(deserialize_version(&envelope.payload.version))
6804            })?
6805            .await
6806            .with_context(|| format!("waiting for version for buffer {}", buffer.entity_id()))?;
6807
6808        let start = envelope
6809            .payload
6810            .start
6811            .and_then(deserialize_anchor)
6812            .context("missing range start")?;
6813        let end = envelope
6814            .payload
6815            .end
6816            .and_then(deserialize_anchor)
6817            .context("missing range end")?;
6818        let buffer_hints = this
6819            .update(&mut cx, |lsp_store, cx| {
6820                lsp_store.inlay_hints(buffer.clone(), start..end, cx)
6821            })?
6822            .await
6823            .context("inlay hints fetch")?;
6824
6825        this.update(&mut cx, |project, cx| {
6826            InlayHints::response_to_proto(
6827                buffer_hints,
6828                project,
6829                sender_id,
6830                &buffer.read(cx).version(),
6831                cx,
6832            )
6833        })
6834    }
6835
6836    async fn handle_resolve_inlay_hint(
6837        this: Entity<Self>,
6838        envelope: TypedEnvelope<proto::ResolveInlayHint>,
6839        mut cx: AsyncApp,
6840    ) -> Result<proto::ResolveInlayHintResponse> {
6841        let proto_hint = envelope
6842            .payload
6843            .hint
6844            .expect("incorrect protobuf resolve inlay hint message: missing the inlay hint");
6845        let hint = InlayHints::proto_to_project_hint(proto_hint)
6846            .context("resolved proto inlay hint conversion")?;
6847        let buffer = this.update(&mut cx, |this, cx| {
6848            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
6849            this.buffer_store.read(cx).get_existing(buffer_id)
6850        })??;
6851        let response_hint = this
6852            .update(&mut cx, |this, cx| {
6853                this.resolve_inlay_hint(
6854                    hint,
6855                    buffer,
6856                    LanguageServerId(envelope.payload.language_server_id as usize),
6857                    cx,
6858                )
6859            })?
6860            .await
6861            .context("inlay hints fetch")?;
6862        Ok(proto::ResolveInlayHintResponse {
6863            hint: Some(InlayHints::project_to_proto_hint(response_hint)),
6864        })
6865    }
6866
6867    async fn handle_open_buffer_for_symbol(
6868        this: Entity<Self>,
6869        envelope: TypedEnvelope<proto::OpenBufferForSymbol>,
6870        mut cx: AsyncApp,
6871    ) -> Result<proto::OpenBufferForSymbolResponse> {
6872        let peer_id = envelope.original_sender_id().unwrap_or_default();
6873        let symbol = envelope
6874            .payload
6875            .symbol
6876            .ok_or_else(|| anyhow!("invalid symbol"))?;
6877        let symbol = Self::deserialize_symbol(symbol)?;
6878        let symbol = this.update(&mut cx, |this, _| {
6879            let signature = this.symbol_signature(&symbol.path);
6880            if signature == symbol.signature {
6881                Ok(symbol)
6882            } else {
6883                Err(anyhow!("invalid symbol signature"))
6884            }
6885        })??;
6886        let buffer = this
6887            .update(&mut cx, |this, cx| {
6888                this.open_buffer_for_symbol(
6889                    &Symbol {
6890                        language_server_name: symbol.language_server_name,
6891                        source_worktree_id: symbol.source_worktree_id,
6892                        source_language_server_id: symbol.source_language_server_id,
6893                        path: symbol.path,
6894                        name: symbol.name,
6895                        kind: symbol.kind,
6896                        range: symbol.range,
6897                        signature: symbol.signature,
6898                        label: CodeLabel {
6899                            text: Default::default(),
6900                            runs: Default::default(),
6901                            filter_range: Default::default(),
6902                        },
6903                    },
6904                    cx,
6905                )
6906            })?
6907            .await?;
6908
6909        this.update(&mut cx, |this, cx| {
6910            let is_private = buffer
6911                .read(cx)
6912                .file()
6913                .map(|f| f.is_private())
6914                .unwrap_or_default();
6915            if is_private {
6916                Err(anyhow!(rpc::ErrorCode::UnsharedItem))
6917            } else {
6918                this.buffer_store
6919                    .update(cx, |buffer_store, cx| {
6920                        buffer_store.create_buffer_for_peer(&buffer, peer_id, cx)
6921                    })
6922                    .detach_and_log_err(cx);
6923                let buffer_id = buffer.read(cx).remote_id().to_proto();
6924                Ok(proto::OpenBufferForSymbolResponse { buffer_id })
6925            }
6926        })?
6927    }
6928
6929    fn symbol_signature(&self, project_path: &ProjectPath) -> [u8; 32] {
6930        let mut hasher = Sha256::new();
6931        hasher.update(project_path.worktree_id.to_proto().to_be_bytes());
6932        hasher.update(project_path.path.to_string_lossy().as_bytes());
6933        hasher.update(self.nonce.to_be_bytes());
6934        hasher.finalize().as_slice().try_into().unwrap()
6935    }
6936
6937    pub async fn handle_get_project_symbols(
6938        this: Entity<Self>,
6939        envelope: TypedEnvelope<proto::GetProjectSymbols>,
6940        mut cx: AsyncApp,
6941    ) -> Result<proto::GetProjectSymbolsResponse> {
6942        let symbols = this
6943            .update(&mut cx, |this, cx| {
6944                this.symbols(&envelope.payload.query, cx)
6945            })?
6946            .await?;
6947
6948        Ok(proto::GetProjectSymbolsResponse {
6949            symbols: symbols.iter().map(Self::serialize_symbol).collect(),
6950        })
6951    }
6952
6953    pub async fn handle_restart_language_servers(
6954        this: Entity<Self>,
6955        envelope: TypedEnvelope<proto::RestartLanguageServers>,
6956        mut cx: AsyncApp,
6957    ) -> Result<proto::Ack> {
6958        this.update(&mut cx, |this, cx| {
6959            let buffers = this.buffer_ids_to_buffers(envelope.payload.buffer_ids.into_iter(), cx);
6960            this.restart_language_servers_for_buffers(buffers, cx);
6961        })?;
6962
6963        Ok(proto::Ack {})
6964    }
6965
6966    pub async fn handle_cancel_language_server_work(
6967        this: Entity<Self>,
6968        envelope: TypedEnvelope<proto::CancelLanguageServerWork>,
6969        mut cx: AsyncApp,
6970    ) -> Result<proto::Ack> {
6971        this.update(&mut cx, |this, cx| {
6972            if let Some(work) = envelope.payload.work {
6973                match work {
6974                    proto::cancel_language_server_work::Work::Buffers(buffers) => {
6975                        let buffers =
6976                            this.buffer_ids_to_buffers(buffers.buffer_ids.into_iter(), cx);
6977                        this.cancel_language_server_work_for_buffers(buffers, cx);
6978                    }
6979                    proto::cancel_language_server_work::Work::LanguageServerWork(work) => {
6980                        let server_id = LanguageServerId::from_proto(work.language_server_id);
6981                        this.cancel_language_server_work(server_id, work.token, cx);
6982                    }
6983                }
6984            }
6985        })?;
6986
6987        Ok(proto::Ack {})
6988    }
6989
6990    fn buffer_ids_to_buffers(
6991        &mut self,
6992        buffer_ids: impl Iterator<Item = u64>,
6993        cx: &mut Context<Self>,
6994    ) -> Vec<Entity<Buffer>> {
6995        buffer_ids
6996            .into_iter()
6997            .flat_map(|buffer_id| {
6998                self.buffer_store
6999                    .read(cx)
7000                    .get(BufferId::new(buffer_id).log_err()?)
7001            })
7002            .collect::<Vec<_>>()
7003    }
7004
7005    async fn handle_apply_additional_edits_for_completion(
7006        this: Entity<Self>,
7007        envelope: TypedEnvelope<proto::ApplyCompletionAdditionalEdits>,
7008        mut cx: AsyncApp,
7009    ) -> Result<proto::ApplyCompletionAdditionalEditsResponse> {
7010        let (buffer, completion) = this.update(&mut cx, |this, cx| {
7011            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
7012            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
7013            let completion = Self::deserialize_completion(
7014                envelope
7015                    .payload
7016                    .completion
7017                    .ok_or_else(|| anyhow!("invalid completion"))?,
7018            )?;
7019            anyhow::Ok((buffer, completion))
7020        })??;
7021
7022        let apply_additional_edits = this.update(&mut cx, |this, cx| {
7023            this.apply_additional_edits_for_completion(
7024                buffer,
7025                Rc::new(RefCell::new(Box::new([Completion {
7026                    old_range: completion.old_range,
7027                    new_text: completion.new_text,
7028                    lsp_completion: completion.lsp_completion,
7029                    server_id: completion.server_id,
7030                    documentation: None,
7031                    label: CodeLabel {
7032                        text: Default::default(),
7033                        runs: Default::default(),
7034                        filter_range: Default::default(),
7035                    },
7036                    confirm: None,
7037                    resolved: completion.resolved,
7038                }]))),
7039                0,
7040                false,
7041                cx,
7042            )
7043        })?;
7044
7045        Ok(proto::ApplyCompletionAdditionalEditsResponse {
7046            transaction: apply_additional_edits
7047                .await?
7048                .as_ref()
7049                .map(language::proto::serialize_transaction),
7050        })
7051    }
7052
7053    pub fn last_formatting_failure(&self) -> Option<&str> {
7054        self.last_formatting_failure.as_deref()
7055    }
7056
7057    pub fn reset_last_formatting_failure(&mut self) {
7058        self.last_formatting_failure = None;
7059    }
7060
7061    pub fn environment_for_buffer(
7062        &self,
7063        buffer: &Entity<Buffer>,
7064        cx: &mut Context<Self>,
7065    ) -> Shared<Task<Option<HashMap<String, String>>>> {
7066        let worktree_id = buffer.read(cx).file().map(|file| file.worktree_id(cx));
7067        let worktree_abs_path = worktree_id.and_then(|worktree_id| {
7068            self.worktree_store
7069                .read(cx)
7070                .worktree_for_id(worktree_id, cx)
7071                .map(|entry| entry.read(cx).abs_path().clone())
7072        });
7073
7074        if let Some(environment) = &self.as_local().map(|local| local.environment.clone()) {
7075            environment.update(cx, |env, cx| {
7076                env.get_environment(worktree_id, worktree_abs_path, cx)
7077            })
7078        } else {
7079            Task::ready(None).shared()
7080        }
7081    }
7082
7083    pub fn format(
7084        &mut self,
7085        buffers: HashSet<Entity<Buffer>>,
7086        target: LspFormatTarget,
7087        push_to_history: bool,
7088        trigger: FormatTrigger,
7089        cx: &mut Context<Self>,
7090    ) -> Task<anyhow::Result<ProjectTransaction>> {
7091        if let Some(_) = self.as_local() {
7092            let buffers = buffers
7093                .into_iter()
7094                .map(|buffer_handle| {
7095                    let buffer = buffer_handle.read(cx);
7096                    let buffer_abs_path = File::from_dyn(buffer.file())
7097                        .and_then(|file| file.as_local().map(|f| f.abs_path(cx)));
7098
7099                    (buffer_handle, buffer_abs_path, buffer.remote_id())
7100                })
7101                .collect::<Vec<_>>();
7102
7103            cx.spawn(move |lsp_store, mut cx| async move {
7104                let mut formattable_buffers = Vec::with_capacity(buffers.len());
7105
7106                for (handle, abs_path, id) in buffers {
7107                    let env = lsp_store
7108                        .update(&mut cx, |lsp_store, cx| {
7109                            lsp_store.environment_for_buffer(&handle, cx)
7110                        })?
7111                        .await;
7112
7113                    let ranges = match &target {
7114                        LspFormatTarget::Buffers => None,
7115                        LspFormatTarget::Ranges(ranges) => {
7116                            let Some(ranges) = ranges.get(&id) else {
7117                                return Err(anyhow!("No format ranges provided for buffer"));
7118                            };
7119                            Some(ranges.clone())
7120                        }
7121                    };
7122
7123                    formattable_buffers.push(FormattableBuffer {
7124                        handle,
7125                        abs_path,
7126                        env,
7127                        ranges,
7128                    });
7129                }
7130
7131                let result = LocalLspStore::format_locally(
7132                    lsp_store.clone(),
7133                    formattable_buffers,
7134                    push_to_history,
7135                    trigger,
7136                    cx.clone(),
7137                )
7138                .await;
7139                lsp_store.update(&mut cx, |lsp_store, _| {
7140                    lsp_store.update_last_formatting_failure(&result);
7141                })?;
7142
7143                result
7144            })
7145        } else if let Some((client, project_id)) = self.upstream_client() {
7146            // Don't support formatting ranges via remote
7147            match target {
7148                LspFormatTarget::Buffers => {}
7149                LspFormatTarget::Ranges(_) => {
7150                    return Task::ready(Ok(ProjectTransaction::default()));
7151                }
7152            }
7153
7154            let buffer_store = self.buffer_store();
7155            cx.spawn(move |lsp_store, mut cx| async move {
7156                let result = client
7157                    .request(proto::FormatBuffers {
7158                        project_id,
7159                        trigger: trigger as i32,
7160                        buffer_ids: buffers
7161                            .iter()
7162                            .map(|buffer| {
7163                                buffer.update(&mut cx, |buffer, _| buffer.remote_id().into())
7164                            })
7165                            .collect::<Result<_>>()?,
7166                    })
7167                    .await
7168                    .and_then(|result| result.transaction.context("missing transaction"));
7169
7170                lsp_store.update(&mut cx, |lsp_store, _| {
7171                    lsp_store.update_last_formatting_failure(&result);
7172                })?;
7173
7174                let transaction_response = result?;
7175                buffer_store
7176                    .update(&mut cx, |buffer_store, cx| {
7177                        buffer_store.deserialize_project_transaction(
7178                            transaction_response,
7179                            push_to_history,
7180                            cx,
7181                        )
7182                    })?
7183                    .await
7184            })
7185        } else {
7186            Task::ready(Ok(ProjectTransaction::default()))
7187        }
7188    }
7189
7190    async fn handle_format_buffers(
7191        this: Entity<Self>,
7192        envelope: TypedEnvelope<proto::FormatBuffers>,
7193        mut cx: AsyncApp,
7194    ) -> Result<proto::FormatBuffersResponse> {
7195        let sender_id = envelope.original_sender_id().unwrap_or_default();
7196        let format = this.update(&mut cx, |this, cx| {
7197            let mut buffers = HashSet::default();
7198            for buffer_id in &envelope.payload.buffer_ids {
7199                let buffer_id = BufferId::new(*buffer_id)?;
7200                buffers.insert(this.buffer_store.read(cx).get_existing(buffer_id)?);
7201            }
7202            let trigger = FormatTrigger::from_proto(envelope.payload.trigger);
7203            anyhow::Ok(this.format(buffers, LspFormatTarget::Buffers, false, trigger, cx))
7204        })??;
7205
7206        let project_transaction = format.await?;
7207        let project_transaction = this.update(&mut cx, |this, cx| {
7208            this.buffer_store.update(cx, |buffer_store, cx| {
7209                buffer_store.serialize_project_transaction_for_peer(
7210                    project_transaction,
7211                    sender_id,
7212                    cx,
7213                )
7214            })
7215        })?;
7216        Ok(proto::FormatBuffersResponse {
7217            transaction: Some(project_transaction),
7218        })
7219    }
7220
7221    async fn shutdown_language_server(
7222        server_state: Option<LanguageServerState>,
7223        name: LanguageServerName,
7224        cx: AsyncApp,
7225    ) {
7226        let server = match server_state {
7227            Some(LanguageServerState::Starting { startup, .. }) => {
7228                let mut timer = cx
7229                    .background_executor()
7230                    .timer(SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT)
7231                    .fuse();
7232
7233                select! {
7234                    server = startup.fuse() => server,
7235                    _ = timer => {
7236                        log::info!(
7237                            "timeout waiting for language server {} to finish launching before stopping",
7238                            name
7239                        );
7240                        None
7241                    },
7242                }
7243            }
7244
7245            Some(LanguageServerState::Running { server, .. }) => Some(server),
7246
7247            None => None,
7248        };
7249
7250        if let Some(server) = server {
7251            if let Some(shutdown) = server.shutdown() {
7252                shutdown.await;
7253            }
7254        }
7255    }
7256
7257    // Returns a list of all of the worktrees which no longer have a language server and the root path
7258    // for the stopped server
7259    fn stop_local_language_server(
7260        &mut self,
7261        server_id: LanguageServerId,
7262        name: LanguageServerName,
7263        cx: &mut Context<Self>,
7264    ) -> Task<Vec<WorktreeId>> {
7265        let local = match &mut self.mode {
7266            LspStoreMode::Local(local) => local,
7267            _ => {
7268                return Task::ready(Vec::new());
7269            }
7270        };
7271
7272        let mut orphaned_worktrees = vec![];
7273        // Remove this server ID from all entries in the given worktree.
7274        local.language_server_ids.retain(|(worktree, _), ids| {
7275            if !ids.remove(&server_id) {
7276                return true;
7277            }
7278
7279            if ids.is_empty() {
7280                orphaned_worktrees.push(*worktree);
7281                false
7282            } else {
7283                true
7284            }
7285        });
7286        let _ = self.language_server_statuses.remove(&server_id);
7287        log::info!("stopping language server {name}");
7288        self.buffer_store.update(cx, |buffer_store, cx| {
7289            for buffer in buffer_store.buffers() {
7290                buffer.update(cx, |buffer, cx| {
7291                    buffer.update_diagnostics(server_id, DiagnosticSet::new([], buffer), cx);
7292                    buffer.set_completion_triggers(server_id, Default::default(), cx);
7293                });
7294            }
7295        });
7296
7297        for (worktree_id, summaries) in self.diagnostic_summaries.iter_mut() {
7298            summaries.retain(|path, summaries_by_server_id| {
7299                if summaries_by_server_id.remove(&server_id).is_some() {
7300                    if let Some((client, project_id)) = self.downstream_client.clone() {
7301                        client
7302                            .send(proto::UpdateDiagnosticSummary {
7303                                project_id,
7304                                worktree_id: worktree_id.to_proto(),
7305                                summary: Some(proto::DiagnosticSummary {
7306                                    path: path.as_ref().to_proto(),
7307                                    language_server_id: server_id.0 as u64,
7308                                    error_count: 0,
7309                                    warning_count: 0,
7310                                }),
7311                            })
7312                            .log_err();
7313                    }
7314                    !summaries_by_server_id.is_empty()
7315                } else {
7316                    true
7317                }
7318            });
7319        }
7320
7321        let local = self.as_local_mut().unwrap();
7322        for diagnostics in local.diagnostics.values_mut() {
7323            diagnostics.retain(|_, diagnostics_by_server_id| {
7324                if let Ok(ix) = diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0) {
7325                    diagnostics_by_server_id.remove(ix);
7326                    !diagnostics_by_server_id.is_empty()
7327                } else {
7328                    true
7329                }
7330            });
7331        }
7332        local.language_server_watched_paths.remove(&server_id);
7333        let server_state = local.language_servers.remove(&server_id);
7334        cx.notify();
7335        cx.emit(LspStoreEvent::LanguageServerRemoved(server_id));
7336        cx.spawn(move |_, cx| async move {
7337            Self::shutdown_language_server(server_state, name, cx).await;
7338            orphaned_worktrees
7339        })
7340    }
7341
7342    pub fn restart_language_servers_for_buffers(
7343        &mut self,
7344        buffers: Vec<Entity<Buffer>>,
7345        cx: &mut Context<Self>,
7346    ) {
7347        if let Some((client, project_id)) = self.upstream_client() {
7348            let request = client.request(proto::RestartLanguageServers {
7349                project_id,
7350                buffer_ids: buffers
7351                    .into_iter()
7352                    .map(|b| b.read(cx).remote_id().to_proto())
7353                    .collect(),
7354            });
7355            cx.background_spawn(request).detach_and_log_err(cx);
7356        } else {
7357            let Some(local) = self.as_local_mut() else {
7358                return;
7359            };
7360            let language_servers_to_stop = buffers
7361                .iter()
7362                .flat_map(|buffer| {
7363                    buffer.update(cx, |buffer, cx| {
7364                        local.language_server_ids_for_buffer(buffer, cx)
7365                    })
7366                })
7367                .collect::<BTreeSet<_>>();
7368            local.lsp_tree.update(cx, |this, _| {
7369                this.remove_nodes(&language_servers_to_stop);
7370            });
7371            let tasks = language_servers_to_stop
7372                .into_iter()
7373                .map(|server| {
7374                    let name = self
7375                        .language_server_statuses
7376                        .get(&server)
7377                        .map(|state| state.name.as_str().into())
7378                        .unwrap_or_else(|| LanguageServerName::from("Unknown"));
7379                    self.stop_local_language_server(server, name, cx)
7380                })
7381                .collect::<Vec<_>>();
7382
7383            cx.spawn(|this, mut cx| async move {
7384                cx.background_spawn(futures::future::join_all(tasks)).await;
7385                this.update(&mut cx, |this, cx| {
7386                    for buffer in buffers {
7387                        this.register_buffer_with_language_servers(&buffer, true, cx);
7388                    }
7389                })
7390                .ok()
7391            })
7392            .detach();
7393        }
7394    }
7395
7396    pub fn update_diagnostics(
7397        &mut self,
7398        language_server_id: LanguageServerId,
7399        mut params: lsp::PublishDiagnosticsParams,
7400        disk_based_sources: &[String],
7401        cx: &mut Context<Self>,
7402    ) -> Result<()> {
7403        if !self.mode.is_local() {
7404            anyhow::bail!("called update_diagnostics on remote");
7405        }
7406        let abs_path = params
7407            .uri
7408            .to_file_path()
7409            .map_err(|_| anyhow!("URI is not a file"))?;
7410        let mut diagnostics = Vec::default();
7411        let mut primary_diagnostic_group_ids = HashMap::default();
7412        let mut sources_by_group_id = HashMap::default();
7413        let mut supporting_diagnostics = HashMap::default();
7414
7415        // Ensure that primary diagnostics are always the most severe
7416        params.diagnostics.sort_by_key(|item| item.severity);
7417
7418        for diagnostic in &params.diagnostics {
7419            let source = diagnostic.source.as_ref();
7420            let range = range_from_lsp(diagnostic.range);
7421            let is_supporting = diagnostic
7422                .related_information
7423                .as_ref()
7424                .map_or(false, |infos| {
7425                    infos.iter().any(|info| {
7426                        primary_diagnostic_group_ids.contains_key(&(
7427                            source,
7428                            diagnostic.code.clone(),
7429                            range_from_lsp(info.location.range),
7430                        ))
7431                    })
7432                });
7433
7434            let is_unnecessary = diagnostic.tags.as_ref().map_or(false, |tags| {
7435                tags.iter().any(|tag| *tag == DiagnosticTag::UNNECESSARY)
7436            });
7437
7438            if is_supporting {
7439                supporting_diagnostics.insert(
7440                    (source, diagnostic.code.clone(), range),
7441                    (diagnostic.severity, is_unnecessary),
7442                );
7443            } else {
7444                let group_id = post_inc(&mut self.as_local_mut().unwrap().next_diagnostic_group_id);
7445                let is_disk_based =
7446                    source.map_or(false, |source| disk_based_sources.contains(source));
7447
7448                sources_by_group_id.insert(group_id, source);
7449                primary_diagnostic_group_ids
7450                    .insert((source, diagnostic.code.clone(), range.clone()), group_id);
7451
7452                diagnostics.push(DiagnosticEntry {
7453                    range,
7454                    diagnostic: Diagnostic {
7455                        source: diagnostic.source.clone(),
7456                        code: diagnostic.code.clone(),
7457                        severity: diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR),
7458                        message: diagnostic.message.trim().to_string(),
7459                        group_id,
7460                        is_primary: true,
7461                        is_disk_based,
7462                        is_unnecessary,
7463                        data: diagnostic.data.clone(),
7464                    },
7465                });
7466                if let Some(infos) = &diagnostic.related_information {
7467                    for info in infos {
7468                        if info.location.uri == params.uri && !info.message.is_empty() {
7469                            let range = range_from_lsp(info.location.range);
7470                            diagnostics.push(DiagnosticEntry {
7471                                range,
7472                                diagnostic: Diagnostic {
7473                                    source: diagnostic.source.clone(),
7474                                    code: diagnostic.code.clone(),
7475                                    severity: DiagnosticSeverity::INFORMATION,
7476                                    message: info.message.trim().to_string(),
7477                                    group_id,
7478                                    is_primary: false,
7479                                    is_disk_based,
7480                                    is_unnecessary: false,
7481                                    data: diagnostic.data.clone(),
7482                                },
7483                            });
7484                        }
7485                    }
7486                }
7487            }
7488        }
7489
7490        for entry in &mut diagnostics {
7491            let diagnostic = &mut entry.diagnostic;
7492            if !diagnostic.is_primary {
7493                let source = *sources_by_group_id.get(&diagnostic.group_id).unwrap();
7494                if let Some(&(severity, is_unnecessary)) = supporting_diagnostics.get(&(
7495                    source,
7496                    diagnostic.code.clone(),
7497                    entry.range.clone(),
7498                )) {
7499                    if let Some(severity) = severity {
7500                        diagnostic.severity = severity;
7501                    }
7502                    diagnostic.is_unnecessary = is_unnecessary;
7503                }
7504            }
7505        }
7506
7507        self.update_diagnostic_entries(
7508            language_server_id,
7509            abs_path,
7510            params.version,
7511            diagnostics,
7512            cx,
7513        )?;
7514        Ok(())
7515    }
7516
7517    fn insert_newly_running_language_server(
7518        &mut self,
7519        adapter: Arc<CachedLspAdapter>,
7520        language_server: Arc<LanguageServer>,
7521        server_id: LanguageServerId,
7522        key: (WorktreeId, LanguageServerName),
7523        workspace_folders: Arc<Mutex<BTreeSet<Url>>>,
7524        cx: &mut Context<Self>,
7525    ) {
7526        let Some(local) = self.as_local_mut() else {
7527            return;
7528        };
7529        // If the language server for this key doesn't match the server id, don't store the
7530        // server. Which will cause it to be dropped, killing the process
7531        if local
7532            .language_server_ids
7533            .get(&key)
7534            .map(|ids| !ids.contains(&server_id))
7535            .unwrap_or(false)
7536        {
7537            return;
7538        }
7539
7540        // Update language_servers collection with Running variant of LanguageServerState
7541        // indicating that the server is up and running and ready
7542        local.language_servers.insert(
7543            server_id,
7544            LanguageServerState::running(
7545                workspace_folders.lock().clone(),
7546                adapter.clone(),
7547                language_server.clone(),
7548                None,
7549            ),
7550        );
7551        if let Some(file_ops_caps) = language_server
7552            .capabilities()
7553            .workspace
7554            .as_ref()
7555            .and_then(|ws| ws.file_operations.as_ref())
7556        {
7557            let did_rename_caps = file_ops_caps.did_rename.as_ref();
7558            let will_rename_caps = file_ops_caps.will_rename.as_ref();
7559            if did_rename_caps.or(will_rename_caps).is_some() {
7560                let watcher = RenamePathsWatchedForServer::default()
7561                    .with_did_rename_patterns(did_rename_caps)
7562                    .with_will_rename_patterns(will_rename_caps);
7563                local
7564                    .language_server_paths_watched_for_rename
7565                    .insert(server_id, watcher);
7566            }
7567        }
7568
7569        self.language_server_statuses.insert(
7570            server_id,
7571            LanguageServerStatus {
7572                name: language_server.name().to_string(),
7573                pending_work: Default::default(),
7574                has_pending_diagnostic_updates: false,
7575                progress_tokens: Default::default(),
7576            },
7577        );
7578
7579        cx.emit(LspStoreEvent::LanguageServerAdded(
7580            server_id,
7581            language_server.name(),
7582            Some(key.0),
7583        ));
7584        cx.emit(LspStoreEvent::RefreshInlayHints);
7585
7586        if let Some((downstream_client, project_id)) = self.downstream_client.as_ref() {
7587            downstream_client
7588                .send(proto::StartLanguageServer {
7589                    project_id: *project_id,
7590                    server: Some(proto::LanguageServer {
7591                        id: server_id.0 as u64,
7592                        name: language_server.name().to_string(),
7593                        worktree_id: Some(key.0.to_proto()),
7594                    }),
7595                })
7596                .log_err();
7597        }
7598
7599        // Tell the language server about every open buffer in the worktree that matches the language.
7600        self.buffer_store.clone().update(cx, |buffer_store, cx| {
7601            for buffer_handle in buffer_store.buffers() {
7602                let buffer = buffer_handle.read(cx);
7603                let file = match File::from_dyn(buffer.file()) {
7604                    Some(file) => file,
7605                    None => continue,
7606                };
7607                let language = match buffer.language() {
7608                    Some(language) => language,
7609                    None => continue,
7610                };
7611
7612                if file.worktree.read(cx).id() != key.0
7613                    || !self
7614                        .languages
7615                        .lsp_adapters(&language.name())
7616                        .iter()
7617                        .any(|a| a.name == key.1)
7618                {
7619                    continue;
7620                }
7621                // didOpen
7622                let file = match file.as_local() {
7623                    Some(file) => file,
7624                    None => continue,
7625                };
7626
7627                let local = self.as_local_mut().unwrap();
7628
7629                if local.registered_buffers.contains_key(&buffer.remote_id()) {
7630                    let versions = local
7631                        .buffer_snapshots
7632                        .entry(buffer.remote_id())
7633                        .or_default()
7634                        .entry(server_id)
7635                        .and_modify(|_| {
7636                            assert!(
7637                            false,
7638                            "There should not be an existing snapshot for a newly inserted buffer"
7639                        )
7640                        })
7641                        .or_insert_with(|| {
7642                            vec![LspBufferSnapshot {
7643                                version: 0,
7644                                snapshot: buffer.text_snapshot(),
7645                            }]
7646                        });
7647
7648                    let snapshot = versions.last().unwrap();
7649                    let version = snapshot.version;
7650                    let initial_snapshot = &snapshot.snapshot;
7651                    let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap();
7652                    language_server.register_buffer(
7653                        uri,
7654                        adapter.language_id(&language.name()),
7655                        version,
7656                        initial_snapshot.text(),
7657                    );
7658                }
7659                buffer_handle.update(cx, |buffer, cx| {
7660                    buffer.set_completion_triggers(
7661                        server_id,
7662                        language_server
7663                            .capabilities()
7664                            .completion_provider
7665                            .as_ref()
7666                            .and_then(|provider| {
7667                                provider
7668                                    .trigger_characters
7669                                    .as_ref()
7670                                    .map(|characters| characters.iter().cloned().collect())
7671                            })
7672                            .unwrap_or_default(),
7673                        cx,
7674                    )
7675                });
7676            }
7677        });
7678
7679        cx.notify();
7680    }
7681
7682    pub fn language_servers_running_disk_based_diagnostics(
7683        &self,
7684    ) -> impl Iterator<Item = LanguageServerId> + '_ {
7685        self.language_server_statuses
7686            .iter()
7687            .filter_map(|(id, status)| {
7688                if status.has_pending_diagnostic_updates {
7689                    Some(*id)
7690                } else {
7691                    None
7692                }
7693            })
7694    }
7695
7696    pub(crate) fn cancel_language_server_work_for_buffers(
7697        &mut self,
7698        buffers: impl IntoIterator<Item = Entity<Buffer>>,
7699        cx: &mut Context<Self>,
7700    ) {
7701        if let Some((client, project_id)) = self.upstream_client() {
7702            let request = client.request(proto::CancelLanguageServerWork {
7703                project_id,
7704                work: Some(proto::cancel_language_server_work::Work::Buffers(
7705                    proto::cancel_language_server_work::Buffers {
7706                        buffer_ids: buffers
7707                            .into_iter()
7708                            .map(|b| b.read(cx).remote_id().to_proto())
7709                            .collect(),
7710                    },
7711                )),
7712            });
7713            cx.background_spawn(request).detach_and_log_err(cx);
7714        } else if let Some(local) = self.as_local() {
7715            let servers = buffers
7716                .into_iter()
7717                .flat_map(|buffer| {
7718                    buffer.update(cx, |buffer, cx| {
7719                        local.language_server_ids_for_buffer(buffer, cx).into_iter()
7720                    })
7721                })
7722                .collect::<HashSet<_>>();
7723            for server_id in servers {
7724                self.cancel_language_server_work(server_id, None, cx);
7725            }
7726        }
7727    }
7728
7729    pub(crate) fn cancel_language_server_work(
7730        &mut self,
7731        server_id: LanguageServerId,
7732        token_to_cancel: Option<String>,
7733        cx: &mut Context<Self>,
7734    ) {
7735        if let Some(local) = self.as_local() {
7736            let status = self.language_server_statuses.get(&server_id);
7737            let server = local.language_servers.get(&server_id);
7738            if let Some((LanguageServerState::Running { server, .. }, status)) = server.zip(status)
7739            {
7740                for (token, progress) in &status.pending_work {
7741                    if let Some(token_to_cancel) = token_to_cancel.as_ref() {
7742                        if token != token_to_cancel {
7743                            continue;
7744                        }
7745                    }
7746                    if progress.is_cancellable {
7747                        server
7748                            .notify::<lsp::notification::WorkDoneProgressCancel>(
7749                                &WorkDoneProgressCancelParams {
7750                                    token: lsp::NumberOrString::String(token.clone()),
7751                                },
7752                            )
7753                            .ok();
7754                    }
7755                }
7756            }
7757        } else if let Some((client, project_id)) = self.upstream_client() {
7758            let request = client.request(proto::CancelLanguageServerWork {
7759                project_id,
7760                work: Some(
7761                    proto::cancel_language_server_work::Work::LanguageServerWork(
7762                        proto::cancel_language_server_work::LanguageServerWork {
7763                            language_server_id: server_id.to_proto(),
7764                            token: token_to_cancel,
7765                        },
7766                    ),
7767                ),
7768            });
7769            cx.background_spawn(request).detach_and_log_err(cx);
7770        }
7771    }
7772
7773    fn register_supplementary_language_server(
7774        &mut self,
7775        id: LanguageServerId,
7776        name: LanguageServerName,
7777        server: Arc<LanguageServer>,
7778        cx: &mut Context<Self>,
7779    ) {
7780        if let Some(local) = self.as_local_mut() {
7781            local
7782                .supplementary_language_servers
7783                .insert(id, (name.clone(), server));
7784            cx.emit(LspStoreEvent::LanguageServerAdded(id, name, None));
7785        }
7786    }
7787
7788    fn unregister_supplementary_language_server(
7789        &mut self,
7790        id: LanguageServerId,
7791        cx: &mut Context<Self>,
7792    ) {
7793        if let Some(local) = self.as_local_mut() {
7794            local.supplementary_language_servers.remove(&id);
7795            cx.emit(LspStoreEvent::LanguageServerRemoved(id));
7796        }
7797    }
7798
7799    pub(crate) fn supplementary_language_servers(
7800        &self,
7801    ) -> impl '_ + Iterator<Item = (LanguageServerId, LanguageServerName)> {
7802        self.as_local().into_iter().flat_map(|local| {
7803            local
7804                .supplementary_language_servers
7805                .iter()
7806                .map(|(id, (name, _))| (*id, name.clone()))
7807        })
7808    }
7809
7810    pub fn language_server_adapter_for_id(
7811        &self,
7812        id: LanguageServerId,
7813    ) -> Option<Arc<CachedLspAdapter>> {
7814        self.as_local()
7815            .and_then(|local| local.language_servers.get(&id))
7816            .and_then(|language_server_state| match language_server_state {
7817                LanguageServerState::Running { adapter, .. } => Some(adapter.clone()),
7818                _ => None,
7819            })
7820    }
7821
7822    pub(super) fn update_local_worktree_language_servers(
7823        &mut self,
7824        worktree_handle: &Entity<Worktree>,
7825        changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
7826        cx: &mut Context<Self>,
7827    ) {
7828        if changes.is_empty() {
7829            return;
7830        }
7831
7832        let Some(local) = self.as_local() else { return };
7833
7834        local.prettier_store.update(cx, |prettier_store, cx| {
7835            prettier_store.update_prettier_settings(&worktree_handle, changes, cx)
7836        });
7837
7838        let worktree_id = worktree_handle.read(cx).id();
7839        let mut language_server_ids = local
7840            .language_server_ids
7841            .iter()
7842            .flat_map(|((server_worktree, _), server_ids)| {
7843                server_ids
7844                    .iter()
7845                    .filter_map(|server_id| server_worktree.eq(&worktree_id).then(|| *server_id))
7846            })
7847            .collect::<Vec<_>>();
7848        language_server_ids.sort();
7849        language_server_ids.dedup();
7850
7851        let abs_path = worktree_handle.read(cx).abs_path();
7852        for server_id in &language_server_ids {
7853            if let Some(LanguageServerState::Running { server, .. }) =
7854                local.language_servers.get(server_id)
7855            {
7856                if let Some(watched_paths) = local
7857                    .language_server_watched_paths
7858                    .get(server_id)
7859                    .and_then(|paths| paths.worktree_paths.get(&worktree_id))
7860                {
7861                    let params = lsp::DidChangeWatchedFilesParams {
7862                        changes: changes
7863                            .iter()
7864                            .filter_map(|(path, _, change)| {
7865                                if !watched_paths.is_match(path) {
7866                                    return None;
7867                                }
7868                                let typ = match change {
7869                                    PathChange::Loaded => return None,
7870                                    PathChange::Added => lsp::FileChangeType::CREATED,
7871                                    PathChange::Removed => lsp::FileChangeType::DELETED,
7872                                    PathChange::Updated => lsp::FileChangeType::CHANGED,
7873                                    PathChange::AddedOrUpdated => lsp::FileChangeType::CHANGED,
7874                                };
7875                                Some(lsp::FileEvent {
7876                                    uri: lsp::Url::from_file_path(abs_path.join(path)).unwrap(),
7877                                    typ,
7878                                })
7879                            })
7880                            .collect(),
7881                    };
7882                    if !params.changes.is_empty() {
7883                        server
7884                            .notify::<lsp::notification::DidChangeWatchedFiles>(&params)
7885                            .log_err();
7886                    }
7887                }
7888            }
7889        }
7890    }
7891
7892    pub fn wait_for_remote_buffer(
7893        &mut self,
7894        id: BufferId,
7895        cx: &mut Context<Self>,
7896    ) -> Task<Result<Entity<Buffer>>> {
7897        self.buffer_store.update(cx, |buffer_store, cx| {
7898            buffer_store.wait_for_remote_buffer(id, cx)
7899        })
7900    }
7901
7902    fn serialize_symbol(symbol: &Symbol) -> proto::Symbol {
7903        proto::Symbol {
7904            language_server_name: symbol.language_server_name.0.to_string(),
7905            source_worktree_id: symbol.source_worktree_id.to_proto(),
7906            language_server_id: symbol.source_language_server_id.to_proto(),
7907            worktree_id: symbol.path.worktree_id.to_proto(),
7908            path: symbol.path.path.as_ref().to_proto(),
7909            name: symbol.name.clone(),
7910            kind: unsafe { mem::transmute::<lsp::SymbolKind, i32>(symbol.kind) },
7911            start: Some(proto::PointUtf16 {
7912                row: symbol.range.start.0.row,
7913                column: symbol.range.start.0.column,
7914            }),
7915            end: Some(proto::PointUtf16 {
7916                row: symbol.range.end.0.row,
7917                column: symbol.range.end.0.column,
7918            }),
7919            signature: symbol.signature.to_vec(),
7920        }
7921    }
7922
7923    fn deserialize_symbol(serialized_symbol: proto::Symbol) -> Result<CoreSymbol> {
7924        let source_worktree_id = WorktreeId::from_proto(serialized_symbol.source_worktree_id);
7925        let worktree_id = WorktreeId::from_proto(serialized_symbol.worktree_id);
7926        let kind = unsafe { mem::transmute::<i32, lsp::SymbolKind>(serialized_symbol.kind) };
7927        let path = ProjectPath {
7928            worktree_id,
7929            path: Arc::<Path>::from_proto(serialized_symbol.path),
7930        };
7931
7932        let start = serialized_symbol
7933            .start
7934            .ok_or_else(|| anyhow!("invalid start"))?;
7935        let end = serialized_symbol
7936            .end
7937            .ok_or_else(|| anyhow!("invalid end"))?;
7938        Ok(CoreSymbol {
7939            language_server_name: LanguageServerName(serialized_symbol.language_server_name.into()),
7940            source_worktree_id,
7941            source_language_server_id: LanguageServerId::from_proto(
7942                serialized_symbol.language_server_id,
7943            ),
7944            path,
7945            name: serialized_symbol.name,
7946            range: Unclipped(PointUtf16::new(start.row, start.column))
7947                ..Unclipped(PointUtf16::new(end.row, end.column)),
7948            kind,
7949            signature: serialized_symbol
7950                .signature
7951                .try_into()
7952                .map_err(|_| anyhow!("invalid signature"))?,
7953        })
7954    }
7955
7956    pub(crate) fn serialize_completion(completion: &CoreCompletion) -> proto::Completion {
7957        proto::Completion {
7958            old_start: Some(serialize_anchor(&completion.old_range.start)),
7959            old_end: Some(serialize_anchor(&completion.old_range.end)),
7960            new_text: completion.new_text.clone(),
7961            server_id: completion.server_id.0 as u64,
7962            lsp_completion: serde_json::to_vec(&completion.lsp_completion).unwrap(),
7963            resolved: completion.resolved,
7964        }
7965    }
7966
7967    pub(crate) fn deserialize_completion(completion: proto::Completion) -> Result<CoreCompletion> {
7968        let old_start = completion
7969            .old_start
7970            .and_then(deserialize_anchor)
7971            .ok_or_else(|| anyhow!("invalid old start"))?;
7972        let old_end = completion
7973            .old_end
7974            .and_then(deserialize_anchor)
7975            .ok_or_else(|| anyhow!("invalid old end"))?;
7976        let lsp_completion = serde_json::from_slice(&completion.lsp_completion)?;
7977
7978        Ok(CoreCompletion {
7979            old_range: old_start..old_end,
7980            new_text: completion.new_text,
7981            server_id: LanguageServerId(completion.server_id as usize),
7982            lsp_completion,
7983            resolved: completion.resolved,
7984        })
7985    }
7986
7987    pub(crate) fn serialize_code_action(action: &CodeAction) -> proto::CodeAction {
7988        proto::CodeAction {
7989            server_id: action.server_id.0 as u64,
7990            start: Some(serialize_anchor(&action.range.start)),
7991            end: Some(serialize_anchor(&action.range.end)),
7992            lsp_action: serde_json::to_vec(&action.lsp_action).unwrap(),
7993        }
7994    }
7995
7996    pub(crate) fn deserialize_code_action(action: proto::CodeAction) -> Result<CodeAction> {
7997        let start = action
7998            .start
7999            .and_then(deserialize_anchor)
8000            .ok_or_else(|| anyhow!("invalid start"))?;
8001        let end = action
8002            .end
8003            .and_then(deserialize_anchor)
8004            .ok_or_else(|| anyhow!("invalid end"))?;
8005        let lsp_action = serde_json::from_slice(&action.lsp_action)?;
8006        Ok(CodeAction {
8007            server_id: LanguageServerId(action.server_id as usize),
8008            range: start..end,
8009            lsp_action,
8010        })
8011    }
8012
8013    fn update_last_formatting_failure<T>(&mut self, formatting_result: &anyhow::Result<T>) {
8014        match &formatting_result {
8015            Ok(_) => self.last_formatting_failure = None,
8016            Err(error) => {
8017                let error_string = format!("{error:#}");
8018                log::error!("Formatting failed: {error_string}");
8019                self.last_formatting_failure
8020                    .replace(error_string.lines().join(" "));
8021            }
8022        }
8023    }
8024}
8025
8026impl EventEmitter<LspStoreEvent> for LspStore {}
8027
8028fn remove_empty_hover_blocks(mut hover: Hover) -> Option<Hover> {
8029    hover
8030        .contents
8031        .retain(|hover_block| !hover_block.text.trim().is_empty());
8032    if hover.contents.is_empty() {
8033        None
8034    } else {
8035        Some(hover)
8036    }
8037}
8038
8039async fn populate_labels_for_completions(
8040    mut new_completions: Vec<CoreCompletion>,
8041    language: Option<Arc<Language>>,
8042    lsp_adapter: Option<Arc<CachedLspAdapter>>,
8043    completions: &mut Vec<Completion>,
8044) {
8045    let lsp_completions = new_completions
8046        .iter_mut()
8047        .map(|completion| mem::take(&mut completion.lsp_completion))
8048        .collect::<Vec<_>>();
8049
8050    let labels = if let Some((language, lsp_adapter)) = language.as_ref().zip(lsp_adapter) {
8051        lsp_adapter
8052            .labels_for_completions(&lsp_completions, language)
8053            .await
8054            .log_err()
8055            .unwrap_or_default()
8056    } else {
8057        Vec::new()
8058    };
8059
8060    for ((completion, lsp_completion), label) in new_completions
8061        .into_iter()
8062        .zip(lsp_completions)
8063        .zip(labels.into_iter().chain(iter::repeat(None)))
8064    {
8065        let documentation = if let Some(docs) = lsp_completion.documentation.clone() {
8066            Some(docs.into())
8067        } else {
8068            None
8069        };
8070
8071        let mut label = label.unwrap_or_else(|| {
8072            CodeLabel::fallback_for_completion(&lsp_completion, language.as_deref())
8073        });
8074        ensure_uniform_list_compatible_label(&mut label);
8075
8076        completions.push(Completion {
8077            old_range: completion.old_range,
8078            new_text: completion.new_text,
8079            label,
8080            server_id: completion.server_id,
8081            documentation,
8082            lsp_completion,
8083            confirm: None,
8084            resolved: false,
8085        })
8086    }
8087}
8088
8089#[derive(Debug)]
8090pub enum LanguageServerToQuery {
8091    Primary,
8092    Other(LanguageServerId),
8093}
8094
8095#[derive(Default)]
8096struct RenamePathsWatchedForServer {
8097    did_rename: Vec<RenameActionPredicate>,
8098    will_rename: Vec<RenameActionPredicate>,
8099}
8100
8101impl RenamePathsWatchedForServer {
8102    fn with_did_rename_patterns(
8103        mut self,
8104        did_rename: Option<&FileOperationRegistrationOptions>,
8105    ) -> Self {
8106        if let Some(did_rename) = did_rename {
8107            self.did_rename = did_rename
8108                .filters
8109                .iter()
8110                .filter_map(|filter| filter.try_into().log_err())
8111                .collect();
8112        }
8113        self
8114    }
8115    fn with_will_rename_patterns(
8116        mut self,
8117        will_rename: Option<&FileOperationRegistrationOptions>,
8118    ) -> Self {
8119        if let Some(will_rename) = will_rename {
8120            self.will_rename = will_rename
8121                .filters
8122                .iter()
8123                .filter_map(|filter| filter.try_into().log_err())
8124                .collect();
8125        }
8126        self
8127    }
8128
8129    fn should_send_did_rename(&self, path: &str, is_dir: bool) -> bool {
8130        self.did_rename.iter().any(|pred| pred.eval(path, is_dir))
8131    }
8132    fn should_send_will_rename(&self, path: &str, is_dir: bool) -> bool {
8133        self.will_rename.iter().any(|pred| pred.eval(path, is_dir))
8134    }
8135}
8136
8137impl TryFrom<&FileOperationFilter> for RenameActionPredicate {
8138    type Error = globset::Error;
8139    fn try_from(ops: &FileOperationFilter) -> Result<Self, globset::Error> {
8140        Ok(Self {
8141            kind: ops.pattern.matches.clone(),
8142            glob: GlobBuilder::new(&ops.pattern.glob)
8143                .case_insensitive(
8144                    ops.pattern
8145                        .options
8146                        .as_ref()
8147                        .map_or(false, |ops| ops.ignore_case.unwrap_or(false)),
8148                )
8149                .build()?
8150                .compile_matcher(),
8151        })
8152    }
8153}
8154struct RenameActionPredicate {
8155    glob: GlobMatcher,
8156    kind: Option<FileOperationPatternKind>,
8157}
8158
8159impl RenameActionPredicate {
8160    // Returns true if language server should be notified
8161    fn eval(&self, path: &str, is_dir: bool) -> bool {
8162        self.kind.as_ref().map_or(true, |kind| {
8163            let expected_kind = if is_dir {
8164                FileOperationPatternKind::Folder
8165            } else {
8166                FileOperationPatternKind::File
8167            };
8168            kind == &expected_kind
8169        }) && self.glob.is_match(path)
8170    }
8171}
8172
8173#[derive(Default)]
8174struct LanguageServerWatchedPaths {
8175    worktree_paths: HashMap<WorktreeId, GlobSet>,
8176    abs_paths: HashMap<Arc<Path>, (GlobSet, Task<()>)>,
8177}
8178
8179#[derive(Default)]
8180struct LanguageServerWatchedPathsBuilder {
8181    worktree_paths: HashMap<WorktreeId, GlobSet>,
8182    abs_paths: HashMap<Arc<Path>, GlobSet>,
8183}
8184
8185impl LanguageServerWatchedPathsBuilder {
8186    fn watch_worktree(&mut self, worktree_id: WorktreeId, glob_set: GlobSet) {
8187        self.worktree_paths.insert(worktree_id, glob_set);
8188    }
8189    fn watch_abs_path(&mut self, path: Arc<Path>, glob_set: GlobSet) {
8190        self.abs_paths.insert(path, glob_set);
8191    }
8192    fn build(
8193        self,
8194        fs: Arc<dyn Fs>,
8195        language_server_id: LanguageServerId,
8196        cx: &mut Context<LspStore>,
8197    ) -> LanguageServerWatchedPaths {
8198        let project = cx.weak_entity();
8199
8200        const LSP_ABS_PATH_OBSERVE: Duration = Duration::from_millis(100);
8201        let abs_paths = self
8202            .abs_paths
8203            .into_iter()
8204            .map(|(abs_path, globset)| {
8205                let task = cx.spawn({
8206                    let abs_path = abs_path.clone();
8207                    let fs = fs.clone();
8208
8209                    let lsp_store = project.clone();
8210                    |_, mut cx| async move {
8211                        maybe!(async move {
8212                            let mut push_updates = fs.watch(&abs_path, LSP_ABS_PATH_OBSERVE).await;
8213                            while let Some(update) = push_updates.0.next().await {
8214                                let action = lsp_store
8215                                    .update(&mut cx, |this, _| {
8216                                        let Some(local) = this.as_local() else {
8217                                            return ControlFlow::Break(());
8218                                        };
8219                                        let Some(watcher) = local
8220                                            .language_server_watched_paths
8221                                            .get(&language_server_id)
8222                                        else {
8223                                            return ControlFlow::Break(());
8224                                        };
8225                                        let (globs, _) = watcher.abs_paths.get(&abs_path).expect(
8226                                            "Watched abs path is not registered with a watcher",
8227                                        );
8228                                        let matching_entries = update
8229                                            .into_iter()
8230                                            .filter(|event| globs.is_match(&event.path))
8231                                            .collect::<Vec<_>>();
8232                                        this.lsp_notify_abs_paths_changed(
8233                                            language_server_id,
8234                                            matching_entries,
8235                                        );
8236                                        ControlFlow::Continue(())
8237                                    })
8238                                    .ok()?;
8239
8240                                if action.is_break() {
8241                                    break;
8242                                }
8243                            }
8244                            Some(())
8245                        })
8246                        .await;
8247                    }
8248                });
8249                (abs_path, (globset, task))
8250            })
8251            .collect();
8252        LanguageServerWatchedPaths {
8253            worktree_paths: self.worktree_paths,
8254            abs_paths,
8255        }
8256    }
8257}
8258
8259struct LspBufferSnapshot {
8260    version: i32,
8261    snapshot: TextBufferSnapshot,
8262}
8263
8264/// A prompt requested by LSP server.
8265#[derive(Clone, Debug)]
8266pub struct LanguageServerPromptRequest {
8267    pub level: PromptLevel,
8268    pub message: String,
8269    pub actions: Vec<MessageActionItem>,
8270    pub lsp_name: String,
8271    pub(crate) response_channel: Sender<MessageActionItem>,
8272}
8273
8274impl LanguageServerPromptRequest {
8275    pub async fn respond(self, index: usize) -> Option<()> {
8276        if let Some(response) = self.actions.into_iter().nth(index) {
8277            self.response_channel.send(response).await.ok()
8278        } else {
8279            None
8280        }
8281    }
8282}
8283impl PartialEq for LanguageServerPromptRequest {
8284    fn eq(&self, other: &Self) -> bool {
8285        self.message == other.message && self.actions == other.actions
8286    }
8287}
8288
8289#[derive(Clone, Debug, PartialEq)]
8290pub enum LanguageServerLogType {
8291    Log(MessageType),
8292    Trace(Option<String>),
8293}
8294
8295impl LanguageServerLogType {
8296    pub fn to_proto(&self) -> proto::language_server_log::LogType {
8297        match self {
8298            Self::Log(log_type) => {
8299                let message_type = match *log_type {
8300                    MessageType::ERROR => 1,
8301                    MessageType::WARNING => 2,
8302                    MessageType::INFO => 3,
8303                    MessageType::LOG => 4,
8304                    other => {
8305                        log::warn!("Unknown lsp log message type: {:?}", other);
8306                        4
8307                    }
8308                };
8309                proto::language_server_log::LogType::LogMessageType(message_type)
8310            }
8311            Self::Trace(message) => {
8312                proto::language_server_log::LogType::LogTrace(proto::LspLogTrace {
8313                    message: message.clone(),
8314                })
8315            }
8316        }
8317    }
8318
8319    pub fn from_proto(log_type: proto::language_server_log::LogType) -> Self {
8320        match log_type {
8321            proto::language_server_log::LogType::LogMessageType(message_type) => {
8322                Self::Log(match message_type {
8323                    1 => MessageType::ERROR,
8324                    2 => MessageType::WARNING,
8325                    3 => MessageType::INFO,
8326                    4 => MessageType::LOG,
8327                    _ => MessageType::LOG,
8328                })
8329            }
8330            proto::language_server_log::LogType::LogTrace(trace) => Self::Trace(trace.message),
8331        }
8332    }
8333}
8334
8335pub enum LanguageServerState {
8336    Starting {
8337        startup: Task<Option<Arc<LanguageServer>>>,
8338        /// List of language servers that will be added to the workspace once it's initialization completes.
8339        pending_workspace_folders: Arc<Mutex<BTreeSet<Url>>>,
8340    },
8341
8342    Running {
8343        adapter: Arc<CachedLspAdapter>,
8344        server: Arc<LanguageServer>,
8345        simulate_disk_based_diagnostics_completion: Option<Task<()>>,
8346    },
8347}
8348
8349impl LanguageServerState {
8350    fn add_workspace_folder(&self, uri: Url) {
8351        match self {
8352            LanguageServerState::Starting {
8353                pending_workspace_folders,
8354                ..
8355            } => {
8356                pending_workspace_folders.lock().insert(uri);
8357            }
8358            LanguageServerState::Running { server, .. } => {
8359                server.add_workspace_folder(uri);
8360            }
8361        }
8362    }
8363    fn _remove_workspace_folder(&self, uri: Url) {
8364        match self {
8365            LanguageServerState::Starting {
8366                pending_workspace_folders,
8367                ..
8368            } => {
8369                pending_workspace_folders.lock().remove(&uri);
8370            }
8371            LanguageServerState::Running { server, .. } => server.remove_workspace_folder(uri),
8372        }
8373    }
8374    fn running(
8375        workspace_folders: BTreeSet<Url>,
8376        adapter: Arc<CachedLspAdapter>,
8377        server: Arc<LanguageServer>,
8378        simulate_disk_based_diagnostics_completion: Option<Task<()>>,
8379    ) -> Self {
8380        server.set_workspace_folders(workspace_folders);
8381        Self::Running {
8382            adapter,
8383            server,
8384            simulate_disk_based_diagnostics_completion,
8385        }
8386    }
8387}
8388
8389impl std::fmt::Debug for LanguageServerState {
8390    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8391        match self {
8392            LanguageServerState::Starting { .. } => {
8393                f.debug_struct("LanguageServerState::Starting").finish()
8394            }
8395            LanguageServerState::Running { .. } => {
8396                f.debug_struct("LanguageServerState::Running").finish()
8397            }
8398        }
8399    }
8400}
8401
8402#[derive(Clone, Debug, Serialize)]
8403pub struct LanguageServerProgress {
8404    pub is_disk_based_diagnostics_progress: bool,
8405    pub is_cancellable: bool,
8406    pub title: Option<String>,
8407    pub message: Option<String>,
8408    pub percentage: Option<usize>,
8409    #[serde(skip_serializing)]
8410    pub last_update_at: Instant,
8411}
8412
8413#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize)]
8414pub struct DiagnosticSummary {
8415    pub error_count: usize,
8416    pub warning_count: usize,
8417}
8418
8419impl DiagnosticSummary {
8420    pub fn new<'a, T: 'a>(diagnostics: impl IntoIterator<Item = &'a DiagnosticEntry<T>>) -> Self {
8421        let mut this = Self {
8422            error_count: 0,
8423            warning_count: 0,
8424        };
8425
8426        for entry in diagnostics {
8427            if entry.diagnostic.is_primary {
8428                match entry.diagnostic.severity {
8429                    DiagnosticSeverity::ERROR => this.error_count += 1,
8430                    DiagnosticSeverity::WARNING => this.warning_count += 1,
8431                    _ => {}
8432                }
8433            }
8434        }
8435
8436        this
8437    }
8438
8439    pub fn is_empty(&self) -> bool {
8440        self.error_count == 0 && self.warning_count == 0
8441    }
8442
8443    pub fn to_proto(
8444        &self,
8445        language_server_id: LanguageServerId,
8446        path: &Path,
8447    ) -> proto::DiagnosticSummary {
8448        proto::DiagnosticSummary {
8449            path: path.to_proto(),
8450            language_server_id: language_server_id.0 as u64,
8451            error_count: self.error_count as u32,
8452            warning_count: self.warning_count as u32,
8453        }
8454    }
8455}
8456
8457#[derive(Clone, Debug)]
8458pub enum CompletionDocumentation {
8459    /// There is no documentation for this completion.
8460    Undocumented,
8461    /// A single line of documentation.
8462    SingleLine(SharedString),
8463    /// Multiple lines of plain text documentation.
8464    MultiLinePlainText(SharedString),
8465    /// Markdown documentation.
8466    MultiLineMarkdown(SharedString),
8467}
8468
8469impl From<lsp::Documentation> for CompletionDocumentation {
8470    fn from(docs: lsp::Documentation) -> Self {
8471        match docs {
8472            lsp::Documentation::String(text) => {
8473                if text.lines().count() <= 1 {
8474                    CompletionDocumentation::SingleLine(text.into())
8475                } else {
8476                    CompletionDocumentation::MultiLinePlainText(text.into())
8477                }
8478            }
8479
8480            lsp::Documentation::MarkupContent(lsp::MarkupContent { kind, value }) => match kind {
8481                lsp::MarkupKind::PlainText => {
8482                    if value.lines().count() <= 1 {
8483                        CompletionDocumentation::SingleLine(value.into())
8484                    } else {
8485                        CompletionDocumentation::MultiLinePlainText(value.into())
8486                    }
8487                }
8488
8489                lsp::MarkupKind::Markdown => {
8490                    CompletionDocumentation::MultiLineMarkdown(value.into())
8491                }
8492            },
8493        }
8494    }
8495}
8496
8497fn glob_literal_prefix(glob: &Path) -> PathBuf {
8498    glob.components()
8499        .take_while(|component| match component {
8500            path::Component::Normal(part) => !part.to_string_lossy().contains(['*', '?', '{', '}']),
8501            _ => true,
8502        })
8503        .collect()
8504}
8505
8506pub struct SshLspAdapter {
8507    name: LanguageServerName,
8508    binary: LanguageServerBinary,
8509    initialization_options: Option<String>,
8510    code_action_kinds: Option<Vec<CodeActionKind>>,
8511}
8512
8513impl SshLspAdapter {
8514    pub fn new(
8515        name: LanguageServerName,
8516        binary: LanguageServerBinary,
8517        initialization_options: Option<String>,
8518        code_action_kinds: Option<String>,
8519    ) -> Self {
8520        Self {
8521            name,
8522            binary,
8523            initialization_options,
8524            code_action_kinds: code_action_kinds
8525                .as_ref()
8526                .and_then(|c| serde_json::from_str(c).ok()),
8527        }
8528    }
8529}
8530
8531#[async_trait(?Send)]
8532impl LspAdapter for SshLspAdapter {
8533    fn name(&self) -> LanguageServerName {
8534        self.name.clone()
8535    }
8536
8537    async fn initialization_options(
8538        self: Arc<Self>,
8539        _: &dyn Fs,
8540        _: &Arc<dyn LspAdapterDelegate>,
8541    ) -> Result<Option<serde_json::Value>> {
8542        let Some(options) = &self.initialization_options else {
8543            return Ok(None);
8544        };
8545        let result = serde_json::from_str(options)?;
8546        Ok(result)
8547    }
8548
8549    fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
8550        self.code_action_kinds.clone()
8551    }
8552
8553    async fn check_if_user_installed(
8554        &self,
8555        _: &dyn LspAdapterDelegate,
8556        _: Arc<dyn LanguageToolchainStore>,
8557        _: &AsyncApp,
8558    ) -> Option<LanguageServerBinary> {
8559        Some(self.binary.clone())
8560    }
8561
8562    async fn cached_server_binary(
8563        &self,
8564        _: PathBuf,
8565        _: &dyn LspAdapterDelegate,
8566    ) -> Option<LanguageServerBinary> {
8567        None
8568    }
8569
8570    async fn fetch_latest_server_version(
8571        &self,
8572        _: &dyn LspAdapterDelegate,
8573    ) -> Result<Box<dyn 'static + Send + Any>> {
8574        anyhow::bail!("SshLspAdapter does not support fetch_latest_server_version")
8575    }
8576
8577    async fn fetch_server_binary(
8578        &self,
8579        _: Box<dyn 'static + Send + Any>,
8580        _: PathBuf,
8581        _: &dyn LspAdapterDelegate,
8582    ) -> Result<LanguageServerBinary> {
8583        anyhow::bail!("SshLspAdapter does not support fetch_server_binary")
8584    }
8585}
8586
8587pub fn language_server_settings<'a>(
8588    delegate: &'a dyn LspAdapterDelegate,
8589    language: &LanguageServerName,
8590    cx: &'a App,
8591) -> Option<&'a LspSettings> {
8592    language_server_settings_for(
8593        SettingsLocation {
8594            worktree_id: delegate.worktree_id(),
8595            path: delegate.worktree_root_path(),
8596        },
8597        language,
8598        cx,
8599    )
8600}
8601
8602pub(crate) fn language_server_settings_for<'a>(
8603    location: SettingsLocation<'a>,
8604    language: &LanguageServerName,
8605    cx: &'a App,
8606) -> Option<&'a LspSettings> {
8607    ProjectSettings::get(Some(location), cx).lsp.get(language)
8608}
8609
8610pub struct LocalLspAdapterDelegate {
8611    lsp_store: WeakEntity<LspStore>,
8612    worktree: worktree::Snapshot,
8613    fs: Arc<dyn Fs>,
8614    http_client: Arc<dyn HttpClient>,
8615    language_registry: Arc<LanguageRegistry>,
8616    load_shell_env_task: Shared<Task<Option<HashMap<String, String>>>>,
8617}
8618
8619impl LocalLspAdapterDelegate {
8620    pub fn new(
8621        language_registry: Arc<LanguageRegistry>,
8622        environment: &Entity<ProjectEnvironment>,
8623        lsp_store: WeakEntity<LspStore>,
8624        worktree: &Entity<Worktree>,
8625        http_client: Arc<dyn HttpClient>,
8626        fs: Arc<dyn Fs>,
8627        cx: &mut App,
8628    ) -> Arc<Self> {
8629        let (worktree_id, worktree_abs_path) = {
8630            let worktree = worktree.read(cx);
8631            (worktree.id(), worktree.abs_path())
8632        };
8633
8634        let load_shell_env_task = environment.update(cx, |env, cx| {
8635            env.get_environment(Some(worktree_id), Some(worktree_abs_path), cx)
8636        });
8637
8638        Arc::new(Self {
8639            lsp_store,
8640            worktree: worktree.read(cx).snapshot(),
8641            fs,
8642            http_client,
8643            language_registry,
8644            load_shell_env_task,
8645        })
8646    }
8647
8648    fn from_local_lsp(
8649        local: &LocalLspStore,
8650        worktree: &Entity<Worktree>,
8651        cx: &mut App,
8652    ) -> Arc<Self> {
8653        Self::new(
8654            local.languages.clone(),
8655            &local.environment,
8656            local.weak.clone(),
8657            worktree,
8658            local.http_client.clone(),
8659            local.fs.clone(),
8660            cx,
8661        )
8662    }
8663}
8664
8665#[async_trait]
8666impl LspAdapterDelegate for LocalLspAdapterDelegate {
8667    fn show_notification(&self, message: &str, cx: &mut App) {
8668        self.lsp_store
8669            .update(cx, |_, cx| {
8670                cx.emit(LspStoreEvent::Notification(message.to_owned()))
8671            })
8672            .ok();
8673    }
8674
8675    fn http_client(&self) -> Arc<dyn HttpClient> {
8676        self.http_client.clone()
8677    }
8678
8679    fn worktree_id(&self) -> WorktreeId {
8680        self.worktree.id()
8681    }
8682
8683    fn exists(&self, path: &Path, is_dir: Option<bool>) -> bool {
8684        self.worktree.entry_for_path(path).map_or(false, |entry| {
8685            is_dir.map_or(true, |is_required_to_be_dir| {
8686                is_required_to_be_dir == entry.is_dir()
8687            })
8688        })
8689    }
8690
8691    fn worktree_root_path(&self) -> &Path {
8692        self.worktree.abs_path().as_ref()
8693    }
8694
8695    async fn shell_env(&self) -> HashMap<String, String> {
8696        let task = self.load_shell_env_task.clone();
8697        task.await.unwrap_or_default()
8698    }
8699
8700    async fn npm_package_installed_version(
8701        &self,
8702        package_name: &str,
8703    ) -> Result<Option<(PathBuf, String)>> {
8704        let local_package_directory = self.worktree_root_path();
8705        let node_modules_directory = local_package_directory.join("node_modules");
8706
8707        if let Some(version) =
8708            read_package_installed_version(node_modules_directory.clone(), package_name).await?
8709        {
8710            return Ok(Some((node_modules_directory, version)));
8711        }
8712        let Some(npm) = self.which("npm".as_ref()).await else {
8713            log::warn!(
8714                "Failed to find npm executable for {:?}",
8715                local_package_directory
8716            );
8717            return Ok(None);
8718        };
8719
8720        let env = self.shell_env().await;
8721        let output = util::command::new_smol_command(&npm)
8722            .args(["root", "-g"])
8723            .envs(env)
8724            .current_dir(local_package_directory)
8725            .output()
8726            .await?;
8727        let global_node_modules =
8728            PathBuf::from(String::from_utf8_lossy(&output.stdout).to_string());
8729
8730        if let Some(version) =
8731            read_package_installed_version(global_node_modules.clone(), package_name).await?
8732        {
8733            return Ok(Some((global_node_modules, version)));
8734        }
8735        return Ok(None);
8736    }
8737
8738    #[cfg(not(target_os = "windows"))]
8739    async fn which(&self, command: &OsStr) -> Option<PathBuf> {
8740        let worktree_abs_path = self.worktree.abs_path();
8741        let shell_path = self.shell_env().await.get("PATH").cloned();
8742        which::which_in(command, shell_path.as_ref(), worktree_abs_path).ok()
8743    }
8744
8745    #[cfg(target_os = "windows")]
8746    async fn which(&self, command: &OsStr) -> Option<PathBuf> {
8747        // todo(windows) Getting the shell env variables in a current directory on Windows is more complicated than other platforms
8748        //               there isn't a 'default shell' necessarily. The closest would be the default profile on the windows terminal
8749        //               SEE: https://learn.microsoft.com/en-us/windows/terminal/customize-settings/startup
8750        which::which(command).ok()
8751    }
8752
8753    async fn try_exec(&self, command: LanguageServerBinary) -> Result<()> {
8754        let working_dir = self.worktree_root_path();
8755        let output = util::command::new_smol_command(&command.path)
8756            .args(command.arguments)
8757            .envs(command.env.clone().unwrap_or_default())
8758            .current_dir(working_dir)
8759            .output()
8760            .await?;
8761
8762        if output.status.success() {
8763            return Ok(());
8764        }
8765        Err(anyhow!(
8766            "{}, stdout: {:?}, stderr: {:?}",
8767            output.status,
8768            String::from_utf8_lossy(&output.stdout),
8769            String::from_utf8_lossy(&output.stderr)
8770        ))
8771    }
8772
8773    fn update_status(
8774        &self,
8775        server_name: LanguageServerName,
8776        status: language::LanguageServerBinaryStatus,
8777    ) {
8778        self.language_registry
8779            .update_lsp_status(server_name, status);
8780    }
8781
8782    async fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>> {
8783        let dir = self.language_registry.language_server_download_dir(name)?;
8784
8785        if !dir.exists() {
8786            smol::fs::create_dir_all(&dir)
8787                .await
8788                .context("failed to create container directory")
8789                .log_err()?;
8790        }
8791
8792        Some(dir)
8793    }
8794
8795    async fn read_text_file(&self, path: PathBuf) -> Result<String> {
8796        let entry = self
8797            .worktree
8798            .entry_for_path(&path)
8799            .with_context(|| format!("no worktree entry for path {path:?}"))?;
8800        let abs_path = self
8801            .worktree
8802            .absolutize(&entry.path)
8803            .with_context(|| format!("cannot absolutize path {path:?}"))?;
8804
8805        self.fs.load(&abs_path).await
8806    }
8807}
8808
8809async fn populate_labels_for_symbols(
8810    symbols: Vec<CoreSymbol>,
8811    language_registry: &Arc<LanguageRegistry>,
8812    lsp_adapter: Option<Arc<CachedLspAdapter>>,
8813    output: &mut Vec<Symbol>,
8814) {
8815    #[allow(clippy::mutable_key_type)]
8816    let mut symbols_by_language = HashMap::<Option<Arc<Language>>, Vec<CoreSymbol>>::default();
8817
8818    let mut unknown_paths = BTreeSet::new();
8819    for symbol in symbols {
8820        let language = language_registry
8821            .language_for_file_path(&symbol.path.path)
8822            .await
8823            .ok()
8824            .or_else(|| {
8825                unknown_paths.insert(symbol.path.path.clone());
8826                None
8827            });
8828        symbols_by_language
8829            .entry(language)
8830            .or_default()
8831            .push(symbol);
8832    }
8833
8834    for unknown_path in unknown_paths {
8835        log::info!(
8836            "no language found for symbol path {}",
8837            unknown_path.display()
8838        );
8839    }
8840
8841    let mut label_params = Vec::new();
8842    for (language, mut symbols) in symbols_by_language {
8843        label_params.clear();
8844        label_params.extend(
8845            symbols
8846                .iter_mut()
8847                .map(|symbol| (mem::take(&mut symbol.name), symbol.kind)),
8848        );
8849
8850        let mut labels = Vec::new();
8851        if let Some(language) = language {
8852            let lsp_adapter = lsp_adapter.clone().or_else(|| {
8853                language_registry
8854                    .lsp_adapters(&language.name())
8855                    .first()
8856                    .cloned()
8857            });
8858            if let Some(lsp_adapter) = lsp_adapter {
8859                labels = lsp_adapter
8860                    .labels_for_symbols(&label_params, &language)
8861                    .await
8862                    .log_err()
8863                    .unwrap_or_default();
8864            }
8865        }
8866
8867        for ((symbol, (name, _)), label) in symbols
8868            .into_iter()
8869            .zip(label_params.drain(..))
8870            .zip(labels.into_iter().chain(iter::repeat(None)))
8871        {
8872            output.push(Symbol {
8873                language_server_name: symbol.language_server_name,
8874                source_worktree_id: symbol.source_worktree_id,
8875                source_language_server_id: symbol.source_language_server_id,
8876                path: symbol.path,
8877                label: label.unwrap_or_else(|| CodeLabel::plain(name.clone(), None)),
8878                name,
8879                kind: symbol.kind,
8880                range: symbol.range,
8881                signature: symbol.signature,
8882            });
8883        }
8884    }
8885}
8886
8887fn include_text(server: &lsp::LanguageServer) -> Option<bool> {
8888    match server.capabilities().text_document_sync.as_ref()? {
8889        lsp::TextDocumentSyncCapability::Kind(kind) => match *kind {
8890            lsp::TextDocumentSyncKind::NONE => None,
8891            lsp::TextDocumentSyncKind::FULL => Some(true),
8892            lsp::TextDocumentSyncKind::INCREMENTAL => Some(false),
8893            _ => None,
8894        },
8895        lsp::TextDocumentSyncCapability::Options(options) => match options.save.as_ref()? {
8896            lsp::TextDocumentSyncSaveOptions::Supported(supported) => {
8897                if *supported {
8898                    Some(true)
8899                } else {
8900                    None
8901                }
8902            }
8903            lsp::TextDocumentSyncSaveOptions::SaveOptions(save_options) => {
8904                Some(save_options.include_text.unwrap_or(false))
8905            }
8906        },
8907    }
8908}
8909
8910/// Completion items are displayed in a `UniformList`.
8911/// Usually, those items are single-line strings, but in LSP responses,
8912/// completion items `label`, `detail` and `label_details.description` may contain newlines or long spaces.
8913/// Many language plugins construct these items by joining these parts together, and we may use `CodeLabel::fallback_for_completion` that uses `label` at least.
8914/// 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,
8915/// breaking the completions menu presentation.
8916///
8917/// 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.
8918fn ensure_uniform_list_compatible_label(label: &mut CodeLabel) {
8919    let mut new_text = String::with_capacity(label.text.len());
8920    let mut offset_map = vec![0; label.text.len() + 1];
8921    let mut last_char_was_space = false;
8922    let mut new_idx = 0;
8923    let mut chars = label.text.char_indices().fuse();
8924    let mut newlines_removed = false;
8925
8926    while let Some((idx, c)) = chars.next() {
8927        offset_map[idx] = new_idx;
8928
8929        match c {
8930            '\n' if last_char_was_space => {
8931                newlines_removed = true;
8932            }
8933            '\t' | ' ' if last_char_was_space => {}
8934            '\n' if !last_char_was_space => {
8935                new_text.push(' ');
8936                new_idx += 1;
8937                last_char_was_space = true;
8938                newlines_removed = true;
8939            }
8940            ' ' | '\t' => {
8941                new_text.push(' ');
8942                new_idx += 1;
8943                last_char_was_space = true;
8944            }
8945            _ => {
8946                new_text.push(c);
8947                new_idx += c.len_utf8();
8948                last_char_was_space = false;
8949            }
8950        }
8951    }
8952    offset_map[label.text.len()] = new_idx;
8953
8954    // Only modify the label if newlines were removed.
8955    if !newlines_removed {
8956        return;
8957    }
8958
8959    let last_index = new_idx;
8960    let mut run_ranges_errors = Vec::new();
8961    label.runs.retain_mut(|(range, _)| {
8962        match offset_map.get(range.start) {
8963            Some(&start) => range.start = start,
8964            None => {
8965                run_ranges_errors.push(range.clone());
8966                return false;
8967            }
8968        }
8969
8970        match offset_map.get(range.end) {
8971            Some(&end) => range.end = end,
8972            None => {
8973                run_ranges_errors.push(range.clone());
8974                range.end = last_index;
8975            }
8976        }
8977        true
8978    });
8979    if !run_ranges_errors.is_empty() {
8980        log::error!(
8981            "Completion label has errors in its run ranges: {run_ranges_errors:?}, label text: {}",
8982            label.text
8983        );
8984    }
8985
8986    let mut wrong_filter_range = None;
8987    if label.filter_range == (0..label.text.len()) {
8988        label.filter_range = 0..new_text.len();
8989    } else {
8990        let mut original_filter_range = Some(label.filter_range.clone());
8991        match offset_map.get(label.filter_range.start) {
8992            Some(&start) => label.filter_range.start = start,
8993            None => {
8994                wrong_filter_range = original_filter_range.take();
8995                label.filter_range.start = last_index;
8996            }
8997        }
8998
8999        match offset_map.get(label.filter_range.end) {
9000            Some(&end) => label.filter_range.end = end,
9001            None => {
9002                wrong_filter_range = original_filter_range.take();
9003                label.filter_range.end = last_index;
9004            }
9005        }
9006    }
9007    if let Some(wrong_filter_range) = wrong_filter_range {
9008        log::error!(
9009            "Completion label has an invalid filter range: {wrong_filter_range:?}, label text: {}",
9010            label.text
9011        );
9012    }
9013
9014    label.text = new_text;
9015}
9016
9017#[cfg(test)]
9018mod tests {
9019    use language::HighlightId;
9020
9021    use super::*;
9022
9023    #[test]
9024    fn test_glob_literal_prefix() {
9025        assert_eq!(glob_literal_prefix(Path::new("**/*.js")), Path::new(""));
9026        assert_eq!(
9027            glob_literal_prefix(Path::new("node_modules/**/*.js")),
9028            Path::new("node_modules")
9029        );
9030        assert_eq!(
9031            glob_literal_prefix(Path::new("foo/{bar,baz}.js")),
9032            Path::new("foo")
9033        );
9034        assert_eq!(
9035            glob_literal_prefix(Path::new("foo/bar/baz.js")),
9036            Path::new("foo/bar/baz.js")
9037        );
9038
9039        #[cfg(target_os = "windows")]
9040        {
9041            assert_eq!(glob_literal_prefix(Path::new("**\\*.js")), Path::new(""));
9042            assert_eq!(
9043                glob_literal_prefix(Path::new("node_modules\\**/*.js")),
9044                Path::new("node_modules")
9045            );
9046            assert_eq!(
9047                glob_literal_prefix(Path::new("foo/{bar,baz}.js")),
9048                Path::new("foo")
9049            );
9050            assert_eq!(
9051                glob_literal_prefix(Path::new("foo\\bar\\baz.js")),
9052                Path::new("foo/bar/baz.js")
9053            );
9054        }
9055    }
9056
9057    #[test]
9058    fn test_multi_len_chars_normalization() {
9059        let mut label = CodeLabel {
9060            text: "myElˇ (parameter) myElˇ: {\n    foo: string;\n}".to_string(),
9061            runs: vec![(0..6, HighlightId(1))],
9062            filter_range: 0..6,
9063        };
9064        ensure_uniform_list_compatible_label(&mut label);
9065        assert_eq!(
9066            label,
9067            CodeLabel {
9068                text: "myElˇ (parameter) myElˇ: { foo: string; }".to_string(),
9069                runs: vec![(0..6, HighlightId(1))],
9070                filter_range: 0..6,
9071            }
9072        );
9073    }
9074}