project.rs

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