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