project.rs

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