lsp_store.rs

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