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