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