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