lsp_store.rs

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