project.rs

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