project.rs

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