project.rs

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