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