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