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