project.rs

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