project.rs

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