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