lsp_store.rs

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