project.rs

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