lsp_store.rs

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