project.rs

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