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
3006            let server_id = language_server.server_id();
3007            let test_binary = match language_server.test_installation_binary() {
3008                Some(test_binary) => test_binary.clone(),
3009                None => return,
3010            };
3011
3012            const PROCESS_TIMEOUT: Duration = Duration::from_secs(5);
3013            let mut timeout = cx.background().timer(PROCESS_TIMEOUT).fuse();
3014
3015            let mut errored = false;
3016            let result = smol::process::Command::new(&test_binary.path)
3017                .current_dir(&test_binary.path)
3018                .args(test_binary.arguments)
3019                .stdin(Stdio::piped())
3020                .stdout(Stdio::piped())
3021                .stderr(Stdio::inherit())
3022                .kill_on_drop(true)
3023                .spawn();
3024
3025            if let Ok(mut process) = result {
3026                futures::select! {
3027                    status = process.status().fuse() => match status {
3028                        Ok(status) => errored = !status.success(),
3029                        Err(_) => errored = true,
3030                    },
3031
3032                    _ = timeout => {}
3033                }
3034            } else {
3035                errored = true;
3036            }
3037
3038            if errored {
3039                let task = this.update(&mut cx, move |this, mut cx| {
3040                    this.reinstall_language_server(server_id, &mut cx)
3041                });
3042
3043                if let Some(task) = task {
3044                    task.await;
3045                }
3046            }
3047        })
3048        .detach();
3049    }
3050
3051    fn on_lsp_progress(
3052        &mut self,
3053        progress: lsp::ProgressParams,
3054        language_server_id: LanguageServerId,
3055        disk_based_diagnostics_progress_token: Option<String>,
3056        cx: &mut ModelContext<Self>,
3057    ) {
3058        let token = match progress.token {
3059            lsp::NumberOrString::String(token) => token,
3060            lsp::NumberOrString::Number(token) => {
3061                log::info!("skipping numeric progress token {}", token);
3062                return;
3063            }
3064        };
3065        let lsp::ProgressParamsValue::WorkDone(progress) = progress.value;
3066        let language_server_status =
3067            if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
3068                status
3069            } else {
3070                return;
3071            };
3072
3073        if !language_server_status.progress_tokens.contains(&token) {
3074            return;
3075        }
3076
3077        let is_disk_based_diagnostics_progress = disk_based_diagnostics_progress_token
3078            .as_ref()
3079            .map_or(false, |disk_based_token| {
3080                token.starts_with(disk_based_token)
3081            });
3082
3083        match progress {
3084            lsp::WorkDoneProgress::Begin(report) => {
3085                if is_disk_based_diagnostics_progress {
3086                    language_server_status.has_pending_diagnostic_updates = true;
3087                    self.disk_based_diagnostics_started(language_server_id, cx);
3088                    self.buffer_ordered_messages_tx
3089                        .unbounded_send(BufferOrderedMessage::LanguageServerUpdate {
3090                            language_server_id,
3091                            message: proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(Default::default())
3092                        })
3093                        .ok();
3094                } else {
3095                    self.on_lsp_work_start(
3096                        language_server_id,
3097                        token.clone(),
3098                        LanguageServerProgress {
3099                            message: report.message.clone(),
3100                            percentage: report.percentage.map(|p| p as usize),
3101                            last_update_at: Instant::now(),
3102                        },
3103                        cx,
3104                    );
3105                    self.buffer_ordered_messages_tx
3106                        .unbounded_send(BufferOrderedMessage::LanguageServerUpdate {
3107                            language_server_id,
3108                            message: proto::update_language_server::Variant::WorkStart(
3109                                proto::LspWorkStart {
3110                                    token,
3111                                    message: report.message,
3112                                    percentage: report.percentage.map(|p| p as u32),
3113                                },
3114                            ),
3115                        })
3116                        .ok();
3117                }
3118            }
3119            lsp::WorkDoneProgress::Report(report) => {
3120                if !is_disk_based_diagnostics_progress {
3121                    self.on_lsp_work_progress(
3122                        language_server_id,
3123                        token.clone(),
3124                        LanguageServerProgress {
3125                            message: report.message.clone(),
3126                            percentage: report.percentage.map(|p| p as usize),
3127                            last_update_at: Instant::now(),
3128                        },
3129                        cx,
3130                    );
3131                    self.buffer_ordered_messages_tx
3132                        .unbounded_send(BufferOrderedMessage::LanguageServerUpdate {
3133                            language_server_id,
3134                            message: proto::update_language_server::Variant::WorkProgress(
3135                                proto::LspWorkProgress {
3136                                    token,
3137                                    message: report.message,
3138                                    percentage: report.percentage.map(|p| p as u32),
3139                                },
3140                            ),
3141                        })
3142                        .ok();
3143                }
3144            }
3145            lsp::WorkDoneProgress::End(_) => {
3146                language_server_status.progress_tokens.remove(&token);
3147
3148                if is_disk_based_diagnostics_progress {
3149                    language_server_status.has_pending_diagnostic_updates = false;
3150                    self.disk_based_diagnostics_finished(language_server_id, cx);
3151                    self.buffer_ordered_messages_tx
3152                        .unbounded_send(BufferOrderedMessage::LanguageServerUpdate {
3153                            language_server_id,
3154                            message:
3155                                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
3156                                    Default::default(),
3157                                ),
3158                        })
3159                        .ok();
3160                } else {
3161                    self.on_lsp_work_end(language_server_id, token.clone(), cx);
3162                    self.buffer_ordered_messages_tx
3163                        .unbounded_send(BufferOrderedMessage::LanguageServerUpdate {
3164                            language_server_id,
3165                            message: proto::update_language_server::Variant::WorkEnd(
3166                                proto::LspWorkEnd { token },
3167                            ),
3168                        })
3169                        .ok();
3170                }
3171            }
3172        }
3173    }
3174
3175    fn on_lsp_work_start(
3176        &mut self,
3177        language_server_id: LanguageServerId,
3178        token: String,
3179        progress: LanguageServerProgress,
3180        cx: &mut ModelContext<Self>,
3181    ) {
3182        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
3183            status.pending_work.insert(token, progress);
3184            cx.notify();
3185        }
3186    }
3187
3188    fn on_lsp_work_progress(
3189        &mut self,
3190        language_server_id: LanguageServerId,
3191        token: String,
3192        progress: LanguageServerProgress,
3193        cx: &mut ModelContext<Self>,
3194    ) {
3195        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
3196            let entry = status
3197                .pending_work
3198                .entry(token)
3199                .or_insert(LanguageServerProgress {
3200                    message: Default::default(),
3201                    percentage: Default::default(),
3202                    last_update_at: progress.last_update_at,
3203                });
3204            if progress.message.is_some() {
3205                entry.message = progress.message;
3206            }
3207            if progress.percentage.is_some() {
3208                entry.percentage = progress.percentage;
3209            }
3210            entry.last_update_at = progress.last_update_at;
3211            cx.notify();
3212        }
3213    }
3214
3215    fn on_lsp_work_end(
3216        &mut self,
3217        language_server_id: LanguageServerId,
3218        token: String,
3219        cx: &mut ModelContext<Self>,
3220    ) {
3221        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
3222            status.pending_work.remove(&token);
3223            cx.notify();
3224        }
3225    }
3226
3227    fn on_lsp_did_change_watched_files(
3228        &mut self,
3229        language_server_id: LanguageServerId,
3230        params: DidChangeWatchedFilesRegistrationOptions,
3231        cx: &mut ModelContext<Self>,
3232    ) {
3233        if let Some(LanguageServerState::Running { watched_paths, .. }) =
3234            self.language_servers.get_mut(&language_server_id)
3235        {
3236            let mut builders = HashMap::default();
3237            for watcher in params.watchers {
3238                for worktree in &self.worktrees {
3239                    if let Some(worktree) = worktree.upgrade(cx) {
3240                        let worktree = worktree.read(cx);
3241                        if let Some(abs_path) = worktree.abs_path().to_str() {
3242                            if let Some(suffix) = match &watcher.glob_pattern {
3243                                lsp::GlobPattern::String(s) => s,
3244                                lsp::GlobPattern::Relative(rp) => &rp.pattern,
3245                            }
3246                            .strip_prefix(abs_path)
3247                            .and_then(|s| s.strip_prefix(std::path::MAIN_SEPARATOR))
3248                            {
3249                                if let Some(glob) = Glob::new(suffix).log_err() {
3250                                    builders
3251                                        .entry(worktree.id())
3252                                        .or_insert_with(|| GlobSetBuilder::new())
3253                                        .add(glob);
3254                                }
3255                                break;
3256                            }
3257                        }
3258                    }
3259                }
3260            }
3261
3262            watched_paths.clear();
3263            for (worktree_id, builder) in builders {
3264                if let Ok(globset) = builder.build() {
3265                    watched_paths.insert(worktree_id, globset);
3266                }
3267            }
3268
3269            cx.notify();
3270        }
3271    }
3272
3273    async fn on_lsp_workspace_edit(
3274        this: WeakModelHandle<Self>,
3275        params: lsp::ApplyWorkspaceEditParams,
3276        server_id: LanguageServerId,
3277        adapter: Arc<CachedLspAdapter>,
3278        mut cx: AsyncAppContext,
3279    ) -> Result<lsp::ApplyWorkspaceEditResponse> {
3280        let this = this
3281            .upgrade(&cx)
3282            .ok_or_else(|| anyhow!("project project closed"))?;
3283        let language_server = this
3284            .read_with(&cx, |this, _| this.language_server_for_id(server_id))
3285            .ok_or_else(|| anyhow!("language server not found"))?;
3286        let transaction = Self::deserialize_workspace_edit(
3287            this.clone(),
3288            params.edit,
3289            true,
3290            adapter.clone(),
3291            language_server.clone(),
3292            &mut cx,
3293        )
3294        .await
3295        .log_err();
3296        this.update(&mut cx, |this, _| {
3297            if let Some(transaction) = transaction {
3298                this.last_workspace_edits_by_language_server
3299                    .insert(server_id, transaction);
3300            }
3301        });
3302        Ok(lsp::ApplyWorkspaceEditResponse {
3303            applied: true,
3304            failed_change: None,
3305            failure_reason: None,
3306        })
3307    }
3308
3309    pub fn language_server_statuses(
3310        &self,
3311    ) -> impl DoubleEndedIterator<Item = &LanguageServerStatus> {
3312        self.language_server_statuses.values()
3313    }
3314
3315    pub fn update_diagnostics(
3316        &mut self,
3317        language_server_id: LanguageServerId,
3318        mut params: lsp::PublishDiagnosticsParams,
3319        disk_based_sources: &[String],
3320        cx: &mut ModelContext<Self>,
3321    ) -> Result<()> {
3322        let abs_path = params
3323            .uri
3324            .to_file_path()
3325            .map_err(|_| anyhow!("URI is not a file"))?;
3326        let mut diagnostics = Vec::default();
3327        let mut primary_diagnostic_group_ids = HashMap::default();
3328        let mut sources_by_group_id = HashMap::default();
3329        let mut supporting_diagnostics = HashMap::default();
3330
3331        // Ensure that primary diagnostics are always the most severe
3332        params.diagnostics.sort_by_key(|item| item.severity);
3333
3334        for diagnostic in &params.diagnostics {
3335            let source = diagnostic.source.as_ref();
3336            let code = diagnostic.code.as_ref().map(|code| match code {
3337                lsp::NumberOrString::Number(code) => code.to_string(),
3338                lsp::NumberOrString::String(code) => code.clone(),
3339            });
3340            let range = range_from_lsp(diagnostic.range);
3341            let is_supporting = diagnostic
3342                .related_information
3343                .as_ref()
3344                .map_or(false, |infos| {
3345                    infos.iter().any(|info| {
3346                        primary_diagnostic_group_ids.contains_key(&(
3347                            source,
3348                            code.clone(),
3349                            range_from_lsp(info.location.range),
3350                        ))
3351                    })
3352                });
3353
3354            let is_unnecessary = diagnostic.tags.as_ref().map_or(false, |tags| {
3355                tags.iter().any(|tag| *tag == DiagnosticTag::UNNECESSARY)
3356            });
3357
3358            if is_supporting {
3359                supporting_diagnostics.insert(
3360                    (source, code.clone(), range),
3361                    (diagnostic.severity, is_unnecessary),
3362                );
3363            } else {
3364                let group_id = post_inc(&mut self.next_diagnostic_group_id);
3365                let is_disk_based =
3366                    source.map_or(false, |source| disk_based_sources.contains(source));
3367
3368                sources_by_group_id.insert(group_id, source);
3369                primary_diagnostic_group_ids
3370                    .insert((source, code.clone(), range.clone()), group_id);
3371
3372                diagnostics.push(DiagnosticEntry {
3373                    range,
3374                    diagnostic: Diagnostic {
3375                        source: diagnostic.source.clone(),
3376                        code: code.clone(),
3377                        severity: diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR),
3378                        message: diagnostic.message.clone(),
3379                        group_id,
3380                        is_primary: true,
3381                        is_valid: true,
3382                        is_disk_based,
3383                        is_unnecessary,
3384                    },
3385                });
3386                if let Some(infos) = &diagnostic.related_information {
3387                    for info in infos {
3388                        if info.location.uri == params.uri && !info.message.is_empty() {
3389                            let range = range_from_lsp(info.location.range);
3390                            diagnostics.push(DiagnosticEntry {
3391                                range,
3392                                diagnostic: Diagnostic {
3393                                    source: diagnostic.source.clone(),
3394                                    code: code.clone(),
3395                                    severity: DiagnosticSeverity::INFORMATION,
3396                                    message: info.message.clone(),
3397                                    group_id,
3398                                    is_primary: false,
3399                                    is_valid: true,
3400                                    is_disk_based,
3401                                    is_unnecessary: false,
3402                                },
3403                            });
3404                        }
3405                    }
3406                }
3407            }
3408        }
3409
3410        for entry in &mut diagnostics {
3411            let diagnostic = &mut entry.diagnostic;
3412            if !diagnostic.is_primary {
3413                let source = *sources_by_group_id.get(&diagnostic.group_id).unwrap();
3414                if let Some(&(severity, is_unnecessary)) = supporting_diagnostics.get(&(
3415                    source,
3416                    diagnostic.code.clone(),
3417                    entry.range.clone(),
3418                )) {
3419                    if let Some(severity) = severity {
3420                        diagnostic.severity = severity;
3421                    }
3422                    diagnostic.is_unnecessary = is_unnecessary;
3423                }
3424            }
3425        }
3426
3427        self.update_diagnostic_entries(
3428            language_server_id,
3429            abs_path,
3430            params.version,
3431            diagnostics,
3432            cx,
3433        )?;
3434        Ok(())
3435    }
3436
3437    pub fn update_diagnostic_entries(
3438        &mut self,
3439        server_id: LanguageServerId,
3440        abs_path: PathBuf,
3441        version: Option<i32>,
3442        diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
3443        cx: &mut ModelContext<Project>,
3444    ) -> Result<(), anyhow::Error> {
3445        let (worktree, relative_path) = self
3446            .find_local_worktree(&abs_path, cx)
3447            .ok_or_else(|| anyhow!("no worktree found for diagnostics path {abs_path:?}"))?;
3448
3449        let project_path = ProjectPath {
3450            worktree_id: worktree.read(cx).id(),
3451            path: relative_path.into(),
3452        };
3453
3454        if let Some(buffer) = self.get_open_buffer(&project_path, cx) {
3455            self.update_buffer_diagnostics(&buffer, server_id, version, diagnostics.clone(), cx)?;
3456        }
3457
3458        let updated = worktree.update(cx, |worktree, cx| {
3459            worktree
3460                .as_local_mut()
3461                .ok_or_else(|| anyhow!("not a local worktree"))?
3462                .update_diagnostics(server_id, project_path.path.clone(), diagnostics, cx)
3463        })?;
3464        if updated {
3465            cx.emit(Event::DiagnosticsUpdated {
3466                language_server_id: server_id,
3467                path: project_path,
3468            });
3469        }
3470        Ok(())
3471    }
3472
3473    fn update_buffer_diagnostics(
3474        &mut self,
3475        buffer: &ModelHandle<Buffer>,
3476        server_id: LanguageServerId,
3477        version: Option<i32>,
3478        mut diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
3479        cx: &mut ModelContext<Self>,
3480    ) -> Result<()> {
3481        fn compare_diagnostics(a: &Diagnostic, b: &Diagnostic) -> Ordering {
3482            Ordering::Equal
3483                .then_with(|| b.is_primary.cmp(&a.is_primary))
3484                .then_with(|| a.is_disk_based.cmp(&b.is_disk_based))
3485                .then_with(|| a.severity.cmp(&b.severity))
3486                .then_with(|| a.message.cmp(&b.message))
3487        }
3488
3489        let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx)?;
3490
3491        diagnostics.sort_unstable_by(|a, b| {
3492            Ordering::Equal
3493                .then_with(|| a.range.start.cmp(&b.range.start))
3494                .then_with(|| b.range.end.cmp(&a.range.end))
3495                .then_with(|| compare_diagnostics(&a.diagnostic, &b.diagnostic))
3496        });
3497
3498        let mut sanitized_diagnostics = Vec::new();
3499        let edits_since_save = Patch::new(
3500            snapshot
3501                .edits_since::<Unclipped<PointUtf16>>(buffer.read(cx).saved_version())
3502                .collect(),
3503        );
3504        for entry in diagnostics {
3505            let start;
3506            let end;
3507            if entry.diagnostic.is_disk_based {
3508                // Some diagnostics are based on files on disk instead of buffers'
3509                // current contents. Adjust these diagnostics' ranges to reflect
3510                // any unsaved edits.
3511                start = edits_since_save.old_to_new(entry.range.start);
3512                end = edits_since_save.old_to_new(entry.range.end);
3513            } else {
3514                start = entry.range.start;
3515                end = entry.range.end;
3516            }
3517
3518            let mut range = snapshot.clip_point_utf16(start, Bias::Left)
3519                ..snapshot.clip_point_utf16(end, Bias::Right);
3520
3521            // Expand empty ranges by one codepoint
3522            if range.start == range.end {
3523                // This will be go to the next boundary when being clipped
3524                range.end.column += 1;
3525                range.end = snapshot.clip_point_utf16(Unclipped(range.end), Bias::Right);
3526                if range.start == range.end && range.end.column > 0 {
3527                    range.start.column -= 1;
3528                    range.end = snapshot.clip_point_utf16(Unclipped(range.end), Bias::Left);
3529                }
3530            }
3531
3532            sanitized_diagnostics.push(DiagnosticEntry {
3533                range,
3534                diagnostic: entry.diagnostic,
3535            });
3536        }
3537        drop(edits_since_save);
3538
3539        let set = DiagnosticSet::new(sanitized_diagnostics, &snapshot);
3540        buffer.update(cx, |buffer, cx| {
3541            buffer.update_diagnostics(server_id, set, cx)
3542        });
3543        Ok(())
3544    }
3545
3546    pub fn reload_buffers(
3547        &self,
3548        buffers: HashSet<ModelHandle<Buffer>>,
3549        push_to_history: bool,
3550        cx: &mut ModelContext<Self>,
3551    ) -> Task<Result<ProjectTransaction>> {
3552        let mut local_buffers = Vec::new();
3553        let mut remote_buffers = None;
3554        for buffer_handle in buffers {
3555            let buffer = buffer_handle.read(cx);
3556            if buffer.is_dirty() {
3557                if let Some(file) = File::from_dyn(buffer.file()) {
3558                    if file.is_local() {
3559                        local_buffers.push(buffer_handle);
3560                    } else {
3561                        remote_buffers.get_or_insert(Vec::new()).push(buffer_handle);
3562                    }
3563                }
3564            }
3565        }
3566
3567        let remote_buffers = self.remote_id().zip(remote_buffers);
3568        let client = self.client.clone();
3569
3570        cx.spawn(|this, mut cx| async move {
3571            let mut project_transaction = ProjectTransaction::default();
3572
3573            if let Some((project_id, remote_buffers)) = remote_buffers {
3574                let response = client
3575                    .request(proto::ReloadBuffers {
3576                        project_id,
3577                        buffer_ids: remote_buffers
3578                            .iter()
3579                            .map(|buffer| buffer.read_with(&cx, |buffer, _| buffer.remote_id()))
3580                            .collect(),
3581                    })
3582                    .await?
3583                    .transaction
3584                    .ok_or_else(|| anyhow!("missing transaction"))?;
3585                project_transaction = this
3586                    .update(&mut cx, |this, cx| {
3587                        this.deserialize_project_transaction(response, push_to_history, cx)
3588                    })
3589                    .await?;
3590            }
3591
3592            for buffer in local_buffers {
3593                let transaction = buffer
3594                    .update(&mut cx, |buffer, cx| buffer.reload(cx))
3595                    .await?;
3596                buffer.update(&mut cx, |buffer, cx| {
3597                    if let Some(transaction) = transaction {
3598                        if !push_to_history {
3599                            buffer.forget_transaction(transaction.id);
3600                        }
3601                        project_transaction.0.insert(cx.handle(), transaction);
3602                    }
3603                });
3604            }
3605
3606            Ok(project_transaction)
3607        })
3608    }
3609
3610    pub fn format(
3611        &self,
3612        buffers: HashSet<ModelHandle<Buffer>>,
3613        push_to_history: bool,
3614        trigger: FormatTrigger,
3615        cx: &mut ModelContext<Project>,
3616    ) -> Task<Result<ProjectTransaction>> {
3617        if self.is_local() {
3618            let mut buffers_with_paths_and_servers = buffers
3619                .into_iter()
3620                .filter_map(|buffer_handle| {
3621                    let buffer = buffer_handle.read(cx);
3622                    let file = File::from_dyn(buffer.file())?;
3623                    let buffer_abs_path = file.as_local().map(|f| f.abs_path(cx));
3624                    let server = self
3625                        .primary_language_servers_for_buffer(buffer, cx)
3626                        .map(|s| s.1.clone());
3627                    Some((buffer_handle, buffer_abs_path, server))
3628                })
3629                .collect::<Vec<_>>();
3630
3631            cx.spawn(|this, mut cx| async move {
3632                // Do not allow multiple concurrent formatting requests for the
3633                // same buffer.
3634                this.update(&mut cx, |this, cx| {
3635                    buffers_with_paths_and_servers.retain(|(buffer, _, _)| {
3636                        this.buffers_being_formatted
3637                            .insert(buffer.read(cx).remote_id())
3638                    });
3639                });
3640
3641                let _cleanup = defer({
3642                    let this = this.clone();
3643                    let mut cx = cx.clone();
3644                    let buffers = &buffers_with_paths_and_servers;
3645                    move || {
3646                        this.update(&mut cx, |this, cx| {
3647                            for (buffer, _, _) in buffers {
3648                                this.buffers_being_formatted
3649                                    .remove(&buffer.read(cx).remote_id());
3650                            }
3651                        });
3652                    }
3653                });
3654
3655                let mut project_transaction = ProjectTransaction::default();
3656                for (buffer, buffer_abs_path, language_server) in &buffers_with_paths_and_servers {
3657                    let settings = buffer.read_with(&cx, |buffer, cx| {
3658                        language_settings(buffer.language(), buffer.file(), cx).clone()
3659                    });
3660
3661                    let remove_trailing_whitespace = settings.remove_trailing_whitespace_on_save;
3662                    let ensure_final_newline = settings.ensure_final_newline_on_save;
3663                    let format_on_save = settings.format_on_save.clone();
3664                    let formatter = settings.formatter.clone();
3665                    let tab_size = settings.tab_size;
3666
3667                    // First, format buffer's whitespace according to the settings.
3668                    let trailing_whitespace_diff = if remove_trailing_whitespace {
3669                        Some(
3670                            buffer
3671                                .read_with(&cx, |b, cx| b.remove_trailing_whitespace(cx))
3672                                .await,
3673                        )
3674                    } else {
3675                        None
3676                    };
3677                    let whitespace_transaction_id = buffer.update(&mut cx, |buffer, cx| {
3678                        buffer.finalize_last_transaction();
3679                        buffer.start_transaction();
3680                        if let Some(diff) = trailing_whitespace_diff {
3681                            buffer.apply_diff(diff, cx);
3682                        }
3683                        if ensure_final_newline {
3684                            buffer.ensure_final_newline(cx);
3685                        }
3686                        buffer.end_transaction(cx)
3687                    });
3688
3689                    // Currently, formatting operations are represented differently depending on
3690                    // whether they come from a language server or an external command.
3691                    enum FormatOperation {
3692                        Lsp(Vec<(Range<Anchor>, String)>),
3693                        External(Diff),
3694                    }
3695
3696                    // Apply language-specific formatting using either a language server
3697                    // or external command.
3698                    let mut format_operation = None;
3699                    match (formatter, format_on_save) {
3700                        (_, FormatOnSave::Off) if trigger == FormatTrigger::Save => {}
3701
3702                        (Formatter::LanguageServer, FormatOnSave::On | FormatOnSave::Off)
3703                        | (_, FormatOnSave::LanguageServer) => {
3704                            if let Some((language_server, buffer_abs_path)) =
3705                                language_server.as_ref().zip(buffer_abs_path.as_ref())
3706                            {
3707                                format_operation = Some(FormatOperation::Lsp(
3708                                    Self::format_via_lsp(
3709                                        &this,
3710                                        &buffer,
3711                                        buffer_abs_path,
3712                                        &language_server,
3713                                        tab_size,
3714                                        &mut cx,
3715                                    )
3716                                    .await
3717                                    .context("failed to format via language server")?,
3718                                ));
3719                            }
3720                        }
3721
3722                        (
3723                            Formatter::External { command, arguments },
3724                            FormatOnSave::On | FormatOnSave::Off,
3725                        )
3726                        | (_, FormatOnSave::External { command, arguments }) => {
3727                            if let Some(buffer_abs_path) = buffer_abs_path {
3728                                format_operation = Self::format_via_external_command(
3729                                    &buffer,
3730                                    &buffer_abs_path,
3731                                    &command,
3732                                    &arguments,
3733                                    &mut cx,
3734                                )
3735                                .await
3736                                .context(format!(
3737                                    "failed to format via external command {:?}",
3738                                    command
3739                                ))?
3740                                .map(FormatOperation::External);
3741                            }
3742                        }
3743                    };
3744
3745                    buffer.update(&mut cx, |b, cx| {
3746                        // If the buffer had its whitespace formatted and was edited while the language-specific
3747                        // formatting was being computed, avoid applying the language-specific formatting, because
3748                        // it can't be grouped with the whitespace formatting in the undo history.
3749                        if let Some(transaction_id) = whitespace_transaction_id {
3750                            if b.peek_undo_stack()
3751                                .map_or(true, |e| e.transaction_id() != transaction_id)
3752                            {
3753                                format_operation.take();
3754                            }
3755                        }
3756
3757                        // Apply any language-specific formatting, and group the two formatting operations
3758                        // in the buffer's undo history.
3759                        if let Some(operation) = format_operation {
3760                            match operation {
3761                                FormatOperation::Lsp(edits) => {
3762                                    b.edit(edits, None, cx);
3763                                }
3764                                FormatOperation::External(diff) => {
3765                                    b.apply_diff(diff, cx);
3766                                }
3767                            }
3768
3769                            if let Some(transaction_id) = whitespace_transaction_id {
3770                                b.group_until_transaction(transaction_id);
3771                            }
3772                        }
3773
3774                        if let Some(transaction) = b.finalize_last_transaction().cloned() {
3775                            if !push_to_history {
3776                                b.forget_transaction(transaction.id);
3777                            }
3778                            project_transaction.0.insert(buffer.clone(), transaction);
3779                        }
3780                    });
3781                }
3782
3783                Ok(project_transaction)
3784            })
3785        } else {
3786            let remote_id = self.remote_id();
3787            let client = self.client.clone();
3788            cx.spawn(|this, mut cx| async move {
3789                let mut project_transaction = ProjectTransaction::default();
3790                if let Some(project_id) = remote_id {
3791                    let response = client
3792                        .request(proto::FormatBuffers {
3793                            project_id,
3794                            trigger: trigger as i32,
3795                            buffer_ids: buffers
3796                                .iter()
3797                                .map(|buffer| buffer.read_with(&cx, |buffer, _| buffer.remote_id()))
3798                                .collect(),
3799                        })
3800                        .await?
3801                        .transaction
3802                        .ok_or_else(|| anyhow!("missing transaction"))?;
3803                    project_transaction = this
3804                        .update(&mut cx, |this, cx| {
3805                            this.deserialize_project_transaction(response, push_to_history, cx)
3806                        })
3807                        .await?;
3808                }
3809                Ok(project_transaction)
3810            })
3811        }
3812    }
3813
3814    async fn format_via_lsp(
3815        this: &ModelHandle<Self>,
3816        buffer: &ModelHandle<Buffer>,
3817        abs_path: &Path,
3818        language_server: &Arc<LanguageServer>,
3819        tab_size: NonZeroU32,
3820        cx: &mut AsyncAppContext,
3821    ) -> Result<Vec<(Range<Anchor>, String)>> {
3822        let uri = lsp::Url::from_file_path(abs_path)
3823            .map_err(|_| anyhow!("failed to convert abs path to uri"))?;
3824        let text_document = lsp::TextDocumentIdentifier::new(uri);
3825        let capabilities = &language_server.capabilities();
3826
3827        let formatting_provider = capabilities.document_formatting_provider.as_ref();
3828        let range_formatting_provider = capabilities.document_range_formatting_provider.as_ref();
3829
3830        let result = if !matches!(formatting_provider, Some(OneOf::Left(false))) {
3831            language_server
3832                .request::<lsp::request::Formatting>(lsp::DocumentFormattingParams {
3833                    text_document,
3834                    options: lsp_command::lsp_formatting_options(tab_size.get()),
3835                    work_done_progress_params: Default::default(),
3836                })
3837                .await
3838        } else if !matches!(range_formatting_provider, Some(OneOf::Left(false))) {
3839            let buffer_start = lsp::Position::new(0, 0);
3840            let buffer_end = buffer.read_with(cx, |b, _| point_to_lsp(b.max_point_utf16()));
3841
3842            language_server
3843                .request::<lsp::request::RangeFormatting>(lsp::DocumentRangeFormattingParams {
3844                    text_document,
3845                    range: lsp::Range::new(buffer_start, buffer_end),
3846                    options: lsp_command::lsp_formatting_options(tab_size.get()),
3847                    work_done_progress_params: Default::default(),
3848                })
3849                .await
3850        } else {
3851            Ok(None)
3852        };
3853
3854        let lsp_edits = match result {
3855            Ok(lsp_edits) => lsp_edits,
3856
3857            Err(err) => {
3858                log::warn!(
3859                    "Error firing format request to {}: {}",
3860                    language_server.name(),
3861                    err
3862                );
3863
3864                this.update(cx, |this, cx| {
3865                    this.check_errored_lsp_installation(language_server.clone(), cx);
3866                });
3867
3868                None
3869            }
3870        };
3871
3872        if let Some(lsp_edits) = lsp_edits {
3873            this.update(cx, |this, cx| {
3874                this.edits_from_lsp(buffer, lsp_edits, language_server.server_id(), None, cx)
3875            })
3876            .await
3877        } else {
3878            Ok(Vec::new())
3879        }
3880    }
3881
3882    async fn format_via_external_command(
3883        buffer: &ModelHandle<Buffer>,
3884        buffer_abs_path: &Path,
3885        command: &str,
3886        arguments: &[String],
3887        cx: &mut AsyncAppContext,
3888    ) -> Result<Option<Diff>> {
3889        let working_dir_path = buffer.read_with(cx, |buffer, cx| {
3890            let file = File::from_dyn(buffer.file())?;
3891            let worktree = file.worktree.read(cx).as_local()?;
3892            let mut worktree_path = worktree.abs_path().to_path_buf();
3893            if worktree.root_entry()?.is_file() {
3894                worktree_path.pop();
3895            }
3896            Some(worktree_path)
3897        });
3898
3899        if let Some(working_dir_path) = working_dir_path {
3900            let mut child =
3901                smol::process::Command::new(command)
3902                    .args(arguments.iter().map(|arg| {
3903                        arg.replace("{buffer_path}", &buffer_abs_path.to_string_lossy())
3904                    }))
3905                    .current_dir(&working_dir_path)
3906                    .stdin(smol::process::Stdio::piped())
3907                    .stdout(smol::process::Stdio::piped())
3908                    .stderr(smol::process::Stdio::piped())
3909                    .spawn()?;
3910            let stdin = child
3911                .stdin
3912                .as_mut()
3913                .ok_or_else(|| anyhow!("failed to acquire stdin"))?;
3914            let text = buffer.read_with(cx, |buffer, _| buffer.as_rope().clone());
3915            for chunk in text.chunks() {
3916                stdin.write_all(chunk.as_bytes()).await?;
3917            }
3918            stdin.flush().await?;
3919
3920            let output = child.output().await?;
3921            if !output.status.success() {
3922                return Err(anyhow!(
3923                    "command failed with exit code {:?}:\nstdout: {}\nstderr: {}",
3924                    output.status.code(),
3925                    String::from_utf8_lossy(&output.stdout),
3926                    String::from_utf8_lossy(&output.stderr),
3927                ));
3928            }
3929
3930            let stdout = String::from_utf8(output.stdout)?;
3931            Ok(Some(
3932                buffer
3933                    .read_with(cx, |buffer, cx| buffer.diff(stdout, cx))
3934                    .await,
3935            ))
3936        } else {
3937            Ok(None)
3938        }
3939    }
3940
3941    pub fn definition<T: ToPointUtf16>(
3942        &self,
3943        buffer: &ModelHandle<Buffer>,
3944        position: T,
3945        cx: &mut ModelContext<Self>,
3946    ) -> Task<Result<Vec<LocationLink>>> {
3947        let position = position.to_point_utf16(buffer.read(cx));
3948        self.request_lsp(buffer.clone(), GetDefinition { position }, cx)
3949    }
3950
3951    pub fn type_definition<T: ToPointUtf16>(
3952        &self,
3953        buffer: &ModelHandle<Buffer>,
3954        position: T,
3955        cx: &mut ModelContext<Self>,
3956    ) -> Task<Result<Vec<LocationLink>>> {
3957        let position = position.to_point_utf16(buffer.read(cx));
3958        self.request_lsp(buffer.clone(), GetTypeDefinition { position }, cx)
3959    }
3960
3961    pub fn references<T: ToPointUtf16>(
3962        &self,
3963        buffer: &ModelHandle<Buffer>,
3964        position: T,
3965        cx: &mut ModelContext<Self>,
3966    ) -> Task<Result<Vec<Location>>> {
3967        let position = position.to_point_utf16(buffer.read(cx));
3968        self.request_lsp(buffer.clone(), GetReferences { position }, cx)
3969    }
3970
3971    pub fn document_highlights<T: ToPointUtf16>(
3972        &self,
3973        buffer: &ModelHandle<Buffer>,
3974        position: T,
3975        cx: &mut ModelContext<Self>,
3976    ) -> Task<Result<Vec<DocumentHighlight>>> {
3977        let position = position.to_point_utf16(buffer.read(cx));
3978        self.request_lsp(buffer.clone(), GetDocumentHighlights { position }, cx)
3979    }
3980
3981    pub fn symbols(&self, query: &str, cx: &mut ModelContext<Self>) -> Task<Result<Vec<Symbol>>> {
3982        if self.is_local() {
3983            let mut requests = Vec::new();
3984            for ((worktree_id, _), server_id) in self.language_server_ids.iter() {
3985                let worktree_id = *worktree_id;
3986                let worktree_handle = self.worktree_for_id(worktree_id, cx);
3987                let worktree = match worktree_handle.and_then(|tree| tree.read(cx).as_local()) {
3988                    Some(worktree) => worktree,
3989                    None => continue,
3990                };
3991                let worktree_abs_path = worktree.abs_path().clone();
3992
3993                let (adapter, language, server) = match self.language_servers.get(server_id) {
3994                    Some(LanguageServerState::Running {
3995                        adapter,
3996                        language,
3997                        server,
3998                        ..
3999                    }) => (adapter.clone(), language.clone(), server),
4000
4001                    _ => continue,
4002                };
4003
4004                requests.push(
4005                    server
4006                        .request::<lsp::request::WorkspaceSymbolRequest>(
4007                            lsp::WorkspaceSymbolParams {
4008                                query: query.to_string(),
4009                                ..Default::default()
4010                            },
4011                        )
4012                        .map_ok(move |response| {
4013                            let lsp_symbols = response.map(|symbol_response| match symbol_response {
4014                                lsp::WorkspaceSymbolResponse::Flat(flat_responses) => {
4015                                    flat_responses.into_iter().map(|lsp_symbol| {
4016                                        (lsp_symbol.name, lsp_symbol.kind, lsp_symbol.location)
4017                                    }).collect::<Vec<_>>()
4018                                }
4019                                lsp::WorkspaceSymbolResponse::Nested(nested_responses) => {
4020                                    nested_responses.into_iter().filter_map(|lsp_symbol| {
4021                                        let location = match lsp_symbol.location {
4022                                            OneOf::Left(location) => location,
4023                                            OneOf::Right(_) => {
4024                                                error!("Unexpected: client capabilities forbid symbol resolutions in workspace.symbol.resolveSupport");
4025                                                return None
4026                                            }
4027                                        };
4028                                        Some((lsp_symbol.name, lsp_symbol.kind, location))
4029                                    }).collect::<Vec<_>>()
4030                                }
4031                            }).unwrap_or_default();
4032
4033                            (
4034                                adapter,
4035                                language,
4036                                worktree_id,
4037                                worktree_abs_path,
4038                                lsp_symbols,
4039                            )
4040                        }),
4041                );
4042            }
4043
4044            cx.spawn_weak(|this, cx| async move {
4045                let responses = futures::future::join_all(requests).await;
4046                let this = match this.upgrade(&cx) {
4047                    Some(this) => this,
4048                    None => return Ok(Vec::new()),
4049                };
4050
4051                let symbols = this.read_with(&cx, |this, cx| {
4052                    let mut symbols = Vec::new();
4053                    for response in responses {
4054                        let (
4055                            adapter,
4056                            adapter_language,
4057                            source_worktree_id,
4058                            worktree_abs_path,
4059                            lsp_symbols,
4060                        ) = match response {
4061                            Ok(response) => response,
4062
4063                            Err(err) => {
4064                                // TODO: Prompt installation validity check LSP ERROR
4065                                return Vec::new();
4066                            }
4067                        };
4068
4069                        symbols.extend(lsp_symbols.into_iter().filter_map(
4070                            |(symbol_name, symbol_kind, symbol_location)| {
4071                                let abs_path = symbol_location.uri.to_file_path().ok()?;
4072                                let mut worktree_id = source_worktree_id;
4073                                let path;
4074                                if let Some((worktree, rel_path)) =
4075                                    this.find_local_worktree(&abs_path, cx)
4076                                {
4077                                    worktree_id = worktree.read(cx).id();
4078                                    path = rel_path;
4079                                } else {
4080                                    path = relativize_path(&worktree_abs_path, &abs_path);
4081                                }
4082
4083                                let project_path = ProjectPath {
4084                                    worktree_id,
4085                                    path: path.into(),
4086                                };
4087                                let signature = this.symbol_signature(&project_path);
4088                                let adapter_language = adapter_language.clone();
4089                                let language = this
4090                                    .languages
4091                                    .language_for_file(&project_path.path, None)
4092                                    .unwrap_or_else(move |_| adapter_language);
4093                                let language_server_name = adapter.name.clone();
4094                                Some(async move {
4095                                    let language = language.await;
4096                                    let label =
4097                                        language.label_for_symbol(&symbol_name, symbol_kind).await;
4098
4099                                    Symbol {
4100                                        language_server_name,
4101                                        source_worktree_id,
4102                                        path: project_path,
4103                                        label: label.unwrap_or_else(|| {
4104                                            CodeLabel::plain(symbol_name.clone(), None)
4105                                        }),
4106                                        kind: symbol_kind,
4107                                        name: symbol_name,
4108                                        range: range_from_lsp(symbol_location.range),
4109                                        signature,
4110                                    }
4111                                })
4112                            },
4113                        ));
4114                    }
4115
4116                    symbols
4117                });
4118
4119                Ok(futures::future::join_all(symbols).await)
4120            })
4121        } else if let Some(project_id) = self.remote_id() {
4122            let request = self.client.request(proto::GetProjectSymbols {
4123                project_id,
4124                query: query.to_string(),
4125            });
4126            cx.spawn_weak(|this, cx| async move {
4127                let response = request.await?;
4128                let mut symbols = Vec::new();
4129                if let Some(this) = this.upgrade(&cx) {
4130                    let new_symbols = this.read_with(&cx, |this, _| {
4131                        response
4132                            .symbols
4133                            .into_iter()
4134                            .map(|symbol| this.deserialize_symbol(symbol))
4135                            .collect::<Vec<_>>()
4136                    });
4137                    symbols = futures::future::join_all(new_symbols)
4138                        .await
4139                        .into_iter()
4140                        .filter_map(|symbol| symbol.log_err())
4141                        .collect::<Vec<_>>();
4142                }
4143                Ok(symbols)
4144            })
4145        } else {
4146            Task::ready(Ok(Default::default()))
4147        }
4148    }
4149
4150    pub fn open_buffer_for_symbol(
4151        &mut self,
4152        symbol: &Symbol,
4153        cx: &mut ModelContext<Self>,
4154    ) -> Task<Result<ModelHandle<Buffer>>> {
4155        if self.is_local() {
4156            let language_server_id = if let Some(id) = self.language_server_ids.get(&(
4157                symbol.source_worktree_id,
4158                symbol.language_server_name.clone(),
4159            )) {
4160                *id
4161            } else {
4162                return Task::ready(Err(anyhow!(
4163                    "language server for worktree and language not found"
4164                )));
4165            };
4166
4167            let worktree_abs_path = if let Some(worktree_abs_path) = self
4168                .worktree_for_id(symbol.path.worktree_id, cx)
4169                .and_then(|worktree| worktree.read(cx).as_local())
4170                .map(|local_worktree| local_worktree.abs_path())
4171            {
4172                worktree_abs_path
4173            } else {
4174                return Task::ready(Err(anyhow!("worktree not found for symbol")));
4175            };
4176            let symbol_abs_path = worktree_abs_path.join(&symbol.path.path);
4177            let symbol_uri = if let Ok(uri) = lsp::Url::from_file_path(symbol_abs_path) {
4178                uri
4179            } else {
4180                return Task::ready(Err(anyhow!("invalid symbol path")));
4181            };
4182
4183            self.open_local_buffer_via_lsp(
4184                symbol_uri,
4185                language_server_id,
4186                symbol.language_server_name.clone(),
4187                cx,
4188            )
4189        } else if let Some(project_id) = self.remote_id() {
4190            let request = self.client.request(proto::OpenBufferForSymbol {
4191                project_id,
4192                symbol: Some(serialize_symbol(symbol)),
4193            });
4194            cx.spawn(|this, mut cx| async move {
4195                let response = request.await?;
4196                this.update(&mut cx, |this, cx| {
4197                    this.wait_for_remote_buffer(response.buffer_id, cx)
4198                })
4199                .await
4200            })
4201        } else {
4202            Task::ready(Err(anyhow!("project does not have a remote id")))
4203        }
4204    }
4205
4206    pub fn hover<T: ToPointUtf16>(
4207        &self,
4208        buffer: &ModelHandle<Buffer>,
4209        position: T,
4210        cx: &mut ModelContext<Self>,
4211    ) -> Task<Result<Option<Hover>>> {
4212        let position = position.to_point_utf16(buffer.read(cx));
4213        self.request_lsp(buffer.clone(), GetHover { position }, cx)
4214    }
4215
4216    pub fn completions<T: ToPointUtf16>(
4217        &self,
4218        buffer: &ModelHandle<Buffer>,
4219        position: T,
4220        cx: &mut ModelContext<Self>,
4221    ) -> Task<Result<Vec<Completion>>> {
4222        let position = position.to_point_utf16(buffer.read(cx));
4223        self.request_lsp(buffer.clone(), GetCompletions { position }, cx)
4224    }
4225
4226    pub fn apply_additional_edits_for_completion(
4227        &self,
4228        buffer_handle: ModelHandle<Buffer>,
4229        completion: Completion,
4230        push_to_history: bool,
4231        cx: &mut ModelContext<Self>,
4232    ) -> Task<Result<Option<Transaction>>> {
4233        let buffer = buffer_handle.read(cx);
4234        let buffer_id = buffer.remote_id();
4235
4236        if self.is_local() {
4237            let lang_server = match self.primary_language_servers_for_buffer(buffer, cx) {
4238                Some((_, server)) => server.clone(),
4239                _ => return Task::ready(Ok(Default::default())),
4240            };
4241
4242            cx.spawn(|this, mut cx| async move {
4243                let resolved_completion = match lang_server
4244                    .request::<lsp::request::ResolveCompletionItem>(completion.lsp_completion)
4245                    .await
4246                {
4247                    Ok(resolved_completion) => resolved_completion,
4248
4249                    Err(err) => {
4250                        // TODO: LSP ERROR
4251                        return Ok(None);
4252                    }
4253                };
4254
4255                if let Some(edits) = resolved_completion.additional_text_edits {
4256                    let edits = this
4257                        .update(&mut cx, |this, cx| {
4258                            this.edits_from_lsp(
4259                                &buffer_handle,
4260                                edits,
4261                                lang_server.server_id(),
4262                                None,
4263                                cx,
4264                            )
4265                        })
4266                        .await?;
4267
4268                    buffer_handle.update(&mut cx, |buffer, cx| {
4269                        buffer.finalize_last_transaction();
4270                        buffer.start_transaction();
4271
4272                        for (range, text) in edits {
4273                            let primary = &completion.old_range;
4274                            let start_within = primary.start.cmp(&range.start, buffer).is_le()
4275                                && primary.end.cmp(&range.start, buffer).is_ge();
4276                            let end_within = range.start.cmp(&primary.end, buffer).is_le()
4277                                && range.end.cmp(&primary.end, buffer).is_ge();
4278
4279                            //Skip additional edits which overlap with the primary completion edit
4280                            //https://github.com/zed-industries/zed/pull/1871
4281                            if !start_within && !end_within {
4282                                buffer.edit([(range, text)], None, cx);
4283                            }
4284                        }
4285
4286                        let transaction = if buffer.end_transaction(cx).is_some() {
4287                            let transaction = buffer.finalize_last_transaction().unwrap().clone();
4288                            if !push_to_history {
4289                                buffer.forget_transaction(transaction.id);
4290                            }
4291                            Some(transaction)
4292                        } else {
4293                            None
4294                        };
4295                        Ok(transaction)
4296                    })
4297                } else {
4298                    Ok(None)
4299                }
4300            })
4301        } else if let Some(project_id) = self.remote_id() {
4302            let client = self.client.clone();
4303            cx.spawn(|_, mut cx| async move {
4304                let response = client
4305                    .request(proto::ApplyCompletionAdditionalEdits {
4306                        project_id,
4307                        buffer_id,
4308                        completion: Some(language::proto::serialize_completion(&completion)),
4309                    })
4310                    .await?;
4311
4312                if let Some(transaction) = response.transaction {
4313                    let transaction = language::proto::deserialize_transaction(transaction)?;
4314                    buffer_handle
4315                        .update(&mut cx, |buffer, _| {
4316                            buffer.wait_for_edits(transaction.edit_ids.iter().copied())
4317                        })
4318                        .await?;
4319                    if push_to_history {
4320                        buffer_handle.update(&mut cx, |buffer, _| {
4321                            buffer.push_transaction(transaction.clone(), Instant::now());
4322                        });
4323                    }
4324                    Ok(Some(transaction))
4325                } else {
4326                    Ok(None)
4327                }
4328            })
4329        } else {
4330            Task::ready(Err(anyhow!("project does not have a remote id")))
4331        }
4332    }
4333
4334    pub fn code_actions<T: Clone + ToOffset>(
4335        &self,
4336        buffer_handle: &ModelHandle<Buffer>,
4337        range: Range<T>,
4338        cx: &mut ModelContext<Self>,
4339    ) -> Task<Result<Vec<CodeAction>>> {
4340        let buffer = buffer_handle.read(cx);
4341        let range = buffer.anchor_before(range.start)..buffer.anchor_before(range.end);
4342        self.request_lsp(buffer_handle.clone(), GetCodeActions { range }, cx)
4343    }
4344
4345    pub fn apply_code_action(
4346        &self,
4347        buffer_handle: ModelHandle<Buffer>,
4348        mut action: CodeAction,
4349        push_to_history: bool,
4350        cx: &mut ModelContext<Self>,
4351    ) -> Task<Result<ProjectTransaction>> {
4352        if self.is_local() {
4353            let buffer = buffer_handle.read(cx);
4354            let (lsp_adapter, lang_server) = if let Some((adapter, server)) =
4355                self.language_server_for_buffer(buffer, action.server_id, cx)
4356            {
4357                (adapter.clone(), server.clone())
4358            } else {
4359                return Task::ready(Ok(Default::default()));
4360            };
4361            let range = action.range.to_point_utf16(buffer);
4362
4363            cx.spawn(|this, mut cx| async move {
4364                if let Some(lsp_range) = action
4365                    .lsp_action
4366                    .data
4367                    .as_mut()
4368                    .and_then(|d| d.get_mut("codeActionParams"))
4369                    .and_then(|d| d.get_mut("range"))
4370                {
4371                    *lsp_range = serde_json::to_value(&range_to_lsp(range)).unwrap();
4372                    action.lsp_action = match lang_server
4373                        .request::<lsp::request::CodeActionResolveRequest>(action.lsp_action)
4374                        .await
4375                    {
4376                        Ok(lsp_action) => lsp_action,
4377
4378                        Err(err) => {
4379                            // LSP ERROR
4380                            return Err(err);
4381                        }
4382                    };
4383                } else {
4384                    let actions = this
4385                        .update(&mut cx, |this, cx| {
4386                            this.code_actions(&buffer_handle, action.range, cx)
4387                        })
4388                        .await?;
4389                    action.lsp_action = actions
4390                        .into_iter()
4391                        .find(|a| a.lsp_action.title == action.lsp_action.title)
4392                        .ok_or_else(|| anyhow!("code action is outdated"))?
4393                        .lsp_action;
4394                }
4395
4396                if let Some(edit) = action.lsp_action.edit {
4397                    if edit.changes.is_some() || edit.document_changes.is_some() {
4398                        return Self::deserialize_workspace_edit(
4399                            this,
4400                            edit,
4401                            push_to_history,
4402                            lsp_adapter.clone(),
4403                            lang_server.clone(),
4404                            &mut cx,
4405                        )
4406                        .await;
4407                    }
4408                }
4409
4410                if let Some(command) = action.lsp_action.command {
4411                    this.update(&mut cx, |this, _| {
4412                        this.last_workspace_edits_by_language_server
4413                            .remove(&lang_server.server_id());
4414                    });
4415
4416                    let result = lang_server
4417                        .request::<lsp::request::ExecuteCommand>(lsp::ExecuteCommandParams {
4418                            command: command.command,
4419                            arguments: command.arguments.unwrap_or_default(),
4420                            ..Default::default()
4421                        })
4422                        .await;
4423
4424                    if let Err(err) = result {
4425                        // TODO: LSP ERROR
4426                        return Err(err);
4427                    }
4428
4429                    return Ok(this.update(&mut cx, |this, _| {
4430                        this.last_workspace_edits_by_language_server
4431                            .remove(&lang_server.server_id())
4432                            .unwrap_or_default()
4433                    }));
4434                }
4435
4436                Ok(ProjectTransaction::default())
4437            })
4438        } else if let Some(project_id) = self.remote_id() {
4439            let client = self.client.clone();
4440            let request = proto::ApplyCodeAction {
4441                project_id,
4442                buffer_id: buffer_handle.read(cx).remote_id(),
4443                action: Some(language::proto::serialize_code_action(&action)),
4444            };
4445            cx.spawn(|this, mut cx| async move {
4446                let response = client
4447                    .request(request)
4448                    .await?
4449                    .transaction
4450                    .ok_or_else(|| anyhow!("missing transaction"))?;
4451                this.update(&mut cx, |this, cx| {
4452                    this.deserialize_project_transaction(response, push_to_history, cx)
4453                })
4454                .await
4455            })
4456        } else {
4457            Task::ready(Err(anyhow!("project does not have a remote id")))
4458        }
4459    }
4460
4461    fn apply_on_type_formatting(
4462        &self,
4463        buffer: ModelHandle<Buffer>,
4464        position: Anchor,
4465        trigger: String,
4466        cx: &mut ModelContext<Self>,
4467    ) -> Task<Result<Option<Transaction>>> {
4468        if self.is_local() {
4469            cx.spawn(|this, mut cx| async move {
4470                // Do not allow multiple concurrent formatting requests for the
4471                // same buffer.
4472                this.update(&mut cx, |this, cx| {
4473                    this.buffers_being_formatted
4474                        .insert(buffer.read(cx).remote_id())
4475                });
4476
4477                let _cleanup = defer({
4478                    let this = this.clone();
4479                    let mut cx = cx.clone();
4480                    let closure_buffer = buffer.clone();
4481                    move || {
4482                        this.update(&mut cx, |this, cx| {
4483                            this.buffers_being_formatted
4484                                .remove(&closure_buffer.read(cx).remote_id());
4485                        });
4486                    }
4487                });
4488
4489                buffer
4490                    .update(&mut cx, |buffer, _| {
4491                        buffer.wait_for_edits(Some(position.timestamp))
4492                    })
4493                    .await?;
4494                this.update(&mut cx, |this, cx| {
4495                    let position = position.to_point_utf16(buffer.read(cx));
4496                    this.on_type_format(buffer, position, trigger, false, cx)
4497                })
4498                .await
4499            })
4500        } else if let Some(project_id) = self.remote_id() {
4501            let client = self.client.clone();
4502            let request = proto::OnTypeFormatting {
4503                project_id,
4504                buffer_id: buffer.read(cx).remote_id(),
4505                position: Some(serialize_anchor(&position)),
4506                trigger,
4507                version: serialize_version(&buffer.read(cx).version()),
4508            };
4509            cx.spawn(|_, _| async move {
4510                client
4511                    .request(request)
4512                    .await?
4513                    .transaction
4514                    .map(language::proto::deserialize_transaction)
4515                    .transpose()
4516            })
4517        } else {
4518            Task::ready(Err(anyhow!("project does not have a remote id")))
4519        }
4520    }
4521
4522    async fn deserialize_edits(
4523        this: ModelHandle<Self>,
4524        buffer_to_edit: ModelHandle<Buffer>,
4525        edits: Vec<lsp::TextEdit>,
4526        push_to_history: bool,
4527        _: Arc<CachedLspAdapter>,
4528        language_server: Arc<LanguageServer>,
4529        cx: &mut AsyncAppContext,
4530    ) -> Result<Option<Transaction>> {
4531        let edits = this
4532            .update(cx, |this, cx| {
4533                this.edits_from_lsp(
4534                    &buffer_to_edit,
4535                    edits,
4536                    language_server.server_id(),
4537                    None,
4538                    cx,
4539                )
4540            })
4541            .await?;
4542
4543        let transaction = buffer_to_edit.update(cx, |buffer, cx| {
4544            buffer.finalize_last_transaction();
4545            buffer.start_transaction();
4546            for (range, text) in edits {
4547                buffer.edit([(range, text)], None, cx);
4548            }
4549
4550            if buffer.end_transaction(cx).is_some() {
4551                let transaction = buffer.finalize_last_transaction().unwrap().clone();
4552                if !push_to_history {
4553                    buffer.forget_transaction(transaction.id);
4554                }
4555                Some(transaction)
4556            } else {
4557                None
4558            }
4559        });
4560
4561        Ok(transaction)
4562    }
4563
4564    async fn deserialize_workspace_edit(
4565        this: ModelHandle<Self>,
4566        edit: lsp::WorkspaceEdit,
4567        push_to_history: bool,
4568        lsp_adapter: Arc<CachedLspAdapter>,
4569        language_server: Arc<LanguageServer>,
4570        cx: &mut AsyncAppContext,
4571    ) -> Result<ProjectTransaction> {
4572        let fs = this.read_with(cx, |this, _| this.fs.clone());
4573        let mut operations = Vec::new();
4574        if let Some(document_changes) = edit.document_changes {
4575            match document_changes {
4576                lsp::DocumentChanges::Edits(edits) => {
4577                    operations.extend(edits.into_iter().map(lsp::DocumentChangeOperation::Edit))
4578                }
4579                lsp::DocumentChanges::Operations(ops) => operations = ops,
4580            }
4581        } else if let Some(changes) = edit.changes {
4582            operations.extend(changes.into_iter().map(|(uri, edits)| {
4583                lsp::DocumentChangeOperation::Edit(lsp::TextDocumentEdit {
4584                    text_document: lsp::OptionalVersionedTextDocumentIdentifier {
4585                        uri,
4586                        version: None,
4587                    },
4588                    edits: edits.into_iter().map(OneOf::Left).collect(),
4589                })
4590            }));
4591        }
4592
4593        let mut project_transaction = ProjectTransaction::default();
4594        for operation in operations {
4595            match operation {
4596                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Create(op)) => {
4597                    let abs_path = op
4598                        .uri
4599                        .to_file_path()
4600                        .map_err(|_| anyhow!("can't convert URI to path"))?;
4601
4602                    if let Some(parent_path) = abs_path.parent() {
4603                        fs.create_dir(parent_path).await?;
4604                    }
4605                    if abs_path.ends_with("/") {
4606                        fs.create_dir(&abs_path).await?;
4607                    } else {
4608                        fs.create_file(&abs_path, op.options.map(Into::into).unwrap_or_default())
4609                            .await?;
4610                    }
4611                }
4612
4613                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Rename(op)) => {
4614                    let source_abs_path = op
4615                        .old_uri
4616                        .to_file_path()
4617                        .map_err(|_| anyhow!("can't convert URI to path"))?;
4618                    let target_abs_path = op
4619                        .new_uri
4620                        .to_file_path()
4621                        .map_err(|_| anyhow!("can't convert URI to path"))?;
4622                    fs.rename(
4623                        &source_abs_path,
4624                        &target_abs_path,
4625                        op.options.map(Into::into).unwrap_or_default(),
4626                    )
4627                    .await?;
4628                }
4629
4630                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Delete(op)) => {
4631                    let abs_path = op
4632                        .uri
4633                        .to_file_path()
4634                        .map_err(|_| anyhow!("can't convert URI to path"))?;
4635                    let options = op.options.map(Into::into).unwrap_or_default();
4636                    if abs_path.ends_with("/") {
4637                        fs.remove_dir(&abs_path, options).await?;
4638                    } else {
4639                        fs.remove_file(&abs_path, options).await?;
4640                    }
4641                }
4642
4643                lsp::DocumentChangeOperation::Edit(op) => {
4644                    let buffer_to_edit = this
4645                        .update(cx, |this, cx| {
4646                            this.open_local_buffer_via_lsp(
4647                                op.text_document.uri,
4648                                language_server.server_id(),
4649                                lsp_adapter.name.clone(),
4650                                cx,
4651                            )
4652                        })
4653                        .await?;
4654
4655                    let edits = this
4656                        .update(cx, |this, cx| {
4657                            let edits = op.edits.into_iter().map(|edit| match edit {
4658                                OneOf::Left(edit) => edit,
4659                                OneOf::Right(edit) => edit.text_edit,
4660                            });
4661                            this.edits_from_lsp(
4662                                &buffer_to_edit,
4663                                edits,
4664                                language_server.server_id(),
4665                                op.text_document.version,
4666                                cx,
4667                            )
4668                        })
4669                        .await?;
4670
4671                    let transaction = buffer_to_edit.update(cx, |buffer, cx| {
4672                        buffer.finalize_last_transaction();
4673                        buffer.start_transaction();
4674                        for (range, text) in edits {
4675                            buffer.edit([(range, text)], None, cx);
4676                        }
4677                        let transaction = if buffer.end_transaction(cx).is_some() {
4678                            let transaction = buffer.finalize_last_transaction().unwrap().clone();
4679                            if !push_to_history {
4680                                buffer.forget_transaction(transaction.id);
4681                            }
4682                            Some(transaction)
4683                        } else {
4684                            None
4685                        };
4686
4687                        transaction
4688                    });
4689                    if let Some(transaction) = transaction {
4690                        project_transaction.0.insert(buffer_to_edit, transaction);
4691                    }
4692                }
4693            }
4694        }
4695
4696        Ok(project_transaction)
4697    }
4698
4699    pub fn prepare_rename<T: ToPointUtf16>(
4700        &self,
4701        buffer: ModelHandle<Buffer>,
4702        position: T,
4703        cx: &mut ModelContext<Self>,
4704    ) -> Task<Result<Option<Range<Anchor>>>> {
4705        let position = position.to_point_utf16(buffer.read(cx));
4706        self.request_lsp(buffer, PrepareRename { position }, cx)
4707    }
4708
4709    pub fn perform_rename<T: ToPointUtf16>(
4710        &self,
4711        buffer: ModelHandle<Buffer>,
4712        position: T,
4713        new_name: String,
4714        push_to_history: bool,
4715        cx: &mut ModelContext<Self>,
4716    ) -> Task<Result<ProjectTransaction>> {
4717        let position = position.to_point_utf16(buffer.read(cx));
4718        self.request_lsp(
4719            buffer,
4720            PerformRename {
4721                position,
4722                new_name,
4723                push_to_history,
4724            },
4725            cx,
4726        )
4727    }
4728
4729    pub fn on_type_format<T: ToPointUtf16>(
4730        &self,
4731        buffer: ModelHandle<Buffer>,
4732        position: T,
4733        trigger: String,
4734        push_to_history: bool,
4735        cx: &mut ModelContext<Self>,
4736    ) -> Task<Result<Option<Transaction>>> {
4737        let (position, tab_size) = buffer.read_with(cx, |buffer, cx| {
4738            let position = position.to_point_utf16(buffer);
4739            (
4740                position,
4741                language_settings(buffer.language_at(position).as_ref(), buffer.file(), cx)
4742                    .tab_size,
4743            )
4744        });
4745        self.request_lsp(
4746            buffer.clone(),
4747            OnTypeFormatting {
4748                position,
4749                trigger,
4750                options: lsp_command::lsp_formatting_options(tab_size.get()).into(),
4751                push_to_history,
4752            },
4753            cx,
4754        )
4755    }
4756
4757    #[allow(clippy::type_complexity)]
4758    pub fn search(
4759        &self,
4760        query: SearchQuery,
4761        cx: &mut ModelContext<Self>,
4762    ) -> Task<Result<HashMap<ModelHandle<Buffer>, Vec<Range<Anchor>>>>> {
4763        if self.is_local() {
4764            let snapshots = self
4765                .visible_worktrees(cx)
4766                .filter_map(|tree| {
4767                    let tree = tree.read(cx).as_local()?;
4768                    Some(tree.snapshot())
4769                })
4770                .collect::<Vec<_>>();
4771
4772            let background = cx.background().clone();
4773            let path_count: usize = snapshots.iter().map(|s| s.visible_file_count()).sum();
4774            if path_count == 0 {
4775                return Task::ready(Ok(Default::default()));
4776            }
4777            let workers = background.num_cpus().min(path_count);
4778            let (matching_paths_tx, mut matching_paths_rx) = smol::channel::bounded(1024);
4779            cx.background()
4780                .spawn({
4781                    let fs = self.fs.clone();
4782                    let background = cx.background().clone();
4783                    let query = query.clone();
4784                    async move {
4785                        let fs = &fs;
4786                        let query = &query;
4787                        let matching_paths_tx = &matching_paths_tx;
4788                        let paths_per_worker = (path_count + workers - 1) / workers;
4789                        let snapshots = &snapshots;
4790                        background
4791                            .scoped(|scope| {
4792                                for worker_ix in 0..workers {
4793                                    let worker_start_ix = worker_ix * paths_per_worker;
4794                                    let worker_end_ix = worker_start_ix + paths_per_worker;
4795                                    scope.spawn(async move {
4796                                        let mut snapshot_start_ix = 0;
4797                                        let mut abs_path = PathBuf::new();
4798                                        for snapshot in snapshots {
4799                                            let snapshot_end_ix =
4800                                                snapshot_start_ix + snapshot.visible_file_count();
4801                                            if worker_end_ix <= snapshot_start_ix {
4802                                                break;
4803                                            } else if worker_start_ix > snapshot_end_ix {
4804                                                snapshot_start_ix = snapshot_end_ix;
4805                                                continue;
4806                                            } else {
4807                                                let start_in_snapshot = worker_start_ix
4808                                                    .saturating_sub(snapshot_start_ix);
4809                                                let end_in_snapshot =
4810                                                    cmp::min(worker_end_ix, snapshot_end_ix)
4811                                                        - snapshot_start_ix;
4812
4813                                                for entry in snapshot
4814                                                    .files(false, start_in_snapshot)
4815                                                    .take(end_in_snapshot - start_in_snapshot)
4816                                                {
4817                                                    if matching_paths_tx.is_closed() {
4818                                                        break;
4819                                                    }
4820                                                    let matches = if query
4821                                                        .file_matches(Some(&entry.path))
4822                                                    {
4823                                                        abs_path.clear();
4824                                                        abs_path.push(&snapshot.abs_path());
4825                                                        abs_path.push(&entry.path);
4826                                                        if let Some(file) =
4827                                                            fs.open_sync(&abs_path).await.log_err()
4828                                                        {
4829                                                            query.detect(file).unwrap_or(false)
4830                                                        } else {
4831                                                            false
4832                                                        }
4833                                                    } else {
4834                                                        false
4835                                                    };
4836
4837                                                    if matches {
4838                                                        let project_path =
4839                                                            (snapshot.id(), entry.path.clone());
4840                                                        if matching_paths_tx
4841                                                            .send(project_path)
4842                                                            .await
4843                                                            .is_err()
4844                                                        {
4845                                                            break;
4846                                                        }
4847                                                    }
4848                                                }
4849
4850                                                snapshot_start_ix = snapshot_end_ix;
4851                                            }
4852                                        }
4853                                    });
4854                                }
4855                            })
4856                            .await;
4857                    }
4858                })
4859                .detach();
4860
4861            let (buffers_tx, buffers_rx) = smol::channel::bounded(1024);
4862            let open_buffers = self
4863                .opened_buffers
4864                .values()
4865                .filter_map(|b| b.upgrade(cx))
4866                .collect::<HashSet<_>>();
4867            cx.spawn(|this, cx| async move {
4868                for buffer in &open_buffers {
4869                    let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
4870                    buffers_tx.send((buffer.clone(), snapshot)).await?;
4871                }
4872
4873                let open_buffers = Rc::new(RefCell::new(open_buffers));
4874                while let Some(project_path) = matching_paths_rx.next().await {
4875                    if buffers_tx.is_closed() {
4876                        break;
4877                    }
4878
4879                    let this = this.clone();
4880                    let open_buffers = open_buffers.clone();
4881                    let buffers_tx = buffers_tx.clone();
4882                    cx.spawn(|mut cx| async move {
4883                        if let Some(buffer) = this
4884                            .update(&mut cx, |this, cx| this.open_buffer(project_path, cx))
4885                            .await
4886                            .log_err()
4887                        {
4888                            if open_buffers.borrow_mut().insert(buffer.clone()) {
4889                                let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
4890                                buffers_tx.send((buffer, snapshot)).await?;
4891                            }
4892                        }
4893
4894                        Ok::<_, anyhow::Error>(())
4895                    })
4896                    .detach();
4897                }
4898
4899                Ok::<_, anyhow::Error>(())
4900            })
4901            .detach_and_log_err(cx);
4902
4903            let background = cx.background().clone();
4904            cx.background().spawn(async move {
4905                let query = &query;
4906                let mut matched_buffers = Vec::new();
4907                for _ in 0..workers {
4908                    matched_buffers.push(HashMap::default());
4909                }
4910                background
4911                    .scoped(|scope| {
4912                        for worker_matched_buffers in matched_buffers.iter_mut() {
4913                            let mut buffers_rx = buffers_rx.clone();
4914                            scope.spawn(async move {
4915                                while let Some((buffer, snapshot)) = buffers_rx.next().await {
4916                                    let buffer_matches = if query.file_matches(
4917                                        snapshot.file().map(|file| file.path().as_ref()),
4918                                    ) {
4919                                        query
4920                                            .search(snapshot.as_rope())
4921                                            .await
4922                                            .iter()
4923                                            .map(|range| {
4924                                                snapshot.anchor_before(range.start)
4925                                                    ..snapshot.anchor_after(range.end)
4926                                            })
4927                                            .collect()
4928                                    } else {
4929                                        Vec::new()
4930                                    };
4931                                    if !buffer_matches.is_empty() {
4932                                        worker_matched_buffers
4933                                            .insert(buffer.clone(), buffer_matches);
4934                                    }
4935                                }
4936                            });
4937                        }
4938                    })
4939                    .await;
4940                Ok(matched_buffers.into_iter().flatten().collect())
4941            })
4942        } else if let Some(project_id) = self.remote_id() {
4943            let request = self.client.request(query.to_proto(project_id));
4944            cx.spawn(|this, mut cx| async move {
4945                let response = request.await?;
4946                let mut result = HashMap::default();
4947                for location in response.locations {
4948                    let target_buffer = this
4949                        .update(&mut cx, |this, cx| {
4950                            this.wait_for_remote_buffer(location.buffer_id, cx)
4951                        })
4952                        .await?;
4953                    let start = location
4954                        .start
4955                        .and_then(deserialize_anchor)
4956                        .ok_or_else(|| anyhow!("missing target start"))?;
4957                    let end = location
4958                        .end
4959                        .and_then(deserialize_anchor)
4960                        .ok_or_else(|| anyhow!("missing target end"))?;
4961                    result
4962                        .entry(target_buffer)
4963                        .or_insert(Vec::new())
4964                        .push(start..end)
4965                }
4966                Ok(result)
4967            })
4968        } else {
4969            Task::ready(Ok(Default::default()))
4970        }
4971    }
4972
4973    // TODO: Wire this up to allow selecting a server?
4974    fn request_lsp<R: LspCommand>(
4975        &self,
4976        buffer_handle: ModelHandle<Buffer>,
4977        request: R,
4978        cx: &mut ModelContext<Self>,
4979    ) -> Task<Result<R::Response>>
4980    where
4981        <R::LspRequest as lsp::request::Request>::Result: Send,
4982    {
4983        let buffer = buffer_handle.read(cx);
4984        if self.is_local() {
4985            let file = File::from_dyn(buffer.file()).and_then(File::as_local);
4986            if let Some((file, language_server)) = file.zip(
4987                self.primary_language_servers_for_buffer(buffer, cx)
4988                    .map(|(_, server)| server.clone()),
4989            ) {
4990                let lsp_params = request.to_lsp(&file.abs_path(cx), buffer, &language_server, cx);
4991                return cx.spawn(|this, cx| async move {
4992                    if !request.check_capabilities(language_server.capabilities()) {
4993                        return Ok(Default::default());
4994                    }
4995
4996                    let result = language_server.request::<R::LspRequest>(lsp_params).await;
4997                    let response = match result {
4998                        Ok(response) => response,
4999
5000                        Err(err) => {
5001                            log::warn!(
5002                                "Generic lsp request to {} failed: {}",
5003                                language_server.name(),
5004                                err
5005                            );
5006                            return Err(err);
5007                        }
5008                    };
5009
5010                    request
5011                        .response_from_lsp(
5012                            response,
5013                            this,
5014                            buffer_handle,
5015                            language_server.server_id(),
5016                            cx,
5017                        )
5018                        .await
5019                });
5020            }
5021        } else if let Some(project_id) = self.remote_id() {
5022            let rpc = self.client.clone();
5023            let message = request.to_proto(project_id, buffer);
5024            return cx.spawn_weak(|this, cx| async move {
5025                // Ensure the project is still alive by the time the task
5026                // is scheduled.
5027                this.upgrade(&cx)
5028                    .ok_or_else(|| anyhow!("project dropped"))?;
5029
5030                let response = rpc.request(message).await?;
5031
5032                let this = this
5033                    .upgrade(&cx)
5034                    .ok_or_else(|| anyhow!("project dropped"))?;
5035                if this.read_with(&cx, |this, _| this.is_read_only()) {
5036                    Err(anyhow!("disconnected before completing request"))
5037                } else {
5038                    request
5039                        .response_from_proto(response, this, buffer_handle, cx)
5040                        .await
5041                }
5042            });
5043        }
5044        Task::ready(Ok(Default::default()))
5045    }
5046
5047    pub fn find_or_create_local_worktree(
5048        &mut self,
5049        abs_path: impl AsRef<Path>,
5050        visible: bool,
5051        cx: &mut ModelContext<Self>,
5052    ) -> Task<Result<(ModelHandle<Worktree>, PathBuf)>> {
5053        let abs_path = abs_path.as_ref();
5054        if let Some((tree, relative_path)) = self.find_local_worktree(abs_path, cx) {
5055            Task::ready(Ok((tree, relative_path)))
5056        } else {
5057            let worktree = self.create_local_worktree(abs_path, visible, cx);
5058            cx.foreground()
5059                .spawn(async move { Ok((worktree.await?, PathBuf::new())) })
5060        }
5061    }
5062
5063    pub fn find_local_worktree(
5064        &self,
5065        abs_path: &Path,
5066        cx: &AppContext,
5067    ) -> Option<(ModelHandle<Worktree>, PathBuf)> {
5068        for tree in &self.worktrees {
5069            if let Some(tree) = tree.upgrade(cx) {
5070                if let Some(relative_path) = tree
5071                    .read(cx)
5072                    .as_local()
5073                    .and_then(|t| abs_path.strip_prefix(t.abs_path()).ok())
5074                {
5075                    return Some((tree.clone(), relative_path.into()));
5076                }
5077            }
5078        }
5079        None
5080    }
5081
5082    pub fn is_shared(&self) -> bool {
5083        match &self.client_state {
5084            Some(ProjectClientState::Local { .. }) => true,
5085            _ => false,
5086        }
5087    }
5088
5089    fn create_local_worktree(
5090        &mut self,
5091        abs_path: impl AsRef<Path>,
5092        visible: bool,
5093        cx: &mut ModelContext<Self>,
5094    ) -> Task<Result<ModelHandle<Worktree>>> {
5095        let fs = self.fs.clone();
5096        let client = self.client.clone();
5097        let next_entry_id = self.next_entry_id.clone();
5098        let path: Arc<Path> = abs_path.as_ref().into();
5099        let task = self
5100            .loading_local_worktrees
5101            .entry(path.clone())
5102            .or_insert_with(|| {
5103                cx.spawn(|project, mut cx| {
5104                    async move {
5105                        let worktree = Worktree::local(
5106                            client.clone(),
5107                            path.clone(),
5108                            visible,
5109                            fs,
5110                            next_entry_id,
5111                            &mut cx,
5112                        )
5113                        .await;
5114
5115                        project.update(&mut cx, |project, _| {
5116                            project.loading_local_worktrees.remove(&path);
5117                        });
5118
5119                        let worktree = worktree?;
5120                        project.update(&mut cx, |project, cx| project.add_worktree(&worktree, cx));
5121                        Ok(worktree)
5122                    }
5123                    .map_err(Arc::new)
5124                })
5125                .shared()
5126            })
5127            .clone();
5128        cx.foreground().spawn(async move {
5129            match task.await {
5130                Ok(worktree) => Ok(worktree),
5131                Err(err) => Err(anyhow!("{}", err)),
5132            }
5133        })
5134    }
5135
5136    pub fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut ModelContext<Self>) {
5137        self.worktrees.retain(|worktree| {
5138            if let Some(worktree) = worktree.upgrade(cx) {
5139                let id = worktree.read(cx).id();
5140                if id == id_to_remove {
5141                    cx.emit(Event::WorktreeRemoved(id));
5142                    false
5143                } else {
5144                    true
5145                }
5146            } else {
5147                false
5148            }
5149        });
5150        self.metadata_changed(cx);
5151    }
5152
5153    fn add_worktree(&mut self, worktree: &ModelHandle<Worktree>, cx: &mut ModelContext<Self>) {
5154        cx.observe(worktree, |_, _, cx| cx.notify()).detach();
5155        if worktree.read(cx).is_local() {
5156            cx.subscribe(worktree, |this, worktree, event, cx| match event {
5157                worktree::Event::UpdatedEntries(changes) => {
5158                    this.update_local_worktree_buffers(&worktree, changes, cx);
5159                    this.update_local_worktree_language_servers(&worktree, changes, cx);
5160                    this.update_local_worktree_settings(&worktree, changes, cx);
5161                }
5162                worktree::Event::UpdatedGitRepositories(updated_repos) => {
5163                    this.update_local_worktree_buffers_git_repos(worktree, updated_repos, cx)
5164                }
5165            })
5166            .detach();
5167        }
5168
5169        let push_strong_handle = {
5170            let worktree = worktree.read(cx);
5171            self.is_shared() || worktree.is_visible() || worktree.is_remote()
5172        };
5173        if push_strong_handle {
5174            self.worktrees
5175                .push(WorktreeHandle::Strong(worktree.clone()));
5176        } else {
5177            self.worktrees
5178                .push(WorktreeHandle::Weak(worktree.downgrade()));
5179        }
5180
5181        let handle_id = worktree.id();
5182        cx.observe_release(worktree, move |this, worktree, cx| {
5183            let _ = this.remove_worktree(worktree.id(), cx);
5184            cx.update_global::<SettingsStore, _, _>(|store, cx| {
5185                store.clear_local_settings(handle_id, cx).log_err()
5186            });
5187        })
5188        .detach();
5189
5190        cx.emit(Event::WorktreeAdded);
5191        self.metadata_changed(cx);
5192    }
5193
5194    fn update_local_worktree_buffers(
5195        &mut self,
5196        worktree_handle: &ModelHandle<Worktree>,
5197        changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
5198        cx: &mut ModelContext<Self>,
5199    ) {
5200        let snapshot = worktree_handle.read(cx).snapshot();
5201
5202        let mut renamed_buffers = Vec::new();
5203        for (path, entry_id, _) in changes {
5204            let worktree_id = worktree_handle.read(cx).id();
5205            let project_path = ProjectPath {
5206                worktree_id,
5207                path: path.clone(),
5208            };
5209
5210            let buffer_id = match self.local_buffer_ids_by_entry_id.get(entry_id) {
5211                Some(&buffer_id) => buffer_id,
5212                None => match self.local_buffer_ids_by_path.get(&project_path) {
5213                    Some(&buffer_id) => buffer_id,
5214                    None => continue,
5215                },
5216            };
5217
5218            let open_buffer = self.opened_buffers.get(&buffer_id);
5219            let buffer = if let Some(buffer) = open_buffer.and_then(|buffer| buffer.upgrade(cx)) {
5220                buffer
5221            } else {
5222                self.opened_buffers.remove(&buffer_id);
5223                self.local_buffer_ids_by_path.remove(&project_path);
5224                self.local_buffer_ids_by_entry_id.remove(entry_id);
5225                continue;
5226            };
5227
5228            buffer.update(cx, |buffer, cx| {
5229                if let Some(old_file) = File::from_dyn(buffer.file()) {
5230                    if old_file.worktree != *worktree_handle {
5231                        return;
5232                    }
5233
5234                    let new_file = if let Some(entry) = snapshot.entry_for_id(old_file.entry_id) {
5235                        File {
5236                            is_local: true,
5237                            entry_id: entry.id,
5238                            mtime: entry.mtime,
5239                            path: entry.path.clone(),
5240                            worktree: worktree_handle.clone(),
5241                            is_deleted: false,
5242                        }
5243                    } else if let Some(entry) = snapshot.entry_for_path(old_file.path().as_ref()) {
5244                        File {
5245                            is_local: true,
5246                            entry_id: entry.id,
5247                            mtime: entry.mtime,
5248                            path: entry.path.clone(),
5249                            worktree: worktree_handle.clone(),
5250                            is_deleted: false,
5251                        }
5252                    } else {
5253                        File {
5254                            is_local: true,
5255                            entry_id: old_file.entry_id,
5256                            path: old_file.path().clone(),
5257                            mtime: old_file.mtime(),
5258                            worktree: worktree_handle.clone(),
5259                            is_deleted: true,
5260                        }
5261                    };
5262
5263                    let old_path = old_file.abs_path(cx);
5264                    if new_file.abs_path(cx) != old_path {
5265                        renamed_buffers.push((cx.handle(), old_file.clone()));
5266                        self.local_buffer_ids_by_path.remove(&project_path);
5267                        self.local_buffer_ids_by_path.insert(
5268                            ProjectPath {
5269                                worktree_id,
5270                                path: path.clone(),
5271                            },
5272                            buffer_id,
5273                        );
5274                    }
5275
5276                    if new_file.entry_id != *entry_id {
5277                        self.local_buffer_ids_by_entry_id.remove(entry_id);
5278                        self.local_buffer_ids_by_entry_id
5279                            .insert(new_file.entry_id, buffer_id);
5280                    }
5281
5282                    if new_file != *old_file {
5283                        if let Some(project_id) = self.remote_id() {
5284                            self.client
5285                                .send(proto::UpdateBufferFile {
5286                                    project_id,
5287                                    buffer_id: buffer_id as u64,
5288                                    file: Some(new_file.to_proto()),
5289                                })
5290                                .log_err();
5291                        }
5292
5293                        buffer.file_updated(Arc::new(new_file), cx).detach();
5294                    }
5295                }
5296            });
5297        }
5298
5299        for (buffer, old_file) in renamed_buffers {
5300            self.unregister_buffer_from_language_servers(&buffer, &old_file, cx);
5301            self.detect_language_for_buffer(&buffer, cx);
5302            self.register_buffer_with_language_servers(&buffer, cx);
5303        }
5304    }
5305
5306    fn update_local_worktree_language_servers(
5307        &mut self,
5308        worktree_handle: &ModelHandle<Worktree>,
5309        changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
5310        cx: &mut ModelContext<Self>,
5311    ) {
5312        if changes.is_empty() {
5313            return;
5314        }
5315
5316        let worktree_id = worktree_handle.read(cx).id();
5317        let mut language_server_ids = self
5318            .language_server_ids
5319            .iter()
5320            .filter_map(|((server_worktree_id, _), server_id)| {
5321                (*server_worktree_id == worktree_id).then_some(*server_id)
5322            })
5323            .collect::<Vec<_>>();
5324        language_server_ids.sort();
5325        language_server_ids.dedup();
5326
5327        let abs_path = worktree_handle.read(cx).abs_path();
5328        for server_id in &language_server_ids {
5329            if let Some(server) = self.language_servers.get(server_id) {
5330                if let LanguageServerState::Running {
5331                    server,
5332                    watched_paths,
5333                    ..
5334                } = server
5335                {
5336                    if let Some(watched_paths) = watched_paths.get(&worktree_id) {
5337                        let params = lsp::DidChangeWatchedFilesParams {
5338                            changes: changes
5339                                .iter()
5340                                .filter_map(|(path, _, change)| {
5341                                    if !watched_paths.is_match(&path) {
5342                                        return None;
5343                                    }
5344                                    let typ = match change {
5345                                        PathChange::Loaded => return None,
5346                                        PathChange::Added => lsp::FileChangeType::CREATED,
5347                                        PathChange::Removed => lsp::FileChangeType::DELETED,
5348                                        PathChange::Updated => lsp::FileChangeType::CHANGED,
5349                                        PathChange::AddedOrUpdated => lsp::FileChangeType::CHANGED,
5350                                    };
5351                                    Some(lsp::FileEvent {
5352                                        uri: lsp::Url::from_file_path(abs_path.join(path)).unwrap(),
5353                                        typ,
5354                                    })
5355                                })
5356                                .collect(),
5357                        };
5358
5359                        if !params.changes.is_empty() {
5360                            server
5361                                .notify::<lsp::notification::DidChangeWatchedFiles>(params)
5362                                .log_err();
5363                        }
5364                    }
5365                }
5366            }
5367        }
5368    }
5369
5370    fn update_local_worktree_buffers_git_repos(
5371        &mut self,
5372        worktree_handle: ModelHandle<Worktree>,
5373        changed_repos: &UpdatedGitRepositoriesSet,
5374        cx: &mut ModelContext<Self>,
5375    ) {
5376        debug_assert!(worktree_handle.read(cx).is_local());
5377
5378        // Identify the loading buffers whose containing repository that has changed.
5379        let future_buffers = self
5380            .loading_buffers_by_path
5381            .iter()
5382            .filter_map(|(project_path, receiver)| {
5383                if project_path.worktree_id != worktree_handle.read(cx).id() {
5384                    return None;
5385                }
5386                let path = &project_path.path;
5387                changed_repos
5388                    .iter()
5389                    .find(|(work_dir, _)| path.starts_with(work_dir))?;
5390                let receiver = receiver.clone();
5391                let path = path.clone();
5392                Some(async move {
5393                    wait_for_loading_buffer(receiver)
5394                        .await
5395                        .ok()
5396                        .map(|buffer| (buffer, path))
5397                })
5398            })
5399            .collect::<FuturesUnordered<_>>();
5400
5401        // Identify the current buffers whose containing repository has changed.
5402        let current_buffers = self
5403            .opened_buffers
5404            .values()
5405            .filter_map(|buffer| {
5406                let buffer = buffer.upgrade(cx)?;
5407                let file = File::from_dyn(buffer.read(cx).file())?;
5408                if file.worktree != worktree_handle {
5409                    return None;
5410                }
5411                let path = file.path();
5412                changed_repos
5413                    .iter()
5414                    .find(|(work_dir, _)| path.starts_with(work_dir))?;
5415                Some((buffer, path.clone()))
5416            })
5417            .collect::<Vec<_>>();
5418
5419        if future_buffers.len() + current_buffers.len() == 0 {
5420            return;
5421        }
5422
5423        let remote_id = self.remote_id();
5424        let client = self.client.clone();
5425        cx.spawn_weak(move |_, mut cx| async move {
5426            // Wait for all of the buffers to load.
5427            let future_buffers = future_buffers.collect::<Vec<_>>().await;
5428
5429            // Reload the diff base for every buffer whose containing git repository has changed.
5430            let snapshot =
5431                worktree_handle.read_with(&cx, |tree, _| tree.as_local().unwrap().snapshot());
5432            let diff_bases_by_buffer = cx
5433                .background()
5434                .spawn(async move {
5435                    future_buffers
5436                        .into_iter()
5437                        .filter_map(|e| e)
5438                        .chain(current_buffers)
5439                        .filter_map(|(buffer, path)| {
5440                            let (work_directory, repo) =
5441                                snapshot.repository_and_work_directory_for_path(&path)?;
5442                            let repo = snapshot.get_local_repo(&repo)?;
5443                            let relative_path = path.strip_prefix(&work_directory).ok()?;
5444                            let base_text = repo.repo_ptr.lock().load_index_text(&relative_path);
5445                            Some((buffer, base_text))
5446                        })
5447                        .collect::<Vec<_>>()
5448                })
5449                .await;
5450
5451            // Assign the new diff bases on all of the buffers.
5452            for (buffer, diff_base) in diff_bases_by_buffer {
5453                let buffer_id = buffer.update(&mut cx, |buffer, cx| {
5454                    buffer.set_diff_base(diff_base.clone(), cx);
5455                    buffer.remote_id()
5456                });
5457                if let Some(project_id) = remote_id {
5458                    client
5459                        .send(proto::UpdateDiffBase {
5460                            project_id,
5461                            buffer_id,
5462                            diff_base,
5463                        })
5464                        .log_err();
5465                }
5466            }
5467        })
5468        .detach();
5469    }
5470
5471    fn update_local_worktree_settings(
5472        &mut self,
5473        worktree: &ModelHandle<Worktree>,
5474        changes: &UpdatedEntriesSet,
5475        cx: &mut ModelContext<Self>,
5476    ) {
5477        let project_id = self.remote_id();
5478        let worktree_id = worktree.id();
5479        let worktree = worktree.read(cx).as_local().unwrap();
5480        let remote_worktree_id = worktree.id();
5481
5482        let mut settings_contents = Vec::new();
5483        for (path, _, change) in changes.iter() {
5484            if path.ends_with(&*LOCAL_SETTINGS_RELATIVE_PATH) {
5485                let settings_dir = Arc::from(
5486                    path.ancestors()
5487                        .nth(LOCAL_SETTINGS_RELATIVE_PATH.components().count())
5488                        .unwrap(),
5489                );
5490                let fs = self.fs.clone();
5491                let removed = *change == PathChange::Removed;
5492                let abs_path = worktree.absolutize(path);
5493                settings_contents.push(async move {
5494                    (settings_dir, (!removed).then_some(fs.load(&abs_path).await))
5495                });
5496            }
5497        }
5498
5499        if settings_contents.is_empty() {
5500            return;
5501        }
5502
5503        let client = self.client.clone();
5504        cx.spawn_weak(move |_, mut cx| async move {
5505            let settings_contents: Vec<(Arc<Path>, _)> =
5506                futures::future::join_all(settings_contents).await;
5507            cx.update(|cx| {
5508                cx.update_global::<SettingsStore, _, _>(|store, cx| {
5509                    for (directory, file_content) in settings_contents {
5510                        let file_content = file_content.and_then(|content| content.log_err());
5511                        store
5512                            .set_local_settings(
5513                                worktree_id,
5514                                directory.clone(),
5515                                file_content.as_ref().map(String::as_str),
5516                                cx,
5517                            )
5518                            .log_err();
5519                        if let Some(remote_id) = project_id {
5520                            client
5521                                .send(proto::UpdateWorktreeSettings {
5522                                    project_id: remote_id,
5523                                    worktree_id: remote_worktree_id.to_proto(),
5524                                    path: directory.to_string_lossy().into_owned(),
5525                                    content: file_content,
5526                                })
5527                                .log_err();
5528                        }
5529                    }
5530                });
5531            });
5532        })
5533        .detach();
5534    }
5535
5536    pub fn set_active_path(&mut self, entry: Option<ProjectPath>, cx: &mut ModelContext<Self>) {
5537        let new_active_entry = entry.and_then(|project_path| {
5538            let worktree = self.worktree_for_id(project_path.worktree_id, cx)?;
5539            let entry = worktree.read(cx).entry_for_path(project_path.path)?;
5540            Some(entry.id)
5541        });
5542        if new_active_entry != self.active_entry {
5543            self.active_entry = new_active_entry;
5544            cx.emit(Event::ActiveEntryChanged(new_active_entry));
5545        }
5546    }
5547
5548    pub fn language_servers_running_disk_based_diagnostics(
5549        &self,
5550    ) -> impl Iterator<Item = LanguageServerId> + '_ {
5551        self.language_server_statuses
5552            .iter()
5553            .filter_map(|(id, status)| {
5554                if status.has_pending_diagnostic_updates {
5555                    Some(*id)
5556                } else {
5557                    None
5558                }
5559            })
5560    }
5561
5562    pub fn diagnostic_summary(&self, cx: &AppContext) -> DiagnosticSummary {
5563        let mut summary = DiagnosticSummary::default();
5564        for (_, _, path_summary) in self.diagnostic_summaries(cx) {
5565            summary.error_count += path_summary.error_count;
5566            summary.warning_count += path_summary.warning_count;
5567        }
5568        summary
5569    }
5570
5571    pub fn diagnostic_summaries<'a>(
5572        &'a self,
5573        cx: &'a AppContext,
5574    ) -> impl Iterator<Item = (ProjectPath, LanguageServerId, DiagnosticSummary)> + 'a {
5575        self.visible_worktrees(cx).flat_map(move |worktree| {
5576            let worktree = worktree.read(cx);
5577            let worktree_id = worktree.id();
5578            worktree
5579                .diagnostic_summaries()
5580                .map(move |(path, server_id, summary)| {
5581                    (ProjectPath { worktree_id, path }, server_id, summary)
5582                })
5583        })
5584    }
5585
5586    pub fn disk_based_diagnostics_started(
5587        &mut self,
5588        language_server_id: LanguageServerId,
5589        cx: &mut ModelContext<Self>,
5590    ) {
5591        cx.emit(Event::DiskBasedDiagnosticsStarted { language_server_id });
5592    }
5593
5594    pub fn disk_based_diagnostics_finished(
5595        &mut self,
5596        language_server_id: LanguageServerId,
5597        cx: &mut ModelContext<Self>,
5598    ) {
5599        cx.emit(Event::DiskBasedDiagnosticsFinished { language_server_id });
5600    }
5601
5602    pub fn active_entry(&self) -> Option<ProjectEntryId> {
5603        self.active_entry
5604    }
5605
5606    pub fn entry_for_path(&self, path: &ProjectPath, cx: &AppContext) -> Option<Entry> {
5607        self.worktree_for_id(path.worktree_id, cx)?
5608            .read(cx)
5609            .entry_for_path(&path.path)
5610            .cloned()
5611    }
5612
5613    pub fn path_for_entry(&self, entry_id: ProjectEntryId, cx: &AppContext) -> Option<ProjectPath> {
5614        let worktree = self.worktree_for_entry(entry_id, cx)?;
5615        let worktree = worktree.read(cx);
5616        let worktree_id = worktree.id();
5617        let path = worktree.entry_for_id(entry_id)?.path.clone();
5618        Some(ProjectPath { worktree_id, path })
5619    }
5620
5621    pub fn absolute_path(&self, project_path: &ProjectPath, cx: &AppContext) -> Option<PathBuf> {
5622        let workspace_root = self
5623            .worktree_for_id(project_path.worktree_id, cx)?
5624            .read(cx)
5625            .abs_path();
5626        let project_path = project_path.path.as_ref();
5627
5628        Some(if project_path == Path::new("") {
5629            workspace_root.to_path_buf()
5630        } else {
5631            workspace_root.join(project_path)
5632        })
5633    }
5634
5635    // RPC message handlers
5636
5637    async fn handle_unshare_project(
5638        this: ModelHandle<Self>,
5639        _: TypedEnvelope<proto::UnshareProject>,
5640        _: Arc<Client>,
5641        mut cx: AsyncAppContext,
5642    ) -> Result<()> {
5643        this.update(&mut cx, |this, cx| {
5644            if this.is_local() {
5645                this.unshare(cx)?;
5646            } else {
5647                this.disconnected_from_host(cx);
5648            }
5649            Ok(())
5650        })
5651    }
5652
5653    async fn handle_add_collaborator(
5654        this: ModelHandle<Self>,
5655        mut envelope: TypedEnvelope<proto::AddProjectCollaborator>,
5656        _: Arc<Client>,
5657        mut cx: AsyncAppContext,
5658    ) -> Result<()> {
5659        let collaborator = envelope
5660            .payload
5661            .collaborator
5662            .take()
5663            .ok_or_else(|| anyhow!("empty collaborator"))?;
5664
5665        let collaborator = Collaborator::from_proto(collaborator)?;
5666        this.update(&mut cx, |this, cx| {
5667            this.shared_buffers.remove(&collaborator.peer_id);
5668            this.collaborators
5669                .insert(collaborator.peer_id, collaborator);
5670            cx.notify();
5671        });
5672
5673        Ok(())
5674    }
5675
5676    async fn handle_update_project_collaborator(
5677        this: ModelHandle<Self>,
5678        envelope: TypedEnvelope<proto::UpdateProjectCollaborator>,
5679        _: Arc<Client>,
5680        mut cx: AsyncAppContext,
5681    ) -> Result<()> {
5682        let old_peer_id = envelope
5683            .payload
5684            .old_peer_id
5685            .ok_or_else(|| anyhow!("missing old peer id"))?;
5686        let new_peer_id = envelope
5687            .payload
5688            .new_peer_id
5689            .ok_or_else(|| anyhow!("missing new peer id"))?;
5690        this.update(&mut cx, |this, cx| {
5691            let collaborator = this
5692                .collaborators
5693                .remove(&old_peer_id)
5694                .ok_or_else(|| anyhow!("received UpdateProjectCollaborator for unknown peer"))?;
5695            let is_host = collaborator.replica_id == 0;
5696            this.collaborators.insert(new_peer_id, collaborator);
5697
5698            let buffers = this.shared_buffers.remove(&old_peer_id);
5699            log::info!(
5700                "peer {} became {}. moving buffers {:?}",
5701                old_peer_id,
5702                new_peer_id,
5703                &buffers
5704            );
5705            if let Some(buffers) = buffers {
5706                this.shared_buffers.insert(new_peer_id, buffers);
5707            }
5708
5709            if is_host {
5710                this.opened_buffers
5711                    .retain(|_, buffer| !matches!(buffer, OpenBuffer::Operations(_)));
5712                this.buffer_ordered_messages_tx
5713                    .unbounded_send(BufferOrderedMessage::Resync)
5714                    .unwrap();
5715            }
5716
5717            cx.emit(Event::CollaboratorUpdated {
5718                old_peer_id,
5719                new_peer_id,
5720            });
5721            cx.notify();
5722            Ok(())
5723        })
5724    }
5725
5726    async fn handle_remove_collaborator(
5727        this: ModelHandle<Self>,
5728        envelope: TypedEnvelope<proto::RemoveProjectCollaborator>,
5729        _: Arc<Client>,
5730        mut cx: AsyncAppContext,
5731    ) -> Result<()> {
5732        this.update(&mut cx, |this, cx| {
5733            let peer_id = envelope
5734                .payload
5735                .peer_id
5736                .ok_or_else(|| anyhow!("invalid peer id"))?;
5737            let replica_id = this
5738                .collaborators
5739                .remove(&peer_id)
5740                .ok_or_else(|| anyhow!("unknown peer {:?}", peer_id))?
5741                .replica_id;
5742            for buffer in this.opened_buffers.values() {
5743                if let Some(buffer) = buffer.upgrade(cx) {
5744                    buffer.update(cx, |buffer, cx| buffer.remove_peer(replica_id, cx));
5745                }
5746            }
5747            this.shared_buffers.remove(&peer_id);
5748
5749            cx.emit(Event::CollaboratorLeft(peer_id));
5750            cx.notify();
5751            Ok(())
5752        })
5753    }
5754
5755    async fn handle_update_project(
5756        this: ModelHandle<Self>,
5757        envelope: TypedEnvelope<proto::UpdateProject>,
5758        _: Arc<Client>,
5759        mut cx: AsyncAppContext,
5760    ) -> Result<()> {
5761        this.update(&mut cx, |this, cx| {
5762            // Don't handle messages that were sent before the response to us joining the project
5763            if envelope.message_id > this.join_project_response_message_id {
5764                this.set_worktrees_from_proto(envelope.payload.worktrees, cx)?;
5765            }
5766            Ok(())
5767        })
5768    }
5769
5770    async fn handle_update_worktree(
5771        this: ModelHandle<Self>,
5772        envelope: TypedEnvelope<proto::UpdateWorktree>,
5773        _: Arc<Client>,
5774        mut cx: AsyncAppContext,
5775    ) -> Result<()> {
5776        this.update(&mut cx, |this, cx| {
5777            let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
5778            if let Some(worktree) = this.worktree_for_id(worktree_id, cx) {
5779                worktree.update(cx, |worktree, _| {
5780                    let worktree = worktree.as_remote_mut().unwrap();
5781                    worktree.update_from_remote(envelope.payload);
5782                });
5783            }
5784            Ok(())
5785        })
5786    }
5787
5788    async fn handle_update_worktree_settings(
5789        this: ModelHandle<Self>,
5790        envelope: TypedEnvelope<proto::UpdateWorktreeSettings>,
5791        _: Arc<Client>,
5792        mut cx: AsyncAppContext,
5793    ) -> Result<()> {
5794        this.update(&mut cx, |this, cx| {
5795            let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
5796            if let Some(worktree) = this.worktree_for_id(worktree_id, cx) {
5797                cx.update_global::<SettingsStore, _, _>(|store, cx| {
5798                    store
5799                        .set_local_settings(
5800                            worktree.id(),
5801                            PathBuf::from(&envelope.payload.path).into(),
5802                            envelope.payload.content.as_ref().map(String::as_str),
5803                            cx,
5804                        )
5805                        .log_err();
5806                });
5807            }
5808            Ok(())
5809        })
5810    }
5811
5812    async fn handle_create_project_entry(
5813        this: ModelHandle<Self>,
5814        envelope: TypedEnvelope<proto::CreateProjectEntry>,
5815        _: Arc<Client>,
5816        mut cx: AsyncAppContext,
5817    ) -> Result<proto::ProjectEntryResponse> {
5818        let worktree = this.update(&mut cx, |this, cx| {
5819            let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
5820            this.worktree_for_id(worktree_id, cx)
5821                .ok_or_else(|| anyhow!("worktree not found"))
5822        })?;
5823        let worktree_scan_id = worktree.read_with(&cx, |worktree, _| worktree.scan_id());
5824        let entry = worktree
5825            .update(&mut cx, |worktree, cx| {
5826                let worktree = worktree.as_local_mut().unwrap();
5827                let path = PathBuf::from(envelope.payload.path);
5828                worktree.create_entry(path, envelope.payload.is_directory, cx)
5829            })
5830            .await?;
5831        Ok(proto::ProjectEntryResponse {
5832            entry: Some((&entry).into()),
5833            worktree_scan_id: worktree_scan_id as u64,
5834        })
5835    }
5836
5837    async fn handle_rename_project_entry(
5838        this: ModelHandle<Self>,
5839        envelope: TypedEnvelope<proto::RenameProjectEntry>,
5840        _: Arc<Client>,
5841        mut cx: AsyncAppContext,
5842    ) -> Result<proto::ProjectEntryResponse> {
5843        let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id);
5844        let worktree = this.read_with(&cx, |this, cx| {
5845            this.worktree_for_entry(entry_id, cx)
5846                .ok_or_else(|| anyhow!("worktree not found"))
5847        })?;
5848        let worktree_scan_id = worktree.read_with(&cx, |worktree, _| worktree.scan_id());
5849        let entry = worktree
5850            .update(&mut cx, |worktree, cx| {
5851                let new_path = PathBuf::from(envelope.payload.new_path);
5852                worktree
5853                    .as_local_mut()
5854                    .unwrap()
5855                    .rename_entry(entry_id, new_path, cx)
5856                    .ok_or_else(|| anyhow!("invalid entry"))
5857            })?
5858            .await?;
5859        Ok(proto::ProjectEntryResponse {
5860            entry: Some((&entry).into()),
5861            worktree_scan_id: worktree_scan_id as u64,
5862        })
5863    }
5864
5865    async fn handle_copy_project_entry(
5866        this: ModelHandle<Self>,
5867        envelope: TypedEnvelope<proto::CopyProjectEntry>,
5868        _: Arc<Client>,
5869        mut cx: AsyncAppContext,
5870    ) -> Result<proto::ProjectEntryResponse> {
5871        let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id);
5872        let worktree = this.read_with(&cx, |this, cx| {
5873            this.worktree_for_entry(entry_id, cx)
5874                .ok_or_else(|| anyhow!("worktree not found"))
5875        })?;
5876        let worktree_scan_id = worktree.read_with(&cx, |worktree, _| worktree.scan_id());
5877        let entry = worktree
5878            .update(&mut cx, |worktree, cx| {
5879                let new_path = PathBuf::from(envelope.payload.new_path);
5880                worktree
5881                    .as_local_mut()
5882                    .unwrap()
5883                    .copy_entry(entry_id, new_path, cx)
5884                    .ok_or_else(|| anyhow!("invalid entry"))
5885            })?
5886            .await?;
5887        Ok(proto::ProjectEntryResponse {
5888            entry: Some((&entry).into()),
5889            worktree_scan_id: worktree_scan_id as u64,
5890        })
5891    }
5892
5893    async fn handle_delete_project_entry(
5894        this: ModelHandle<Self>,
5895        envelope: TypedEnvelope<proto::DeleteProjectEntry>,
5896        _: Arc<Client>,
5897        mut cx: AsyncAppContext,
5898    ) -> Result<proto::ProjectEntryResponse> {
5899        let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id);
5900
5901        this.update(&mut cx, |_, cx| cx.emit(Event::DeletedEntry(entry_id)));
5902
5903        let worktree = this.read_with(&cx, |this, cx| {
5904            this.worktree_for_entry(entry_id, cx)
5905                .ok_or_else(|| anyhow!("worktree not found"))
5906        })?;
5907        let worktree_scan_id = worktree.read_with(&cx, |worktree, _| worktree.scan_id());
5908        worktree
5909            .update(&mut cx, |worktree, cx| {
5910                worktree
5911                    .as_local_mut()
5912                    .unwrap()
5913                    .delete_entry(entry_id, cx)
5914                    .ok_or_else(|| anyhow!("invalid entry"))
5915            })?
5916            .await?;
5917        Ok(proto::ProjectEntryResponse {
5918            entry: None,
5919            worktree_scan_id: worktree_scan_id as u64,
5920        })
5921    }
5922
5923    async fn handle_update_diagnostic_summary(
5924        this: ModelHandle<Self>,
5925        envelope: TypedEnvelope<proto::UpdateDiagnosticSummary>,
5926        _: Arc<Client>,
5927        mut cx: AsyncAppContext,
5928    ) -> Result<()> {
5929        this.update(&mut cx, |this, cx| {
5930            let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
5931            if let Some(worktree) = this.worktree_for_id(worktree_id, cx) {
5932                if let Some(summary) = envelope.payload.summary {
5933                    let project_path = ProjectPath {
5934                        worktree_id,
5935                        path: Path::new(&summary.path).into(),
5936                    };
5937                    worktree.update(cx, |worktree, _| {
5938                        worktree
5939                            .as_remote_mut()
5940                            .unwrap()
5941                            .update_diagnostic_summary(project_path.path.clone(), &summary);
5942                    });
5943                    cx.emit(Event::DiagnosticsUpdated {
5944                        language_server_id: LanguageServerId(summary.language_server_id as usize),
5945                        path: project_path,
5946                    });
5947                }
5948            }
5949            Ok(())
5950        })
5951    }
5952
5953    async fn handle_start_language_server(
5954        this: ModelHandle<Self>,
5955        envelope: TypedEnvelope<proto::StartLanguageServer>,
5956        _: Arc<Client>,
5957        mut cx: AsyncAppContext,
5958    ) -> Result<()> {
5959        let server = envelope
5960            .payload
5961            .server
5962            .ok_or_else(|| anyhow!("invalid server"))?;
5963        this.update(&mut cx, |this, cx| {
5964            this.language_server_statuses.insert(
5965                LanguageServerId(server.id as usize),
5966                LanguageServerStatus {
5967                    name: server.name,
5968                    pending_work: Default::default(),
5969                    has_pending_diagnostic_updates: false,
5970                    progress_tokens: Default::default(),
5971                },
5972            );
5973            cx.notify();
5974        });
5975        Ok(())
5976    }
5977
5978    async fn handle_update_language_server(
5979        this: ModelHandle<Self>,
5980        envelope: TypedEnvelope<proto::UpdateLanguageServer>,
5981        _: Arc<Client>,
5982        mut cx: AsyncAppContext,
5983    ) -> Result<()> {
5984        this.update(&mut cx, |this, cx| {
5985            let language_server_id = LanguageServerId(envelope.payload.language_server_id as usize);
5986
5987            match envelope
5988                .payload
5989                .variant
5990                .ok_or_else(|| anyhow!("invalid variant"))?
5991            {
5992                proto::update_language_server::Variant::WorkStart(payload) => {
5993                    this.on_lsp_work_start(
5994                        language_server_id,
5995                        payload.token,
5996                        LanguageServerProgress {
5997                            message: payload.message,
5998                            percentage: payload.percentage.map(|p| p as usize),
5999                            last_update_at: Instant::now(),
6000                        },
6001                        cx,
6002                    );
6003                }
6004
6005                proto::update_language_server::Variant::WorkProgress(payload) => {
6006                    this.on_lsp_work_progress(
6007                        language_server_id,
6008                        payload.token,
6009                        LanguageServerProgress {
6010                            message: payload.message,
6011                            percentage: payload.percentage.map(|p| p as usize),
6012                            last_update_at: Instant::now(),
6013                        },
6014                        cx,
6015                    );
6016                }
6017
6018                proto::update_language_server::Variant::WorkEnd(payload) => {
6019                    this.on_lsp_work_end(language_server_id, payload.token, cx);
6020                }
6021
6022                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(_) => {
6023                    this.disk_based_diagnostics_started(language_server_id, cx);
6024                }
6025
6026                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(_) => {
6027                    this.disk_based_diagnostics_finished(language_server_id, cx)
6028                }
6029            }
6030
6031            Ok(())
6032        })
6033    }
6034
6035    async fn handle_update_buffer(
6036        this: ModelHandle<Self>,
6037        envelope: TypedEnvelope<proto::UpdateBuffer>,
6038        _: Arc<Client>,
6039        mut cx: AsyncAppContext,
6040    ) -> Result<proto::Ack> {
6041        this.update(&mut cx, |this, cx| {
6042            let payload = envelope.payload.clone();
6043            let buffer_id = payload.buffer_id;
6044            let ops = payload
6045                .operations
6046                .into_iter()
6047                .map(language::proto::deserialize_operation)
6048                .collect::<Result<Vec<_>, _>>()?;
6049            let is_remote = this.is_remote();
6050            match this.opened_buffers.entry(buffer_id) {
6051                hash_map::Entry::Occupied(mut e) => match e.get_mut() {
6052                    OpenBuffer::Strong(buffer) => {
6053                        buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx))?;
6054                    }
6055                    OpenBuffer::Operations(operations) => operations.extend_from_slice(&ops),
6056                    OpenBuffer::Weak(_) => {}
6057                },
6058                hash_map::Entry::Vacant(e) => {
6059                    assert!(
6060                        is_remote,
6061                        "received buffer update from {:?}",
6062                        envelope.original_sender_id
6063                    );
6064                    e.insert(OpenBuffer::Operations(ops));
6065                }
6066            }
6067            Ok(proto::Ack {})
6068        })
6069    }
6070
6071    async fn handle_create_buffer_for_peer(
6072        this: ModelHandle<Self>,
6073        envelope: TypedEnvelope<proto::CreateBufferForPeer>,
6074        _: Arc<Client>,
6075        mut cx: AsyncAppContext,
6076    ) -> Result<()> {
6077        this.update(&mut cx, |this, cx| {
6078            match envelope
6079                .payload
6080                .variant
6081                .ok_or_else(|| anyhow!("missing variant"))?
6082            {
6083                proto::create_buffer_for_peer::Variant::State(mut state) => {
6084                    let mut buffer_file = None;
6085                    if let Some(file) = state.file.take() {
6086                        let worktree_id = WorktreeId::from_proto(file.worktree_id);
6087                        let worktree = this.worktree_for_id(worktree_id, cx).ok_or_else(|| {
6088                            anyhow!("no worktree found for id {}", file.worktree_id)
6089                        })?;
6090                        buffer_file = Some(Arc::new(File::from_proto(file, worktree.clone(), cx)?)
6091                            as Arc<dyn language::File>);
6092                    }
6093
6094                    let buffer_id = state.id;
6095                    let buffer = cx.add_model(|_| {
6096                        Buffer::from_proto(this.replica_id(), state, buffer_file).unwrap()
6097                    });
6098                    this.incomplete_remote_buffers
6099                        .insert(buffer_id, Some(buffer));
6100                }
6101                proto::create_buffer_for_peer::Variant::Chunk(chunk) => {
6102                    let buffer = this
6103                        .incomplete_remote_buffers
6104                        .get(&chunk.buffer_id)
6105                        .cloned()
6106                        .flatten()
6107                        .ok_or_else(|| {
6108                            anyhow!(
6109                                "received chunk for buffer {} without initial state",
6110                                chunk.buffer_id
6111                            )
6112                        })?;
6113                    let operations = chunk
6114                        .operations
6115                        .into_iter()
6116                        .map(language::proto::deserialize_operation)
6117                        .collect::<Result<Vec<_>>>()?;
6118                    buffer.update(cx, |buffer, cx| buffer.apply_ops(operations, cx))?;
6119
6120                    if chunk.is_last {
6121                        this.incomplete_remote_buffers.remove(&chunk.buffer_id);
6122                        this.register_buffer(&buffer, cx)?;
6123                    }
6124                }
6125            }
6126
6127            Ok(())
6128        })
6129    }
6130
6131    async fn handle_update_diff_base(
6132        this: ModelHandle<Self>,
6133        envelope: TypedEnvelope<proto::UpdateDiffBase>,
6134        _: Arc<Client>,
6135        mut cx: AsyncAppContext,
6136    ) -> Result<()> {
6137        this.update(&mut cx, |this, cx| {
6138            let buffer_id = envelope.payload.buffer_id;
6139            let diff_base = envelope.payload.diff_base;
6140            if let Some(buffer) = this
6141                .opened_buffers
6142                .get_mut(&buffer_id)
6143                .and_then(|b| b.upgrade(cx))
6144                .or_else(|| {
6145                    this.incomplete_remote_buffers
6146                        .get(&buffer_id)
6147                        .cloned()
6148                        .flatten()
6149                })
6150            {
6151                buffer.update(cx, |buffer, cx| buffer.set_diff_base(diff_base, cx));
6152            }
6153            Ok(())
6154        })
6155    }
6156
6157    async fn handle_update_buffer_file(
6158        this: ModelHandle<Self>,
6159        envelope: TypedEnvelope<proto::UpdateBufferFile>,
6160        _: Arc<Client>,
6161        mut cx: AsyncAppContext,
6162    ) -> Result<()> {
6163        let buffer_id = envelope.payload.buffer_id;
6164
6165        this.update(&mut cx, |this, cx| {
6166            let payload = envelope.payload.clone();
6167            if let Some(buffer) = this
6168                .opened_buffers
6169                .get(&buffer_id)
6170                .and_then(|b| b.upgrade(cx))
6171                .or_else(|| {
6172                    this.incomplete_remote_buffers
6173                        .get(&buffer_id)
6174                        .cloned()
6175                        .flatten()
6176                })
6177            {
6178                let file = payload.file.ok_or_else(|| anyhow!("invalid file"))?;
6179                let worktree = this
6180                    .worktree_for_id(WorktreeId::from_proto(file.worktree_id), cx)
6181                    .ok_or_else(|| anyhow!("no such worktree"))?;
6182                let file = File::from_proto(file, worktree, cx)?;
6183                buffer.update(cx, |buffer, cx| {
6184                    buffer.file_updated(Arc::new(file), cx).detach();
6185                });
6186                this.detect_language_for_buffer(&buffer, cx);
6187            }
6188            Ok(())
6189        })
6190    }
6191
6192    async fn handle_save_buffer(
6193        this: ModelHandle<Self>,
6194        envelope: TypedEnvelope<proto::SaveBuffer>,
6195        _: Arc<Client>,
6196        mut cx: AsyncAppContext,
6197    ) -> Result<proto::BufferSaved> {
6198        let buffer_id = envelope.payload.buffer_id;
6199        let (project_id, buffer) = this.update(&mut cx, |this, cx| {
6200            let project_id = this.remote_id().ok_or_else(|| anyhow!("not connected"))?;
6201            let buffer = this
6202                .opened_buffers
6203                .get(&buffer_id)
6204                .and_then(|buffer| buffer.upgrade(cx))
6205                .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?;
6206            anyhow::Ok((project_id, buffer))
6207        })?;
6208        buffer
6209            .update(&mut cx, |buffer, _| {
6210                buffer.wait_for_version(deserialize_version(&envelope.payload.version))
6211            })
6212            .await?;
6213        let buffer_id = buffer.read_with(&cx, |buffer, _| buffer.remote_id());
6214
6215        this.update(&mut cx, |this, cx| this.save_buffer(buffer.clone(), cx))
6216            .await?;
6217        Ok(buffer.read_with(&cx, |buffer, _| proto::BufferSaved {
6218            project_id,
6219            buffer_id,
6220            version: serialize_version(buffer.saved_version()),
6221            mtime: Some(buffer.saved_mtime().into()),
6222            fingerprint: language::proto::serialize_fingerprint(buffer.saved_version_fingerprint()),
6223        }))
6224    }
6225
6226    async fn handle_reload_buffers(
6227        this: ModelHandle<Self>,
6228        envelope: TypedEnvelope<proto::ReloadBuffers>,
6229        _: Arc<Client>,
6230        mut cx: AsyncAppContext,
6231    ) -> Result<proto::ReloadBuffersResponse> {
6232        let sender_id = envelope.original_sender_id()?;
6233        let reload = this.update(&mut cx, |this, cx| {
6234            let mut buffers = HashSet::default();
6235            for buffer_id in &envelope.payload.buffer_ids {
6236                buffers.insert(
6237                    this.opened_buffers
6238                        .get(buffer_id)
6239                        .and_then(|buffer| buffer.upgrade(cx))
6240                        .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?,
6241                );
6242            }
6243            Ok::<_, anyhow::Error>(this.reload_buffers(buffers, false, cx))
6244        })?;
6245
6246        let project_transaction = reload.await?;
6247        let project_transaction = this.update(&mut cx, |this, cx| {
6248            this.serialize_project_transaction_for_peer(project_transaction, sender_id, cx)
6249        });
6250        Ok(proto::ReloadBuffersResponse {
6251            transaction: Some(project_transaction),
6252        })
6253    }
6254
6255    async fn handle_synchronize_buffers(
6256        this: ModelHandle<Self>,
6257        envelope: TypedEnvelope<proto::SynchronizeBuffers>,
6258        _: Arc<Client>,
6259        mut cx: AsyncAppContext,
6260    ) -> Result<proto::SynchronizeBuffersResponse> {
6261        let project_id = envelope.payload.project_id;
6262        let mut response = proto::SynchronizeBuffersResponse {
6263            buffers: Default::default(),
6264        };
6265
6266        this.update(&mut cx, |this, cx| {
6267            let Some(guest_id) = envelope.original_sender_id else {
6268                error!("missing original_sender_id on SynchronizeBuffers request");
6269                return;
6270            };
6271
6272            this.shared_buffers.entry(guest_id).or_default().clear();
6273            for buffer in envelope.payload.buffers {
6274                let buffer_id = buffer.id;
6275                let remote_version = language::proto::deserialize_version(&buffer.version);
6276                if let Some(buffer) = this.buffer_for_id(buffer_id, cx) {
6277                    this.shared_buffers
6278                        .entry(guest_id)
6279                        .or_default()
6280                        .insert(buffer_id);
6281
6282                    let buffer = buffer.read(cx);
6283                    response.buffers.push(proto::BufferVersion {
6284                        id: buffer_id,
6285                        version: language::proto::serialize_version(&buffer.version),
6286                    });
6287
6288                    let operations = buffer.serialize_ops(Some(remote_version), cx);
6289                    let client = this.client.clone();
6290                    if let Some(file) = buffer.file() {
6291                        client
6292                            .send(proto::UpdateBufferFile {
6293                                project_id,
6294                                buffer_id: buffer_id as u64,
6295                                file: Some(file.to_proto()),
6296                            })
6297                            .log_err();
6298                    }
6299
6300                    client
6301                        .send(proto::UpdateDiffBase {
6302                            project_id,
6303                            buffer_id: buffer_id as u64,
6304                            diff_base: buffer.diff_base().map(Into::into),
6305                        })
6306                        .log_err();
6307
6308                    client
6309                        .send(proto::BufferReloaded {
6310                            project_id,
6311                            buffer_id,
6312                            version: language::proto::serialize_version(buffer.saved_version()),
6313                            mtime: Some(buffer.saved_mtime().into()),
6314                            fingerprint: language::proto::serialize_fingerprint(
6315                                buffer.saved_version_fingerprint(),
6316                            ),
6317                            line_ending: language::proto::serialize_line_ending(
6318                                buffer.line_ending(),
6319                            ) as i32,
6320                        })
6321                        .log_err();
6322
6323                    cx.background()
6324                        .spawn(
6325                            async move {
6326                                let operations = operations.await;
6327                                for chunk in split_operations(operations) {
6328                                    client
6329                                        .request(proto::UpdateBuffer {
6330                                            project_id,
6331                                            buffer_id,
6332                                            operations: chunk,
6333                                        })
6334                                        .await?;
6335                                }
6336                                anyhow::Ok(())
6337                            }
6338                            .log_err(),
6339                        )
6340                        .detach();
6341                }
6342            }
6343        });
6344
6345        Ok(response)
6346    }
6347
6348    async fn handle_format_buffers(
6349        this: ModelHandle<Self>,
6350        envelope: TypedEnvelope<proto::FormatBuffers>,
6351        _: Arc<Client>,
6352        mut cx: AsyncAppContext,
6353    ) -> Result<proto::FormatBuffersResponse> {
6354        let sender_id = envelope.original_sender_id()?;
6355        let format = this.update(&mut cx, |this, cx| {
6356            let mut buffers = HashSet::default();
6357            for buffer_id in &envelope.payload.buffer_ids {
6358                buffers.insert(
6359                    this.opened_buffers
6360                        .get(buffer_id)
6361                        .and_then(|buffer| buffer.upgrade(cx))
6362                        .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?,
6363                );
6364            }
6365            let trigger = FormatTrigger::from_proto(envelope.payload.trigger);
6366            Ok::<_, anyhow::Error>(this.format(buffers, false, trigger, cx))
6367        })?;
6368
6369        let project_transaction = format.await?;
6370        let project_transaction = this.update(&mut cx, |this, cx| {
6371            this.serialize_project_transaction_for_peer(project_transaction, sender_id, cx)
6372        });
6373        Ok(proto::FormatBuffersResponse {
6374            transaction: Some(project_transaction),
6375        })
6376    }
6377
6378    async fn handle_apply_additional_edits_for_completion(
6379        this: ModelHandle<Self>,
6380        envelope: TypedEnvelope<proto::ApplyCompletionAdditionalEdits>,
6381        _: Arc<Client>,
6382        mut cx: AsyncAppContext,
6383    ) -> Result<proto::ApplyCompletionAdditionalEditsResponse> {
6384        let (buffer, completion) = this.update(&mut cx, |this, cx| {
6385            let buffer = this
6386                .opened_buffers
6387                .get(&envelope.payload.buffer_id)
6388                .and_then(|buffer| buffer.upgrade(cx))
6389                .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))?;
6390            let language = buffer.read(cx).language();
6391            let completion = language::proto::deserialize_completion(
6392                envelope
6393                    .payload
6394                    .completion
6395                    .ok_or_else(|| anyhow!("invalid completion"))?,
6396                language.cloned(),
6397            );
6398            Ok::<_, anyhow::Error>((buffer, completion))
6399        })?;
6400
6401        let completion = completion.await?;
6402
6403        let apply_additional_edits = this.update(&mut cx, |this, cx| {
6404            this.apply_additional_edits_for_completion(buffer, completion, false, cx)
6405        });
6406
6407        Ok(proto::ApplyCompletionAdditionalEditsResponse {
6408            transaction: apply_additional_edits
6409                .await?
6410                .as_ref()
6411                .map(language::proto::serialize_transaction),
6412        })
6413    }
6414
6415    async fn handle_apply_code_action(
6416        this: ModelHandle<Self>,
6417        envelope: TypedEnvelope<proto::ApplyCodeAction>,
6418        _: Arc<Client>,
6419        mut cx: AsyncAppContext,
6420    ) -> Result<proto::ApplyCodeActionResponse> {
6421        let sender_id = envelope.original_sender_id()?;
6422        let action = language::proto::deserialize_code_action(
6423            envelope
6424                .payload
6425                .action
6426                .ok_or_else(|| anyhow!("invalid action"))?,
6427        )?;
6428        let apply_code_action = this.update(&mut cx, |this, cx| {
6429            let buffer = this
6430                .opened_buffers
6431                .get(&envelope.payload.buffer_id)
6432                .and_then(|buffer| buffer.upgrade(cx))
6433                .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))?;
6434            Ok::<_, anyhow::Error>(this.apply_code_action(buffer, action, false, cx))
6435        })?;
6436
6437        let project_transaction = apply_code_action.await?;
6438        let project_transaction = this.update(&mut cx, |this, cx| {
6439            this.serialize_project_transaction_for_peer(project_transaction, sender_id, cx)
6440        });
6441        Ok(proto::ApplyCodeActionResponse {
6442            transaction: Some(project_transaction),
6443        })
6444    }
6445
6446    async fn handle_on_type_formatting(
6447        this: ModelHandle<Self>,
6448        envelope: TypedEnvelope<proto::OnTypeFormatting>,
6449        _: Arc<Client>,
6450        mut cx: AsyncAppContext,
6451    ) -> Result<proto::OnTypeFormattingResponse> {
6452        let on_type_formatting = this.update(&mut cx, |this, cx| {
6453            let buffer = this
6454                .opened_buffers
6455                .get(&envelope.payload.buffer_id)
6456                .and_then(|buffer| buffer.upgrade(cx))
6457                .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))?;
6458            let position = envelope
6459                .payload
6460                .position
6461                .and_then(deserialize_anchor)
6462                .ok_or_else(|| anyhow!("invalid position"))?;
6463            Ok::<_, anyhow::Error>(this.apply_on_type_formatting(
6464                buffer,
6465                position,
6466                envelope.payload.trigger.clone(),
6467                cx,
6468            ))
6469        })?;
6470
6471        let transaction = on_type_formatting
6472            .await?
6473            .as_ref()
6474            .map(language::proto::serialize_transaction);
6475        Ok(proto::OnTypeFormattingResponse { transaction })
6476    }
6477
6478    async fn handle_lsp_command<T: LspCommand>(
6479        this: ModelHandle<Self>,
6480        envelope: TypedEnvelope<T::ProtoRequest>,
6481        _: Arc<Client>,
6482        mut cx: AsyncAppContext,
6483    ) -> Result<<T::ProtoRequest as proto::RequestMessage>::Response>
6484    where
6485        <T::LspRequest as lsp::request::Request>::Result: Send,
6486    {
6487        let sender_id = envelope.original_sender_id()?;
6488        let buffer_id = T::buffer_id_from_proto(&envelope.payload);
6489        let buffer_handle = this.read_with(&cx, |this, _| {
6490            this.opened_buffers
6491                .get(&buffer_id)
6492                .and_then(|buffer| buffer.upgrade(&cx))
6493                .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))
6494        })?;
6495        let request = T::from_proto(
6496            envelope.payload,
6497            this.clone(),
6498            buffer_handle.clone(),
6499            cx.clone(),
6500        )
6501        .await?;
6502        let buffer_version = buffer_handle.read_with(&cx, |buffer, _| buffer.version());
6503        let response = this
6504            .update(&mut cx, |this, cx| {
6505                this.request_lsp(buffer_handle, request, cx)
6506            })
6507            .await?;
6508        this.update(&mut cx, |this, cx| {
6509            Ok(T::response_to_proto(
6510                response,
6511                this,
6512                sender_id,
6513                &buffer_version,
6514                cx,
6515            ))
6516        })
6517    }
6518
6519    async fn handle_get_project_symbols(
6520        this: ModelHandle<Self>,
6521        envelope: TypedEnvelope<proto::GetProjectSymbols>,
6522        _: Arc<Client>,
6523        mut cx: AsyncAppContext,
6524    ) -> Result<proto::GetProjectSymbolsResponse> {
6525        let symbols = this
6526            .update(&mut cx, |this, cx| {
6527                this.symbols(&envelope.payload.query, cx)
6528            })
6529            .await?;
6530
6531        Ok(proto::GetProjectSymbolsResponse {
6532            symbols: symbols.iter().map(serialize_symbol).collect(),
6533        })
6534    }
6535
6536    async fn handle_search_project(
6537        this: ModelHandle<Self>,
6538        envelope: TypedEnvelope<proto::SearchProject>,
6539        _: Arc<Client>,
6540        mut cx: AsyncAppContext,
6541    ) -> Result<proto::SearchProjectResponse> {
6542        let peer_id = envelope.original_sender_id()?;
6543        let query = SearchQuery::from_proto(envelope.payload)?;
6544        let result = this
6545            .update(&mut cx, |this, cx| this.search(query, cx))
6546            .await?;
6547
6548        this.update(&mut cx, |this, cx| {
6549            let mut locations = Vec::new();
6550            for (buffer, ranges) in result {
6551                for range in ranges {
6552                    let start = serialize_anchor(&range.start);
6553                    let end = serialize_anchor(&range.end);
6554                    let buffer_id = this.create_buffer_for_peer(&buffer, peer_id, cx);
6555                    locations.push(proto::Location {
6556                        buffer_id,
6557                        start: Some(start),
6558                        end: Some(end),
6559                    });
6560                }
6561            }
6562            Ok(proto::SearchProjectResponse { locations })
6563        })
6564    }
6565
6566    async fn handle_open_buffer_for_symbol(
6567        this: ModelHandle<Self>,
6568        envelope: TypedEnvelope<proto::OpenBufferForSymbol>,
6569        _: Arc<Client>,
6570        mut cx: AsyncAppContext,
6571    ) -> Result<proto::OpenBufferForSymbolResponse> {
6572        let peer_id = envelope.original_sender_id()?;
6573        let symbol = envelope
6574            .payload
6575            .symbol
6576            .ok_or_else(|| anyhow!("invalid symbol"))?;
6577        let symbol = this
6578            .read_with(&cx, |this, _| this.deserialize_symbol(symbol))
6579            .await?;
6580        let symbol = this.read_with(&cx, |this, _| {
6581            let signature = this.symbol_signature(&symbol.path);
6582            if signature == symbol.signature {
6583                Ok(symbol)
6584            } else {
6585                Err(anyhow!("invalid symbol signature"))
6586            }
6587        })?;
6588        let buffer = this
6589            .update(&mut cx, |this, cx| this.open_buffer_for_symbol(&symbol, cx))
6590            .await?;
6591
6592        Ok(proto::OpenBufferForSymbolResponse {
6593            buffer_id: this.update(&mut cx, |this, cx| {
6594                this.create_buffer_for_peer(&buffer, peer_id, cx)
6595            }),
6596        })
6597    }
6598
6599    fn symbol_signature(&self, project_path: &ProjectPath) -> [u8; 32] {
6600        let mut hasher = Sha256::new();
6601        hasher.update(project_path.worktree_id.to_proto().to_be_bytes());
6602        hasher.update(project_path.path.to_string_lossy().as_bytes());
6603        hasher.update(self.nonce.to_be_bytes());
6604        hasher.finalize().as_slice().try_into().unwrap()
6605    }
6606
6607    async fn handle_open_buffer_by_id(
6608        this: ModelHandle<Self>,
6609        envelope: TypedEnvelope<proto::OpenBufferById>,
6610        _: Arc<Client>,
6611        mut cx: AsyncAppContext,
6612    ) -> Result<proto::OpenBufferResponse> {
6613        let peer_id = envelope.original_sender_id()?;
6614        let buffer = this
6615            .update(&mut cx, |this, cx| {
6616                this.open_buffer_by_id(envelope.payload.id, cx)
6617            })
6618            .await?;
6619        this.update(&mut cx, |this, cx| {
6620            Ok(proto::OpenBufferResponse {
6621                buffer_id: this.create_buffer_for_peer(&buffer, peer_id, cx),
6622            })
6623        })
6624    }
6625
6626    async fn handle_open_buffer_by_path(
6627        this: ModelHandle<Self>,
6628        envelope: TypedEnvelope<proto::OpenBufferByPath>,
6629        _: Arc<Client>,
6630        mut cx: AsyncAppContext,
6631    ) -> Result<proto::OpenBufferResponse> {
6632        let peer_id = envelope.original_sender_id()?;
6633        let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
6634        let open_buffer = this.update(&mut cx, |this, cx| {
6635            this.open_buffer(
6636                ProjectPath {
6637                    worktree_id,
6638                    path: PathBuf::from(envelope.payload.path).into(),
6639                },
6640                cx,
6641            )
6642        });
6643
6644        let buffer = open_buffer.await?;
6645        this.update(&mut cx, |this, cx| {
6646            Ok(proto::OpenBufferResponse {
6647                buffer_id: this.create_buffer_for_peer(&buffer, peer_id, cx),
6648            })
6649        })
6650    }
6651
6652    fn serialize_project_transaction_for_peer(
6653        &mut self,
6654        project_transaction: ProjectTransaction,
6655        peer_id: proto::PeerId,
6656        cx: &mut AppContext,
6657    ) -> proto::ProjectTransaction {
6658        let mut serialized_transaction = proto::ProjectTransaction {
6659            buffer_ids: Default::default(),
6660            transactions: Default::default(),
6661        };
6662        for (buffer, transaction) in project_transaction.0 {
6663            serialized_transaction
6664                .buffer_ids
6665                .push(self.create_buffer_for_peer(&buffer, peer_id, cx));
6666            serialized_transaction
6667                .transactions
6668                .push(language::proto::serialize_transaction(&transaction));
6669        }
6670        serialized_transaction
6671    }
6672
6673    fn deserialize_project_transaction(
6674        &mut self,
6675        message: proto::ProjectTransaction,
6676        push_to_history: bool,
6677        cx: &mut ModelContext<Self>,
6678    ) -> Task<Result<ProjectTransaction>> {
6679        cx.spawn(|this, mut cx| async move {
6680            let mut project_transaction = ProjectTransaction::default();
6681            for (buffer_id, transaction) in message.buffer_ids.into_iter().zip(message.transactions)
6682            {
6683                let buffer = this
6684                    .update(&mut cx, |this, cx| {
6685                        this.wait_for_remote_buffer(buffer_id, cx)
6686                    })
6687                    .await?;
6688                let transaction = language::proto::deserialize_transaction(transaction)?;
6689                project_transaction.0.insert(buffer, transaction);
6690            }
6691
6692            for (buffer, transaction) in &project_transaction.0 {
6693                buffer
6694                    .update(&mut cx, |buffer, _| {
6695                        buffer.wait_for_edits(transaction.edit_ids.iter().copied())
6696                    })
6697                    .await?;
6698
6699                if push_to_history {
6700                    buffer.update(&mut cx, |buffer, _| {
6701                        buffer.push_transaction(transaction.clone(), Instant::now());
6702                    });
6703                }
6704            }
6705
6706            Ok(project_transaction)
6707        })
6708    }
6709
6710    fn create_buffer_for_peer(
6711        &mut self,
6712        buffer: &ModelHandle<Buffer>,
6713        peer_id: proto::PeerId,
6714        cx: &mut AppContext,
6715    ) -> u64 {
6716        let buffer_id = buffer.read(cx).remote_id();
6717        if let Some(ProjectClientState::Local { updates_tx, .. }) = &self.client_state {
6718            updates_tx
6719                .unbounded_send(LocalProjectUpdate::CreateBufferForPeer { peer_id, buffer_id })
6720                .ok();
6721        }
6722        buffer_id
6723    }
6724
6725    fn wait_for_remote_buffer(
6726        &mut self,
6727        id: u64,
6728        cx: &mut ModelContext<Self>,
6729    ) -> Task<Result<ModelHandle<Buffer>>> {
6730        let mut opened_buffer_rx = self.opened_buffer.1.clone();
6731
6732        cx.spawn_weak(|this, mut cx| async move {
6733            let buffer = loop {
6734                let Some(this) = this.upgrade(&cx) else {
6735                    return Err(anyhow!("project dropped"));
6736                };
6737
6738                let buffer = this.read_with(&cx, |this, cx| {
6739                    this.opened_buffers
6740                        .get(&id)
6741                        .and_then(|buffer| buffer.upgrade(cx))
6742                });
6743
6744                if let Some(buffer) = buffer {
6745                    break buffer;
6746                } else if this.read_with(&cx, |this, _| this.is_read_only()) {
6747                    return Err(anyhow!("disconnected before buffer {} could be opened", id));
6748                }
6749
6750                this.update(&mut cx, |this, _| {
6751                    this.incomplete_remote_buffers.entry(id).or_default();
6752                });
6753                drop(this);
6754
6755                opened_buffer_rx
6756                    .next()
6757                    .await
6758                    .ok_or_else(|| anyhow!("project dropped while waiting for buffer"))?;
6759            };
6760
6761            Ok(buffer)
6762        })
6763    }
6764
6765    fn synchronize_remote_buffers(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
6766        let project_id = match self.client_state.as_ref() {
6767            Some(ProjectClientState::Remote {
6768                sharing_has_stopped,
6769                remote_id,
6770                ..
6771            }) => {
6772                if *sharing_has_stopped {
6773                    return Task::ready(Err(anyhow!(
6774                        "can't synchronize remote buffers on a readonly project"
6775                    )));
6776                } else {
6777                    *remote_id
6778                }
6779            }
6780            Some(ProjectClientState::Local { .. }) | None => {
6781                return Task::ready(Err(anyhow!(
6782                    "can't synchronize remote buffers on a local project"
6783                )))
6784            }
6785        };
6786
6787        let client = self.client.clone();
6788        cx.spawn(|this, cx| async move {
6789            let (buffers, incomplete_buffer_ids) = this.read_with(&cx, |this, cx| {
6790                let buffers = this
6791                    .opened_buffers
6792                    .iter()
6793                    .filter_map(|(id, buffer)| {
6794                        let buffer = buffer.upgrade(cx)?;
6795                        Some(proto::BufferVersion {
6796                            id: *id,
6797                            version: language::proto::serialize_version(&buffer.read(cx).version),
6798                        })
6799                    })
6800                    .collect();
6801                let incomplete_buffer_ids = this
6802                    .incomplete_remote_buffers
6803                    .keys()
6804                    .copied()
6805                    .collect::<Vec<_>>();
6806
6807                (buffers, incomplete_buffer_ids)
6808            });
6809            let response = client
6810                .request(proto::SynchronizeBuffers {
6811                    project_id,
6812                    buffers,
6813                })
6814                .await?;
6815
6816            let send_updates_for_buffers = response.buffers.into_iter().map(|buffer| {
6817                let client = client.clone();
6818                let buffer_id = buffer.id;
6819                let remote_version = language::proto::deserialize_version(&buffer.version);
6820                this.read_with(&cx, |this, cx| {
6821                    if let Some(buffer) = this.buffer_for_id(buffer_id, cx) {
6822                        let operations = buffer.read(cx).serialize_ops(Some(remote_version), cx);
6823                        cx.background().spawn(async move {
6824                            let operations = operations.await;
6825                            for chunk in split_operations(operations) {
6826                                client
6827                                    .request(proto::UpdateBuffer {
6828                                        project_id,
6829                                        buffer_id,
6830                                        operations: chunk,
6831                                    })
6832                                    .await?;
6833                            }
6834                            anyhow::Ok(())
6835                        })
6836                    } else {
6837                        Task::ready(Ok(()))
6838                    }
6839                })
6840            });
6841
6842            // Any incomplete buffers have open requests waiting. Request that the host sends
6843            // creates these buffers for us again to unblock any waiting futures.
6844            for id in incomplete_buffer_ids {
6845                cx.background()
6846                    .spawn(client.request(proto::OpenBufferById { project_id, id }))
6847                    .detach();
6848            }
6849
6850            futures::future::join_all(send_updates_for_buffers)
6851                .await
6852                .into_iter()
6853                .collect()
6854        })
6855    }
6856
6857    pub fn worktree_metadata_protos(&self, cx: &AppContext) -> Vec<proto::WorktreeMetadata> {
6858        self.worktrees(cx)
6859            .map(|worktree| {
6860                let worktree = worktree.read(cx);
6861                proto::WorktreeMetadata {
6862                    id: worktree.id().to_proto(),
6863                    root_name: worktree.root_name().into(),
6864                    visible: worktree.is_visible(),
6865                    abs_path: worktree.abs_path().to_string_lossy().into(),
6866                }
6867            })
6868            .collect()
6869    }
6870
6871    fn set_worktrees_from_proto(
6872        &mut self,
6873        worktrees: Vec<proto::WorktreeMetadata>,
6874        cx: &mut ModelContext<Project>,
6875    ) -> Result<()> {
6876        let replica_id = self.replica_id();
6877        let remote_id = self.remote_id().ok_or_else(|| anyhow!("invalid project"))?;
6878
6879        let mut old_worktrees_by_id = self
6880            .worktrees
6881            .drain(..)
6882            .filter_map(|worktree| {
6883                let worktree = worktree.upgrade(cx)?;
6884                Some((worktree.read(cx).id(), worktree))
6885            })
6886            .collect::<HashMap<_, _>>();
6887
6888        for worktree in worktrees {
6889            if let Some(old_worktree) =
6890                old_worktrees_by_id.remove(&WorktreeId::from_proto(worktree.id))
6891            {
6892                self.worktrees.push(WorktreeHandle::Strong(old_worktree));
6893            } else {
6894                let worktree =
6895                    Worktree::remote(remote_id, replica_id, worktree, self.client.clone(), cx);
6896                let _ = self.add_worktree(&worktree, cx);
6897            }
6898        }
6899
6900        self.metadata_changed(cx);
6901        for id in old_worktrees_by_id.keys() {
6902            cx.emit(Event::WorktreeRemoved(*id));
6903        }
6904
6905        Ok(())
6906    }
6907
6908    fn set_collaborators_from_proto(
6909        &mut self,
6910        messages: Vec<proto::Collaborator>,
6911        cx: &mut ModelContext<Self>,
6912    ) -> Result<()> {
6913        let mut collaborators = HashMap::default();
6914        for message in messages {
6915            let collaborator = Collaborator::from_proto(message)?;
6916            collaborators.insert(collaborator.peer_id, collaborator);
6917        }
6918        for old_peer_id in self.collaborators.keys() {
6919            if !collaborators.contains_key(old_peer_id) {
6920                cx.emit(Event::CollaboratorLeft(*old_peer_id));
6921            }
6922        }
6923        self.collaborators = collaborators;
6924        Ok(())
6925    }
6926
6927    fn deserialize_symbol(
6928        &self,
6929        serialized_symbol: proto::Symbol,
6930    ) -> impl Future<Output = Result<Symbol>> {
6931        let languages = self.languages.clone();
6932        async move {
6933            let source_worktree_id = WorktreeId::from_proto(serialized_symbol.source_worktree_id);
6934            let worktree_id = WorktreeId::from_proto(serialized_symbol.worktree_id);
6935            let start = serialized_symbol
6936                .start
6937                .ok_or_else(|| anyhow!("invalid start"))?;
6938            let end = serialized_symbol
6939                .end
6940                .ok_or_else(|| anyhow!("invalid end"))?;
6941            let kind = unsafe { mem::transmute(serialized_symbol.kind) };
6942            let path = ProjectPath {
6943                worktree_id,
6944                path: PathBuf::from(serialized_symbol.path).into(),
6945            };
6946            let language = languages
6947                .language_for_file(&path.path, None)
6948                .await
6949                .log_err();
6950            Ok(Symbol {
6951                language_server_name: LanguageServerName(
6952                    serialized_symbol.language_server_name.into(),
6953                ),
6954                source_worktree_id,
6955                path,
6956                label: {
6957                    match language {
6958                        Some(language) => {
6959                            language
6960                                .label_for_symbol(&serialized_symbol.name, kind)
6961                                .await
6962                        }
6963                        None => None,
6964                    }
6965                    .unwrap_or_else(|| CodeLabel::plain(serialized_symbol.name.clone(), None))
6966                },
6967
6968                name: serialized_symbol.name,
6969                range: Unclipped(PointUtf16::new(start.row, start.column))
6970                    ..Unclipped(PointUtf16::new(end.row, end.column)),
6971                kind,
6972                signature: serialized_symbol
6973                    .signature
6974                    .try_into()
6975                    .map_err(|_| anyhow!("invalid signature"))?,
6976            })
6977        }
6978    }
6979
6980    async fn handle_buffer_saved(
6981        this: ModelHandle<Self>,
6982        envelope: TypedEnvelope<proto::BufferSaved>,
6983        _: Arc<Client>,
6984        mut cx: AsyncAppContext,
6985    ) -> Result<()> {
6986        let fingerprint = deserialize_fingerprint(&envelope.payload.fingerprint)?;
6987        let version = deserialize_version(&envelope.payload.version);
6988        let mtime = envelope
6989            .payload
6990            .mtime
6991            .ok_or_else(|| anyhow!("missing mtime"))?
6992            .into();
6993
6994        this.update(&mut cx, |this, cx| {
6995            let buffer = this
6996                .opened_buffers
6997                .get(&envelope.payload.buffer_id)
6998                .and_then(|buffer| buffer.upgrade(cx))
6999                .or_else(|| {
7000                    this.incomplete_remote_buffers
7001                        .get(&envelope.payload.buffer_id)
7002                        .and_then(|b| b.clone())
7003                });
7004            if let Some(buffer) = buffer {
7005                buffer.update(cx, |buffer, cx| {
7006                    buffer.did_save(version, fingerprint, mtime, cx);
7007                });
7008            }
7009            Ok(())
7010        })
7011    }
7012
7013    async fn handle_buffer_reloaded(
7014        this: ModelHandle<Self>,
7015        envelope: TypedEnvelope<proto::BufferReloaded>,
7016        _: Arc<Client>,
7017        mut cx: AsyncAppContext,
7018    ) -> Result<()> {
7019        let payload = envelope.payload;
7020        let version = deserialize_version(&payload.version);
7021        let fingerprint = deserialize_fingerprint(&payload.fingerprint)?;
7022        let line_ending = deserialize_line_ending(
7023            proto::LineEnding::from_i32(payload.line_ending)
7024                .ok_or_else(|| anyhow!("missing line ending"))?,
7025        );
7026        let mtime = payload
7027            .mtime
7028            .ok_or_else(|| anyhow!("missing mtime"))?
7029            .into();
7030        this.update(&mut cx, |this, cx| {
7031            let buffer = this
7032                .opened_buffers
7033                .get(&payload.buffer_id)
7034                .and_then(|buffer| buffer.upgrade(cx))
7035                .or_else(|| {
7036                    this.incomplete_remote_buffers
7037                        .get(&payload.buffer_id)
7038                        .cloned()
7039                        .flatten()
7040                });
7041            if let Some(buffer) = buffer {
7042                buffer.update(cx, |buffer, cx| {
7043                    buffer.did_reload(version, fingerprint, line_ending, mtime, cx);
7044                });
7045            }
7046            Ok(())
7047        })
7048    }
7049
7050    #[allow(clippy::type_complexity)]
7051    fn edits_from_lsp(
7052        &mut self,
7053        buffer: &ModelHandle<Buffer>,
7054        lsp_edits: impl 'static + Send + IntoIterator<Item = lsp::TextEdit>,
7055        server_id: LanguageServerId,
7056        version: Option<i32>,
7057        cx: &mut ModelContext<Self>,
7058    ) -> Task<Result<Vec<(Range<Anchor>, String)>>> {
7059        let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx);
7060        cx.background().spawn(async move {
7061            let snapshot = snapshot?;
7062            let mut lsp_edits = lsp_edits
7063                .into_iter()
7064                .map(|edit| (range_from_lsp(edit.range), edit.new_text))
7065                .collect::<Vec<_>>();
7066            lsp_edits.sort_by_key(|(range, _)| range.start);
7067
7068            let mut lsp_edits = lsp_edits.into_iter().peekable();
7069            let mut edits = Vec::new();
7070            while let Some((range, mut new_text)) = lsp_edits.next() {
7071                // Clip invalid ranges provided by the language server.
7072                let mut range = snapshot.clip_point_utf16(range.start, Bias::Left)
7073                    ..snapshot.clip_point_utf16(range.end, Bias::Left);
7074
7075                // Combine any LSP edits that are adjacent.
7076                //
7077                // Also, combine LSP edits that are separated from each other by only
7078                // a newline. This is important because for some code actions,
7079                // Rust-analyzer rewrites the entire buffer via a series of edits that
7080                // are separated by unchanged newline characters.
7081                //
7082                // In order for the diffing logic below to work properly, any edits that
7083                // cancel each other out must be combined into one.
7084                while let Some((next_range, next_text)) = lsp_edits.peek() {
7085                    if next_range.start.0 > range.end {
7086                        if next_range.start.0.row > range.end.row + 1
7087                            || next_range.start.0.column > 0
7088                            || snapshot.clip_point_utf16(
7089                                Unclipped(PointUtf16::new(range.end.row, u32::MAX)),
7090                                Bias::Left,
7091                            ) > range.end
7092                        {
7093                            break;
7094                        }
7095                        new_text.push('\n');
7096                    }
7097                    range.end = snapshot.clip_point_utf16(next_range.end, Bias::Left);
7098                    new_text.push_str(next_text);
7099                    lsp_edits.next();
7100                }
7101
7102                // For multiline edits, perform a diff of the old and new text so that
7103                // we can identify the changes more precisely, preserving the locations
7104                // of any anchors positioned in the unchanged regions.
7105                if range.end.row > range.start.row {
7106                    let mut offset = range.start.to_offset(&snapshot);
7107                    let old_text = snapshot.text_for_range(range).collect::<String>();
7108
7109                    let diff = TextDiff::from_lines(old_text.as_str(), &new_text);
7110                    let mut moved_since_edit = true;
7111                    for change in diff.iter_all_changes() {
7112                        let tag = change.tag();
7113                        let value = change.value();
7114                        match tag {
7115                            ChangeTag::Equal => {
7116                                offset += value.len();
7117                                moved_since_edit = true;
7118                            }
7119                            ChangeTag::Delete => {
7120                                let start = snapshot.anchor_after(offset);
7121                                let end = snapshot.anchor_before(offset + value.len());
7122                                if moved_since_edit {
7123                                    edits.push((start..end, String::new()));
7124                                } else {
7125                                    edits.last_mut().unwrap().0.end = end;
7126                                }
7127                                offset += value.len();
7128                                moved_since_edit = false;
7129                            }
7130                            ChangeTag::Insert => {
7131                                if moved_since_edit {
7132                                    let anchor = snapshot.anchor_after(offset);
7133                                    edits.push((anchor..anchor, value.to_string()));
7134                                } else {
7135                                    edits.last_mut().unwrap().1.push_str(value);
7136                                }
7137                                moved_since_edit = false;
7138                            }
7139                        }
7140                    }
7141                } else if range.end == range.start {
7142                    let anchor = snapshot.anchor_after(range.start);
7143                    edits.push((anchor..anchor, new_text));
7144                } else {
7145                    let edit_start = snapshot.anchor_after(range.start);
7146                    let edit_end = snapshot.anchor_before(range.end);
7147                    edits.push((edit_start..edit_end, new_text));
7148                }
7149            }
7150
7151            Ok(edits)
7152        })
7153    }
7154
7155    fn buffer_snapshot_for_lsp_version(
7156        &mut self,
7157        buffer: &ModelHandle<Buffer>,
7158        server_id: LanguageServerId,
7159        version: Option<i32>,
7160        cx: &AppContext,
7161    ) -> Result<TextBufferSnapshot> {
7162        const OLD_VERSIONS_TO_RETAIN: i32 = 10;
7163
7164        if let Some(version) = version {
7165            let buffer_id = buffer.read(cx).remote_id();
7166            let snapshots = self
7167                .buffer_snapshots
7168                .get_mut(&buffer_id)
7169                .and_then(|m| m.get_mut(&server_id))
7170                .ok_or_else(|| {
7171                    anyhow!("no snapshots found for buffer {buffer_id} and server {server_id}")
7172                })?;
7173
7174            let found_snapshot = snapshots
7175                .binary_search_by_key(&version, |e| e.version)
7176                .map(|ix| snapshots[ix].snapshot.clone())
7177                .map_err(|_| {
7178                    anyhow!("snapshot not found for buffer {buffer_id} server {server_id} at version {version}")
7179                })?;
7180
7181            snapshots.retain(|snapshot| snapshot.version + OLD_VERSIONS_TO_RETAIN >= version);
7182            Ok(found_snapshot)
7183        } else {
7184            Ok((buffer.read(cx)).text_snapshot())
7185        }
7186    }
7187
7188    pub fn language_servers(
7189        &self,
7190    ) -> impl '_ + Iterator<Item = (LanguageServerId, LanguageServerName, WorktreeId)> {
7191        self.language_server_ids
7192            .iter()
7193            .map(|((worktree_id, server_name), server_id)| {
7194                (*server_id, server_name.clone(), *worktree_id)
7195            })
7196    }
7197
7198    pub fn language_server_for_id(&self, id: LanguageServerId) -> Option<Arc<LanguageServer>> {
7199        if let LanguageServerState::Running { server, .. } = self.language_servers.get(&id)? {
7200            Some(server.clone())
7201        } else {
7202            None
7203        }
7204    }
7205
7206    pub fn language_servers_for_buffer(
7207        &self,
7208        buffer: &Buffer,
7209        cx: &AppContext,
7210    ) -> impl Iterator<Item = (&Arc<CachedLspAdapter>, &Arc<LanguageServer>)> {
7211        self.language_server_ids_for_buffer(buffer, cx)
7212            .into_iter()
7213            .filter_map(|server_id| {
7214                let server = self.language_servers.get(&server_id)?;
7215                if let LanguageServerState::Running {
7216                    adapter, server, ..
7217                } = server
7218                {
7219                    Some((adapter, server))
7220                } else {
7221                    None
7222                }
7223            })
7224    }
7225
7226    fn primary_language_servers_for_buffer(
7227        &self,
7228        buffer: &Buffer,
7229        cx: &AppContext,
7230    ) -> Option<(&Arc<CachedLspAdapter>, &Arc<LanguageServer>)> {
7231        self.language_servers_for_buffer(buffer, cx).next()
7232    }
7233
7234    fn language_server_for_buffer(
7235        &self,
7236        buffer: &Buffer,
7237        server_id: LanguageServerId,
7238        cx: &AppContext,
7239    ) -> Option<(&Arc<CachedLspAdapter>, &Arc<LanguageServer>)> {
7240        self.language_servers_for_buffer(buffer, cx)
7241            .find(|(_, s)| s.server_id() == server_id)
7242    }
7243
7244    fn language_server_ids_for_buffer(
7245        &self,
7246        buffer: &Buffer,
7247        cx: &AppContext,
7248    ) -> Vec<LanguageServerId> {
7249        if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) {
7250            let worktree_id = file.worktree_id(cx);
7251            language
7252                .lsp_adapters()
7253                .iter()
7254                .flat_map(|adapter| {
7255                    let key = (worktree_id, adapter.name.clone());
7256                    self.language_server_ids.get(&key).copied()
7257                })
7258                .collect()
7259        } else {
7260            Vec::new()
7261        }
7262    }
7263}
7264
7265impl WorktreeHandle {
7266    pub fn upgrade(&self, cx: &AppContext) -> Option<ModelHandle<Worktree>> {
7267        match self {
7268            WorktreeHandle::Strong(handle) => Some(handle.clone()),
7269            WorktreeHandle::Weak(handle) => handle.upgrade(cx),
7270        }
7271    }
7272
7273    pub fn handle_id(&self) -> usize {
7274        match self {
7275            WorktreeHandle::Strong(handle) => handle.id(),
7276            WorktreeHandle::Weak(handle) => handle.id(),
7277        }
7278    }
7279}
7280
7281impl OpenBuffer {
7282    pub fn upgrade(&self, cx: &impl BorrowAppContext) -> Option<ModelHandle<Buffer>> {
7283        match self {
7284            OpenBuffer::Strong(handle) => Some(handle.clone()),
7285            OpenBuffer::Weak(handle) => handle.upgrade(cx),
7286            OpenBuffer::Operations(_) => None,
7287        }
7288    }
7289}
7290
7291pub struct PathMatchCandidateSet {
7292    pub snapshot: Snapshot,
7293    pub include_ignored: bool,
7294    pub include_root_name: bool,
7295}
7296
7297impl<'a> fuzzy::PathMatchCandidateSet<'a> for PathMatchCandidateSet {
7298    type Candidates = PathMatchCandidateSetIter<'a>;
7299
7300    fn id(&self) -> usize {
7301        self.snapshot.id().to_usize()
7302    }
7303
7304    fn len(&self) -> usize {
7305        if self.include_ignored {
7306            self.snapshot.file_count()
7307        } else {
7308            self.snapshot.visible_file_count()
7309        }
7310    }
7311
7312    fn prefix(&self) -> Arc<str> {
7313        if self.snapshot.root_entry().map_or(false, |e| e.is_file()) {
7314            self.snapshot.root_name().into()
7315        } else if self.include_root_name {
7316            format!("{}/", self.snapshot.root_name()).into()
7317        } else {
7318            "".into()
7319        }
7320    }
7321
7322    fn candidates(&'a self, start: usize) -> Self::Candidates {
7323        PathMatchCandidateSetIter {
7324            traversal: self.snapshot.files(self.include_ignored, start),
7325        }
7326    }
7327}
7328
7329pub struct PathMatchCandidateSetIter<'a> {
7330    traversal: Traversal<'a>,
7331}
7332
7333impl<'a> Iterator for PathMatchCandidateSetIter<'a> {
7334    type Item = fuzzy::PathMatchCandidate<'a>;
7335
7336    fn next(&mut self) -> Option<Self::Item> {
7337        self.traversal.next().map(|entry| {
7338            if let EntryKind::File(char_bag) = entry.kind {
7339                fuzzy::PathMatchCandidate {
7340                    path: &entry.path,
7341                    char_bag,
7342                }
7343            } else {
7344                unreachable!()
7345            }
7346        })
7347    }
7348}
7349
7350impl Entity for Project {
7351    type Event = Event;
7352
7353    fn release(&mut self, cx: &mut gpui::AppContext) {
7354        match &self.client_state {
7355            Some(ProjectClientState::Local { .. }) => {
7356                let _ = self.unshare_internal(cx);
7357            }
7358            Some(ProjectClientState::Remote { remote_id, .. }) => {
7359                let _ = self.client.send(proto::LeaveProject {
7360                    project_id: *remote_id,
7361                });
7362                self.disconnected_from_host_internal(cx);
7363            }
7364            _ => {}
7365        }
7366    }
7367
7368    fn app_will_quit(
7369        &mut self,
7370        _: &mut AppContext,
7371    ) -> Option<std::pin::Pin<Box<dyn 'static + Future<Output = ()>>>> {
7372        let shutdown_futures = self
7373            .language_servers
7374            .drain()
7375            .map(|(_, server_state)| async {
7376                use LanguageServerState::*;
7377                match server_state {
7378                    Running { server, .. } => server.shutdown()?.await,
7379                    Starting(task) | Validating(task) => task.await?.shutdown()?.await,
7380                }
7381            })
7382            .collect::<Vec<_>>();
7383
7384        Some(
7385            async move {
7386                futures::future::join_all(shutdown_futures).await;
7387            }
7388            .boxed(),
7389        )
7390    }
7391}
7392
7393impl Collaborator {
7394    fn from_proto(message: proto::Collaborator) -> Result<Self> {
7395        Ok(Self {
7396            peer_id: message.peer_id.ok_or_else(|| anyhow!("invalid peer id"))?,
7397            replica_id: message.replica_id as ReplicaId,
7398        })
7399    }
7400}
7401
7402impl<P: AsRef<Path>> From<(WorktreeId, P)> for ProjectPath {
7403    fn from((worktree_id, path): (WorktreeId, P)) -> Self {
7404        Self {
7405            worktree_id,
7406            path: path.as_ref().into(),
7407        }
7408    }
7409}
7410
7411fn split_operations(
7412    mut operations: Vec<proto::Operation>,
7413) -> impl Iterator<Item = Vec<proto::Operation>> {
7414    #[cfg(any(test, feature = "test-support"))]
7415    const CHUNK_SIZE: usize = 5;
7416
7417    #[cfg(not(any(test, feature = "test-support")))]
7418    const CHUNK_SIZE: usize = 100;
7419
7420    let mut done = false;
7421    std::iter::from_fn(move || {
7422        if done {
7423            return None;
7424        }
7425
7426        let operations = operations
7427            .drain(..cmp::min(CHUNK_SIZE, operations.len()))
7428            .collect::<Vec<_>>();
7429        if operations.is_empty() {
7430            done = true;
7431        }
7432        Some(operations)
7433    })
7434}
7435
7436fn serialize_symbol(symbol: &Symbol) -> proto::Symbol {
7437    proto::Symbol {
7438        language_server_name: symbol.language_server_name.0.to_string(),
7439        source_worktree_id: symbol.source_worktree_id.to_proto(),
7440        worktree_id: symbol.path.worktree_id.to_proto(),
7441        path: symbol.path.path.to_string_lossy().to_string(),
7442        name: symbol.name.clone(),
7443        kind: unsafe { mem::transmute(symbol.kind) },
7444        start: Some(proto::PointUtf16 {
7445            row: symbol.range.start.0.row,
7446            column: symbol.range.start.0.column,
7447        }),
7448        end: Some(proto::PointUtf16 {
7449            row: symbol.range.end.0.row,
7450            column: symbol.range.end.0.column,
7451        }),
7452        signature: symbol.signature.to_vec(),
7453    }
7454}
7455
7456fn relativize_path(base: &Path, path: &Path) -> PathBuf {
7457    let mut path_components = path.components();
7458    let mut base_components = base.components();
7459    let mut components: Vec<Component> = Vec::new();
7460    loop {
7461        match (path_components.next(), base_components.next()) {
7462            (None, None) => break,
7463            (Some(a), None) => {
7464                components.push(a);
7465                components.extend(path_components.by_ref());
7466                break;
7467            }
7468            (None, _) => components.push(Component::ParentDir),
7469            (Some(a), Some(b)) if components.is_empty() && a == b => (),
7470            (Some(a), Some(b)) if b == Component::CurDir => components.push(a),
7471            (Some(a), Some(_)) => {
7472                components.push(Component::ParentDir);
7473                for _ in base_components {
7474                    components.push(Component::ParentDir);
7475                }
7476                components.push(a);
7477                components.extend(path_components.by_ref());
7478                break;
7479            }
7480        }
7481    }
7482    components.iter().map(|c| c.as_os_str()).collect()
7483}
7484
7485impl Item for Buffer {
7486    fn entry_id(&self, cx: &AppContext) -> Option<ProjectEntryId> {
7487        File::from_dyn(self.file()).and_then(|file| file.project_entry_id(cx))
7488    }
7489
7490    fn project_path(&self, cx: &AppContext) -> Option<ProjectPath> {
7491        File::from_dyn(self.file()).map(|file| ProjectPath {
7492            worktree_id: file.worktree_id(cx),
7493            path: file.path().clone(),
7494        })
7495    }
7496}
7497
7498async fn wait_for_loading_buffer(
7499    mut receiver: postage::watch::Receiver<Option<Result<ModelHandle<Buffer>, Arc<anyhow::Error>>>>,
7500) -> Result<ModelHandle<Buffer>, Arc<anyhow::Error>> {
7501    loop {
7502        if let Some(result) = receiver.borrow().as_ref() {
7503            match result {
7504                Ok(buffer) => return Ok(buffer.to_owned()),
7505                Err(e) => return Err(e.to_owned()),
7506            }
7507        }
7508        receiver.next().await;
7509    }
7510}