project.rs

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