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