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