lsp_store.rs

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