project.rs

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