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