project.rs

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