project.rs

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