lsp_store.rs

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