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