project.rs

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