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