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