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