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