lsp_store.rs

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