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