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