project.rs

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