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