project.rs

   1mod ignore;
   2mod lsp_command;
   3pub mod search;
   4pub mod terminals;
   5pub mod worktree;
   6
   7#[cfg(test)]
   8mod project_tests;
   9
  10use anyhow::{anyhow, Context, Result};
  11use client::{proto, Client, TypedEnvelope, UserStore};
  12use clock::ReplicaId;
  13use collections::{hash_map, BTreeMap, HashMap, HashSet};
  14use futures::{
  15    channel::{mpsc, oneshot},
  16    future::{try_join_all, Shared},
  17    AsyncWriteExt, Future, FutureExt, StreamExt, TryFutureExt,
  18};
  19use gpui::{
  20    AnyModelHandle, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
  21    MutableAppContext, Task, UpgradeModelHandle, WeakModelHandle,
  22};
  23use language::{
  24    point_to_lsp,
  25    proto::{
  26        deserialize_anchor, deserialize_fingerprint, deserialize_line_ending, deserialize_version,
  27        serialize_anchor, serialize_version,
  28    },
  29    range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CachedLspAdapter, CharKind, CodeAction,
  30    CodeLabel, Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Diff, Event as BufferEvent,
  31    File as _, Language, LanguageRegistry, LanguageServerName, LocalFile, OffsetRangeExt,
  32    Operation, Patch, PointUtf16, RopeFingerprint, TextBufferSnapshot, ToOffset, ToPointUtf16,
  33    Transaction, Unclipped,
  34};
  35use lsp::{
  36    DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, LanguageServer, LanguageString,
  37    MarkedString,
  38};
  39use lsp_command::*;
  40use parking_lot::Mutex;
  41use postage::watch;
  42use rand::prelude::*;
  43use search::SearchQuery;
  44use serde::Serialize;
  45use settings::{FormatOnSave, Formatter, Settings};
  46use sha2::{Digest, Sha256};
  47use similar::{ChangeTag, TextDiff};
  48use std::{
  49    cell::RefCell,
  50    cmp::{self, Ordering},
  51    convert::TryInto,
  52    hash::Hash,
  53    mem,
  54    num::NonZeroU32,
  55    ops::Range,
  56    path::{Component, Path, PathBuf},
  57    rc::Rc,
  58    str,
  59    sync::{
  60        atomic::{AtomicUsize, Ordering::SeqCst},
  61        Arc,
  62    },
  63    time::{Duration, Instant, SystemTime},
  64};
  65use terminals::Terminals;
  66
  67use util::{debug_panic, defer, merge_json_value_into, post_inc, ResultExt, TryFutureExt as _};
  68
  69pub use fs::*;
  70pub use worktree::*;
  71
  72pub trait Item {
  73    fn entry_id(&self, cx: &AppContext) -> Option<ProjectEntryId>;
  74    fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>;
  75}
  76
  77// Language server state is stored across 3 collections:
  78//     language_servers =>
  79//         a mapping from unique server id to LanguageServerState which can either be a task for a
  80//         server in the process of starting, or a running server with adapter and language server arcs
  81//     language_server_ids => a mapping from worktreeId and server name to the unique server id
  82//     language_server_statuses => a mapping from unique server id to the current server status
  83//
  84// Multiple worktrees can map to the same language server for example when you jump to the definition
  85// of a file in the standard library. So language_server_ids is used to look up which server is active
  86// for a given worktree and language server name
  87//
  88// When starting a language server, first the id map is checked to make sure a server isn't already available
  89// for that worktree. If there is one, it finishes early. Otherwise, a new id is allocated and and
  90// the Starting variant of LanguageServerState is stored in the language_servers map.
  91pub struct Project {
  92    worktrees: Vec<WorktreeHandle>,
  93    active_entry: Option<ProjectEntryId>,
  94    languages: Arc<LanguageRegistry>,
  95    language_servers: HashMap<usize, LanguageServerState>,
  96    language_server_ids: HashMap<(WorktreeId, LanguageServerName), usize>,
  97    language_server_statuses: BTreeMap<usize, LanguageServerStatus>,
  98    language_server_settings: Arc<Mutex<serde_json::Value>>,
  99    last_workspace_edits_by_language_server: HashMap<usize, ProjectTransaction>,
 100    next_language_server_id: usize,
 101    client: Arc<client::Client>,
 102    next_entry_id: Arc<AtomicUsize>,
 103    next_diagnostic_group_id: usize,
 104    user_store: ModelHandle<UserStore>,
 105    fs: Arc<dyn Fs>,
 106    client_state: Option<ProjectClientState>,
 107    collaborators: HashMap<proto::PeerId, Collaborator>,
 108    client_subscriptions: Vec<client::Subscription>,
 109    _subscriptions: Vec<gpui::Subscription>,
 110    opened_buffer: (watch::Sender<()>, watch::Receiver<()>),
 111    shared_buffers: HashMap<proto::PeerId, HashSet<u64>>,
 112    #[allow(clippy::type_complexity)]
 113    loading_buffers_by_path: HashMap<
 114        ProjectPath,
 115        postage::watch::Receiver<Option<Result<ModelHandle<Buffer>, Arc<anyhow::Error>>>>,
 116    >,
 117    #[allow(clippy::type_complexity)]
 118    loading_local_worktrees:
 119        HashMap<Arc<Path>, Shared<Task<Result<ModelHandle<Worktree>, Arc<anyhow::Error>>>>>,
 120    opened_buffers: HashMap<u64, OpenBuffer>,
 121    /// A mapping from a buffer ID to None means that we've started waiting for an ID but haven't finished loading it.
 122    /// Used for re-issuing buffer requests when peers temporarily disconnect
 123    incomplete_remote_buffers: HashMap<u64, Option<ModelHandle<Buffer>>>,
 124    buffer_snapshots: HashMap<u64, Vec<(i32, TextBufferSnapshot)>>,
 125    buffers_being_formatted: HashSet<usize>,
 126    nonce: u128,
 127    _maintain_buffer_languages: Task<()>,
 128    _maintain_workspace_config: Task<()>,
 129    terminals: Terminals,
 130}
 131
 132enum OpenBuffer {
 133    Strong(ModelHandle<Buffer>),
 134    Weak(WeakModelHandle<Buffer>),
 135    Operations(Vec<Operation>),
 136}
 137
 138enum WorktreeHandle {
 139    Strong(ModelHandle<Worktree>),
 140    Weak(WeakModelHandle<Worktree>),
 141}
 142
 143enum ProjectClientState {
 144    Local {
 145        remote_id: u64,
 146        metadata_changed: mpsc::UnboundedSender<oneshot::Sender<()>>,
 147        _maintain_metadata: Task<()>,
 148    },
 149    Remote {
 150        sharing_has_stopped: bool,
 151        remote_id: u64,
 152        replica_id: ReplicaId,
 153    },
 154}
 155
 156#[derive(Clone, Debug)]
 157pub struct Collaborator {
 158    pub peer_id: proto::PeerId,
 159    pub replica_id: ReplicaId,
 160}
 161
 162#[derive(Clone, Debug, PartialEq, Eq)]
 163pub enum Event {
 164    ActiveEntryChanged(Option<ProjectEntryId>),
 165    WorktreeAdded,
 166    WorktreeRemoved(WorktreeId),
 167    DiskBasedDiagnosticsStarted {
 168        language_server_id: usize,
 169    },
 170    DiskBasedDiagnosticsFinished {
 171        language_server_id: usize,
 172    },
 173    DiagnosticsUpdated {
 174        path: ProjectPath,
 175        language_server_id: usize,
 176    },
 177    RemoteIdChanged(Option<u64>),
 178    DisconnectedFromHost,
 179    Closed,
 180    CollaboratorUpdated {
 181        old_peer_id: proto::PeerId,
 182        new_peer_id: proto::PeerId,
 183    },
 184    CollaboratorLeft(proto::PeerId),
 185}
 186
 187pub enum LanguageServerState {
 188    Starting(Task<Option<Arc<LanguageServer>>>),
 189    Running {
 190        language: Arc<Language>,
 191        adapter: Arc<CachedLspAdapter>,
 192        server: Arc<LanguageServer>,
 193        simulate_disk_based_diagnostics_completion: Option<Task<()>>,
 194    },
 195}
 196
 197#[derive(Serialize)]
 198pub struct LanguageServerStatus {
 199    pub name: String,
 200    pub pending_work: BTreeMap<String, LanguageServerProgress>,
 201    pub has_pending_diagnostic_updates: bool,
 202    progress_tokens: HashSet<String>,
 203}
 204
 205#[derive(Clone, Debug, Serialize)]
 206pub struct LanguageServerProgress {
 207    pub message: Option<String>,
 208    pub percentage: Option<usize>,
 209    #[serde(skip_serializing)]
 210    pub last_update_at: Instant,
 211}
 212
 213#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
 214pub struct ProjectPath {
 215    pub worktree_id: WorktreeId,
 216    pub path: Arc<Path>,
 217}
 218
 219#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize)]
 220pub struct DiagnosticSummary {
 221    pub language_server_id: usize,
 222    pub error_count: usize,
 223    pub warning_count: usize,
 224}
 225
 226#[derive(Debug, Clone)]
 227pub struct Location {
 228    pub buffer: ModelHandle<Buffer>,
 229    pub range: Range<language::Anchor>,
 230}
 231
 232#[derive(Debug, Clone)]
 233pub struct LocationLink {
 234    pub origin: Option<Location>,
 235    pub target: Location,
 236}
 237
 238#[derive(Debug)]
 239pub struct DocumentHighlight {
 240    pub range: Range<language::Anchor>,
 241    pub kind: DocumentHighlightKind,
 242}
 243
 244#[derive(Clone, Debug)]
 245pub struct Symbol {
 246    pub language_server_name: LanguageServerName,
 247    pub source_worktree_id: WorktreeId,
 248    pub path: ProjectPath,
 249    pub label: CodeLabel,
 250    pub name: String,
 251    pub kind: lsp::SymbolKind,
 252    pub range: Range<Unclipped<PointUtf16>>,
 253    pub signature: [u8; 32],
 254}
 255
 256#[derive(Clone, Debug, PartialEq)]
 257pub struct HoverBlock {
 258    pub text: String,
 259    pub language: Option<String>,
 260}
 261
 262impl HoverBlock {
 263    fn try_new(marked_string: MarkedString) -> Option<Self> {
 264        let result = match marked_string {
 265            MarkedString::LanguageString(LanguageString { language, value }) => HoverBlock {
 266                text: value,
 267                language: Some(language),
 268            },
 269            MarkedString::String(text) => HoverBlock {
 270                text,
 271                language: None,
 272            },
 273        };
 274        if result.text.is_empty() {
 275            None
 276        } else {
 277            Some(result)
 278        }
 279    }
 280}
 281
 282#[derive(Debug)]
 283pub struct Hover {
 284    pub contents: Vec<HoverBlock>,
 285    pub range: Option<Range<language::Anchor>>,
 286}
 287
 288#[derive(Default)]
 289pub struct ProjectTransaction(pub HashMap<ModelHandle<Buffer>, language::Transaction>);
 290
 291impl DiagnosticSummary {
 292    fn new<'a, T: 'a>(
 293        language_server_id: usize,
 294        diagnostics: impl IntoIterator<Item = &'a DiagnosticEntry<T>>,
 295    ) -> Self {
 296        let mut this = Self {
 297            language_server_id,
 298            error_count: 0,
 299            warning_count: 0,
 300        };
 301
 302        for entry in diagnostics {
 303            if entry.diagnostic.is_primary {
 304                match entry.diagnostic.severity {
 305                    DiagnosticSeverity::ERROR => this.error_count += 1,
 306                    DiagnosticSeverity::WARNING => this.warning_count += 1,
 307                    _ => {}
 308                }
 309            }
 310        }
 311
 312        this
 313    }
 314
 315    pub fn is_empty(&self) -> bool {
 316        self.error_count == 0 && self.warning_count == 0
 317    }
 318
 319    pub fn to_proto(&self, path: &Path) -> proto::DiagnosticSummary {
 320        proto::DiagnosticSummary {
 321            path: path.to_string_lossy().to_string(),
 322            language_server_id: self.language_server_id as u64,
 323            error_count: self.error_count as u32,
 324            warning_count: self.warning_count as u32,
 325        }
 326    }
 327}
 328
 329#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
 330pub struct ProjectEntryId(usize);
 331
 332impl ProjectEntryId {
 333    pub const MAX: Self = Self(usize::MAX);
 334
 335    pub fn new(counter: &AtomicUsize) -> Self {
 336        Self(counter.fetch_add(1, SeqCst))
 337    }
 338
 339    pub fn from_proto(id: u64) -> Self {
 340        Self(id as usize)
 341    }
 342
 343    pub fn to_proto(&self) -> u64 {
 344        self.0 as u64
 345    }
 346
 347    pub fn to_usize(&self) -> usize {
 348        self.0
 349    }
 350}
 351
 352#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 353pub enum FormatTrigger {
 354    Save,
 355    Manual,
 356}
 357
 358impl FormatTrigger {
 359    fn from_proto(value: i32) -> FormatTrigger {
 360        match value {
 361            0 => FormatTrigger::Save,
 362            1 => FormatTrigger::Manual,
 363            _ => FormatTrigger::Save,
 364        }
 365    }
 366}
 367
 368impl Project {
 369    pub fn init(client: &Arc<Client>) {
 370        client.add_model_message_handler(Self::handle_add_collaborator);
 371        client.add_model_message_handler(Self::handle_update_project_collaborator);
 372        client.add_model_message_handler(Self::handle_remove_collaborator);
 373        client.add_model_message_handler(Self::handle_buffer_reloaded);
 374        client.add_model_message_handler(Self::handle_buffer_saved);
 375        client.add_model_message_handler(Self::handle_start_language_server);
 376        client.add_model_message_handler(Self::handle_update_language_server);
 377        client.add_model_message_handler(Self::handle_update_project);
 378        client.add_model_message_handler(Self::handle_unshare_project);
 379        client.add_model_message_handler(Self::handle_create_buffer_for_peer);
 380        client.add_model_message_handler(Self::handle_update_buffer_file);
 381        client.add_model_message_handler(Self::handle_update_buffer);
 382        client.add_model_message_handler(Self::handle_update_diagnostic_summary);
 383        client.add_model_message_handler(Self::handle_update_worktree);
 384        client.add_model_request_handler(Self::handle_create_project_entry);
 385        client.add_model_request_handler(Self::handle_rename_project_entry);
 386        client.add_model_request_handler(Self::handle_copy_project_entry);
 387        client.add_model_request_handler(Self::handle_delete_project_entry);
 388        client.add_model_request_handler(Self::handle_apply_additional_edits_for_completion);
 389        client.add_model_request_handler(Self::handle_apply_code_action);
 390        client.add_model_request_handler(Self::handle_reload_buffers);
 391        client.add_model_request_handler(Self::handle_synchronize_buffers);
 392        client.add_model_request_handler(Self::handle_format_buffers);
 393        client.add_model_request_handler(Self::handle_get_code_actions);
 394        client.add_model_request_handler(Self::handle_get_completions);
 395        client.add_model_request_handler(Self::handle_lsp_command::<GetHover>);
 396        client.add_model_request_handler(Self::handle_lsp_command::<GetDefinition>);
 397        client.add_model_request_handler(Self::handle_lsp_command::<GetTypeDefinition>);
 398        client.add_model_request_handler(Self::handle_lsp_command::<GetDocumentHighlights>);
 399        client.add_model_request_handler(Self::handle_lsp_command::<GetReferences>);
 400        client.add_model_request_handler(Self::handle_lsp_command::<PrepareRename>);
 401        client.add_model_request_handler(Self::handle_lsp_command::<PerformRename>);
 402        client.add_model_request_handler(Self::handle_search_project);
 403        client.add_model_request_handler(Self::handle_get_project_symbols);
 404        client.add_model_request_handler(Self::handle_open_buffer_for_symbol);
 405        client.add_model_request_handler(Self::handle_open_buffer_by_id);
 406        client.add_model_request_handler(Self::handle_open_buffer_by_path);
 407        client.add_model_request_handler(Self::handle_save_buffer);
 408        client.add_model_message_handler(Self::handle_update_diff_base);
 409    }
 410
 411    pub fn local(
 412        client: Arc<Client>,
 413        user_store: ModelHandle<UserStore>,
 414        languages: Arc<LanguageRegistry>,
 415        fs: Arc<dyn Fs>,
 416        cx: &mut MutableAppContext,
 417    ) -> ModelHandle<Self> {
 418        cx.add_model(|cx: &mut ModelContext<Self>| Self {
 419            worktrees: Default::default(),
 420            collaborators: Default::default(),
 421            opened_buffers: Default::default(),
 422            shared_buffers: Default::default(),
 423            incomplete_remote_buffers: Default::default(),
 424            loading_buffers_by_path: Default::default(),
 425            loading_local_worktrees: Default::default(),
 426            buffer_snapshots: Default::default(),
 427            client_state: None,
 428            opened_buffer: watch::channel(),
 429            client_subscriptions: Vec::new(),
 430            _subscriptions: vec![cx.observe_global::<Settings, _>(Self::on_settings_changed)],
 431            _maintain_buffer_languages: Self::maintain_buffer_languages(&languages, cx),
 432            _maintain_workspace_config: Self::maintain_workspace_config(languages.clone(), cx),
 433            active_entry: None,
 434            languages,
 435            client,
 436            user_store,
 437            fs,
 438            next_entry_id: Default::default(),
 439            next_diagnostic_group_id: Default::default(),
 440            language_servers: Default::default(),
 441            language_server_ids: Default::default(),
 442            language_server_statuses: Default::default(),
 443            last_workspace_edits_by_language_server: Default::default(),
 444            language_server_settings: Default::default(),
 445            buffers_being_formatted: Default::default(),
 446            next_language_server_id: 0,
 447            nonce: StdRng::from_entropy().gen(),
 448            terminals: Terminals {
 449                local_handles: Vec::new(),
 450            },
 451        })
 452    }
 453
 454    pub async fn remote(
 455        remote_id: u64,
 456        client: Arc<Client>,
 457        user_store: ModelHandle<UserStore>,
 458        languages: Arc<LanguageRegistry>,
 459        fs: Arc<dyn Fs>,
 460        mut cx: AsyncAppContext,
 461    ) -> Result<ModelHandle<Self>> {
 462        client.authenticate_and_connect(true, &cx).await?;
 463
 464        let subscription = client.subscribe_to_entity(remote_id);
 465        let response = client
 466            .request(proto::JoinProject {
 467                project_id: remote_id,
 468            })
 469            .await?;
 470        let this = cx.add_model(|cx| {
 471            let replica_id = response.replica_id as ReplicaId;
 472
 473            let mut worktrees = Vec::new();
 474            for worktree in response.worktrees {
 475                let worktree = cx.update(|cx| {
 476                    Worktree::remote(remote_id, replica_id, worktree, client.clone(), cx)
 477                });
 478                worktrees.push(worktree);
 479            }
 480
 481            let mut this = Self {
 482                worktrees: Vec::new(),
 483                loading_buffers_by_path: Default::default(),
 484                opened_buffer: watch::channel(),
 485                shared_buffers: Default::default(),
 486                incomplete_remote_buffers: Default::default(),
 487                loading_local_worktrees: Default::default(),
 488                active_entry: None,
 489                collaborators: Default::default(),
 490                _maintain_buffer_languages: Self::maintain_buffer_languages(&languages, cx),
 491                _maintain_workspace_config: Self::maintain_workspace_config(languages.clone(), cx),
 492                languages,
 493                user_store: user_store.clone(),
 494                fs,
 495                next_entry_id: Default::default(),
 496                next_diagnostic_group_id: Default::default(),
 497                client_subscriptions: Default::default(),
 498                _subscriptions: Default::default(),
 499                client: client.clone(),
 500                client_state: Some(ProjectClientState::Remote {
 501                    sharing_has_stopped: false,
 502                    remote_id,
 503                    replica_id,
 504                }),
 505                language_servers: Default::default(),
 506                language_server_ids: Default::default(),
 507                language_server_settings: Default::default(),
 508                language_server_statuses: response
 509                    .language_servers
 510                    .into_iter()
 511                    .map(|server| {
 512                        (
 513                            server.id as usize,
 514                            LanguageServerStatus {
 515                                name: server.name,
 516                                pending_work: Default::default(),
 517                                has_pending_diagnostic_updates: false,
 518                                progress_tokens: Default::default(),
 519                            },
 520                        )
 521                    })
 522                    .collect(),
 523                last_workspace_edits_by_language_server: Default::default(),
 524                next_language_server_id: 0,
 525                opened_buffers: Default::default(),
 526                buffers_being_formatted: Default::default(),
 527                buffer_snapshots: Default::default(),
 528                nonce: StdRng::from_entropy().gen(),
 529                terminals: Terminals {
 530                    local_handles: Vec::new(),
 531                },
 532            };
 533            for worktree in worktrees {
 534                let _ = this.add_worktree(&worktree, cx);
 535            }
 536            this
 537        });
 538        let subscription = subscription.set_model(&this, &mut cx);
 539
 540        let user_ids = response
 541            .collaborators
 542            .iter()
 543            .map(|peer| peer.user_id)
 544            .collect();
 545        user_store
 546            .update(&mut cx, |user_store, cx| user_store.get_users(user_ids, cx))
 547            .await?;
 548
 549        this.update(&mut cx, |this, cx| {
 550            this.set_collaborators_from_proto(response.collaborators, cx)?;
 551            this.client_subscriptions.push(subscription);
 552            anyhow::Ok(())
 553        })?;
 554
 555        Ok(this)
 556    }
 557
 558    #[cfg(any(test, feature = "test-support"))]
 559    pub async fn test(
 560        fs: Arc<dyn Fs>,
 561        root_paths: impl IntoIterator<Item = &Path>,
 562        cx: &mut gpui::TestAppContext,
 563    ) -> ModelHandle<Project> {
 564        if !cx.read(|cx| cx.has_global::<Settings>()) {
 565            cx.update(|cx| {
 566                cx.set_global(Settings::test(cx));
 567            });
 568        }
 569
 570        let mut languages = LanguageRegistry::test();
 571        languages.set_executor(cx.background());
 572        let http_client = client::test::FakeHttpClient::with_404_response();
 573        let client = cx.update(|cx| client::Client::new(http_client.clone(), cx));
 574        let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http_client, cx));
 575        let project =
 576            cx.update(|cx| Project::local(client, user_store, Arc::new(languages), fs, cx));
 577        for path in root_paths {
 578            let (tree, _) = project
 579                .update(cx, |project, cx| {
 580                    project.find_or_create_local_worktree(path, true, cx)
 581                })
 582                .await
 583                .unwrap();
 584            tree.read_with(cx, |tree, _| tree.as_local().unwrap().scan_complete())
 585                .await;
 586        }
 587        project
 588    }
 589
 590    fn on_settings_changed(&mut self, cx: &mut ModelContext<Self>) {
 591        let settings = cx.global::<Settings>();
 592
 593        let mut language_servers_to_start = Vec::new();
 594        for buffer in self.opened_buffers.values() {
 595            if let Some(buffer) = buffer.upgrade(cx) {
 596                let buffer = buffer.read(cx);
 597                if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language())
 598                {
 599                    if settings.enable_language_server(Some(&language.name())) {
 600                        let worktree = file.worktree.read(cx);
 601                        language_servers_to_start.push((
 602                            worktree.id(),
 603                            worktree.as_local().unwrap().abs_path().clone(),
 604                            language.clone(),
 605                        ));
 606                    }
 607                }
 608            }
 609        }
 610
 611        let mut language_servers_to_stop = Vec::new();
 612        for language in self.languages.to_vec() {
 613            if let Some(lsp_adapter) = language.lsp_adapter() {
 614                if !settings.enable_language_server(Some(&language.name())) {
 615                    let lsp_name = &lsp_adapter.name;
 616                    for (worktree_id, started_lsp_name) in self.language_server_ids.keys() {
 617                        if lsp_name == started_lsp_name {
 618                            language_servers_to_stop.push((*worktree_id, started_lsp_name.clone()));
 619                        }
 620                    }
 621                }
 622            }
 623        }
 624
 625        // Stop all newly-disabled language servers.
 626        for (worktree_id, adapter_name) in language_servers_to_stop {
 627            self.stop_language_server(worktree_id, adapter_name, cx)
 628                .detach();
 629        }
 630
 631        // Start all the newly-enabled language servers.
 632        for (worktree_id, worktree_path, language) in language_servers_to_start {
 633            self.start_language_server(worktree_id, worktree_path, language, cx);
 634        }
 635
 636        cx.notify();
 637    }
 638
 639    pub fn buffer_for_id(&self, remote_id: u64, cx: &AppContext) -> Option<ModelHandle<Buffer>> {
 640        self.opened_buffers
 641            .get(&remote_id)
 642            .and_then(|buffer| buffer.upgrade(cx))
 643    }
 644
 645    pub fn languages(&self) -> &Arc<LanguageRegistry> {
 646        &self.languages
 647    }
 648
 649    pub fn client(&self) -> Arc<Client> {
 650        self.client.clone()
 651    }
 652
 653    pub fn user_store(&self) -> ModelHandle<UserStore> {
 654        self.user_store.clone()
 655    }
 656
 657    #[cfg(any(test, feature = "test-support"))]
 658    pub fn check_invariants(&self, cx: &AppContext) {
 659        if self.is_local() {
 660            let mut worktree_root_paths = HashMap::default();
 661            for worktree in self.worktrees(cx) {
 662                let worktree = worktree.read(cx);
 663                let abs_path = worktree.as_local().unwrap().abs_path().clone();
 664                let prev_worktree_id = worktree_root_paths.insert(abs_path.clone(), worktree.id());
 665                assert_eq!(
 666                    prev_worktree_id,
 667                    None,
 668                    "abs path {:?} for worktree {:?} is not unique ({:?} was already registered with the same path)",
 669                    abs_path,
 670                    worktree.id(),
 671                    prev_worktree_id
 672                )
 673            }
 674        } else {
 675            let replica_id = self.replica_id();
 676            for buffer in self.opened_buffers.values() {
 677                if let Some(buffer) = buffer.upgrade(cx) {
 678                    let buffer = buffer.read(cx);
 679                    assert_eq!(
 680                        buffer.deferred_ops_len(),
 681                        0,
 682                        "replica {}, buffer {} has deferred operations",
 683                        replica_id,
 684                        buffer.remote_id()
 685                    );
 686                }
 687            }
 688        }
 689    }
 690
 691    #[cfg(any(test, feature = "test-support"))]
 692    pub fn has_open_buffer(&self, path: impl Into<ProjectPath>, cx: &AppContext) -> bool {
 693        let path = path.into();
 694        if let Some(worktree) = self.worktree_for_id(path.worktree_id, cx) {
 695            self.opened_buffers.iter().any(|(_, buffer)| {
 696                if let Some(buffer) = buffer.upgrade(cx) {
 697                    if let Some(file) = File::from_dyn(buffer.read(cx).file()) {
 698                        if file.worktree == worktree && file.path() == &path.path {
 699                            return true;
 700                        }
 701                    }
 702                }
 703                false
 704            })
 705        } else {
 706            false
 707        }
 708    }
 709
 710    pub fn fs(&self) -> &Arc<dyn Fs> {
 711        &self.fs
 712    }
 713
 714    pub fn remote_id(&self) -> Option<u64> {
 715        match self.client_state.as_ref()? {
 716            ProjectClientState::Local { remote_id, .. }
 717            | ProjectClientState::Remote { remote_id, .. } => Some(*remote_id),
 718        }
 719    }
 720
 721    pub fn replica_id(&self) -> ReplicaId {
 722        match &self.client_state {
 723            Some(ProjectClientState::Remote { replica_id, .. }) => *replica_id,
 724            _ => 0,
 725        }
 726    }
 727
 728    fn metadata_changed(&mut self, cx: &mut ModelContext<Self>) -> impl Future<Output = ()> {
 729        let (tx, rx) = oneshot::channel();
 730        if let Some(ProjectClientState::Local {
 731            metadata_changed, ..
 732        }) = &mut self.client_state
 733        {
 734            let _ = metadata_changed.unbounded_send(tx);
 735        }
 736        cx.notify();
 737
 738        async move {
 739            // If the project is shared, this will resolve when the `_maintain_metadata` task has
 740            // a chance to update the metadata. Otherwise, it will resolve right away because `tx`
 741            // will get dropped.
 742            let _ = rx.await;
 743        }
 744    }
 745
 746    pub fn collaborators(&self) -> &HashMap<proto::PeerId, Collaborator> {
 747        &self.collaborators
 748    }
 749
 750    /// Collect all worktrees, including ones that don't appear in the project panel
 751    pub fn worktrees<'a>(
 752        &'a self,
 753        cx: &'a AppContext,
 754    ) -> impl 'a + DoubleEndedIterator<Item = ModelHandle<Worktree>> {
 755        self.worktrees
 756            .iter()
 757            .filter_map(move |worktree| worktree.upgrade(cx))
 758    }
 759
 760    /// Collect all user-visible worktrees, the ones that appear in the project panel
 761    pub fn visible_worktrees<'a>(
 762        &'a self,
 763        cx: &'a AppContext,
 764    ) -> impl 'a + DoubleEndedIterator<Item = ModelHandle<Worktree>> {
 765        self.worktrees.iter().filter_map(|worktree| {
 766            worktree.upgrade(cx).and_then(|worktree| {
 767                if worktree.read(cx).is_visible() {
 768                    Some(worktree)
 769                } else {
 770                    None
 771                }
 772            })
 773        })
 774    }
 775
 776    pub fn worktree_root_names<'a>(&'a self, cx: &'a AppContext) -> impl Iterator<Item = &'a str> {
 777        self.visible_worktrees(cx)
 778            .map(|tree| tree.read(cx).root_name())
 779    }
 780
 781    pub fn worktree_for_id(
 782        &self,
 783        id: WorktreeId,
 784        cx: &AppContext,
 785    ) -> Option<ModelHandle<Worktree>> {
 786        self.worktrees(cx)
 787            .find(|worktree| worktree.read(cx).id() == id)
 788    }
 789
 790    pub fn worktree_for_entry(
 791        &self,
 792        entry_id: ProjectEntryId,
 793        cx: &AppContext,
 794    ) -> Option<ModelHandle<Worktree>> {
 795        self.worktrees(cx)
 796            .find(|worktree| worktree.read(cx).contains_entry(entry_id))
 797    }
 798
 799    pub fn worktree_id_for_entry(
 800        &self,
 801        entry_id: ProjectEntryId,
 802        cx: &AppContext,
 803    ) -> Option<WorktreeId> {
 804        self.worktree_for_entry(entry_id, cx)
 805            .map(|worktree| worktree.read(cx).id())
 806    }
 807
 808    pub fn contains_paths(&self, paths: &[PathBuf], cx: &AppContext) -> bool {
 809        paths.iter().all(|path| self.contains_path(path, cx))
 810    }
 811
 812    pub fn contains_path(&self, path: &Path, cx: &AppContext) -> bool {
 813        for worktree in self.worktrees(cx) {
 814            let worktree = worktree.read(cx).as_local();
 815            if worktree.map_or(false, |w| w.contains_abs_path(path)) {
 816                return true;
 817            }
 818        }
 819        false
 820    }
 821
 822    pub fn create_entry(
 823        &mut self,
 824        project_path: impl Into<ProjectPath>,
 825        is_directory: bool,
 826        cx: &mut ModelContext<Self>,
 827    ) -> Option<Task<Result<Entry>>> {
 828        let project_path = project_path.into();
 829        let worktree = self.worktree_for_id(project_path.worktree_id, cx)?;
 830        if self.is_local() {
 831            Some(worktree.update(cx, |worktree, cx| {
 832                worktree
 833                    .as_local_mut()
 834                    .unwrap()
 835                    .create_entry(project_path.path, is_directory, cx)
 836            }))
 837        } else {
 838            let client = self.client.clone();
 839            let project_id = self.remote_id().unwrap();
 840            Some(cx.spawn_weak(|_, mut cx| async move {
 841                let response = client
 842                    .request(proto::CreateProjectEntry {
 843                        worktree_id: project_path.worktree_id.to_proto(),
 844                        project_id,
 845                        path: project_path.path.to_string_lossy().into(),
 846                        is_directory,
 847                    })
 848                    .await?;
 849                let entry = response
 850                    .entry
 851                    .ok_or_else(|| anyhow!("missing entry in response"))?;
 852                worktree
 853                    .update(&mut cx, |worktree, cx| {
 854                        worktree.as_remote_mut().unwrap().insert_entry(
 855                            entry,
 856                            response.worktree_scan_id as usize,
 857                            cx,
 858                        )
 859                    })
 860                    .await
 861            }))
 862        }
 863    }
 864
 865    pub fn copy_entry(
 866        &mut self,
 867        entry_id: ProjectEntryId,
 868        new_path: impl Into<Arc<Path>>,
 869        cx: &mut ModelContext<Self>,
 870    ) -> Option<Task<Result<Entry>>> {
 871        let worktree = self.worktree_for_entry(entry_id, cx)?;
 872        let new_path = new_path.into();
 873        if self.is_local() {
 874            worktree.update(cx, |worktree, cx| {
 875                worktree
 876                    .as_local_mut()
 877                    .unwrap()
 878                    .copy_entry(entry_id, new_path, cx)
 879            })
 880        } else {
 881            let client = self.client.clone();
 882            let project_id = self.remote_id().unwrap();
 883
 884            Some(cx.spawn_weak(|_, mut cx| async move {
 885                let response = client
 886                    .request(proto::CopyProjectEntry {
 887                        project_id,
 888                        entry_id: entry_id.to_proto(),
 889                        new_path: new_path.to_string_lossy().into(),
 890                    })
 891                    .await?;
 892                let entry = response
 893                    .entry
 894                    .ok_or_else(|| anyhow!("missing entry in response"))?;
 895                worktree
 896                    .update(&mut cx, |worktree, cx| {
 897                        worktree.as_remote_mut().unwrap().insert_entry(
 898                            entry,
 899                            response.worktree_scan_id as usize,
 900                            cx,
 901                        )
 902                    })
 903                    .await
 904            }))
 905        }
 906    }
 907
 908    pub fn rename_entry(
 909        &mut self,
 910        entry_id: ProjectEntryId,
 911        new_path: impl Into<Arc<Path>>,
 912        cx: &mut ModelContext<Self>,
 913    ) -> Option<Task<Result<Entry>>> {
 914        let worktree = self.worktree_for_entry(entry_id, cx)?;
 915        let new_path = new_path.into();
 916        if self.is_local() {
 917            worktree.update(cx, |worktree, cx| {
 918                worktree
 919                    .as_local_mut()
 920                    .unwrap()
 921                    .rename_entry(entry_id, new_path, cx)
 922            })
 923        } else {
 924            let client = self.client.clone();
 925            let project_id = self.remote_id().unwrap();
 926
 927            Some(cx.spawn_weak(|_, mut cx| async move {
 928                let response = client
 929                    .request(proto::RenameProjectEntry {
 930                        project_id,
 931                        entry_id: entry_id.to_proto(),
 932                        new_path: new_path.to_string_lossy().into(),
 933                    })
 934                    .await?;
 935                let entry = response
 936                    .entry
 937                    .ok_or_else(|| anyhow!("missing entry in response"))?;
 938                worktree
 939                    .update(&mut cx, |worktree, cx| {
 940                        worktree.as_remote_mut().unwrap().insert_entry(
 941                            entry,
 942                            response.worktree_scan_id as usize,
 943                            cx,
 944                        )
 945                    })
 946                    .await
 947            }))
 948        }
 949    }
 950
 951    pub fn delete_entry(
 952        &mut self,
 953        entry_id: ProjectEntryId,
 954        cx: &mut ModelContext<Self>,
 955    ) -> Option<Task<Result<()>>> {
 956        let worktree = self.worktree_for_entry(entry_id, cx)?;
 957        if self.is_local() {
 958            worktree.update(cx, |worktree, cx| {
 959                worktree.as_local_mut().unwrap().delete_entry(entry_id, cx)
 960            })
 961        } else {
 962            let client = self.client.clone();
 963            let project_id = self.remote_id().unwrap();
 964            Some(cx.spawn_weak(|_, mut cx| async move {
 965                let response = client
 966                    .request(proto::DeleteProjectEntry {
 967                        project_id,
 968                        entry_id: entry_id.to_proto(),
 969                    })
 970                    .await?;
 971                worktree
 972                    .update(&mut cx, move |worktree, cx| {
 973                        worktree.as_remote_mut().unwrap().delete_entry(
 974                            entry_id,
 975                            response.worktree_scan_id as usize,
 976                            cx,
 977                        )
 978                    })
 979                    .await
 980            }))
 981        }
 982    }
 983
 984    pub fn shared(&mut self, project_id: u64, cx: &mut ModelContext<Self>) -> Result<()> {
 985        if self.client_state.is_some() {
 986            return Err(anyhow!("project was already shared"));
 987        }
 988
 989        for open_buffer in self.opened_buffers.values_mut() {
 990            match open_buffer {
 991                OpenBuffer::Strong(_) => {}
 992                OpenBuffer::Weak(buffer) => {
 993                    if let Some(buffer) = buffer.upgrade(cx) {
 994                        *open_buffer = OpenBuffer::Strong(buffer);
 995                    }
 996                }
 997                OpenBuffer::Operations(_) => unreachable!(),
 998            }
 999        }
1000
1001        for worktree_handle in self.worktrees.iter_mut() {
1002            match worktree_handle {
1003                WorktreeHandle::Strong(_) => {}
1004                WorktreeHandle::Weak(worktree) => {
1005                    if let Some(worktree) = worktree.upgrade(cx) {
1006                        *worktree_handle = WorktreeHandle::Strong(worktree);
1007                    }
1008                }
1009            }
1010        }
1011
1012        for (server_id, status) in &self.language_server_statuses {
1013            self.client
1014                .send(proto::StartLanguageServer {
1015                    project_id,
1016                    server: Some(proto::LanguageServer {
1017                        id: *server_id as u64,
1018                        name: status.name.clone(),
1019                    }),
1020                })
1021                .log_err();
1022        }
1023
1024        self.client_subscriptions.push(
1025            self.client
1026                .subscribe_to_entity(project_id)
1027                .set_model(&cx.handle(), &mut cx.to_async()),
1028        );
1029
1030        let (metadata_changed_tx, mut metadata_changed_rx) = mpsc::unbounded();
1031        self.client_state = Some(ProjectClientState::Local {
1032            remote_id: project_id,
1033            metadata_changed: metadata_changed_tx,
1034            _maintain_metadata: cx.spawn_weak(move |this, mut cx| async move {
1035                let mut txs = Vec::new();
1036                while let Some(tx) = metadata_changed_rx.next().await {
1037                    txs.push(tx);
1038                    while let Ok(Some(next_tx)) = metadata_changed_rx.try_next() {
1039                        txs.push(next_tx);
1040                    }
1041
1042                    let Some(this) = this.upgrade(&cx) else { break };
1043                    let worktrees =
1044                        this.read_with(&cx, |this, cx| this.worktrees(cx).collect::<Vec<_>>());
1045                    let update_project = this
1046                        .read_with(&cx, |this, cx| {
1047                            this.client.request(proto::UpdateProject {
1048                                project_id,
1049                                worktrees: this.worktree_metadata_protos(cx),
1050                            })
1051                        })
1052                        .await;
1053                    if update_project.is_ok() {
1054                        for worktree in worktrees {
1055                            worktree.update(&mut cx, |worktree, cx| {
1056                                let worktree = worktree.as_local_mut().unwrap();
1057                                worktree.share(project_id, cx).detach_and_log_err(cx)
1058                            });
1059                        }
1060                    }
1061
1062                    for tx in txs.drain(..) {
1063                        let _ = tx.send(());
1064                    }
1065                }
1066            }),
1067        });
1068
1069        let _ = self.metadata_changed(cx);
1070        cx.emit(Event::RemoteIdChanged(Some(project_id)));
1071        cx.notify();
1072        Ok(())
1073    }
1074
1075    pub fn reshared(
1076        &mut self,
1077        message: proto::ResharedProject,
1078        cx: &mut ModelContext<Self>,
1079    ) -> Result<()> {
1080        self.set_collaborators_from_proto(message.collaborators, cx)?;
1081        let _ = self.metadata_changed(cx);
1082        Ok(())
1083    }
1084
1085    pub fn rejoined(
1086        &mut self,
1087        message: proto::RejoinedProject,
1088        cx: &mut ModelContext<Self>,
1089    ) -> Result<()> {
1090        self.set_worktrees_from_proto(message.worktrees, cx)?;
1091        self.set_collaborators_from_proto(message.collaborators, cx)?;
1092        self.language_server_statuses = message
1093            .language_servers
1094            .into_iter()
1095            .map(|server| {
1096                (
1097                    server.id as usize,
1098                    LanguageServerStatus {
1099                        name: server.name,
1100                        pending_work: Default::default(),
1101                        has_pending_diagnostic_updates: false,
1102                        progress_tokens: Default::default(),
1103                    },
1104                )
1105            })
1106            .collect();
1107        self.synchronize_remote_buffers(cx).detach_and_log_err(cx);
1108
1109        cx.notify();
1110        Ok(())
1111    }
1112
1113    pub fn unshare(&mut self, cx: &mut ModelContext<Self>) -> Result<()> {
1114        if self.is_remote() {
1115            return Err(anyhow!("attempted to unshare a remote project"));
1116        }
1117
1118        if let Some(ProjectClientState::Local { remote_id, .. }) = self.client_state.take() {
1119            self.collaborators.clear();
1120            self.shared_buffers.clear();
1121            self.client_subscriptions.clear();
1122
1123            for worktree_handle in self.worktrees.iter_mut() {
1124                if let WorktreeHandle::Strong(worktree) = worktree_handle {
1125                    let is_visible = worktree.update(cx, |worktree, _| {
1126                        worktree.as_local_mut().unwrap().unshare();
1127                        worktree.is_visible()
1128                    });
1129                    if !is_visible {
1130                        *worktree_handle = WorktreeHandle::Weak(worktree.downgrade());
1131                    }
1132                }
1133            }
1134
1135            for open_buffer in self.opened_buffers.values_mut() {
1136                if let OpenBuffer::Strong(buffer) = open_buffer {
1137                    *open_buffer = OpenBuffer::Weak(buffer.downgrade());
1138                }
1139            }
1140
1141            let _ = self.metadata_changed(cx);
1142            cx.notify();
1143            self.client.send(proto::UnshareProject {
1144                project_id: remote_id,
1145            })?;
1146
1147            Ok(())
1148        } else {
1149            Err(anyhow!("attempted to unshare an unshared project"))
1150        }
1151    }
1152
1153    pub fn disconnected_from_host(&mut self, cx: &mut ModelContext<Self>) {
1154        if let Some(ProjectClientState::Remote {
1155            sharing_has_stopped,
1156            ..
1157        }) = &mut self.client_state
1158        {
1159            *sharing_has_stopped = true;
1160            self.collaborators.clear();
1161            for worktree in &self.worktrees {
1162                if let Some(worktree) = worktree.upgrade(cx) {
1163                    worktree.update(cx, |worktree, _| {
1164                        if let Some(worktree) = worktree.as_remote_mut() {
1165                            worktree.disconnected_from_host();
1166                        }
1167                    });
1168                }
1169            }
1170            cx.emit(Event::DisconnectedFromHost);
1171            cx.notify();
1172
1173            // Wake up all futures currently waiting on a buffer to get opened,
1174            // to give them a chance to fail now that we've disconnected.
1175            *self.opened_buffer.0.borrow_mut() = ();
1176        }
1177    }
1178
1179    pub fn close(&mut self, cx: &mut ModelContext<Self>) {
1180        cx.emit(Event::Closed);
1181    }
1182
1183    pub fn is_read_only(&self) -> bool {
1184        match &self.client_state {
1185            Some(ProjectClientState::Remote {
1186                sharing_has_stopped,
1187                ..
1188            }) => *sharing_has_stopped,
1189            _ => false,
1190        }
1191    }
1192
1193    pub fn is_local(&self) -> bool {
1194        match &self.client_state {
1195            Some(ProjectClientState::Remote { .. }) => false,
1196            _ => true,
1197        }
1198    }
1199
1200    pub fn is_remote(&self) -> bool {
1201        !self.is_local()
1202    }
1203
1204    pub fn create_buffer(
1205        &mut self,
1206        text: &str,
1207        language: Option<Arc<Language>>,
1208        cx: &mut ModelContext<Self>,
1209    ) -> Result<ModelHandle<Buffer>> {
1210        if self.is_remote() {
1211            return Err(anyhow!("creating buffers as a guest is not supported yet"));
1212        }
1213
1214        let buffer = cx.add_model(|cx| {
1215            Buffer::new(self.replica_id(), text, cx)
1216                .with_language(language.unwrap_or_else(|| language::PLAIN_TEXT.clone()), cx)
1217        });
1218        self.register_buffer(&buffer, cx)?;
1219        Ok(buffer)
1220    }
1221
1222    pub fn open_path(
1223        &mut self,
1224        path: impl Into<ProjectPath>,
1225        cx: &mut ModelContext<Self>,
1226    ) -> Task<Result<(ProjectEntryId, AnyModelHandle)>> {
1227        let task = self.open_buffer(path, cx);
1228        cx.spawn_weak(|_, cx| async move {
1229            let buffer = task.await?;
1230            let project_entry_id = buffer
1231                .read_with(&cx, |buffer, cx| {
1232                    File::from_dyn(buffer.file()).and_then(|file| file.project_entry_id(cx))
1233                })
1234                .ok_or_else(|| anyhow!("no project entry"))?;
1235            Ok((project_entry_id, buffer.into()))
1236        })
1237    }
1238
1239    pub fn open_local_buffer(
1240        &mut self,
1241        abs_path: impl AsRef<Path>,
1242        cx: &mut ModelContext<Self>,
1243    ) -> Task<Result<ModelHandle<Buffer>>> {
1244        if let Some((worktree, relative_path)) = self.find_local_worktree(abs_path.as_ref(), cx) {
1245            self.open_buffer((worktree.read(cx).id(), relative_path), cx)
1246        } else {
1247            Task::ready(Err(anyhow!("no such path")))
1248        }
1249    }
1250
1251    pub fn open_buffer(
1252        &mut self,
1253        path: impl Into<ProjectPath>,
1254        cx: &mut ModelContext<Self>,
1255    ) -> Task<Result<ModelHandle<Buffer>>> {
1256        let project_path = path.into();
1257        let worktree = if let Some(worktree) = self.worktree_for_id(project_path.worktree_id, cx) {
1258            worktree
1259        } else {
1260            return Task::ready(Err(anyhow!("no such worktree")));
1261        };
1262
1263        // If there is already a buffer for the given path, then return it.
1264        let existing_buffer = self.get_open_buffer(&project_path, cx);
1265        if let Some(existing_buffer) = existing_buffer {
1266            return Task::ready(Ok(existing_buffer));
1267        }
1268
1269        let mut loading_watch = match self.loading_buffers_by_path.entry(project_path.clone()) {
1270            // If the given path is already being loaded, then wait for that existing
1271            // task to complete and return the same buffer.
1272            hash_map::Entry::Occupied(e) => e.get().clone(),
1273
1274            // Otherwise, record the fact that this path is now being loaded.
1275            hash_map::Entry::Vacant(entry) => {
1276                let (mut tx, rx) = postage::watch::channel();
1277                entry.insert(rx.clone());
1278
1279                let load_buffer = if worktree.read(cx).is_local() {
1280                    self.open_local_buffer_internal(&project_path.path, &worktree, cx)
1281                } else {
1282                    self.open_remote_buffer_internal(&project_path.path, &worktree, cx)
1283                };
1284
1285                cx.spawn(move |this, mut cx| async move {
1286                    let load_result = load_buffer.await;
1287                    *tx.borrow_mut() = Some(this.update(&mut cx, |this, _| {
1288                        // Record the fact that the buffer is no longer loading.
1289                        this.loading_buffers_by_path.remove(&project_path);
1290                        let buffer = load_result.map_err(Arc::new)?;
1291                        Ok(buffer)
1292                    }));
1293                })
1294                .detach();
1295                rx
1296            }
1297        };
1298
1299        cx.foreground().spawn(async move {
1300            loop {
1301                if let Some(result) = loading_watch.borrow().as_ref() {
1302                    match result {
1303                        Ok(buffer) => return Ok(buffer.clone()),
1304                        Err(error) => return Err(anyhow!("{}", error)),
1305                    }
1306                }
1307                loading_watch.next().await;
1308            }
1309        })
1310    }
1311
1312    fn open_local_buffer_internal(
1313        &mut self,
1314        path: &Arc<Path>,
1315        worktree: &ModelHandle<Worktree>,
1316        cx: &mut ModelContext<Self>,
1317    ) -> Task<Result<ModelHandle<Buffer>>> {
1318        let load_buffer = worktree.update(cx, |worktree, cx| {
1319            let worktree = worktree.as_local_mut().unwrap();
1320            worktree.load_buffer(path, cx)
1321        });
1322        cx.spawn(|this, mut cx| async move {
1323            let buffer = load_buffer.await?;
1324            this.update(&mut cx, |this, cx| this.register_buffer(&buffer, cx))?;
1325            Ok(buffer)
1326        })
1327    }
1328
1329    fn open_remote_buffer_internal(
1330        &mut self,
1331        path: &Arc<Path>,
1332        worktree: &ModelHandle<Worktree>,
1333        cx: &mut ModelContext<Self>,
1334    ) -> Task<Result<ModelHandle<Buffer>>> {
1335        let rpc = self.client.clone();
1336        let project_id = self.remote_id().unwrap();
1337        let remote_worktree_id = worktree.read(cx).id();
1338        let path = path.clone();
1339        let path_string = path.to_string_lossy().to_string();
1340        cx.spawn(|this, mut cx| async move {
1341            let response = rpc
1342                .request(proto::OpenBufferByPath {
1343                    project_id,
1344                    worktree_id: remote_worktree_id.to_proto(),
1345                    path: path_string,
1346                })
1347                .await?;
1348            this.update(&mut cx, |this, cx| {
1349                this.wait_for_remote_buffer(response.buffer_id, cx)
1350            })
1351            .await
1352        })
1353    }
1354
1355    /// LanguageServerName is owned, because it is inserted into a map
1356    fn open_local_buffer_via_lsp(
1357        &mut self,
1358        abs_path: lsp::Url,
1359        language_server_id: usize,
1360        language_server_name: LanguageServerName,
1361        cx: &mut ModelContext<Self>,
1362    ) -> Task<Result<ModelHandle<Buffer>>> {
1363        cx.spawn(|this, mut cx| async move {
1364            let abs_path = abs_path
1365                .to_file_path()
1366                .map_err(|_| anyhow!("can't convert URI to path"))?;
1367            let (worktree, relative_path) = if let Some(result) =
1368                this.read_with(&cx, |this, cx| this.find_local_worktree(&abs_path, cx))
1369            {
1370                result
1371            } else {
1372                let worktree = this
1373                    .update(&mut cx, |this, cx| {
1374                        this.create_local_worktree(&abs_path, false, cx)
1375                    })
1376                    .await?;
1377                this.update(&mut cx, |this, cx| {
1378                    this.language_server_ids.insert(
1379                        (worktree.read(cx).id(), language_server_name),
1380                        language_server_id,
1381                    );
1382                });
1383                (worktree, PathBuf::new())
1384            };
1385
1386            let project_path = ProjectPath {
1387                worktree_id: worktree.read_with(&cx, |worktree, _| worktree.id()),
1388                path: relative_path.into(),
1389            };
1390            this.update(&mut cx, |this, cx| this.open_buffer(project_path, cx))
1391                .await
1392        })
1393    }
1394
1395    pub fn open_buffer_by_id(
1396        &mut self,
1397        id: u64,
1398        cx: &mut ModelContext<Self>,
1399    ) -> Task<Result<ModelHandle<Buffer>>> {
1400        if let Some(buffer) = self.buffer_for_id(id, cx) {
1401            Task::ready(Ok(buffer))
1402        } else if self.is_local() {
1403            Task::ready(Err(anyhow!("buffer {} does not exist", id)))
1404        } else if let Some(project_id) = self.remote_id() {
1405            let request = self
1406                .client
1407                .request(proto::OpenBufferById { project_id, id });
1408            cx.spawn(|this, mut cx| async move {
1409                let buffer_id = request.await?.buffer_id;
1410                this.update(&mut cx, |this, cx| {
1411                    this.wait_for_remote_buffer(buffer_id, cx)
1412                })
1413                .await
1414            })
1415        } else {
1416            Task::ready(Err(anyhow!("cannot open buffer while disconnected")))
1417        }
1418    }
1419
1420    pub fn save_buffers(
1421        &self,
1422        buffers: HashSet<ModelHandle<Buffer>>,
1423        cx: &mut ModelContext<Self>,
1424    ) -> Task<Result<()>> {
1425        cx.spawn(|this, mut cx| async move {
1426            let save_tasks = buffers
1427                .into_iter()
1428                .map(|buffer| this.update(&mut cx, |this, cx| this.save_buffer(buffer, cx)));
1429            try_join_all(save_tasks).await?;
1430            Ok(())
1431        })
1432    }
1433
1434    pub fn save_buffer(
1435        &self,
1436        buffer: ModelHandle<Buffer>,
1437        cx: &mut ModelContext<Self>,
1438    ) -> Task<Result<(clock::Global, RopeFingerprint, SystemTime)>> {
1439        let Some(file) = File::from_dyn(buffer.read(cx).file()) else {
1440            return Task::ready(Err(anyhow!("buffer doesn't have a file")));
1441        };
1442        let worktree = file.worktree.clone();
1443        let path = file.path.clone();
1444        worktree.update(cx, |worktree, cx| match worktree {
1445            Worktree::Local(worktree) => worktree.save_buffer(buffer, path, false, cx),
1446            Worktree::Remote(worktree) => worktree.save_buffer(buffer, cx),
1447        })
1448    }
1449
1450    pub fn save_buffer_as(
1451        &mut self,
1452        buffer: ModelHandle<Buffer>,
1453        abs_path: PathBuf,
1454        cx: &mut ModelContext<Self>,
1455    ) -> Task<Result<()>> {
1456        let worktree_task = self.find_or_create_local_worktree(&abs_path, true, cx);
1457        let old_path =
1458            File::from_dyn(buffer.read(cx).file()).and_then(|f| Some(f.as_local()?.abs_path(cx)));
1459        cx.spawn(|this, mut cx| async move {
1460            if let Some(old_path) = old_path {
1461                this.update(&mut cx, |this, cx| {
1462                    this.unregister_buffer_from_language_server(&buffer, old_path, cx);
1463                });
1464            }
1465            let (worktree, path) = worktree_task.await?;
1466            worktree
1467                .update(&mut cx, |worktree, cx| match worktree {
1468                    Worktree::Local(worktree) => {
1469                        worktree.save_buffer(buffer.clone(), path.into(), true, cx)
1470                    }
1471                    Worktree::Remote(_) => panic!("cannot remote buffers as new files"),
1472                })
1473                .await?;
1474            this.update(&mut cx, |this, cx| {
1475                this.detect_language_for_buffer(&buffer, cx);
1476                this.register_buffer_with_language_server(&buffer, cx);
1477            });
1478            Ok(())
1479        })
1480    }
1481
1482    pub fn get_open_buffer(
1483        &mut self,
1484        path: &ProjectPath,
1485        cx: &mut ModelContext<Self>,
1486    ) -> Option<ModelHandle<Buffer>> {
1487        let worktree = self.worktree_for_id(path.worktree_id, cx)?;
1488        self.opened_buffers.values().find_map(|buffer| {
1489            let buffer = buffer.upgrade(cx)?;
1490            let file = File::from_dyn(buffer.read(cx).file())?;
1491            if file.worktree == worktree && file.path() == &path.path {
1492                Some(buffer)
1493            } else {
1494                None
1495            }
1496        })
1497    }
1498
1499    fn register_buffer(
1500        &mut self,
1501        buffer: &ModelHandle<Buffer>,
1502        cx: &mut ModelContext<Self>,
1503    ) -> Result<()> {
1504        buffer.update(cx, |buffer, _| {
1505            buffer.set_language_registry(self.languages.clone())
1506        });
1507
1508        let remote_id = buffer.read(cx).remote_id();
1509        let open_buffer = if self.is_remote() || self.is_shared() {
1510            OpenBuffer::Strong(buffer.clone())
1511        } else {
1512            OpenBuffer::Weak(buffer.downgrade())
1513        };
1514
1515        match self.opened_buffers.insert(remote_id, open_buffer) {
1516            None => {}
1517            Some(OpenBuffer::Operations(operations)) => {
1518                buffer.update(cx, |buffer, cx| buffer.apply_ops(operations, cx))?
1519            }
1520            Some(OpenBuffer::Weak(existing_handle)) => {
1521                if existing_handle.upgrade(cx).is_some() {
1522                    debug_panic!("already registered buffer with remote id {}", remote_id);
1523                    Err(anyhow!(
1524                        "already registered buffer with remote id {}",
1525                        remote_id
1526                    ))?
1527                }
1528            }
1529            Some(OpenBuffer::Strong(_)) => {
1530                debug_panic!("already registered buffer with remote id {}", remote_id);
1531                Err(anyhow!(
1532                    "already registered buffer with remote id {}",
1533                    remote_id
1534                ))?
1535            }
1536        }
1537        cx.subscribe(buffer, |this, buffer, event, cx| {
1538            this.on_buffer_event(buffer, event, cx);
1539        })
1540        .detach();
1541
1542        self.detect_language_for_buffer(buffer, cx);
1543        self.register_buffer_with_language_server(buffer, cx);
1544        cx.observe_release(buffer, |this, buffer, cx| {
1545            if let Some(file) = File::from_dyn(buffer.file()) {
1546                if file.is_local() {
1547                    let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap();
1548                    if let Some((_, server)) = this.language_server_for_buffer(buffer, cx) {
1549                        server
1550                            .notify::<lsp::notification::DidCloseTextDocument>(
1551                                lsp::DidCloseTextDocumentParams {
1552                                    text_document: lsp::TextDocumentIdentifier::new(uri),
1553                                },
1554                            )
1555                            .log_err();
1556                    }
1557                }
1558            }
1559        })
1560        .detach();
1561
1562        *self.opened_buffer.0.borrow_mut() = ();
1563        Ok(())
1564    }
1565
1566    fn register_buffer_with_language_server(
1567        &mut self,
1568        buffer_handle: &ModelHandle<Buffer>,
1569        cx: &mut ModelContext<Self>,
1570    ) {
1571        let buffer = buffer_handle.read(cx);
1572        let buffer_id = buffer.remote_id();
1573        if let Some(file) = File::from_dyn(buffer.file()) {
1574            if file.is_local() {
1575                let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap();
1576                let initial_snapshot = buffer.text_snapshot();
1577
1578                let mut language_server = None;
1579                let mut language_id = None;
1580                if let Some(language) = buffer.language() {
1581                    let worktree_id = file.worktree_id(cx);
1582                    if let Some(adapter) = language.lsp_adapter() {
1583                        language_id = adapter.language_ids.get(language.name().as_ref()).cloned();
1584                        language_server = self
1585                            .language_server_ids
1586                            .get(&(worktree_id, adapter.name.clone()))
1587                            .and_then(|id| self.language_servers.get(id))
1588                            .and_then(|server_state| {
1589                                if let LanguageServerState::Running { server, .. } = server_state {
1590                                    Some(server.clone())
1591                                } else {
1592                                    None
1593                                }
1594                            });
1595                    }
1596                }
1597
1598                if let Some(local_worktree) = file.worktree.read(cx).as_local() {
1599                    if let Some(diagnostics) = local_worktree.diagnostics_for_path(file.path()) {
1600                        self.update_buffer_diagnostics(buffer_handle, diagnostics, None, cx)
1601                            .log_err();
1602                    }
1603                }
1604
1605                if let Some(server) = language_server {
1606                    server
1607                        .notify::<lsp::notification::DidOpenTextDocument>(
1608                            lsp::DidOpenTextDocumentParams {
1609                                text_document: lsp::TextDocumentItem::new(
1610                                    uri,
1611                                    language_id.unwrap_or_default(),
1612                                    0,
1613                                    initial_snapshot.text(),
1614                                ),
1615                            },
1616                        )
1617                        .log_err();
1618                    buffer_handle.update(cx, |buffer, cx| {
1619                        buffer.set_completion_triggers(
1620                            server
1621                                .capabilities()
1622                                .completion_provider
1623                                .as_ref()
1624                                .and_then(|provider| provider.trigger_characters.clone())
1625                                .unwrap_or_default(),
1626                            cx,
1627                        )
1628                    });
1629                    self.buffer_snapshots
1630                        .insert(buffer_id, vec![(0, initial_snapshot)]);
1631                }
1632            }
1633        }
1634    }
1635
1636    fn unregister_buffer_from_language_server(
1637        &mut self,
1638        buffer: &ModelHandle<Buffer>,
1639        old_path: PathBuf,
1640        cx: &mut ModelContext<Self>,
1641    ) {
1642        buffer.update(cx, |buffer, cx| {
1643            buffer.update_diagnostics(Default::default(), cx);
1644            self.buffer_snapshots.remove(&buffer.remote_id());
1645            if let Some((_, language_server)) = self.language_server_for_buffer(buffer, cx) {
1646                language_server
1647                    .notify::<lsp::notification::DidCloseTextDocument>(
1648                        lsp::DidCloseTextDocumentParams {
1649                            text_document: lsp::TextDocumentIdentifier::new(
1650                                lsp::Url::from_file_path(old_path).unwrap(),
1651                            ),
1652                        },
1653                    )
1654                    .log_err();
1655            }
1656        });
1657    }
1658
1659    fn on_buffer_event(
1660        &mut self,
1661        buffer: ModelHandle<Buffer>,
1662        event: &BufferEvent,
1663        cx: &mut ModelContext<Self>,
1664    ) -> Option<()> {
1665        match event {
1666            BufferEvent::Operation(operation) => {
1667                if let Some(project_id) = self.remote_id() {
1668                    let request = self.client.request(proto::UpdateBuffer {
1669                        project_id,
1670                        buffer_id: buffer.read(cx).remote_id(),
1671                        operations: vec![language::proto::serialize_operation(operation)],
1672                    });
1673                    cx.background().spawn(request).detach_and_log_err(cx);
1674                }
1675            }
1676            BufferEvent::Edited { .. } => {
1677                let language_server = self
1678                    .language_server_for_buffer(buffer.read(cx), cx)
1679                    .map(|(_, server)| server.clone())?;
1680                let buffer = buffer.read(cx);
1681                let file = File::from_dyn(buffer.file())?;
1682                let abs_path = file.as_local()?.abs_path(cx);
1683                let uri = lsp::Url::from_file_path(abs_path).unwrap();
1684                let buffer_snapshots = self.buffer_snapshots.get_mut(&buffer.remote_id())?;
1685                let (version, prev_snapshot) = buffer_snapshots.last()?;
1686                let next_snapshot = buffer.text_snapshot();
1687                let next_version = version + 1;
1688
1689                let content_changes = buffer
1690                    .edits_since::<(PointUtf16, usize)>(prev_snapshot.version())
1691                    .map(|edit| {
1692                        let edit_start = edit.new.start.0;
1693                        let edit_end = edit_start + (edit.old.end.0 - edit.old.start.0);
1694                        let new_text = next_snapshot
1695                            .text_for_range(edit.new.start.1..edit.new.end.1)
1696                            .collect();
1697                        lsp::TextDocumentContentChangeEvent {
1698                            range: Some(lsp::Range::new(
1699                                point_to_lsp(edit_start),
1700                                point_to_lsp(edit_end),
1701                            )),
1702                            range_length: None,
1703                            text: new_text,
1704                        }
1705                    })
1706                    .collect();
1707
1708                buffer_snapshots.push((next_version, next_snapshot));
1709
1710                language_server
1711                    .notify::<lsp::notification::DidChangeTextDocument>(
1712                        lsp::DidChangeTextDocumentParams {
1713                            text_document: lsp::VersionedTextDocumentIdentifier::new(
1714                                uri,
1715                                next_version,
1716                            ),
1717                            content_changes,
1718                        },
1719                    )
1720                    .log_err();
1721            }
1722            BufferEvent::Saved => {
1723                let file = File::from_dyn(buffer.read(cx).file())?;
1724                let worktree_id = file.worktree_id(cx);
1725                let abs_path = file.as_local()?.abs_path(cx);
1726                let text_document = lsp::TextDocumentIdentifier {
1727                    uri: lsp::Url::from_file_path(abs_path).unwrap(),
1728                };
1729
1730                for (_, _, server) in self.language_servers_for_worktree(worktree_id) {
1731                    server
1732                        .notify::<lsp::notification::DidSaveTextDocument>(
1733                            lsp::DidSaveTextDocumentParams {
1734                                text_document: text_document.clone(),
1735                                text: None,
1736                            },
1737                        )
1738                        .log_err();
1739                }
1740
1741                let language_server_id = self.language_server_id_for_buffer(buffer.read(cx), cx)?;
1742                if let Some(LanguageServerState::Running {
1743                    adapter,
1744                    simulate_disk_based_diagnostics_completion,
1745                    ..
1746                }) = self.language_servers.get_mut(&language_server_id)
1747                {
1748                    // After saving a buffer using a language server that doesn't provide
1749                    // a disk-based progress token, kick off a timer that will reset every
1750                    // time the buffer is saved. If the timer eventually fires, simulate
1751                    // disk-based diagnostics being finished so that other pieces of UI
1752                    // (e.g., project diagnostics view, diagnostic status bar) can update.
1753                    // We don't emit an event right away because the language server might take
1754                    // some time to publish diagnostics.
1755                    if adapter.disk_based_diagnostics_progress_token.is_none() {
1756                        const DISK_BASED_DIAGNOSTICS_DEBOUNCE: Duration = Duration::from_secs(1);
1757
1758                        let task = cx.spawn_weak(|this, mut cx| async move {
1759                            cx.background().timer(DISK_BASED_DIAGNOSTICS_DEBOUNCE).await;
1760                            if let Some(this) = this.upgrade(&cx) {
1761                                this.update(&mut cx, |this, cx | {
1762                                    this.disk_based_diagnostics_finished(language_server_id, cx);
1763                                    this.broadcast_language_server_update(
1764                                        language_server_id,
1765                                        proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
1766                                            proto::LspDiskBasedDiagnosticsUpdated {},
1767                                        ),
1768                                    );
1769                                });
1770                            }
1771                        });
1772                        *simulate_disk_based_diagnostics_completion = Some(task);
1773                    }
1774                }
1775            }
1776            _ => {}
1777        }
1778
1779        None
1780    }
1781
1782    fn language_servers_for_worktree(
1783        &self,
1784        worktree_id: WorktreeId,
1785    ) -> impl Iterator<Item = (&Arc<CachedLspAdapter>, &Arc<Language>, &Arc<LanguageServer>)> {
1786        self.language_server_ids
1787            .iter()
1788            .filter_map(move |((language_server_worktree_id, _), id)| {
1789                if *language_server_worktree_id == worktree_id {
1790                    if let Some(LanguageServerState::Running {
1791                        adapter,
1792                        language,
1793                        server,
1794                        ..
1795                    }) = self.language_servers.get(id)
1796                    {
1797                        return Some((adapter, language, server));
1798                    }
1799                }
1800                None
1801            })
1802    }
1803
1804    fn maintain_buffer_languages(
1805        languages: &LanguageRegistry,
1806        cx: &mut ModelContext<Project>,
1807    ) -> Task<()> {
1808        let mut subscription = languages.subscribe();
1809        cx.spawn_weak(|project, mut cx| async move {
1810            while let Some(()) = subscription.next().await {
1811                if let Some(project) = project.upgrade(&cx) {
1812                    project.update(&mut cx, |project, cx| {
1813                        let mut plain_text_buffers = Vec::new();
1814                        let mut buffers_with_unknown_injections = Vec::new();
1815                        for buffer in project.opened_buffers.values() {
1816                            if let Some(handle) = buffer.upgrade(cx) {
1817                                let buffer = &handle.read(cx);
1818                                if buffer.language().is_none()
1819                                    || buffer.language() == Some(&*language::PLAIN_TEXT)
1820                                {
1821                                    plain_text_buffers.push(handle);
1822                                } else if buffer.contains_unknown_injections() {
1823                                    buffers_with_unknown_injections.push(handle);
1824                                }
1825                            }
1826                        }
1827
1828                        for buffer in plain_text_buffers {
1829                            project.detect_language_for_buffer(&buffer, cx);
1830                            project.register_buffer_with_language_server(&buffer, cx);
1831                        }
1832
1833                        for buffer in buffers_with_unknown_injections {
1834                            buffer.update(cx, |buffer, cx| buffer.reparse(cx));
1835                        }
1836                    });
1837                }
1838            }
1839        })
1840    }
1841
1842    fn maintain_workspace_config(
1843        languages: Arc<LanguageRegistry>,
1844        cx: &mut ModelContext<Project>,
1845    ) -> Task<()> {
1846        let mut languages_changed = languages.subscribe();
1847        let (mut settings_changed_tx, mut settings_changed_rx) = watch::channel();
1848        let settings_observation = cx.observe_global::<Settings, _>(move |_, _| {
1849            *settings_changed_tx.borrow_mut() = ();
1850        });
1851        cx.spawn_weak(|this, mut cx| async move {
1852            loop {
1853                futures::select_biased! {
1854                    _ = languages_changed.next().fuse() => {},
1855                    _ = settings_changed_rx.next().fuse() => {}
1856                }
1857
1858                let workspace_config = cx.update(|cx| languages.workspace_configuration(cx)).await;
1859                if let Some(this) = this.upgrade(&cx) {
1860                    this.read_with(&cx, |this, _| {
1861                        for server_state in this.language_servers.values() {
1862                            if let LanguageServerState::Running { server, .. } = server_state {
1863                                server
1864                                    .notify::<lsp::notification::DidChangeConfiguration>(
1865                                        lsp::DidChangeConfigurationParams {
1866                                            settings: workspace_config.clone(),
1867                                        },
1868                                    )
1869                                    .ok();
1870                            }
1871                        }
1872                    })
1873                } else {
1874                    break;
1875                }
1876            }
1877
1878            drop(settings_observation);
1879        })
1880    }
1881
1882    fn detect_language_for_buffer(
1883        &mut self,
1884        buffer: &ModelHandle<Buffer>,
1885        cx: &mut ModelContext<Self>,
1886    ) -> Option<()> {
1887        // If the buffer has a language, set it and start the language server if we haven't already.
1888        let full_path = buffer.read(cx).file()?.full_path(cx);
1889        let new_language = self
1890            .languages
1891            .language_for_path(&full_path)
1892            .now_or_never()?
1893            .ok()?;
1894        self.set_language_for_buffer(buffer, new_language, cx);
1895        None
1896    }
1897
1898    pub fn set_language_for_buffer(
1899        &mut self,
1900        buffer: &ModelHandle<Buffer>,
1901        new_language: Arc<Language>,
1902        cx: &mut ModelContext<Self>,
1903    ) {
1904        buffer.update(cx, |buffer, cx| {
1905            if buffer.language().map_or(true, |old_language| {
1906                !Arc::ptr_eq(old_language, &new_language)
1907            }) {
1908                buffer.set_language(Some(new_language.clone()), cx);
1909            }
1910        });
1911
1912        if let Some(file) = File::from_dyn(buffer.read(cx).file()) {
1913            if let Some(worktree) = file.worktree.read(cx).as_local() {
1914                let worktree_id = worktree.id();
1915                let worktree_abs_path = worktree.abs_path().clone();
1916                self.start_language_server(worktree_id, worktree_abs_path, new_language, cx);
1917            }
1918        }
1919    }
1920
1921    fn start_language_server(
1922        &mut self,
1923        worktree_id: WorktreeId,
1924        worktree_path: Arc<Path>,
1925        language: Arc<Language>,
1926        cx: &mut ModelContext<Self>,
1927    ) {
1928        if !cx
1929            .global::<Settings>()
1930            .enable_language_server(Some(&language.name()))
1931        {
1932            return;
1933        }
1934
1935        let adapter = if let Some(adapter) = language.lsp_adapter() {
1936            adapter
1937        } else {
1938            return;
1939        };
1940        let key = (worktree_id, adapter.name.clone());
1941
1942        let mut initialization_options = adapter.initialization_options.clone();
1943
1944        let lsp = &cx.global::<Settings>().lsp.get(&adapter.name.0);
1945        let override_options = lsp.map(|s| s.initialization_options.clone()).flatten();
1946        match (&mut initialization_options, override_options) {
1947            (Some(initialization_options), Some(override_options)) => {
1948                merge_json_value_into(override_options, initialization_options);
1949            }
1950            (None, override_options) => initialization_options = override_options,
1951            _ => {}
1952        }
1953
1954        self.language_server_ids
1955            .entry(key.clone())
1956            .or_insert_with(|| {
1957                let languages = self.languages.clone();
1958                let server_id = post_inc(&mut self.next_language_server_id);
1959                let language_server = self.languages.start_language_server(
1960                    server_id,
1961                    language.clone(),
1962                    worktree_path,
1963                    self.client.http_client(),
1964                    cx,
1965                );
1966                self.language_servers.insert(
1967                    server_id,
1968                    LanguageServerState::Starting(cx.spawn_weak(|this, mut cx| async move {
1969                        let language_server = language_server?.await.log_err()?;
1970                        let language_server = language_server
1971                            .initialize(initialization_options)
1972                            .await
1973                            .log_err()?;
1974                        let this = this.upgrade(&cx)?;
1975
1976                        language_server
1977                            .on_notification::<lsp::notification::PublishDiagnostics, _>({
1978                                let this = this.downgrade();
1979                                let adapter = adapter.clone();
1980                                move |mut params, cx| {
1981                                    let this = this;
1982                                    let adapter = adapter.clone();
1983                                    cx.spawn(|mut cx| async move {
1984                                        adapter.process_diagnostics(&mut params).await;
1985                                        if let Some(this) = this.upgrade(&cx) {
1986                                            this.update(&mut cx, |this, cx| {
1987                                                this.update_diagnostics(
1988                                                    server_id,
1989                                                    params,
1990                                                    &adapter.disk_based_diagnostic_sources,
1991                                                    cx,
1992                                                )
1993                                                .log_err();
1994                                            });
1995                                        }
1996                                    })
1997                                    .detach();
1998                                }
1999                            })
2000                            .detach();
2001
2002                        language_server
2003                            .on_request::<lsp::request::WorkspaceConfiguration, _, _>({
2004                                move |params, mut cx| {
2005                                    let languages = languages.clone();
2006                                    async move {
2007                                        let workspace_config = cx
2008                                            .update(|cx| languages.workspace_configuration(cx))
2009                                            .await;
2010
2011                                        Ok(params
2012                                            .items
2013                                            .into_iter()
2014                                            .map(|item| {
2015                                                if let Some(section) = &item.section {
2016                                                    workspace_config
2017                                                        .get(section)
2018                                                        .cloned()
2019                                                        .unwrap_or(serde_json::Value::Null)
2020                                                } else {
2021                                                    workspace_config.clone()
2022                                                }
2023                                            })
2024                                            .collect())
2025                                    }
2026                                }
2027                            })
2028                            .detach();
2029
2030                        // Even though we don't have handling for these requests, respond to them to
2031                        // avoid stalling any language server like `gopls` which waits for a response
2032                        // to these requests when initializing.
2033                        language_server
2034                            .on_request::<lsp::request::WorkDoneProgressCreate, _, _>({
2035                                let this = this.downgrade();
2036                                move |params, mut cx| async move {
2037                                    if let Some(this) = this.upgrade(&cx) {
2038                                        this.update(&mut cx, |this, _| {
2039                                            if let Some(status) =
2040                                                this.language_server_statuses.get_mut(&server_id)
2041                                            {
2042                                                if let lsp::NumberOrString::String(token) =
2043                                                    params.token
2044                                                {
2045                                                    status.progress_tokens.insert(token);
2046                                                }
2047                                            }
2048                                        });
2049                                    }
2050                                    Ok(())
2051                                }
2052                            })
2053                            .detach();
2054                        language_server
2055                            .on_request::<lsp::request::RegisterCapability, _, _>(|_, _| async {
2056                                Ok(())
2057                            })
2058                            .detach();
2059
2060                        language_server
2061                            .on_request::<lsp::request::ApplyWorkspaceEdit, _, _>({
2062                                let this = this.downgrade();
2063                                let adapter = adapter.clone();
2064                                let language_server = language_server.clone();
2065                                move |params, cx| {
2066                                    Self::on_lsp_workspace_edit(
2067                                        this,
2068                                        params,
2069                                        server_id,
2070                                        adapter.clone(),
2071                                        language_server.clone(),
2072                                        cx,
2073                                    )
2074                                }
2075                            })
2076                            .detach();
2077
2078                        let disk_based_diagnostics_progress_token =
2079                            adapter.disk_based_diagnostics_progress_token.clone();
2080
2081                        language_server
2082                            .on_notification::<lsp::notification::Progress, _>({
2083                                let this = this.downgrade();
2084                                move |params, mut cx| {
2085                                    if let Some(this) = this.upgrade(&cx) {
2086                                        this.update(&mut cx, |this, cx| {
2087                                            this.on_lsp_progress(
2088                                                params,
2089                                                server_id,
2090                                                disk_based_diagnostics_progress_token.clone(),
2091                                                cx,
2092                                            );
2093                                        });
2094                                    }
2095                                }
2096                            })
2097                            .detach();
2098
2099                        this.update(&mut cx, |this, cx| {
2100                            // If the language server for this key doesn't match the server id, don't store the
2101                            // server. Which will cause it to be dropped, killing the process
2102                            if this
2103                                .language_server_ids
2104                                .get(&key)
2105                                .map(|id| id != &server_id)
2106                                .unwrap_or(false)
2107                            {
2108                                return None;
2109                            }
2110
2111                            // Update language_servers collection with Running variant of LanguageServerState
2112                            // indicating that the server is up and running and ready
2113                            this.language_servers.insert(
2114                                server_id,
2115                                LanguageServerState::Running {
2116                                    adapter: adapter.clone(),
2117                                    language,
2118                                    server: language_server.clone(),
2119                                    simulate_disk_based_diagnostics_completion: None,
2120                                },
2121                            );
2122                            this.language_server_statuses.insert(
2123                                server_id,
2124                                LanguageServerStatus {
2125                                    name: language_server.name().to_string(),
2126                                    pending_work: Default::default(),
2127                                    has_pending_diagnostic_updates: false,
2128                                    progress_tokens: Default::default(),
2129                                },
2130                            );
2131                            language_server
2132                                .notify::<lsp::notification::DidChangeConfiguration>(
2133                                    lsp::DidChangeConfigurationParams {
2134                                        settings: this.language_server_settings.lock().clone(),
2135                                    },
2136                                )
2137                                .ok();
2138
2139                            if let Some(project_id) = this.remote_id() {
2140                                this.client
2141                                    .send(proto::StartLanguageServer {
2142                                        project_id,
2143                                        server: Some(proto::LanguageServer {
2144                                            id: server_id as u64,
2145                                            name: language_server.name().to_string(),
2146                                        }),
2147                                    })
2148                                    .log_err();
2149                            }
2150
2151                            // Tell the language server about every open buffer in the worktree that matches the language.
2152                            for buffer in this.opened_buffers.values() {
2153                                if let Some(buffer_handle) = buffer.upgrade(cx) {
2154                                    let buffer = buffer_handle.read(cx);
2155                                    let file = if let Some(file) = File::from_dyn(buffer.file()) {
2156                                        file
2157                                    } else {
2158                                        continue;
2159                                    };
2160                                    let language = if let Some(language) = buffer.language() {
2161                                        language
2162                                    } else {
2163                                        continue;
2164                                    };
2165                                    if file.worktree.read(cx).id() != key.0
2166                                        || language.lsp_adapter().map(|a| a.name.clone())
2167                                            != Some(key.1.clone())
2168                                    {
2169                                        continue;
2170                                    }
2171
2172                                    let file = file.as_local()?;
2173                                    let versions = this
2174                                        .buffer_snapshots
2175                                        .entry(buffer.remote_id())
2176                                        .or_insert_with(|| vec![(0, buffer.text_snapshot())]);
2177
2178                                    let (version, initial_snapshot) = versions.last().unwrap();
2179                                    let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap();
2180                                    language_server
2181                                        .notify::<lsp::notification::DidOpenTextDocument>(
2182                                            lsp::DidOpenTextDocumentParams {
2183                                                text_document: lsp::TextDocumentItem::new(
2184                                                    uri,
2185                                                    adapter
2186                                                        .language_ids
2187                                                        .get(language.name().as_ref())
2188                                                        .cloned()
2189                                                        .unwrap_or_default(),
2190                                                    *version,
2191                                                    initial_snapshot.text(),
2192                                                ),
2193                                            },
2194                                        )
2195                                        .log_err()?;
2196                                    buffer_handle.update(cx, |buffer, cx| {
2197                                        buffer.set_completion_triggers(
2198                                            language_server
2199                                                .capabilities()
2200                                                .completion_provider
2201                                                .as_ref()
2202                                                .and_then(|provider| {
2203                                                    provider.trigger_characters.clone()
2204                                                })
2205                                                .unwrap_or_default(),
2206                                            cx,
2207                                        )
2208                                    });
2209                                }
2210                            }
2211
2212                            cx.notify();
2213                            Some(language_server)
2214                        })
2215                    })),
2216                );
2217
2218                server_id
2219            });
2220    }
2221
2222    // Returns a list of all of the worktrees which no longer have a language server and the root path
2223    // for the stopped server
2224    fn stop_language_server(
2225        &mut self,
2226        worktree_id: WorktreeId,
2227        adapter_name: LanguageServerName,
2228        cx: &mut ModelContext<Self>,
2229    ) -> Task<(Option<PathBuf>, Vec<WorktreeId>)> {
2230        let key = (worktree_id, adapter_name);
2231        if let Some(server_id) = self.language_server_ids.remove(&key) {
2232            // Remove other entries for this language server as well
2233            let mut orphaned_worktrees = vec![worktree_id];
2234            let other_keys = self.language_server_ids.keys().cloned().collect::<Vec<_>>();
2235            for other_key in other_keys {
2236                if self.language_server_ids.get(&other_key) == Some(&server_id) {
2237                    self.language_server_ids.remove(&other_key);
2238                    orphaned_worktrees.push(other_key.0);
2239                }
2240            }
2241
2242            self.language_server_statuses.remove(&server_id);
2243            cx.notify();
2244
2245            let server_state = self.language_servers.remove(&server_id);
2246            cx.spawn_weak(|this, mut cx| async move {
2247                let mut root_path = None;
2248
2249                let server = match server_state {
2250                    Some(LanguageServerState::Starting(started_language_server)) => {
2251                        started_language_server.await
2252                    }
2253                    Some(LanguageServerState::Running { server, .. }) => Some(server),
2254                    None => None,
2255                };
2256
2257                if let Some(server) = server {
2258                    root_path = Some(server.root_path().clone());
2259                    if let Some(shutdown) = server.shutdown() {
2260                        shutdown.await;
2261                    }
2262                }
2263
2264                if let Some(this) = this.upgrade(&cx) {
2265                    this.update(&mut cx, |this, cx| {
2266                        this.language_server_statuses.remove(&server_id);
2267                        cx.notify();
2268                    });
2269                }
2270
2271                (root_path, orphaned_worktrees)
2272            })
2273        } else {
2274            Task::ready((None, Vec::new()))
2275        }
2276    }
2277
2278    pub fn restart_language_servers_for_buffers(
2279        &mut self,
2280        buffers: impl IntoIterator<Item = ModelHandle<Buffer>>,
2281        cx: &mut ModelContext<Self>,
2282    ) -> Option<()> {
2283        let language_server_lookup_info: HashSet<(WorktreeId, Arc<Path>, PathBuf)> = buffers
2284            .into_iter()
2285            .filter_map(|buffer| {
2286                let file = File::from_dyn(buffer.read(cx).file())?;
2287                let worktree = file.worktree.read(cx).as_local()?;
2288                let worktree_id = worktree.id();
2289                let worktree_abs_path = worktree.abs_path().clone();
2290                let full_path = file.full_path(cx);
2291                Some((worktree_id, worktree_abs_path, full_path))
2292            })
2293            .collect();
2294        for (worktree_id, worktree_abs_path, full_path) in language_server_lookup_info {
2295            if let Some(language) = self
2296                .languages
2297                .language_for_path(&full_path)
2298                .now_or_never()
2299                .and_then(|language| language.ok())
2300            {
2301                self.restart_language_server(worktree_id, worktree_abs_path, language, cx);
2302            }
2303        }
2304
2305        None
2306    }
2307
2308    fn restart_language_server(
2309        &mut self,
2310        worktree_id: WorktreeId,
2311        fallback_path: Arc<Path>,
2312        language: Arc<Language>,
2313        cx: &mut ModelContext<Self>,
2314    ) {
2315        let adapter = if let Some(adapter) = language.lsp_adapter() {
2316            adapter
2317        } else {
2318            return;
2319        };
2320
2321        let server_name = adapter.name.clone();
2322        let stop = self.stop_language_server(worktree_id, server_name.clone(), cx);
2323        cx.spawn_weak(|this, mut cx| async move {
2324            let (original_root_path, orphaned_worktrees) = stop.await;
2325            if let Some(this) = this.upgrade(&cx) {
2326                this.update(&mut cx, |this, cx| {
2327                    // Attempt to restart using original server path. Fallback to passed in
2328                    // path if we could not retrieve the root path
2329                    let root_path = original_root_path
2330                        .map(|path_buf| Arc::from(path_buf.as_path()))
2331                        .unwrap_or(fallback_path);
2332
2333                    this.start_language_server(worktree_id, root_path, language, cx);
2334
2335                    // Lookup new server id and set it for each of the orphaned worktrees
2336                    if let Some(new_server_id) = this
2337                        .language_server_ids
2338                        .get(&(worktree_id, server_name.clone()))
2339                        .cloned()
2340                    {
2341                        for orphaned_worktree in orphaned_worktrees {
2342                            this.language_server_ids
2343                                .insert((orphaned_worktree, server_name.clone()), new_server_id);
2344                        }
2345                    }
2346                });
2347            }
2348        })
2349        .detach();
2350    }
2351
2352    fn on_lsp_progress(
2353        &mut self,
2354        progress: lsp::ProgressParams,
2355        server_id: usize,
2356        disk_based_diagnostics_progress_token: Option<String>,
2357        cx: &mut ModelContext<Self>,
2358    ) {
2359        let token = match progress.token {
2360            lsp::NumberOrString::String(token) => token,
2361            lsp::NumberOrString::Number(token) => {
2362                log::info!("skipping numeric progress token {}", token);
2363                return;
2364            }
2365        };
2366        let lsp::ProgressParamsValue::WorkDone(progress) = progress.value;
2367        let language_server_status =
2368            if let Some(status) = self.language_server_statuses.get_mut(&server_id) {
2369                status
2370            } else {
2371                return;
2372            };
2373
2374        if !language_server_status.progress_tokens.contains(&token) {
2375            return;
2376        }
2377
2378        let is_disk_based_diagnostics_progress = disk_based_diagnostics_progress_token
2379            .as_ref()
2380            .map_or(false, |disk_based_token| {
2381                token.starts_with(disk_based_token)
2382            });
2383
2384        match progress {
2385            lsp::WorkDoneProgress::Begin(report) => {
2386                if is_disk_based_diagnostics_progress {
2387                    language_server_status.has_pending_diagnostic_updates = true;
2388                    self.disk_based_diagnostics_started(server_id, cx);
2389                    self.broadcast_language_server_update(
2390                        server_id,
2391                        proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(
2392                            proto::LspDiskBasedDiagnosticsUpdating {},
2393                        ),
2394                    );
2395                } else {
2396                    self.on_lsp_work_start(
2397                        server_id,
2398                        token.clone(),
2399                        LanguageServerProgress {
2400                            message: report.message.clone(),
2401                            percentage: report.percentage.map(|p| p as usize),
2402                            last_update_at: Instant::now(),
2403                        },
2404                        cx,
2405                    );
2406                    self.broadcast_language_server_update(
2407                        server_id,
2408                        proto::update_language_server::Variant::WorkStart(proto::LspWorkStart {
2409                            token,
2410                            message: report.message,
2411                            percentage: report.percentage.map(|p| p as u32),
2412                        }),
2413                    );
2414                }
2415            }
2416            lsp::WorkDoneProgress::Report(report) => {
2417                if !is_disk_based_diagnostics_progress {
2418                    self.on_lsp_work_progress(
2419                        server_id,
2420                        token.clone(),
2421                        LanguageServerProgress {
2422                            message: report.message.clone(),
2423                            percentage: report.percentage.map(|p| p as usize),
2424                            last_update_at: Instant::now(),
2425                        },
2426                        cx,
2427                    );
2428                    self.broadcast_language_server_update(
2429                        server_id,
2430                        proto::update_language_server::Variant::WorkProgress(
2431                            proto::LspWorkProgress {
2432                                token,
2433                                message: report.message,
2434                                percentage: report.percentage.map(|p| p as u32),
2435                            },
2436                        ),
2437                    );
2438                }
2439            }
2440            lsp::WorkDoneProgress::End(_) => {
2441                language_server_status.progress_tokens.remove(&token);
2442
2443                if is_disk_based_diagnostics_progress {
2444                    language_server_status.has_pending_diagnostic_updates = false;
2445                    self.disk_based_diagnostics_finished(server_id, cx);
2446                    self.broadcast_language_server_update(
2447                        server_id,
2448                        proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
2449                            proto::LspDiskBasedDiagnosticsUpdated {},
2450                        ),
2451                    );
2452                } else {
2453                    self.on_lsp_work_end(server_id, token.clone(), cx);
2454                    self.broadcast_language_server_update(
2455                        server_id,
2456                        proto::update_language_server::Variant::WorkEnd(proto::LspWorkEnd {
2457                            token,
2458                        }),
2459                    );
2460                }
2461            }
2462        }
2463    }
2464
2465    fn on_lsp_work_start(
2466        &mut self,
2467        language_server_id: usize,
2468        token: String,
2469        progress: LanguageServerProgress,
2470        cx: &mut ModelContext<Self>,
2471    ) {
2472        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
2473            status.pending_work.insert(token, progress);
2474            cx.notify();
2475        }
2476    }
2477
2478    fn on_lsp_work_progress(
2479        &mut self,
2480        language_server_id: usize,
2481        token: String,
2482        progress: LanguageServerProgress,
2483        cx: &mut ModelContext<Self>,
2484    ) {
2485        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
2486            let entry = status
2487                .pending_work
2488                .entry(token)
2489                .or_insert(LanguageServerProgress {
2490                    message: Default::default(),
2491                    percentage: Default::default(),
2492                    last_update_at: progress.last_update_at,
2493                });
2494            if progress.message.is_some() {
2495                entry.message = progress.message;
2496            }
2497            if progress.percentage.is_some() {
2498                entry.percentage = progress.percentage;
2499            }
2500            entry.last_update_at = progress.last_update_at;
2501            cx.notify();
2502        }
2503    }
2504
2505    fn on_lsp_work_end(
2506        &mut self,
2507        language_server_id: usize,
2508        token: String,
2509        cx: &mut ModelContext<Self>,
2510    ) {
2511        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
2512            status.pending_work.remove(&token);
2513            cx.notify();
2514        }
2515    }
2516
2517    async fn on_lsp_workspace_edit(
2518        this: WeakModelHandle<Self>,
2519        params: lsp::ApplyWorkspaceEditParams,
2520        server_id: usize,
2521        adapter: Arc<CachedLspAdapter>,
2522        language_server: Arc<LanguageServer>,
2523        mut cx: AsyncAppContext,
2524    ) -> Result<lsp::ApplyWorkspaceEditResponse> {
2525        let this = this
2526            .upgrade(&cx)
2527            .ok_or_else(|| anyhow!("project project closed"))?;
2528        let transaction = Self::deserialize_workspace_edit(
2529            this.clone(),
2530            params.edit,
2531            true,
2532            adapter.clone(),
2533            language_server.clone(),
2534            &mut cx,
2535        )
2536        .await
2537        .log_err();
2538        this.update(&mut cx, |this, _| {
2539            if let Some(transaction) = transaction {
2540                this.last_workspace_edits_by_language_server
2541                    .insert(server_id, transaction);
2542            }
2543        });
2544        Ok(lsp::ApplyWorkspaceEditResponse {
2545            applied: true,
2546            failed_change: None,
2547            failure_reason: None,
2548        })
2549    }
2550
2551    fn broadcast_language_server_update(
2552        &self,
2553        language_server_id: usize,
2554        event: proto::update_language_server::Variant,
2555    ) {
2556        if let Some(project_id) = self.remote_id() {
2557            self.client
2558                .send(proto::UpdateLanguageServer {
2559                    project_id,
2560                    language_server_id: language_server_id as u64,
2561                    variant: Some(event),
2562                })
2563                .log_err();
2564        }
2565    }
2566
2567    pub fn language_server_statuses(
2568        &self,
2569    ) -> impl DoubleEndedIterator<Item = &LanguageServerStatus> {
2570        self.language_server_statuses.values()
2571    }
2572
2573    pub fn update_diagnostics(
2574        &mut self,
2575        language_server_id: usize,
2576        mut params: lsp::PublishDiagnosticsParams,
2577        disk_based_sources: &[String],
2578        cx: &mut ModelContext<Self>,
2579    ) -> Result<()> {
2580        let abs_path = params
2581            .uri
2582            .to_file_path()
2583            .map_err(|_| anyhow!("URI is not a file"))?;
2584        let mut diagnostics = Vec::default();
2585        let mut primary_diagnostic_group_ids = HashMap::default();
2586        let mut sources_by_group_id = HashMap::default();
2587        let mut supporting_diagnostics = HashMap::default();
2588
2589        // Ensure that primary diagnostics are always the most severe
2590        params.diagnostics.sort_by_key(|item| item.severity);
2591
2592        for diagnostic in &params.diagnostics {
2593            let source = diagnostic.source.as_ref();
2594            let code = diagnostic.code.as_ref().map(|code| match code {
2595                lsp::NumberOrString::Number(code) => code.to_string(),
2596                lsp::NumberOrString::String(code) => code.clone(),
2597            });
2598            let range = range_from_lsp(diagnostic.range);
2599            let is_supporting = diagnostic
2600                .related_information
2601                .as_ref()
2602                .map_or(false, |infos| {
2603                    infos.iter().any(|info| {
2604                        primary_diagnostic_group_ids.contains_key(&(
2605                            source,
2606                            code.clone(),
2607                            range_from_lsp(info.location.range),
2608                        ))
2609                    })
2610                });
2611
2612            let is_unnecessary = diagnostic.tags.as_ref().map_or(false, |tags| {
2613                tags.iter().any(|tag| *tag == DiagnosticTag::UNNECESSARY)
2614            });
2615
2616            if is_supporting {
2617                supporting_diagnostics.insert(
2618                    (source, code.clone(), range),
2619                    (diagnostic.severity, is_unnecessary),
2620                );
2621            } else {
2622                let group_id = post_inc(&mut self.next_diagnostic_group_id);
2623                let is_disk_based =
2624                    source.map_or(false, |source| disk_based_sources.contains(source));
2625
2626                sources_by_group_id.insert(group_id, source);
2627                primary_diagnostic_group_ids
2628                    .insert((source, code.clone(), range.clone()), group_id);
2629
2630                diagnostics.push(DiagnosticEntry {
2631                    range,
2632                    diagnostic: Diagnostic {
2633                        code: code.clone(),
2634                        severity: diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR),
2635                        message: diagnostic.message.clone(),
2636                        group_id,
2637                        is_primary: true,
2638                        is_valid: true,
2639                        is_disk_based,
2640                        is_unnecessary,
2641                    },
2642                });
2643                if let Some(infos) = &diagnostic.related_information {
2644                    for info in infos {
2645                        if info.location.uri == params.uri && !info.message.is_empty() {
2646                            let range = range_from_lsp(info.location.range);
2647                            diagnostics.push(DiagnosticEntry {
2648                                range,
2649                                diagnostic: Diagnostic {
2650                                    code: code.clone(),
2651                                    severity: DiagnosticSeverity::INFORMATION,
2652                                    message: info.message.clone(),
2653                                    group_id,
2654                                    is_primary: false,
2655                                    is_valid: true,
2656                                    is_disk_based,
2657                                    is_unnecessary: false,
2658                                },
2659                            });
2660                        }
2661                    }
2662                }
2663            }
2664        }
2665
2666        for entry in &mut diagnostics {
2667            let diagnostic = &mut entry.diagnostic;
2668            if !diagnostic.is_primary {
2669                let source = *sources_by_group_id.get(&diagnostic.group_id).unwrap();
2670                if let Some(&(severity, is_unnecessary)) = supporting_diagnostics.get(&(
2671                    source,
2672                    diagnostic.code.clone(),
2673                    entry.range.clone(),
2674                )) {
2675                    if let Some(severity) = severity {
2676                        diagnostic.severity = severity;
2677                    }
2678                    diagnostic.is_unnecessary = is_unnecessary;
2679                }
2680            }
2681        }
2682
2683        self.update_diagnostic_entries(
2684            language_server_id,
2685            abs_path,
2686            params.version,
2687            diagnostics,
2688            cx,
2689        )?;
2690        Ok(())
2691    }
2692
2693    pub fn update_diagnostic_entries(
2694        &mut self,
2695        language_server_id: usize,
2696        abs_path: PathBuf,
2697        version: Option<i32>,
2698        diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
2699        cx: &mut ModelContext<Project>,
2700    ) -> Result<(), anyhow::Error> {
2701        let (worktree, relative_path) = self
2702            .find_local_worktree(&abs_path, cx)
2703            .ok_or_else(|| anyhow!("no worktree found for diagnostics"))?;
2704
2705        let project_path = ProjectPath {
2706            worktree_id: worktree.read(cx).id(),
2707            path: relative_path.into(),
2708        };
2709
2710        if let Some(buffer) = self.get_open_buffer(&project_path, cx) {
2711            self.update_buffer_diagnostics(&buffer, diagnostics.clone(), version, cx)?;
2712        }
2713
2714        let updated = worktree.update(cx, |worktree, cx| {
2715            worktree
2716                .as_local_mut()
2717                .ok_or_else(|| anyhow!("not a local worktree"))?
2718                .update_diagnostics(
2719                    language_server_id,
2720                    project_path.path.clone(),
2721                    diagnostics,
2722                    cx,
2723                )
2724        })?;
2725        if updated {
2726            cx.emit(Event::DiagnosticsUpdated {
2727                language_server_id,
2728                path: project_path,
2729            });
2730        }
2731        Ok(())
2732    }
2733
2734    fn update_buffer_diagnostics(
2735        &mut self,
2736        buffer: &ModelHandle<Buffer>,
2737        mut diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
2738        version: Option<i32>,
2739        cx: &mut ModelContext<Self>,
2740    ) -> Result<()> {
2741        fn compare_diagnostics(a: &Diagnostic, b: &Diagnostic) -> Ordering {
2742            Ordering::Equal
2743                .then_with(|| b.is_primary.cmp(&a.is_primary))
2744                .then_with(|| a.is_disk_based.cmp(&b.is_disk_based))
2745                .then_with(|| a.severity.cmp(&b.severity))
2746                .then_with(|| a.message.cmp(&b.message))
2747        }
2748
2749        let snapshot = self.buffer_snapshot_for_lsp_version(buffer, version, cx)?;
2750
2751        diagnostics.sort_unstable_by(|a, b| {
2752            Ordering::Equal
2753                .then_with(|| a.range.start.cmp(&b.range.start))
2754                .then_with(|| b.range.end.cmp(&a.range.end))
2755                .then_with(|| compare_diagnostics(&a.diagnostic, &b.diagnostic))
2756        });
2757
2758        let mut sanitized_diagnostics = Vec::new();
2759        let edits_since_save = Patch::new(
2760            snapshot
2761                .edits_since::<Unclipped<PointUtf16>>(buffer.read(cx).saved_version())
2762                .collect(),
2763        );
2764        for entry in diagnostics {
2765            let start;
2766            let end;
2767            if entry.diagnostic.is_disk_based {
2768                // Some diagnostics are based on files on disk instead of buffers'
2769                // current contents. Adjust these diagnostics' ranges to reflect
2770                // any unsaved edits.
2771                start = edits_since_save.old_to_new(entry.range.start);
2772                end = edits_since_save.old_to_new(entry.range.end);
2773            } else {
2774                start = entry.range.start;
2775                end = entry.range.end;
2776            }
2777
2778            let mut range = snapshot.clip_point_utf16(start, Bias::Left)
2779                ..snapshot.clip_point_utf16(end, Bias::Right);
2780
2781            // Expand empty ranges by one codepoint
2782            if range.start == range.end {
2783                // This will be go to the next boundary when being clipped
2784                range.end.column += 1;
2785                range.end = snapshot.clip_point_utf16(Unclipped(range.end), Bias::Right);
2786                if range.start == range.end && range.end.column > 0 {
2787                    range.start.column -= 1;
2788                    range.end = snapshot.clip_point_utf16(Unclipped(range.end), Bias::Left);
2789                }
2790            }
2791
2792            sanitized_diagnostics.push(DiagnosticEntry {
2793                range,
2794                diagnostic: entry.diagnostic,
2795            });
2796        }
2797        drop(edits_since_save);
2798
2799        let set = DiagnosticSet::new(sanitized_diagnostics, &snapshot);
2800        buffer.update(cx, |buffer, cx| buffer.update_diagnostics(set, cx));
2801        Ok(())
2802    }
2803
2804    pub fn reload_buffers(
2805        &self,
2806        buffers: HashSet<ModelHandle<Buffer>>,
2807        push_to_history: bool,
2808        cx: &mut ModelContext<Self>,
2809    ) -> Task<Result<ProjectTransaction>> {
2810        let mut local_buffers = Vec::new();
2811        let mut remote_buffers = None;
2812        for buffer_handle in buffers {
2813            let buffer = buffer_handle.read(cx);
2814            if buffer.is_dirty() {
2815                if let Some(file) = File::from_dyn(buffer.file()) {
2816                    if file.is_local() {
2817                        local_buffers.push(buffer_handle);
2818                    } else {
2819                        remote_buffers.get_or_insert(Vec::new()).push(buffer_handle);
2820                    }
2821                }
2822            }
2823        }
2824
2825        let remote_buffers = self.remote_id().zip(remote_buffers);
2826        let client = self.client.clone();
2827
2828        cx.spawn(|this, mut cx| async move {
2829            let mut project_transaction = ProjectTransaction::default();
2830
2831            if let Some((project_id, remote_buffers)) = remote_buffers {
2832                let response = client
2833                    .request(proto::ReloadBuffers {
2834                        project_id,
2835                        buffer_ids: remote_buffers
2836                            .iter()
2837                            .map(|buffer| buffer.read_with(&cx, |buffer, _| buffer.remote_id()))
2838                            .collect(),
2839                    })
2840                    .await?
2841                    .transaction
2842                    .ok_or_else(|| anyhow!("missing transaction"))?;
2843                project_transaction = this
2844                    .update(&mut cx, |this, cx| {
2845                        this.deserialize_project_transaction(response, push_to_history, cx)
2846                    })
2847                    .await?;
2848            }
2849
2850            for buffer in local_buffers {
2851                let transaction = buffer
2852                    .update(&mut cx, |buffer, cx| buffer.reload(cx))
2853                    .await?;
2854                buffer.update(&mut cx, |buffer, cx| {
2855                    if let Some(transaction) = transaction {
2856                        if !push_to_history {
2857                            buffer.forget_transaction(transaction.id);
2858                        }
2859                        project_transaction.0.insert(cx.handle(), transaction);
2860                    }
2861                });
2862            }
2863
2864            Ok(project_transaction)
2865        })
2866    }
2867
2868    pub fn format(
2869        &self,
2870        buffers: HashSet<ModelHandle<Buffer>>,
2871        push_to_history: bool,
2872        trigger: FormatTrigger,
2873        cx: &mut ModelContext<Project>,
2874    ) -> Task<Result<ProjectTransaction>> {
2875        if self.is_local() {
2876            let mut buffers_with_paths_and_servers = buffers
2877                .into_iter()
2878                .filter_map(|buffer_handle| {
2879                    let buffer = buffer_handle.read(cx);
2880                    let file = File::from_dyn(buffer.file())?;
2881                    let buffer_abs_path = file.as_local().map(|f| f.abs_path(cx));
2882                    let server = self
2883                        .language_server_for_buffer(buffer, cx)
2884                        .map(|s| s.1.clone());
2885                    Some((buffer_handle, buffer_abs_path, server))
2886                })
2887                .collect::<Vec<_>>();
2888
2889            cx.spawn(|this, mut cx| async move {
2890                // Do not allow multiple concurrent formatting requests for the
2891                // same buffer.
2892                this.update(&mut cx, |this, _| {
2893                    buffers_with_paths_and_servers
2894                        .retain(|(buffer, _, _)| this.buffers_being_formatted.insert(buffer.id()));
2895                });
2896
2897                let _cleanup = defer({
2898                    let this = this.clone();
2899                    let mut cx = cx.clone();
2900                    let buffers = &buffers_with_paths_and_servers;
2901                    move || {
2902                        this.update(&mut cx, |this, _| {
2903                            for (buffer, _, _) in buffers {
2904                                this.buffers_being_formatted.remove(&buffer.id());
2905                            }
2906                        });
2907                    }
2908                });
2909
2910                let mut project_transaction = ProjectTransaction::default();
2911                for (buffer, buffer_abs_path, language_server) in &buffers_with_paths_and_servers {
2912                    let (
2913                        format_on_save,
2914                        remove_trailing_whitespace,
2915                        ensure_final_newline,
2916                        formatter,
2917                        tab_size,
2918                    ) = buffer.read_with(&cx, |buffer, cx| {
2919                        let settings = cx.global::<Settings>();
2920                        let language_name = buffer.language().map(|language| language.name());
2921                        (
2922                            settings.format_on_save(language_name.as_deref()),
2923                            settings.remove_trailing_whitespace_on_save(language_name.as_deref()),
2924                            settings.ensure_final_newline_on_save(language_name.as_deref()),
2925                            settings.formatter(language_name.as_deref()),
2926                            settings.tab_size(language_name.as_deref()),
2927                        )
2928                    });
2929
2930                    // First, format buffer's whitespace according to the settings.
2931                    let trailing_whitespace_diff = if remove_trailing_whitespace {
2932                        Some(
2933                            buffer
2934                                .read_with(&cx, |b, cx| b.remove_trailing_whitespace(cx))
2935                                .await,
2936                        )
2937                    } else {
2938                        None
2939                    };
2940                    let whitespace_transaction_id = buffer.update(&mut cx, |buffer, cx| {
2941                        buffer.finalize_last_transaction();
2942                        buffer.start_transaction();
2943                        if let Some(diff) = trailing_whitespace_diff {
2944                            buffer.apply_diff(diff, cx);
2945                        }
2946                        if ensure_final_newline {
2947                            buffer.ensure_final_newline(cx);
2948                        }
2949                        buffer.end_transaction(cx)
2950                    });
2951
2952                    // Currently, formatting operations are represented differently depending on
2953                    // whether they come from a language server or an external command.
2954                    enum FormatOperation {
2955                        Lsp(Vec<(Range<Anchor>, String)>),
2956                        External(Diff),
2957                    }
2958
2959                    // Apply language-specific formatting using either a language server
2960                    // or external command.
2961                    let mut format_operation = None;
2962                    match (formatter, format_on_save) {
2963                        (_, FormatOnSave::Off) if trigger == FormatTrigger::Save => {}
2964
2965                        (Formatter::LanguageServer, FormatOnSave::On | FormatOnSave::Off)
2966                        | (_, FormatOnSave::LanguageServer) => {
2967                            if let Some((language_server, buffer_abs_path)) =
2968                                language_server.as_ref().zip(buffer_abs_path.as_ref())
2969                            {
2970                                format_operation = Some(FormatOperation::Lsp(
2971                                    Self::format_via_lsp(
2972                                        &this,
2973                                        &buffer,
2974                                        buffer_abs_path,
2975                                        &language_server,
2976                                        tab_size,
2977                                        &mut cx,
2978                                    )
2979                                    .await
2980                                    .context("failed to format via language server")?,
2981                                ));
2982                            }
2983                        }
2984
2985                        (
2986                            Formatter::External { command, arguments },
2987                            FormatOnSave::On | FormatOnSave::Off,
2988                        )
2989                        | (_, FormatOnSave::External { command, arguments }) => {
2990                            if let Some(buffer_abs_path) = buffer_abs_path {
2991                                format_operation = Self::format_via_external_command(
2992                                    &buffer,
2993                                    &buffer_abs_path,
2994                                    &command,
2995                                    &arguments,
2996                                    &mut cx,
2997                                )
2998                                .await
2999                                .context(format!(
3000                                    "failed to format via external command {:?}",
3001                                    command
3002                                ))?
3003                                .map(FormatOperation::External);
3004                            }
3005                        }
3006                    };
3007
3008                    buffer.update(&mut cx, |b, cx| {
3009                        // If the buffer had its whitespace formatted and was edited while the language-specific
3010                        // formatting was being computed, avoid applying the language-specific formatting, because
3011                        // it can't be grouped with the whitespace formatting in the undo history.
3012                        if let Some(transaction_id) = whitespace_transaction_id {
3013                            if b.peek_undo_stack()
3014                                .map_or(true, |e| e.transaction_id() != transaction_id)
3015                            {
3016                                format_operation.take();
3017                            }
3018                        }
3019
3020                        // Apply any language-specific formatting, and group the two formatting operations
3021                        // in the buffer's undo history.
3022                        if let Some(operation) = format_operation {
3023                            match operation {
3024                                FormatOperation::Lsp(edits) => {
3025                                    b.edit(edits, None, cx);
3026                                }
3027                                FormatOperation::External(diff) => {
3028                                    b.apply_diff(diff, cx);
3029                                }
3030                            }
3031
3032                            if let Some(transaction_id) = whitespace_transaction_id {
3033                                b.group_until_transaction(transaction_id);
3034                            }
3035                        }
3036
3037                        if let Some(transaction) = b.finalize_last_transaction().cloned() {
3038                            if !push_to_history {
3039                                b.forget_transaction(transaction.id);
3040                            }
3041                            project_transaction.0.insert(buffer.clone(), transaction);
3042                        }
3043                    });
3044                }
3045
3046                Ok(project_transaction)
3047            })
3048        } else {
3049            let remote_id = self.remote_id();
3050            let client = self.client.clone();
3051            cx.spawn(|this, mut cx| async move {
3052                let mut project_transaction = ProjectTransaction::default();
3053                if let Some(project_id) = remote_id {
3054                    let response = client
3055                        .request(proto::FormatBuffers {
3056                            project_id,
3057                            trigger: trigger as i32,
3058                            buffer_ids: buffers
3059                                .iter()
3060                                .map(|buffer| buffer.read_with(&cx, |buffer, _| buffer.remote_id()))
3061                                .collect(),
3062                        })
3063                        .await?
3064                        .transaction
3065                        .ok_or_else(|| anyhow!("missing transaction"))?;
3066                    project_transaction = this
3067                        .update(&mut cx, |this, cx| {
3068                            this.deserialize_project_transaction(response, push_to_history, cx)
3069                        })
3070                        .await?;
3071                }
3072                Ok(project_transaction)
3073            })
3074        }
3075    }
3076
3077    async fn format_via_lsp(
3078        this: &ModelHandle<Self>,
3079        buffer: &ModelHandle<Buffer>,
3080        abs_path: &Path,
3081        language_server: &Arc<LanguageServer>,
3082        tab_size: NonZeroU32,
3083        cx: &mut AsyncAppContext,
3084    ) -> Result<Vec<(Range<Anchor>, String)>> {
3085        let text_document =
3086            lsp::TextDocumentIdentifier::new(lsp::Url::from_file_path(abs_path).unwrap());
3087        let capabilities = &language_server.capabilities();
3088        let lsp_edits = if capabilities
3089            .document_formatting_provider
3090            .as_ref()
3091            .map_or(false, |provider| *provider != lsp::OneOf::Left(false))
3092        {
3093            language_server
3094                .request::<lsp::request::Formatting>(lsp::DocumentFormattingParams {
3095                    text_document,
3096                    options: lsp::FormattingOptions {
3097                        tab_size: tab_size.into(),
3098                        insert_spaces: true,
3099                        insert_final_newline: Some(true),
3100                        ..Default::default()
3101                    },
3102                    work_done_progress_params: Default::default(),
3103                })
3104                .await?
3105        } else if capabilities
3106            .document_range_formatting_provider
3107            .as_ref()
3108            .map_or(false, |provider| *provider != lsp::OneOf::Left(false))
3109        {
3110            let buffer_start = lsp::Position::new(0, 0);
3111            let buffer_end =
3112                buffer.read_with(cx, |buffer, _| point_to_lsp(buffer.max_point_utf16()));
3113            language_server
3114                .request::<lsp::request::RangeFormatting>(lsp::DocumentRangeFormattingParams {
3115                    text_document,
3116                    range: lsp::Range::new(buffer_start, buffer_end),
3117                    options: lsp::FormattingOptions {
3118                        tab_size: tab_size.into(),
3119                        insert_spaces: true,
3120                        insert_final_newline: Some(true),
3121                        ..Default::default()
3122                    },
3123                    work_done_progress_params: Default::default(),
3124                })
3125                .await?
3126        } else {
3127            None
3128        };
3129
3130        if let Some(lsp_edits) = lsp_edits {
3131            this.update(cx, |this, cx| {
3132                this.edits_from_lsp(buffer, lsp_edits, None, cx)
3133            })
3134            .await
3135        } else {
3136            Ok(Default::default())
3137        }
3138    }
3139
3140    async fn format_via_external_command(
3141        buffer: &ModelHandle<Buffer>,
3142        buffer_abs_path: &Path,
3143        command: &str,
3144        arguments: &[String],
3145        cx: &mut AsyncAppContext,
3146    ) -> Result<Option<Diff>> {
3147        let working_dir_path = buffer.read_with(cx, |buffer, cx| {
3148            let file = File::from_dyn(buffer.file())?;
3149            let worktree = file.worktree.read(cx).as_local()?;
3150            let mut worktree_path = worktree.abs_path().to_path_buf();
3151            if worktree.root_entry()?.is_file() {
3152                worktree_path.pop();
3153            }
3154            Some(worktree_path)
3155        });
3156
3157        if let Some(working_dir_path) = working_dir_path {
3158            let mut child =
3159                smol::process::Command::new(command)
3160                    .args(arguments.iter().map(|arg| {
3161                        arg.replace("{buffer_path}", &buffer_abs_path.to_string_lossy())
3162                    }))
3163                    .current_dir(&working_dir_path)
3164                    .stdin(smol::process::Stdio::piped())
3165                    .stdout(smol::process::Stdio::piped())
3166                    .stderr(smol::process::Stdio::piped())
3167                    .spawn()?;
3168            let stdin = child
3169                .stdin
3170                .as_mut()
3171                .ok_or_else(|| anyhow!("failed to acquire stdin"))?;
3172            let text = buffer.read_with(cx, |buffer, _| buffer.as_rope().clone());
3173            for chunk in text.chunks() {
3174                stdin.write_all(chunk.as_bytes()).await?;
3175            }
3176            stdin.flush().await?;
3177
3178            let output = child.output().await?;
3179            if !output.status.success() {
3180                return Err(anyhow!(
3181                    "command failed with exit code {:?}:\nstdout: {}\nstderr: {}",
3182                    output.status.code(),
3183                    String::from_utf8_lossy(&output.stdout),
3184                    String::from_utf8_lossy(&output.stderr),
3185                ));
3186            }
3187
3188            let stdout = String::from_utf8(output.stdout)?;
3189            Ok(Some(
3190                buffer
3191                    .read_with(cx, |buffer, cx| buffer.diff(stdout, cx))
3192                    .await,
3193            ))
3194        } else {
3195            Ok(None)
3196        }
3197    }
3198
3199    pub fn definition<T: ToPointUtf16>(
3200        &self,
3201        buffer: &ModelHandle<Buffer>,
3202        position: T,
3203        cx: &mut ModelContext<Self>,
3204    ) -> Task<Result<Vec<LocationLink>>> {
3205        let position = position.to_point_utf16(buffer.read(cx));
3206        self.request_lsp(buffer.clone(), GetDefinition { position }, cx)
3207    }
3208
3209    pub fn type_definition<T: ToPointUtf16>(
3210        &self,
3211        buffer: &ModelHandle<Buffer>,
3212        position: T,
3213        cx: &mut ModelContext<Self>,
3214    ) -> Task<Result<Vec<LocationLink>>> {
3215        let position = position.to_point_utf16(buffer.read(cx));
3216        self.request_lsp(buffer.clone(), GetTypeDefinition { position }, cx)
3217    }
3218
3219    pub fn references<T: ToPointUtf16>(
3220        &self,
3221        buffer: &ModelHandle<Buffer>,
3222        position: T,
3223        cx: &mut ModelContext<Self>,
3224    ) -> Task<Result<Vec<Location>>> {
3225        let position = position.to_point_utf16(buffer.read(cx));
3226        self.request_lsp(buffer.clone(), GetReferences { position }, cx)
3227    }
3228
3229    pub fn document_highlights<T: ToPointUtf16>(
3230        &self,
3231        buffer: &ModelHandle<Buffer>,
3232        position: T,
3233        cx: &mut ModelContext<Self>,
3234    ) -> Task<Result<Vec<DocumentHighlight>>> {
3235        let position = position.to_point_utf16(buffer.read(cx));
3236        self.request_lsp(buffer.clone(), GetDocumentHighlights { position }, cx)
3237    }
3238
3239    pub fn symbols(&self, query: &str, cx: &mut ModelContext<Self>) -> Task<Result<Vec<Symbol>>> {
3240        if self.is_local() {
3241            let mut requests = Vec::new();
3242            for ((worktree_id, _), server_id) in self.language_server_ids.iter() {
3243                let worktree_id = *worktree_id;
3244                if let Some(worktree) = self
3245                    .worktree_for_id(worktree_id, cx)
3246                    .and_then(|worktree| worktree.read(cx).as_local())
3247                {
3248                    if let Some(LanguageServerState::Running {
3249                        adapter,
3250                        language,
3251                        server,
3252                        ..
3253                    }) = self.language_servers.get(server_id)
3254                    {
3255                        let adapter = adapter.clone();
3256                        let language = language.clone();
3257                        let worktree_abs_path = worktree.abs_path().clone();
3258                        requests.push(
3259                            server
3260                                .request::<lsp::request::WorkspaceSymbol>(
3261                                    lsp::WorkspaceSymbolParams {
3262                                        query: query.to_string(),
3263                                        ..Default::default()
3264                                    },
3265                                )
3266                                .log_err()
3267                                .map(move |response| {
3268                                    (
3269                                        adapter,
3270                                        language,
3271                                        worktree_id,
3272                                        worktree_abs_path,
3273                                        response.unwrap_or_default(),
3274                                    )
3275                                }),
3276                        );
3277                    }
3278                }
3279            }
3280
3281            cx.spawn_weak(|this, cx| async move {
3282                let responses = futures::future::join_all(requests).await;
3283                let this = if let Some(this) = this.upgrade(&cx) {
3284                    this
3285                } else {
3286                    return Ok(Default::default());
3287                };
3288                let symbols = this.read_with(&cx, |this, cx| {
3289                    let mut symbols = Vec::new();
3290                    for (
3291                        adapter,
3292                        adapter_language,
3293                        source_worktree_id,
3294                        worktree_abs_path,
3295                        response,
3296                    ) in responses
3297                    {
3298                        symbols.extend(response.into_iter().flatten().filter_map(|lsp_symbol| {
3299                            let abs_path = lsp_symbol.location.uri.to_file_path().ok()?;
3300                            let mut worktree_id = source_worktree_id;
3301                            let path;
3302                            if let Some((worktree, rel_path)) =
3303                                this.find_local_worktree(&abs_path, cx)
3304                            {
3305                                worktree_id = worktree.read(cx).id();
3306                                path = rel_path;
3307                            } else {
3308                                path = relativize_path(&worktree_abs_path, &abs_path);
3309                            }
3310
3311                            let project_path = ProjectPath {
3312                                worktree_id,
3313                                path: path.into(),
3314                            };
3315                            let signature = this.symbol_signature(&project_path);
3316                            let adapter_language = adapter_language.clone();
3317                            let language = this
3318                                .languages
3319                                .language_for_path(&project_path.path)
3320                                .unwrap_or_else(move |_| adapter_language);
3321                            let language_server_name = adapter.name.clone();
3322                            Some(async move {
3323                                let language = language.await;
3324                                let label = language
3325                                    .label_for_symbol(&lsp_symbol.name, lsp_symbol.kind)
3326                                    .await;
3327
3328                                Symbol {
3329                                    language_server_name,
3330                                    source_worktree_id,
3331                                    path: project_path,
3332                                    label: label.unwrap_or_else(|| {
3333                                        CodeLabel::plain(lsp_symbol.name.clone(), None)
3334                                    }),
3335                                    kind: lsp_symbol.kind,
3336                                    name: lsp_symbol.name,
3337                                    range: range_from_lsp(lsp_symbol.location.range),
3338                                    signature,
3339                                }
3340                            })
3341                        }));
3342                    }
3343                    symbols
3344                });
3345                Ok(futures::future::join_all(symbols).await)
3346            })
3347        } else if let Some(project_id) = self.remote_id() {
3348            let request = self.client.request(proto::GetProjectSymbols {
3349                project_id,
3350                query: query.to_string(),
3351            });
3352            cx.spawn_weak(|this, cx| async move {
3353                let response = request.await?;
3354                let mut symbols = Vec::new();
3355                if let Some(this) = this.upgrade(&cx) {
3356                    let new_symbols = this.read_with(&cx, |this, _| {
3357                        response
3358                            .symbols
3359                            .into_iter()
3360                            .map(|symbol| this.deserialize_symbol(symbol))
3361                            .collect::<Vec<_>>()
3362                    });
3363                    symbols = futures::future::join_all(new_symbols)
3364                        .await
3365                        .into_iter()
3366                        .filter_map(|symbol| symbol.log_err())
3367                        .collect::<Vec<_>>();
3368                }
3369                Ok(symbols)
3370            })
3371        } else {
3372            Task::ready(Ok(Default::default()))
3373        }
3374    }
3375
3376    pub fn open_buffer_for_symbol(
3377        &mut self,
3378        symbol: &Symbol,
3379        cx: &mut ModelContext<Self>,
3380    ) -> Task<Result<ModelHandle<Buffer>>> {
3381        if self.is_local() {
3382            let language_server_id = if let Some(id) = self.language_server_ids.get(&(
3383                symbol.source_worktree_id,
3384                symbol.language_server_name.clone(),
3385            )) {
3386                *id
3387            } else {
3388                return Task::ready(Err(anyhow!(
3389                    "language server for worktree and language not found"
3390                )));
3391            };
3392
3393            let worktree_abs_path = if let Some(worktree_abs_path) = self
3394                .worktree_for_id(symbol.path.worktree_id, cx)
3395                .and_then(|worktree| worktree.read(cx).as_local())
3396                .map(|local_worktree| local_worktree.abs_path())
3397            {
3398                worktree_abs_path
3399            } else {
3400                return Task::ready(Err(anyhow!("worktree not found for symbol")));
3401            };
3402            let symbol_abs_path = worktree_abs_path.join(&symbol.path.path);
3403            let symbol_uri = if let Ok(uri) = lsp::Url::from_file_path(symbol_abs_path) {
3404                uri
3405            } else {
3406                return Task::ready(Err(anyhow!("invalid symbol path")));
3407            };
3408
3409            self.open_local_buffer_via_lsp(
3410                symbol_uri,
3411                language_server_id,
3412                symbol.language_server_name.clone(),
3413                cx,
3414            )
3415        } else if let Some(project_id) = self.remote_id() {
3416            let request = self.client.request(proto::OpenBufferForSymbol {
3417                project_id,
3418                symbol: Some(serialize_symbol(symbol)),
3419            });
3420            cx.spawn(|this, mut cx| async move {
3421                let response = request.await?;
3422                this.update(&mut cx, |this, cx| {
3423                    this.wait_for_remote_buffer(response.buffer_id, cx)
3424                })
3425                .await
3426            })
3427        } else {
3428            Task::ready(Err(anyhow!("project does not have a remote id")))
3429        }
3430    }
3431
3432    pub fn hover<T: ToPointUtf16>(
3433        &self,
3434        buffer: &ModelHandle<Buffer>,
3435        position: T,
3436        cx: &mut ModelContext<Self>,
3437    ) -> Task<Result<Option<Hover>>> {
3438        let position = position.to_point_utf16(buffer.read(cx));
3439        self.request_lsp(buffer.clone(), GetHover { position }, cx)
3440    }
3441
3442    pub fn completions<T: ToPointUtf16>(
3443        &self,
3444        source_buffer_handle: &ModelHandle<Buffer>,
3445        position: T,
3446        cx: &mut ModelContext<Self>,
3447    ) -> Task<Result<Vec<Completion>>> {
3448        let source_buffer_handle = source_buffer_handle.clone();
3449        let source_buffer = source_buffer_handle.read(cx);
3450        let buffer_id = source_buffer.remote_id();
3451        let language = source_buffer.language().cloned();
3452        let worktree;
3453        let buffer_abs_path;
3454        if let Some(file) = File::from_dyn(source_buffer.file()) {
3455            worktree = file.worktree.clone();
3456            buffer_abs_path = file.as_local().map(|f| f.abs_path(cx));
3457        } else {
3458            return Task::ready(Ok(Default::default()));
3459        };
3460
3461        let position = Unclipped(position.to_point_utf16(source_buffer));
3462        let anchor = source_buffer.anchor_after(position);
3463
3464        if worktree.read(cx).as_local().is_some() {
3465            let buffer_abs_path = buffer_abs_path.unwrap();
3466            let lang_server =
3467                if let Some((_, server)) = self.language_server_for_buffer(source_buffer, cx) {
3468                    server.clone()
3469                } else {
3470                    return Task::ready(Ok(Default::default()));
3471                };
3472
3473            cx.spawn(|_, cx| async move {
3474                let completions = lang_server
3475                    .request::<lsp::request::Completion>(lsp::CompletionParams {
3476                        text_document_position: lsp::TextDocumentPositionParams::new(
3477                            lsp::TextDocumentIdentifier::new(
3478                                lsp::Url::from_file_path(buffer_abs_path).unwrap(),
3479                            ),
3480                            point_to_lsp(position.0),
3481                        ),
3482                        context: Default::default(),
3483                        work_done_progress_params: Default::default(),
3484                        partial_result_params: Default::default(),
3485                    })
3486                    .await
3487                    .context("lsp completion request failed")?;
3488
3489                let completions = if let Some(completions) = completions {
3490                    match completions {
3491                        lsp::CompletionResponse::Array(completions) => completions,
3492                        lsp::CompletionResponse::List(list) => list.items,
3493                    }
3494                } else {
3495                    Default::default()
3496                };
3497
3498                let completions = source_buffer_handle.read_with(&cx, |this, _| {
3499                    let snapshot = this.snapshot();
3500                    let clipped_position = this.clip_point_utf16(position, Bias::Left);
3501                    let mut range_for_token = None;
3502                    completions
3503                        .into_iter()
3504                        .filter_map(move |mut lsp_completion| {
3505                            // For now, we can only handle additional edits if they are returned
3506                            // when resolving the completion, not if they are present initially.
3507                            if lsp_completion
3508                                .additional_text_edits
3509                                .as_ref()
3510                                .map_or(false, |edits| !edits.is_empty())
3511                            {
3512                                return None;
3513                            }
3514
3515                            let (old_range, mut new_text) = match lsp_completion.text_edit.as_ref()
3516                            {
3517                                // If the language server provides a range to overwrite, then
3518                                // check that the range is valid.
3519                                Some(lsp::CompletionTextEdit::Edit(edit)) => {
3520                                    let range = range_from_lsp(edit.range);
3521                                    let start = snapshot.clip_point_utf16(range.start, Bias::Left);
3522                                    let end = snapshot.clip_point_utf16(range.end, Bias::Left);
3523                                    if start != range.start.0 || end != range.end.0 {
3524                                        log::info!("completion out of expected range");
3525                                        return None;
3526                                    }
3527                                    (
3528                                        snapshot.anchor_before(start)..snapshot.anchor_after(end),
3529                                        edit.new_text.clone(),
3530                                    )
3531                                }
3532                                // If the language server does not provide a range, then infer
3533                                // the range based on the syntax tree.
3534                                None => {
3535                                    if position.0 != clipped_position {
3536                                        log::info!("completion out of expected range");
3537                                        return None;
3538                                    }
3539                                    let Range { start, end } = range_for_token
3540                                        .get_or_insert_with(|| {
3541                                            let offset = position.to_offset(&snapshot);
3542                                            let (range, kind) = snapshot.surrounding_word(offset);
3543                                            if kind == Some(CharKind::Word) {
3544                                                range
3545                                            } else {
3546                                                offset..offset
3547                                            }
3548                                        })
3549                                        .clone();
3550                                    let text = lsp_completion
3551                                        .insert_text
3552                                        .as_ref()
3553                                        .unwrap_or(&lsp_completion.label)
3554                                        .clone();
3555                                    (
3556                                        snapshot.anchor_before(start)..snapshot.anchor_after(end),
3557                                        text,
3558                                    )
3559                                }
3560                                Some(lsp::CompletionTextEdit::InsertAndReplace(_)) => {
3561                                    log::info!("unsupported insert/replace completion");
3562                                    return None;
3563                                }
3564                            };
3565
3566                            LineEnding::normalize(&mut new_text);
3567                            let language = language.clone();
3568                            Some(async move {
3569                                let mut label = None;
3570                                if let Some(language) = language {
3571                                    language.process_completion(&mut lsp_completion).await;
3572                                    label = language.label_for_completion(&lsp_completion).await;
3573                                }
3574                                Completion {
3575                                    old_range,
3576                                    new_text,
3577                                    label: label.unwrap_or_else(|| {
3578                                        CodeLabel::plain(
3579                                            lsp_completion.label.clone(),
3580                                            lsp_completion.filter_text.as_deref(),
3581                                        )
3582                                    }),
3583                                    lsp_completion,
3584                                }
3585                            })
3586                        })
3587                });
3588
3589                Ok(futures::future::join_all(completions).await)
3590            })
3591        } else if let Some(project_id) = self.remote_id() {
3592            let rpc = self.client.clone();
3593            let message = proto::GetCompletions {
3594                project_id,
3595                buffer_id,
3596                position: Some(language::proto::serialize_anchor(&anchor)),
3597                version: serialize_version(&source_buffer.version()),
3598            };
3599            cx.spawn_weak(|this, mut cx| async move {
3600                let response = rpc.request(message).await?;
3601
3602                if this
3603                    .upgrade(&cx)
3604                    .ok_or_else(|| anyhow!("project was dropped"))?
3605                    .read_with(&cx, |this, _| this.is_read_only())
3606                {
3607                    return Err(anyhow!(
3608                        "failed to get completions: project was disconnected"
3609                    ));
3610                } else {
3611                    source_buffer_handle
3612                        .update(&mut cx, |buffer, _| {
3613                            buffer.wait_for_version(deserialize_version(response.version))
3614                        })
3615                        .await;
3616
3617                    let completions = response.completions.into_iter().map(|completion| {
3618                        language::proto::deserialize_completion(completion, language.clone())
3619                    });
3620                    futures::future::try_join_all(completions).await
3621                }
3622            })
3623        } else {
3624            Task::ready(Ok(Default::default()))
3625        }
3626    }
3627
3628    pub fn apply_additional_edits_for_completion(
3629        &self,
3630        buffer_handle: ModelHandle<Buffer>,
3631        completion: Completion,
3632        push_to_history: bool,
3633        cx: &mut ModelContext<Self>,
3634    ) -> Task<Result<Option<Transaction>>> {
3635        let buffer = buffer_handle.read(cx);
3636        let buffer_id = buffer.remote_id();
3637
3638        if self.is_local() {
3639            let lang_server = match self.language_server_for_buffer(buffer, cx) {
3640                Some((_, server)) => server.clone(),
3641                _ => return Task::ready(Ok(Default::default())),
3642            };
3643
3644            cx.spawn(|this, mut cx| async move {
3645                let resolved_completion = lang_server
3646                    .request::<lsp::request::ResolveCompletionItem>(completion.lsp_completion)
3647                    .await?;
3648
3649                if let Some(edits) = resolved_completion.additional_text_edits {
3650                    let edits = this
3651                        .update(&mut cx, |this, cx| {
3652                            this.edits_from_lsp(&buffer_handle, edits, None, cx)
3653                        })
3654                        .await?;
3655
3656                    buffer_handle.update(&mut cx, |buffer, cx| {
3657                        buffer.finalize_last_transaction();
3658                        buffer.start_transaction();
3659
3660                        for (range, text) in edits {
3661                            let primary = &completion.old_range;
3662                            let start_within = primary.start.cmp(&range.start, buffer).is_le()
3663                                && primary.end.cmp(&range.start, buffer).is_ge();
3664                            let end_within = range.start.cmp(&primary.end, buffer).is_le()
3665                                && range.end.cmp(&primary.end, buffer).is_ge();
3666
3667                            //Skip addtional edits which overlap with the primary completion edit
3668                            //https://github.com/zed-industries/zed/pull/1871
3669                            if !start_within && !end_within {
3670                                buffer.edit([(range, text)], None, cx);
3671                            }
3672                        }
3673
3674                        let transaction = if buffer.end_transaction(cx).is_some() {
3675                            let transaction = buffer.finalize_last_transaction().unwrap().clone();
3676                            if !push_to_history {
3677                                buffer.forget_transaction(transaction.id);
3678                            }
3679                            Some(transaction)
3680                        } else {
3681                            None
3682                        };
3683                        Ok(transaction)
3684                    })
3685                } else {
3686                    Ok(None)
3687                }
3688            })
3689        } else if let Some(project_id) = self.remote_id() {
3690            let client = self.client.clone();
3691            cx.spawn(|_, mut cx| async move {
3692                let response = client
3693                    .request(proto::ApplyCompletionAdditionalEdits {
3694                        project_id,
3695                        buffer_id,
3696                        completion: Some(language::proto::serialize_completion(&completion)),
3697                    })
3698                    .await?;
3699
3700                if let Some(transaction) = response.transaction {
3701                    let transaction = language::proto::deserialize_transaction(transaction)?;
3702                    buffer_handle
3703                        .update(&mut cx, |buffer, _| {
3704                            buffer.wait_for_edits(transaction.edit_ids.iter().copied())
3705                        })
3706                        .await;
3707                    if push_to_history {
3708                        buffer_handle.update(&mut cx, |buffer, _| {
3709                            buffer.push_transaction(transaction.clone(), Instant::now());
3710                        });
3711                    }
3712                    Ok(Some(transaction))
3713                } else {
3714                    Ok(None)
3715                }
3716            })
3717        } else {
3718            Task::ready(Err(anyhow!("project does not have a remote id")))
3719        }
3720    }
3721
3722    pub fn code_actions<T: Clone + ToOffset>(
3723        &self,
3724        buffer_handle: &ModelHandle<Buffer>,
3725        range: Range<T>,
3726        cx: &mut ModelContext<Self>,
3727    ) -> Task<Result<Vec<CodeAction>>> {
3728        let buffer_handle = buffer_handle.clone();
3729        let buffer = buffer_handle.read(cx);
3730        let snapshot = buffer.snapshot();
3731        let relevant_diagnostics = snapshot
3732            .diagnostics_in_range::<usize, usize>(range.to_offset(&snapshot), false)
3733            .map(|entry| entry.to_lsp_diagnostic_stub())
3734            .collect();
3735        let buffer_id = buffer.remote_id();
3736        let worktree;
3737        let buffer_abs_path;
3738        if let Some(file) = File::from_dyn(buffer.file()) {
3739            worktree = file.worktree.clone();
3740            buffer_abs_path = file.as_local().map(|f| f.abs_path(cx));
3741        } else {
3742            return Task::ready(Ok(Default::default()));
3743        };
3744        let range = buffer.anchor_before(range.start)..buffer.anchor_before(range.end);
3745
3746        if worktree.read(cx).as_local().is_some() {
3747            let buffer_abs_path = buffer_abs_path.unwrap();
3748            let lang_server = if let Some((_, server)) = self.language_server_for_buffer(buffer, cx)
3749            {
3750                server.clone()
3751            } else {
3752                return Task::ready(Ok(Default::default()));
3753            };
3754
3755            let lsp_range = range_to_lsp(range.to_point_utf16(buffer));
3756            cx.foreground().spawn(async move {
3757                if lang_server.capabilities().code_action_provider.is_none() {
3758                    return Ok(Default::default());
3759                }
3760
3761                Ok(lang_server
3762                    .request::<lsp::request::CodeActionRequest>(lsp::CodeActionParams {
3763                        text_document: lsp::TextDocumentIdentifier::new(
3764                            lsp::Url::from_file_path(buffer_abs_path).unwrap(),
3765                        ),
3766                        range: lsp_range,
3767                        work_done_progress_params: Default::default(),
3768                        partial_result_params: Default::default(),
3769                        context: lsp::CodeActionContext {
3770                            diagnostics: relevant_diagnostics,
3771                            only: Some(vec![
3772                                lsp::CodeActionKind::EMPTY,
3773                                lsp::CodeActionKind::QUICKFIX,
3774                                lsp::CodeActionKind::REFACTOR,
3775                                lsp::CodeActionKind::REFACTOR_EXTRACT,
3776                                lsp::CodeActionKind::SOURCE,
3777                            ]),
3778                        },
3779                    })
3780                    .await?
3781                    .unwrap_or_default()
3782                    .into_iter()
3783                    .filter_map(|entry| {
3784                        if let lsp::CodeActionOrCommand::CodeAction(lsp_action) = entry {
3785                            Some(CodeAction {
3786                                range: range.clone(),
3787                                lsp_action,
3788                            })
3789                        } else {
3790                            None
3791                        }
3792                    })
3793                    .collect())
3794            })
3795        } else if let Some(project_id) = self.remote_id() {
3796            let rpc = self.client.clone();
3797            let version = buffer.version();
3798            cx.spawn_weak(|this, mut cx| async move {
3799                let response = rpc
3800                    .request(proto::GetCodeActions {
3801                        project_id,
3802                        buffer_id,
3803                        start: Some(language::proto::serialize_anchor(&range.start)),
3804                        end: Some(language::proto::serialize_anchor(&range.end)),
3805                        version: serialize_version(&version),
3806                    })
3807                    .await?;
3808
3809                if this
3810                    .upgrade(&cx)
3811                    .ok_or_else(|| anyhow!("project was dropped"))?
3812                    .read_with(&cx, |this, _| this.is_read_only())
3813                {
3814                    return Err(anyhow!(
3815                        "failed to get code actions: project was disconnected"
3816                    ));
3817                } else {
3818                    buffer_handle
3819                        .update(&mut cx, |buffer, _| {
3820                            buffer.wait_for_version(deserialize_version(response.version))
3821                        })
3822                        .await;
3823
3824                    response
3825                        .actions
3826                        .into_iter()
3827                        .map(language::proto::deserialize_code_action)
3828                        .collect()
3829                }
3830            })
3831        } else {
3832            Task::ready(Ok(Default::default()))
3833        }
3834    }
3835
3836    pub fn apply_code_action(
3837        &self,
3838        buffer_handle: ModelHandle<Buffer>,
3839        mut action: CodeAction,
3840        push_to_history: bool,
3841        cx: &mut ModelContext<Self>,
3842    ) -> Task<Result<ProjectTransaction>> {
3843        if self.is_local() {
3844            let buffer = buffer_handle.read(cx);
3845            let (lsp_adapter, lang_server) =
3846                if let Some((adapter, server)) = self.language_server_for_buffer(buffer, cx) {
3847                    (adapter.clone(), server.clone())
3848                } else {
3849                    return Task::ready(Ok(Default::default()));
3850                };
3851            let range = action.range.to_point_utf16(buffer);
3852
3853            cx.spawn(|this, mut cx| async move {
3854                if let Some(lsp_range) = action
3855                    .lsp_action
3856                    .data
3857                    .as_mut()
3858                    .and_then(|d| d.get_mut("codeActionParams"))
3859                    .and_then(|d| d.get_mut("range"))
3860                {
3861                    *lsp_range = serde_json::to_value(&range_to_lsp(range)).unwrap();
3862                    action.lsp_action = lang_server
3863                        .request::<lsp::request::CodeActionResolveRequest>(action.lsp_action)
3864                        .await?;
3865                } else {
3866                    let actions = this
3867                        .update(&mut cx, |this, cx| {
3868                            this.code_actions(&buffer_handle, action.range, cx)
3869                        })
3870                        .await?;
3871                    action.lsp_action = actions
3872                        .into_iter()
3873                        .find(|a| a.lsp_action.title == action.lsp_action.title)
3874                        .ok_or_else(|| anyhow!("code action is outdated"))?
3875                        .lsp_action;
3876                }
3877
3878                if let Some(edit) = action.lsp_action.edit {
3879                    if edit.changes.is_some() || edit.document_changes.is_some() {
3880                        return Self::deserialize_workspace_edit(
3881                            this,
3882                            edit,
3883                            push_to_history,
3884                            lsp_adapter.clone(),
3885                            lang_server.clone(),
3886                            &mut cx,
3887                        )
3888                        .await;
3889                    }
3890                }
3891
3892                if let Some(command) = action.lsp_action.command {
3893                    this.update(&mut cx, |this, _| {
3894                        this.last_workspace_edits_by_language_server
3895                            .remove(&lang_server.server_id());
3896                    });
3897                    lang_server
3898                        .request::<lsp::request::ExecuteCommand>(lsp::ExecuteCommandParams {
3899                            command: command.command,
3900                            arguments: command.arguments.unwrap_or_default(),
3901                            ..Default::default()
3902                        })
3903                        .await?;
3904                    return Ok(this.update(&mut cx, |this, _| {
3905                        this.last_workspace_edits_by_language_server
3906                            .remove(&lang_server.server_id())
3907                            .unwrap_or_default()
3908                    }));
3909                }
3910
3911                Ok(ProjectTransaction::default())
3912            })
3913        } else if let Some(project_id) = self.remote_id() {
3914            let client = self.client.clone();
3915            let request = proto::ApplyCodeAction {
3916                project_id,
3917                buffer_id: buffer_handle.read(cx).remote_id(),
3918                action: Some(language::proto::serialize_code_action(&action)),
3919            };
3920            cx.spawn(|this, mut cx| async move {
3921                let response = client
3922                    .request(request)
3923                    .await?
3924                    .transaction
3925                    .ok_or_else(|| anyhow!("missing transaction"))?;
3926                this.update(&mut cx, |this, cx| {
3927                    this.deserialize_project_transaction(response, push_to_history, cx)
3928                })
3929                .await
3930            })
3931        } else {
3932            Task::ready(Err(anyhow!("project does not have a remote id")))
3933        }
3934    }
3935
3936    async fn deserialize_workspace_edit(
3937        this: ModelHandle<Self>,
3938        edit: lsp::WorkspaceEdit,
3939        push_to_history: bool,
3940        lsp_adapter: Arc<CachedLspAdapter>,
3941        language_server: Arc<LanguageServer>,
3942        cx: &mut AsyncAppContext,
3943    ) -> Result<ProjectTransaction> {
3944        let fs = this.read_with(cx, |this, _| this.fs.clone());
3945        let mut operations = Vec::new();
3946        if let Some(document_changes) = edit.document_changes {
3947            match document_changes {
3948                lsp::DocumentChanges::Edits(edits) => {
3949                    operations.extend(edits.into_iter().map(lsp::DocumentChangeOperation::Edit))
3950                }
3951                lsp::DocumentChanges::Operations(ops) => operations = ops,
3952            }
3953        } else if let Some(changes) = edit.changes {
3954            operations.extend(changes.into_iter().map(|(uri, edits)| {
3955                lsp::DocumentChangeOperation::Edit(lsp::TextDocumentEdit {
3956                    text_document: lsp::OptionalVersionedTextDocumentIdentifier {
3957                        uri,
3958                        version: None,
3959                    },
3960                    edits: edits.into_iter().map(lsp::OneOf::Left).collect(),
3961                })
3962            }));
3963        }
3964
3965        let mut project_transaction = ProjectTransaction::default();
3966        for operation in operations {
3967            match operation {
3968                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Create(op)) => {
3969                    let abs_path = op
3970                        .uri
3971                        .to_file_path()
3972                        .map_err(|_| anyhow!("can't convert URI to path"))?;
3973
3974                    if let Some(parent_path) = abs_path.parent() {
3975                        fs.create_dir(parent_path).await?;
3976                    }
3977                    if abs_path.ends_with("/") {
3978                        fs.create_dir(&abs_path).await?;
3979                    } else {
3980                        fs.create_file(&abs_path, op.options.map(Into::into).unwrap_or_default())
3981                            .await?;
3982                    }
3983                }
3984                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Rename(op)) => {
3985                    let source_abs_path = op
3986                        .old_uri
3987                        .to_file_path()
3988                        .map_err(|_| anyhow!("can't convert URI to path"))?;
3989                    let target_abs_path = op
3990                        .new_uri
3991                        .to_file_path()
3992                        .map_err(|_| anyhow!("can't convert URI to path"))?;
3993                    fs.rename(
3994                        &source_abs_path,
3995                        &target_abs_path,
3996                        op.options.map(Into::into).unwrap_or_default(),
3997                    )
3998                    .await?;
3999                }
4000                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Delete(op)) => {
4001                    let abs_path = op
4002                        .uri
4003                        .to_file_path()
4004                        .map_err(|_| anyhow!("can't convert URI to path"))?;
4005                    let options = op.options.map(Into::into).unwrap_or_default();
4006                    if abs_path.ends_with("/") {
4007                        fs.remove_dir(&abs_path, options).await?;
4008                    } else {
4009                        fs.remove_file(&abs_path, options).await?;
4010                    }
4011                }
4012                lsp::DocumentChangeOperation::Edit(op) => {
4013                    let buffer_to_edit = this
4014                        .update(cx, |this, cx| {
4015                            this.open_local_buffer_via_lsp(
4016                                op.text_document.uri,
4017                                language_server.server_id(),
4018                                lsp_adapter.name.clone(),
4019                                cx,
4020                            )
4021                        })
4022                        .await?;
4023
4024                    let edits = this
4025                        .update(cx, |this, cx| {
4026                            let edits = op.edits.into_iter().map(|edit| match edit {
4027                                lsp::OneOf::Left(edit) => edit,
4028                                lsp::OneOf::Right(edit) => edit.text_edit,
4029                            });
4030                            this.edits_from_lsp(
4031                                &buffer_to_edit,
4032                                edits,
4033                                op.text_document.version,
4034                                cx,
4035                            )
4036                        })
4037                        .await?;
4038
4039                    let transaction = buffer_to_edit.update(cx, |buffer, cx| {
4040                        buffer.finalize_last_transaction();
4041                        buffer.start_transaction();
4042                        for (range, text) in edits {
4043                            buffer.edit([(range, text)], None, cx);
4044                        }
4045                        let transaction = if buffer.end_transaction(cx).is_some() {
4046                            let transaction = buffer.finalize_last_transaction().unwrap().clone();
4047                            if !push_to_history {
4048                                buffer.forget_transaction(transaction.id);
4049                            }
4050                            Some(transaction)
4051                        } else {
4052                            None
4053                        };
4054
4055                        transaction
4056                    });
4057                    if let Some(transaction) = transaction {
4058                        project_transaction.0.insert(buffer_to_edit, transaction);
4059                    }
4060                }
4061            }
4062        }
4063
4064        Ok(project_transaction)
4065    }
4066
4067    pub fn prepare_rename<T: ToPointUtf16>(
4068        &self,
4069        buffer: ModelHandle<Buffer>,
4070        position: T,
4071        cx: &mut ModelContext<Self>,
4072    ) -> Task<Result<Option<Range<Anchor>>>> {
4073        let position = position.to_point_utf16(buffer.read(cx));
4074        self.request_lsp(buffer, PrepareRename { position }, cx)
4075    }
4076
4077    pub fn perform_rename<T: ToPointUtf16>(
4078        &self,
4079        buffer: ModelHandle<Buffer>,
4080        position: T,
4081        new_name: String,
4082        push_to_history: bool,
4083        cx: &mut ModelContext<Self>,
4084    ) -> Task<Result<ProjectTransaction>> {
4085        let position = position.to_point_utf16(buffer.read(cx));
4086        self.request_lsp(
4087            buffer,
4088            PerformRename {
4089                position,
4090                new_name,
4091                push_to_history,
4092            },
4093            cx,
4094        )
4095    }
4096
4097    #[allow(clippy::type_complexity)]
4098    pub fn search(
4099        &self,
4100        query: SearchQuery,
4101        cx: &mut ModelContext<Self>,
4102    ) -> Task<Result<HashMap<ModelHandle<Buffer>, Vec<Range<Anchor>>>>> {
4103        if self.is_local() {
4104            let snapshots = self
4105                .visible_worktrees(cx)
4106                .filter_map(|tree| {
4107                    let tree = tree.read(cx).as_local()?;
4108                    Some(tree.snapshot())
4109                })
4110                .collect::<Vec<_>>();
4111
4112            let background = cx.background().clone();
4113            let path_count: usize = snapshots.iter().map(|s| s.visible_file_count()).sum();
4114            if path_count == 0 {
4115                return Task::ready(Ok(Default::default()));
4116            }
4117            let workers = background.num_cpus().min(path_count);
4118            let (matching_paths_tx, mut matching_paths_rx) = smol::channel::bounded(1024);
4119            cx.background()
4120                .spawn({
4121                    let fs = self.fs.clone();
4122                    let background = cx.background().clone();
4123                    let query = query.clone();
4124                    async move {
4125                        let fs = &fs;
4126                        let query = &query;
4127                        let matching_paths_tx = &matching_paths_tx;
4128                        let paths_per_worker = (path_count + workers - 1) / workers;
4129                        let snapshots = &snapshots;
4130                        background
4131                            .scoped(|scope| {
4132                                for worker_ix in 0..workers {
4133                                    let worker_start_ix = worker_ix * paths_per_worker;
4134                                    let worker_end_ix = worker_start_ix + paths_per_worker;
4135                                    scope.spawn(async move {
4136                                        let mut snapshot_start_ix = 0;
4137                                        let mut abs_path = PathBuf::new();
4138                                        for snapshot in snapshots {
4139                                            let snapshot_end_ix =
4140                                                snapshot_start_ix + snapshot.visible_file_count();
4141                                            if worker_end_ix <= snapshot_start_ix {
4142                                                break;
4143                                            } else if worker_start_ix > snapshot_end_ix {
4144                                                snapshot_start_ix = snapshot_end_ix;
4145                                                continue;
4146                                            } else {
4147                                                let start_in_snapshot = worker_start_ix
4148                                                    .saturating_sub(snapshot_start_ix);
4149                                                let end_in_snapshot =
4150                                                    cmp::min(worker_end_ix, snapshot_end_ix)
4151                                                        - snapshot_start_ix;
4152
4153                                                for entry in snapshot
4154                                                    .files(false, start_in_snapshot)
4155                                                    .take(end_in_snapshot - start_in_snapshot)
4156                                                {
4157                                                    if matching_paths_tx.is_closed() {
4158                                                        break;
4159                                                    }
4160
4161                                                    abs_path.clear();
4162                                                    abs_path.push(&snapshot.abs_path());
4163                                                    abs_path.push(&entry.path);
4164                                                    let matches = if let Some(file) =
4165                                                        fs.open_sync(&abs_path).await.log_err()
4166                                                    {
4167                                                        query.detect(file).unwrap_or(false)
4168                                                    } else {
4169                                                        false
4170                                                    };
4171
4172                                                    if matches {
4173                                                        let project_path =
4174                                                            (snapshot.id(), entry.path.clone());
4175                                                        if matching_paths_tx
4176                                                            .send(project_path)
4177                                                            .await
4178                                                            .is_err()
4179                                                        {
4180                                                            break;
4181                                                        }
4182                                                    }
4183                                                }
4184
4185                                                snapshot_start_ix = snapshot_end_ix;
4186                                            }
4187                                        }
4188                                    });
4189                                }
4190                            })
4191                            .await;
4192                    }
4193                })
4194                .detach();
4195
4196            let (buffers_tx, buffers_rx) = smol::channel::bounded(1024);
4197            let open_buffers = self
4198                .opened_buffers
4199                .values()
4200                .filter_map(|b| b.upgrade(cx))
4201                .collect::<HashSet<_>>();
4202            cx.spawn(|this, cx| async move {
4203                for buffer in &open_buffers {
4204                    let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
4205                    buffers_tx.send((buffer.clone(), snapshot)).await?;
4206                }
4207
4208                let open_buffers = Rc::new(RefCell::new(open_buffers));
4209                while let Some(project_path) = matching_paths_rx.next().await {
4210                    if buffers_tx.is_closed() {
4211                        break;
4212                    }
4213
4214                    let this = this.clone();
4215                    let open_buffers = open_buffers.clone();
4216                    let buffers_tx = buffers_tx.clone();
4217                    cx.spawn(|mut cx| async move {
4218                        if let Some(buffer) = this
4219                            .update(&mut cx, |this, cx| this.open_buffer(project_path, cx))
4220                            .await
4221                            .log_err()
4222                        {
4223                            if open_buffers.borrow_mut().insert(buffer.clone()) {
4224                                let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
4225                                buffers_tx.send((buffer, snapshot)).await?;
4226                            }
4227                        }
4228
4229                        Ok::<_, anyhow::Error>(())
4230                    })
4231                    .detach();
4232                }
4233
4234                Ok::<_, anyhow::Error>(())
4235            })
4236            .detach_and_log_err(cx);
4237
4238            let background = cx.background().clone();
4239            cx.background().spawn(async move {
4240                let query = &query;
4241                let mut matched_buffers = Vec::new();
4242                for _ in 0..workers {
4243                    matched_buffers.push(HashMap::default());
4244                }
4245                background
4246                    .scoped(|scope| {
4247                        for worker_matched_buffers in matched_buffers.iter_mut() {
4248                            let mut buffers_rx = buffers_rx.clone();
4249                            scope.spawn(async move {
4250                                while let Some((buffer, snapshot)) = buffers_rx.next().await {
4251                                    let buffer_matches = query
4252                                        .search(snapshot.as_rope())
4253                                        .await
4254                                        .iter()
4255                                        .map(|range| {
4256                                            snapshot.anchor_before(range.start)
4257                                                ..snapshot.anchor_after(range.end)
4258                                        })
4259                                        .collect::<Vec<_>>();
4260                                    if !buffer_matches.is_empty() {
4261                                        worker_matched_buffers
4262                                            .insert(buffer.clone(), buffer_matches);
4263                                    }
4264                                }
4265                            });
4266                        }
4267                    })
4268                    .await;
4269                Ok(matched_buffers.into_iter().flatten().collect())
4270            })
4271        } else if let Some(project_id) = self.remote_id() {
4272            let request = self.client.request(query.to_proto(project_id));
4273            cx.spawn(|this, mut cx| async move {
4274                let response = request.await?;
4275                let mut result = HashMap::default();
4276                for location in response.locations {
4277                    let target_buffer = this
4278                        .update(&mut cx, |this, cx| {
4279                            this.wait_for_remote_buffer(location.buffer_id, cx)
4280                        })
4281                        .await?;
4282                    let start = location
4283                        .start
4284                        .and_then(deserialize_anchor)
4285                        .ok_or_else(|| anyhow!("missing target start"))?;
4286                    let end = location
4287                        .end
4288                        .and_then(deserialize_anchor)
4289                        .ok_or_else(|| anyhow!("missing target end"))?;
4290                    result
4291                        .entry(target_buffer)
4292                        .or_insert(Vec::new())
4293                        .push(start..end)
4294                }
4295                Ok(result)
4296            })
4297        } else {
4298            Task::ready(Ok(Default::default()))
4299        }
4300    }
4301
4302    fn request_lsp<R: LspCommand>(
4303        &self,
4304        buffer_handle: ModelHandle<Buffer>,
4305        request: R,
4306        cx: &mut ModelContext<Self>,
4307    ) -> Task<Result<R::Response>>
4308    where
4309        <R::LspRequest as lsp::request::Request>::Result: Send,
4310    {
4311        let buffer = buffer_handle.read(cx);
4312        if self.is_local() {
4313            let file = File::from_dyn(buffer.file()).and_then(File::as_local);
4314            if let Some((file, language_server)) = file.zip(
4315                self.language_server_for_buffer(buffer, cx)
4316                    .map(|(_, server)| server.clone()),
4317            ) {
4318                let lsp_params = request.to_lsp(&file.abs_path(cx), cx);
4319                return cx.spawn(|this, cx| async move {
4320                    if !request.check_capabilities(language_server.capabilities()) {
4321                        return Ok(Default::default());
4322                    }
4323
4324                    let response = language_server
4325                        .request::<R::LspRequest>(lsp_params)
4326                        .await
4327                        .context("lsp request failed")?;
4328                    request
4329                        .response_from_lsp(response, this, buffer_handle, cx)
4330                        .await
4331                });
4332            }
4333        } else if let Some(project_id) = self.remote_id() {
4334            let rpc = self.client.clone();
4335            let message = request.to_proto(project_id, buffer);
4336            return cx.spawn_weak(|this, cx| async move {
4337                let response = rpc.request(message).await?;
4338                let this = this
4339                    .upgrade(&cx)
4340                    .ok_or_else(|| anyhow!("project dropped"))?;
4341                if this.read_with(&cx, |this, _| this.is_read_only()) {
4342                    Err(anyhow!("disconnected before completing request"))
4343                } else {
4344                    request
4345                        .response_from_proto(response, this, buffer_handle, cx)
4346                        .await
4347                }
4348            });
4349        }
4350        Task::ready(Ok(Default::default()))
4351    }
4352
4353    pub fn find_or_create_local_worktree(
4354        &mut self,
4355        abs_path: impl AsRef<Path>,
4356        visible: bool,
4357        cx: &mut ModelContext<Self>,
4358    ) -> Task<Result<(ModelHandle<Worktree>, PathBuf)>> {
4359        let abs_path = abs_path.as_ref();
4360        if let Some((tree, relative_path)) = self.find_local_worktree(abs_path, cx) {
4361            Task::ready(Ok((tree, relative_path)))
4362        } else {
4363            let worktree = self.create_local_worktree(abs_path, visible, cx);
4364            cx.foreground()
4365                .spawn(async move { Ok((worktree.await?, PathBuf::new())) })
4366        }
4367    }
4368
4369    pub fn find_local_worktree(
4370        &self,
4371        abs_path: &Path,
4372        cx: &AppContext,
4373    ) -> Option<(ModelHandle<Worktree>, PathBuf)> {
4374        for tree in &self.worktrees {
4375            if let Some(tree) = tree.upgrade(cx) {
4376                if let Some(relative_path) = tree
4377                    .read(cx)
4378                    .as_local()
4379                    .and_then(|t| abs_path.strip_prefix(t.abs_path()).ok())
4380                {
4381                    return Some((tree.clone(), relative_path.into()));
4382                }
4383            }
4384        }
4385        None
4386    }
4387
4388    pub fn is_shared(&self) -> bool {
4389        match &self.client_state {
4390            Some(ProjectClientState::Local { .. }) => true,
4391            _ => false,
4392        }
4393    }
4394
4395    fn create_local_worktree(
4396        &mut self,
4397        abs_path: impl AsRef<Path>,
4398        visible: bool,
4399        cx: &mut ModelContext<Self>,
4400    ) -> Task<Result<ModelHandle<Worktree>>> {
4401        let fs = self.fs.clone();
4402        let client = self.client.clone();
4403        let next_entry_id = self.next_entry_id.clone();
4404        let path: Arc<Path> = abs_path.as_ref().into();
4405        let task = self
4406            .loading_local_worktrees
4407            .entry(path.clone())
4408            .or_insert_with(|| {
4409                cx.spawn(|project, mut cx| {
4410                    async move {
4411                        let worktree = Worktree::local(
4412                            client.clone(),
4413                            path.clone(),
4414                            visible,
4415                            fs,
4416                            next_entry_id,
4417                            &mut cx,
4418                        )
4419                        .await;
4420                        project.update(&mut cx, |project, _| {
4421                            project.loading_local_worktrees.remove(&path);
4422                        });
4423                        let worktree = worktree?;
4424
4425                        project
4426                            .update(&mut cx, |project, cx| project.add_worktree(&worktree, cx))
4427                            .await;
4428
4429                        Ok(worktree)
4430                    }
4431                    .map_err(Arc::new)
4432                })
4433                .shared()
4434            })
4435            .clone();
4436        cx.foreground().spawn(async move {
4437            match task.await {
4438                Ok(worktree) => Ok(worktree),
4439                Err(err) => Err(anyhow!("{}", err)),
4440            }
4441        })
4442    }
4443
4444    pub fn remove_worktree(
4445        &mut self,
4446        id_to_remove: WorktreeId,
4447        cx: &mut ModelContext<Self>,
4448    ) -> impl Future<Output = ()> {
4449        self.worktrees.retain(|worktree| {
4450            if let Some(worktree) = worktree.upgrade(cx) {
4451                let id = worktree.read(cx).id();
4452                if id == id_to_remove {
4453                    cx.emit(Event::WorktreeRemoved(id));
4454                    false
4455                } else {
4456                    true
4457                }
4458            } else {
4459                false
4460            }
4461        });
4462        self.metadata_changed(cx)
4463    }
4464
4465    fn add_worktree(
4466        &mut self,
4467        worktree: &ModelHandle<Worktree>,
4468        cx: &mut ModelContext<Self>,
4469    ) -> impl Future<Output = ()> {
4470        cx.observe(worktree, |_, _, cx| cx.notify()).detach();
4471        if worktree.read(cx).is_local() {
4472            cx.subscribe(worktree, |this, worktree, event, cx| match event {
4473                worktree::Event::UpdatedEntries => this.update_local_worktree_buffers(worktree, cx),
4474                worktree::Event::UpdatedGitRepositories(updated_repos) => {
4475                    this.update_local_worktree_buffers_git_repos(worktree, updated_repos, cx)
4476                }
4477            })
4478            .detach();
4479        }
4480
4481        let push_strong_handle = {
4482            let worktree = worktree.read(cx);
4483            self.is_shared() || worktree.is_visible() || worktree.is_remote()
4484        };
4485        if push_strong_handle {
4486            self.worktrees
4487                .push(WorktreeHandle::Strong(worktree.clone()));
4488        } else {
4489            self.worktrees
4490                .push(WorktreeHandle::Weak(worktree.downgrade()));
4491        }
4492
4493        cx.observe_release(worktree, |this, worktree, cx| {
4494            let _ = this.remove_worktree(worktree.id(), cx);
4495        })
4496        .detach();
4497
4498        cx.emit(Event::WorktreeAdded);
4499        self.metadata_changed(cx)
4500    }
4501
4502    fn update_local_worktree_buffers(
4503        &mut self,
4504        worktree_handle: ModelHandle<Worktree>,
4505        cx: &mut ModelContext<Self>,
4506    ) {
4507        let snapshot = worktree_handle.read(cx).snapshot();
4508        let mut buffers_to_delete = Vec::new();
4509        let mut renamed_buffers = Vec::new();
4510        for (buffer_id, buffer) in &self.opened_buffers {
4511            if let Some(buffer) = buffer.upgrade(cx) {
4512                buffer.update(cx, |buffer, cx| {
4513                    if let Some(old_file) = File::from_dyn(buffer.file()) {
4514                        if old_file.worktree != worktree_handle {
4515                            return;
4516                        }
4517
4518                        let new_file = if let Some(entry) = snapshot.entry_for_id(old_file.entry_id)
4519                        {
4520                            File {
4521                                is_local: true,
4522                                entry_id: entry.id,
4523                                mtime: entry.mtime,
4524                                path: entry.path.clone(),
4525                                worktree: worktree_handle.clone(),
4526                                is_deleted: false,
4527                            }
4528                        } else if let Some(entry) =
4529                            snapshot.entry_for_path(old_file.path().as_ref())
4530                        {
4531                            File {
4532                                is_local: true,
4533                                entry_id: entry.id,
4534                                mtime: entry.mtime,
4535                                path: entry.path.clone(),
4536                                worktree: worktree_handle.clone(),
4537                                is_deleted: false,
4538                            }
4539                        } else {
4540                            File {
4541                                is_local: true,
4542                                entry_id: old_file.entry_id,
4543                                path: old_file.path().clone(),
4544                                mtime: old_file.mtime(),
4545                                worktree: worktree_handle.clone(),
4546                                is_deleted: true,
4547                            }
4548                        };
4549
4550                        let old_path = old_file.abs_path(cx);
4551                        if new_file.abs_path(cx) != old_path {
4552                            renamed_buffers.push((cx.handle(), old_path));
4553                        }
4554
4555                        if new_file != *old_file {
4556                            if let Some(project_id) = self.remote_id() {
4557                                self.client
4558                                    .send(proto::UpdateBufferFile {
4559                                        project_id,
4560                                        buffer_id: *buffer_id as u64,
4561                                        file: Some(new_file.to_proto()),
4562                                    })
4563                                    .log_err();
4564                            }
4565
4566                            buffer.file_updated(Arc::new(new_file), cx).detach();
4567                        }
4568                    }
4569                });
4570            } else {
4571                buffers_to_delete.push(*buffer_id);
4572            }
4573        }
4574
4575        for buffer_id in buffers_to_delete {
4576            self.opened_buffers.remove(&buffer_id);
4577        }
4578
4579        for (buffer, old_path) in renamed_buffers {
4580            self.unregister_buffer_from_language_server(&buffer, old_path, cx);
4581            self.detect_language_for_buffer(&buffer, cx);
4582            self.register_buffer_with_language_server(&buffer, cx);
4583        }
4584    }
4585
4586    fn update_local_worktree_buffers_git_repos(
4587        &mut self,
4588        worktree: ModelHandle<Worktree>,
4589        repos: &[GitRepositoryEntry],
4590        cx: &mut ModelContext<Self>,
4591    ) {
4592        for (_, buffer) in &self.opened_buffers {
4593            if let Some(buffer) = buffer.upgrade(cx) {
4594                let file = match File::from_dyn(buffer.read(cx).file()) {
4595                    Some(file) => file,
4596                    None => continue,
4597                };
4598                if file.worktree != worktree {
4599                    continue;
4600                }
4601
4602                let path = file.path().clone();
4603
4604                let repo = match repos.iter().find(|repo| repo.manages(&path)) {
4605                    Some(repo) => repo.clone(),
4606                    None => return,
4607                };
4608
4609                let relative_repo = match path.strip_prefix(repo.content_path) {
4610                    Ok(relative_repo) => relative_repo.to_owned(),
4611                    Err(_) => return,
4612                };
4613
4614                let remote_id = self.remote_id();
4615                let client = self.client.clone();
4616
4617                cx.spawn(|_, mut cx| async move {
4618                    let diff_base = cx
4619                        .background()
4620                        .spawn(async move { repo.repo.lock().load_index_text(&relative_repo) })
4621                        .await;
4622
4623                    let buffer_id = buffer.update(&mut cx, |buffer, cx| {
4624                        buffer.set_diff_base(diff_base.clone(), cx);
4625                        buffer.remote_id()
4626                    });
4627
4628                    if let Some(project_id) = remote_id {
4629                        client
4630                            .send(proto::UpdateDiffBase {
4631                                project_id,
4632                                buffer_id: buffer_id as u64,
4633                                diff_base,
4634                            })
4635                            .log_err();
4636                    }
4637                })
4638                .detach();
4639            }
4640        }
4641    }
4642
4643    pub fn set_active_path(&mut self, entry: Option<ProjectPath>, cx: &mut ModelContext<Self>) {
4644        let new_active_entry = entry.and_then(|project_path| {
4645            let worktree = self.worktree_for_id(project_path.worktree_id, cx)?;
4646            let entry = worktree.read(cx).entry_for_path(project_path.path)?;
4647            Some(entry.id)
4648        });
4649        if new_active_entry != self.active_entry {
4650            self.active_entry = new_active_entry;
4651            cx.emit(Event::ActiveEntryChanged(new_active_entry));
4652        }
4653    }
4654
4655    pub fn language_servers_running_disk_based_diagnostics(
4656        &self,
4657    ) -> impl Iterator<Item = usize> + '_ {
4658        self.language_server_statuses
4659            .iter()
4660            .filter_map(|(id, status)| {
4661                if status.has_pending_diagnostic_updates {
4662                    Some(*id)
4663                } else {
4664                    None
4665                }
4666            })
4667    }
4668
4669    pub fn diagnostic_summary(&self, cx: &AppContext) -> DiagnosticSummary {
4670        let mut summary = DiagnosticSummary::default();
4671        for (_, path_summary) in self.diagnostic_summaries(cx) {
4672            summary.error_count += path_summary.error_count;
4673            summary.warning_count += path_summary.warning_count;
4674        }
4675        summary
4676    }
4677
4678    pub fn diagnostic_summaries<'a>(
4679        &'a self,
4680        cx: &'a AppContext,
4681    ) -> impl Iterator<Item = (ProjectPath, DiagnosticSummary)> + 'a {
4682        self.visible_worktrees(cx).flat_map(move |worktree| {
4683            let worktree = worktree.read(cx);
4684            let worktree_id = worktree.id();
4685            worktree
4686                .diagnostic_summaries()
4687                .map(move |(path, summary)| (ProjectPath { worktree_id, path }, summary))
4688        })
4689    }
4690
4691    pub fn disk_based_diagnostics_started(
4692        &mut self,
4693        language_server_id: usize,
4694        cx: &mut ModelContext<Self>,
4695    ) {
4696        cx.emit(Event::DiskBasedDiagnosticsStarted { language_server_id });
4697    }
4698
4699    pub fn disk_based_diagnostics_finished(
4700        &mut self,
4701        language_server_id: usize,
4702        cx: &mut ModelContext<Self>,
4703    ) {
4704        cx.emit(Event::DiskBasedDiagnosticsFinished { language_server_id });
4705    }
4706
4707    pub fn active_entry(&self) -> Option<ProjectEntryId> {
4708        self.active_entry
4709    }
4710
4711    pub fn entry_for_path(&self, path: &ProjectPath, cx: &AppContext) -> Option<Entry> {
4712        self.worktree_for_id(path.worktree_id, cx)?
4713            .read(cx)
4714            .entry_for_path(&path.path)
4715            .cloned()
4716    }
4717
4718    pub fn path_for_entry(&self, entry_id: ProjectEntryId, cx: &AppContext) -> Option<ProjectPath> {
4719        let worktree = self.worktree_for_entry(entry_id, cx)?;
4720        let worktree = worktree.read(cx);
4721        let worktree_id = worktree.id();
4722        let path = worktree.entry_for_id(entry_id)?.path.clone();
4723        Some(ProjectPath { worktree_id, path })
4724    }
4725
4726    // RPC message handlers
4727
4728    async fn handle_unshare_project(
4729        this: ModelHandle<Self>,
4730        _: TypedEnvelope<proto::UnshareProject>,
4731        _: Arc<Client>,
4732        mut cx: AsyncAppContext,
4733    ) -> Result<()> {
4734        this.update(&mut cx, |this, cx| {
4735            if this.is_local() {
4736                this.unshare(cx)?;
4737            } else {
4738                this.disconnected_from_host(cx);
4739            }
4740            Ok(())
4741        })
4742    }
4743
4744    async fn handle_add_collaborator(
4745        this: ModelHandle<Self>,
4746        mut envelope: TypedEnvelope<proto::AddProjectCollaborator>,
4747        _: Arc<Client>,
4748        mut cx: AsyncAppContext,
4749    ) -> Result<()> {
4750        let collaborator = envelope
4751            .payload
4752            .collaborator
4753            .take()
4754            .ok_or_else(|| anyhow!("empty collaborator"))?;
4755
4756        let collaborator = Collaborator::from_proto(collaborator)?;
4757        this.update(&mut cx, |this, cx| {
4758            this.collaborators
4759                .insert(collaborator.peer_id, collaborator);
4760            cx.notify();
4761        });
4762
4763        Ok(())
4764    }
4765
4766    async fn handle_update_project_collaborator(
4767        this: ModelHandle<Self>,
4768        envelope: TypedEnvelope<proto::UpdateProjectCollaborator>,
4769        _: Arc<Client>,
4770        mut cx: AsyncAppContext,
4771    ) -> Result<()> {
4772        let old_peer_id = envelope
4773            .payload
4774            .old_peer_id
4775            .ok_or_else(|| anyhow!("missing old peer id"))?;
4776        let new_peer_id = envelope
4777            .payload
4778            .new_peer_id
4779            .ok_or_else(|| anyhow!("missing new peer id"))?;
4780        this.update(&mut cx, |this, cx| {
4781            let collaborator = this
4782                .collaborators
4783                .remove(&old_peer_id)
4784                .ok_or_else(|| anyhow!("received UpdateProjectCollaborator for unknown peer"))?;
4785            let is_host = collaborator.replica_id == 0;
4786            this.collaborators.insert(new_peer_id, collaborator);
4787
4788            let buffers = this.shared_buffers.remove(&old_peer_id);
4789            log::info!(
4790                "peer {} became {}. moving buffers {:?}",
4791                old_peer_id,
4792                new_peer_id,
4793                &buffers
4794            );
4795            if let Some(buffers) = buffers {
4796                this.shared_buffers.insert(new_peer_id, buffers);
4797            }
4798
4799            if is_host {
4800                this.synchronize_remote_buffers(cx).detach_and_log_err(cx);
4801            }
4802
4803            cx.emit(Event::CollaboratorUpdated {
4804                old_peer_id,
4805                new_peer_id,
4806            });
4807            cx.notify();
4808            Ok(())
4809        })
4810    }
4811
4812    async fn handle_remove_collaborator(
4813        this: ModelHandle<Self>,
4814        envelope: TypedEnvelope<proto::RemoveProjectCollaborator>,
4815        _: Arc<Client>,
4816        mut cx: AsyncAppContext,
4817    ) -> Result<()> {
4818        this.update(&mut cx, |this, cx| {
4819            let peer_id = envelope
4820                .payload
4821                .peer_id
4822                .ok_or_else(|| anyhow!("invalid peer id"))?;
4823            let replica_id = this
4824                .collaborators
4825                .remove(&peer_id)
4826                .ok_or_else(|| anyhow!("unknown peer {:?}", peer_id))?
4827                .replica_id;
4828            for buffer in this.opened_buffers.values() {
4829                if let Some(buffer) = buffer.upgrade(cx) {
4830                    buffer.update(cx, |buffer, cx| buffer.remove_peer(replica_id, cx));
4831                }
4832            }
4833            this.shared_buffers.remove(&peer_id);
4834
4835            cx.emit(Event::CollaboratorLeft(peer_id));
4836            cx.notify();
4837            Ok(())
4838        })
4839    }
4840
4841    async fn handle_update_project(
4842        this: ModelHandle<Self>,
4843        envelope: TypedEnvelope<proto::UpdateProject>,
4844        _: Arc<Client>,
4845        mut cx: AsyncAppContext,
4846    ) -> Result<()> {
4847        this.update(&mut cx, |this, cx| {
4848            this.set_worktrees_from_proto(envelope.payload.worktrees, cx)?;
4849            Ok(())
4850        })
4851    }
4852
4853    async fn handle_update_worktree(
4854        this: ModelHandle<Self>,
4855        envelope: TypedEnvelope<proto::UpdateWorktree>,
4856        _: Arc<Client>,
4857        mut cx: AsyncAppContext,
4858    ) -> Result<()> {
4859        this.update(&mut cx, |this, cx| {
4860            let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
4861            if let Some(worktree) = this.worktree_for_id(worktree_id, cx) {
4862                worktree.update(cx, |worktree, _| {
4863                    let worktree = worktree.as_remote_mut().unwrap();
4864                    worktree.update_from_remote(envelope.payload);
4865                });
4866            }
4867            Ok(())
4868        })
4869    }
4870
4871    async fn handle_create_project_entry(
4872        this: ModelHandle<Self>,
4873        envelope: TypedEnvelope<proto::CreateProjectEntry>,
4874        _: Arc<Client>,
4875        mut cx: AsyncAppContext,
4876    ) -> Result<proto::ProjectEntryResponse> {
4877        let worktree = this.update(&mut cx, |this, cx| {
4878            let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
4879            this.worktree_for_id(worktree_id, cx)
4880                .ok_or_else(|| anyhow!("worktree not found"))
4881        })?;
4882        let worktree_scan_id = worktree.read_with(&cx, |worktree, _| worktree.scan_id());
4883        let entry = worktree
4884            .update(&mut cx, |worktree, cx| {
4885                let worktree = worktree.as_local_mut().unwrap();
4886                let path = PathBuf::from(envelope.payload.path);
4887                worktree.create_entry(path, envelope.payload.is_directory, cx)
4888            })
4889            .await?;
4890        Ok(proto::ProjectEntryResponse {
4891            entry: Some((&entry).into()),
4892            worktree_scan_id: worktree_scan_id as u64,
4893        })
4894    }
4895
4896    async fn handle_rename_project_entry(
4897        this: ModelHandle<Self>,
4898        envelope: TypedEnvelope<proto::RenameProjectEntry>,
4899        _: Arc<Client>,
4900        mut cx: AsyncAppContext,
4901    ) -> Result<proto::ProjectEntryResponse> {
4902        let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id);
4903        let worktree = this.read_with(&cx, |this, cx| {
4904            this.worktree_for_entry(entry_id, cx)
4905                .ok_or_else(|| anyhow!("worktree not found"))
4906        })?;
4907        let worktree_scan_id = worktree.read_with(&cx, |worktree, _| worktree.scan_id());
4908        let entry = worktree
4909            .update(&mut cx, |worktree, cx| {
4910                let new_path = PathBuf::from(envelope.payload.new_path);
4911                worktree
4912                    .as_local_mut()
4913                    .unwrap()
4914                    .rename_entry(entry_id, new_path, cx)
4915                    .ok_or_else(|| anyhow!("invalid entry"))
4916            })?
4917            .await?;
4918        Ok(proto::ProjectEntryResponse {
4919            entry: Some((&entry).into()),
4920            worktree_scan_id: worktree_scan_id as u64,
4921        })
4922    }
4923
4924    async fn handle_copy_project_entry(
4925        this: ModelHandle<Self>,
4926        envelope: TypedEnvelope<proto::CopyProjectEntry>,
4927        _: Arc<Client>,
4928        mut cx: AsyncAppContext,
4929    ) -> Result<proto::ProjectEntryResponse> {
4930        let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id);
4931        let worktree = this.read_with(&cx, |this, cx| {
4932            this.worktree_for_entry(entry_id, cx)
4933                .ok_or_else(|| anyhow!("worktree not found"))
4934        })?;
4935        let worktree_scan_id = worktree.read_with(&cx, |worktree, _| worktree.scan_id());
4936        let entry = worktree
4937            .update(&mut cx, |worktree, cx| {
4938                let new_path = PathBuf::from(envelope.payload.new_path);
4939                worktree
4940                    .as_local_mut()
4941                    .unwrap()
4942                    .copy_entry(entry_id, new_path, cx)
4943                    .ok_or_else(|| anyhow!("invalid entry"))
4944            })?
4945            .await?;
4946        Ok(proto::ProjectEntryResponse {
4947            entry: Some((&entry).into()),
4948            worktree_scan_id: worktree_scan_id as u64,
4949        })
4950    }
4951
4952    async fn handle_delete_project_entry(
4953        this: ModelHandle<Self>,
4954        envelope: TypedEnvelope<proto::DeleteProjectEntry>,
4955        _: Arc<Client>,
4956        mut cx: AsyncAppContext,
4957    ) -> Result<proto::ProjectEntryResponse> {
4958        let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id);
4959        let worktree = this.read_with(&cx, |this, cx| {
4960            this.worktree_for_entry(entry_id, cx)
4961                .ok_or_else(|| anyhow!("worktree not found"))
4962        })?;
4963        let worktree_scan_id = worktree.read_with(&cx, |worktree, _| worktree.scan_id());
4964        worktree
4965            .update(&mut cx, |worktree, cx| {
4966                worktree
4967                    .as_local_mut()
4968                    .unwrap()
4969                    .delete_entry(entry_id, cx)
4970                    .ok_or_else(|| anyhow!("invalid entry"))
4971            })?
4972            .await?;
4973        Ok(proto::ProjectEntryResponse {
4974            entry: None,
4975            worktree_scan_id: worktree_scan_id as u64,
4976        })
4977    }
4978
4979    async fn handle_update_diagnostic_summary(
4980        this: ModelHandle<Self>,
4981        envelope: TypedEnvelope<proto::UpdateDiagnosticSummary>,
4982        _: Arc<Client>,
4983        mut cx: AsyncAppContext,
4984    ) -> Result<()> {
4985        this.update(&mut cx, |this, cx| {
4986            let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
4987            if let Some(worktree) = this.worktree_for_id(worktree_id, cx) {
4988                if let Some(summary) = envelope.payload.summary {
4989                    let project_path = ProjectPath {
4990                        worktree_id,
4991                        path: Path::new(&summary.path).into(),
4992                    };
4993                    worktree.update(cx, |worktree, _| {
4994                        worktree
4995                            .as_remote_mut()
4996                            .unwrap()
4997                            .update_diagnostic_summary(project_path.path.clone(), &summary);
4998                    });
4999                    cx.emit(Event::DiagnosticsUpdated {
5000                        language_server_id: summary.language_server_id as usize,
5001                        path: project_path,
5002                    });
5003                }
5004            }
5005            Ok(())
5006        })
5007    }
5008
5009    async fn handle_start_language_server(
5010        this: ModelHandle<Self>,
5011        envelope: TypedEnvelope<proto::StartLanguageServer>,
5012        _: Arc<Client>,
5013        mut cx: AsyncAppContext,
5014    ) -> Result<()> {
5015        let server = envelope
5016            .payload
5017            .server
5018            .ok_or_else(|| anyhow!("invalid server"))?;
5019        this.update(&mut cx, |this, cx| {
5020            this.language_server_statuses.insert(
5021                server.id as usize,
5022                LanguageServerStatus {
5023                    name: server.name,
5024                    pending_work: Default::default(),
5025                    has_pending_diagnostic_updates: false,
5026                    progress_tokens: Default::default(),
5027                },
5028            );
5029            cx.notify();
5030        });
5031        Ok(())
5032    }
5033
5034    async fn handle_update_language_server(
5035        this: ModelHandle<Self>,
5036        envelope: TypedEnvelope<proto::UpdateLanguageServer>,
5037        _: Arc<Client>,
5038        mut cx: AsyncAppContext,
5039    ) -> Result<()> {
5040        this.update(&mut cx, |this, cx| {
5041            let language_server_id = envelope.payload.language_server_id as usize;
5042
5043            match envelope
5044                .payload
5045                .variant
5046                .ok_or_else(|| anyhow!("invalid variant"))?
5047            {
5048                proto::update_language_server::Variant::WorkStart(payload) => {
5049                    this.on_lsp_work_start(
5050                        language_server_id,
5051                        payload.token,
5052                        LanguageServerProgress {
5053                            message: payload.message,
5054                            percentage: payload.percentage.map(|p| p as usize),
5055                            last_update_at: Instant::now(),
5056                        },
5057                        cx,
5058                    );
5059                }
5060
5061                proto::update_language_server::Variant::WorkProgress(payload) => {
5062                    this.on_lsp_work_progress(
5063                        language_server_id,
5064                        payload.token,
5065                        LanguageServerProgress {
5066                            message: payload.message,
5067                            percentage: payload.percentage.map(|p| p as usize),
5068                            last_update_at: Instant::now(),
5069                        },
5070                        cx,
5071                    );
5072                }
5073
5074                proto::update_language_server::Variant::WorkEnd(payload) => {
5075                    this.on_lsp_work_end(language_server_id, payload.token, cx);
5076                }
5077
5078                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(_) => {
5079                    this.disk_based_diagnostics_started(language_server_id, cx);
5080                }
5081
5082                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(_) => {
5083                    this.disk_based_diagnostics_finished(language_server_id, cx)
5084                }
5085            }
5086
5087            Ok(())
5088        })
5089    }
5090
5091    async fn handle_update_buffer(
5092        this: ModelHandle<Self>,
5093        envelope: TypedEnvelope<proto::UpdateBuffer>,
5094        _: Arc<Client>,
5095        mut cx: AsyncAppContext,
5096    ) -> Result<()> {
5097        this.update(&mut cx, |this, cx| {
5098            let payload = envelope.payload.clone();
5099            let buffer_id = payload.buffer_id;
5100            let ops = payload
5101                .operations
5102                .into_iter()
5103                .map(language::proto::deserialize_operation)
5104                .collect::<Result<Vec<_>, _>>()?;
5105            let is_remote = this.is_remote();
5106            match this.opened_buffers.entry(buffer_id) {
5107                hash_map::Entry::Occupied(mut e) => match e.get_mut() {
5108                    OpenBuffer::Strong(buffer) => {
5109                        buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx))?;
5110                    }
5111                    OpenBuffer::Operations(operations) => operations.extend_from_slice(&ops),
5112                    OpenBuffer::Weak(_) => {}
5113                },
5114                hash_map::Entry::Vacant(e) => {
5115                    assert!(
5116                        is_remote,
5117                        "received buffer update from {:?}",
5118                        envelope.original_sender_id
5119                    );
5120                    e.insert(OpenBuffer::Operations(ops));
5121                }
5122            }
5123            Ok(())
5124        })
5125    }
5126
5127    async fn handle_create_buffer_for_peer(
5128        this: ModelHandle<Self>,
5129        envelope: TypedEnvelope<proto::CreateBufferForPeer>,
5130        _: Arc<Client>,
5131        mut cx: AsyncAppContext,
5132    ) -> Result<()> {
5133        this.update(&mut cx, |this, cx| {
5134            match envelope
5135                .payload
5136                .variant
5137                .ok_or_else(|| anyhow!("missing variant"))?
5138            {
5139                proto::create_buffer_for_peer::Variant::State(mut state) => {
5140                    let mut buffer_file = None;
5141                    if let Some(file) = state.file.take() {
5142                        let worktree_id = WorktreeId::from_proto(file.worktree_id);
5143                        let worktree = this.worktree_for_id(worktree_id, cx).ok_or_else(|| {
5144                            anyhow!("no worktree found for id {}", file.worktree_id)
5145                        })?;
5146                        buffer_file = Some(Arc::new(File::from_proto(file, worktree.clone(), cx)?)
5147                            as Arc<dyn language::File>);
5148                    }
5149
5150                    let buffer_id = state.id;
5151                    let buffer = cx.add_model(|_| {
5152                        Buffer::from_proto(this.replica_id(), state, buffer_file).unwrap()
5153                    });
5154                    this.incomplete_remote_buffers
5155                        .insert(buffer_id, Some(buffer));
5156                }
5157                proto::create_buffer_for_peer::Variant::Chunk(chunk) => {
5158                    let buffer = this
5159                        .incomplete_remote_buffers
5160                        .get(&chunk.buffer_id)
5161                        .cloned()
5162                        .flatten()
5163                        .ok_or_else(|| {
5164                            anyhow!(
5165                                "received chunk for buffer {} without initial state",
5166                                chunk.buffer_id
5167                            )
5168                        })?;
5169                    let operations = chunk
5170                        .operations
5171                        .into_iter()
5172                        .map(language::proto::deserialize_operation)
5173                        .collect::<Result<Vec<_>>>()?;
5174                    buffer.update(cx, |buffer, cx| buffer.apply_ops(operations, cx))?;
5175
5176                    if chunk.is_last {
5177                        this.incomplete_remote_buffers.remove(&chunk.buffer_id);
5178                        this.register_buffer(&buffer, cx)?;
5179                    }
5180                }
5181            }
5182
5183            Ok(())
5184        })
5185    }
5186
5187    async fn handle_update_diff_base(
5188        this: ModelHandle<Self>,
5189        envelope: TypedEnvelope<proto::UpdateDiffBase>,
5190        _: Arc<Client>,
5191        mut cx: AsyncAppContext,
5192    ) -> Result<()> {
5193        this.update(&mut cx, |this, cx| {
5194            let buffer_id = envelope.payload.buffer_id;
5195            let diff_base = envelope.payload.diff_base;
5196            if let Some(buffer) = this
5197                .opened_buffers
5198                .get_mut(&buffer_id)
5199                .and_then(|b| b.upgrade(cx))
5200                .or_else(|| {
5201                    this.incomplete_remote_buffers
5202                        .get(&buffer_id)
5203                        .cloned()
5204                        .flatten()
5205                })
5206            {
5207                buffer.update(cx, |buffer, cx| buffer.set_diff_base(diff_base, cx));
5208            }
5209            Ok(())
5210        })
5211    }
5212
5213    async fn handle_update_buffer_file(
5214        this: ModelHandle<Self>,
5215        envelope: TypedEnvelope<proto::UpdateBufferFile>,
5216        _: Arc<Client>,
5217        mut cx: AsyncAppContext,
5218    ) -> Result<()> {
5219        let buffer_id = envelope.payload.buffer_id;
5220        let is_incomplete = this.read_with(&cx, |this, _| {
5221            this.incomplete_remote_buffers.contains_key(&buffer_id)
5222        });
5223
5224        let buffer = if is_incomplete {
5225            Some(
5226                this.update(&mut cx, |this, cx| {
5227                    this.wait_for_remote_buffer(buffer_id, cx)
5228                })
5229                .await?,
5230            )
5231        } else {
5232            None
5233        };
5234
5235        this.update(&mut cx, |this, cx| {
5236            let payload = envelope.payload.clone();
5237            if let Some(buffer) = buffer.or_else(|| {
5238                this.opened_buffers
5239                    .get(&buffer_id)
5240                    .and_then(|b| b.upgrade(cx))
5241            }) {
5242                let file = payload.file.ok_or_else(|| anyhow!("invalid file"))?;
5243                let worktree = this
5244                    .worktree_for_id(WorktreeId::from_proto(file.worktree_id), cx)
5245                    .ok_or_else(|| anyhow!("no such worktree"))?;
5246                let file = File::from_proto(file, worktree, cx)?;
5247                buffer.update(cx, |buffer, cx| {
5248                    buffer.file_updated(Arc::new(file), cx).detach();
5249                });
5250                this.detect_language_for_buffer(&buffer, cx);
5251            }
5252            Ok(())
5253        })
5254    }
5255
5256    async fn handle_save_buffer(
5257        this: ModelHandle<Self>,
5258        envelope: TypedEnvelope<proto::SaveBuffer>,
5259        _: Arc<Client>,
5260        mut cx: AsyncAppContext,
5261    ) -> Result<proto::BufferSaved> {
5262        let buffer_id = envelope.payload.buffer_id;
5263        let requested_version = deserialize_version(envelope.payload.version);
5264
5265        let (project_id, buffer) = this.update(&mut cx, |this, cx| {
5266            let project_id = this.remote_id().ok_or_else(|| anyhow!("not connected"))?;
5267            let buffer = this
5268                .opened_buffers
5269                .get(&buffer_id)
5270                .and_then(|buffer| buffer.upgrade(cx))
5271                .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?;
5272            Ok::<_, anyhow::Error>((project_id, buffer))
5273        })?;
5274        buffer
5275            .update(&mut cx, |buffer, _| {
5276                buffer.wait_for_version(requested_version)
5277            })
5278            .await;
5279
5280        let (saved_version, fingerprint, mtime) = this
5281            .update(&mut cx, |this, cx| this.save_buffer(buffer, cx))
5282            .await?;
5283        Ok(proto::BufferSaved {
5284            project_id,
5285            buffer_id,
5286            version: serialize_version(&saved_version),
5287            mtime: Some(mtime.into()),
5288            fingerprint: language::proto::serialize_fingerprint(fingerprint),
5289        })
5290    }
5291
5292    async fn handle_reload_buffers(
5293        this: ModelHandle<Self>,
5294        envelope: TypedEnvelope<proto::ReloadBuffers>,
5295        _: Arc<Client>,
5296        mut cx: AsyncAppContext,
5297    ) -> Result<proto::ReloadBuffersResponse> {
5298        let sender_id = envelope.original_sender_id()?;
5299        let reload = this.update(&mut cx, |this, cx| {
5300            let mut buffers = HashSet::default();
5301            for buffer_id in &envelope.payload.buffer_ids {
5302                buffers.insert(
5303                    this.opened_buffers
5304                        .get(buffer_id)
5305                        .and_then(|buffer| buffer.upgrade(cx))
5306                        .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?,
5307                );
5308            }
5309            Ok::<_, anyhow::Error>(this.reload_buffers(buffers, false, cx))
5310        })?;
5311
5312        let project_transaction = reload.await?;
5313        let project_transaction = this.update(&mut cx, |this, cx| {
5314            this.serialize_project_transaction_for_peer(project_transaction, sender_id, cx)
5315        });
5316        Ok(proto::ReloadBuffersResponse {
5317            transaction: Some(project_transaction),
5318        })
5319    }
5320
5321    async fn handle_synchronize_buffers(
5322        this: ModelHandle<Self>,
5323        envelope: TypedEnvelope<proto::SynchronizeBuffers>,
5324        _: Arc<Client>,
5325        mut cx: AsyncAppContext,
5326    ) -> Result<proto::SynchronizeBuffersResponse> {
5327        let project_id = envelope.payload.project_id;
5328        let mut response = proto::SynchronizeBuffersResponse {
5329            buffers: Default::default(),
5330        };
5331
5332        this.update(&mut cx, |this, cx| {
5333            let Some(guest_id) = envelope.original_sender_id else {
5334                log::error!("missing original_sender_id on SynchronizeBuffers request");
5335                return;
5336            };
5337
5338            this.shared_buffers.entry(guest_id).or_default().clear();
5339            for buffer in envelope.payload.buffers {
5340                let buffer_id = buffer.id;
5341                let remote_version = language::proto::deserialize_version(buffer.version);
5342                if let Some(buffer) = this.buffer_for_id(buffer_id, cx) {
5343                    this.shared_buffers
5344                        .entry(guest_id)
5345                        .or_default()
5346                        .insert(buffer_id);
5347
5348                    let buffer = buffer.read(cx);
5349                    response.buffers.push(proto::BufferVersion {
5350                        id: buffer_id,
5351                        version: language::proto::serialize_version(&buffer.version),
5352                    });
5353
5354                    let operations = buffer.serialize_ops(Some(remote_version), cx);
5355                    let client = this.client.clone();
5356                    if let Some(file) = buffer.file() {
5357                        client
5358                            .send(proto::UpdateBufferFile {
5359                                project_id,
5360                                buffer_id: buffer_id as u64,
5361                                file: Some(file.to_proto()),
5362                            })
5363                            .log_err();
5364                    }
5365
5366                    client
5367                        .send(proto::UpdateDiffBase {
5368                            project_id,
5369                            buffer_id: buffer_id as u64,
5370                            diff_base: buffer.diff_base().map(Into::into),
5371                        })
5372                        .log_err();
5373
5374                    client
5375                        .send(proto::BufferReloaded {
5376                            project_id,
5377                            buffer_id,
5378                            version: language::proto::serialize_version(buffer.saved_version()),
5379                            mtime: Some(buffer.saved_mtime().into()),
5380                            fingerprint: language::proto::serialize_fingerprint(
5381                                buffer.saved_version_fingerprint(),
5382                            ),
5383                            line_ending: language::proto::serialize_line_ending(
5384                                buffer.line_ending(),
5385                            ) as i32,
5386                        })
5387                        .log_err();
5388
5389                    cx.background()
5390                        .spawn(
5391                            async move {
5392                                let operations = operations.await;
5393                                for chunk in split_operations(operations) {
5394                                    client
5395                                        .request(proto::UpdateBuffer {
5396                                            project_id,
5397                                            buffer_id,
5398                                            operations: chunk,
5399                                        })
5400                                        .await?;
5401                                }
5402                                anyhow::Ok(())
5403                            }
5404                            .log_err(),
5405                        )
5406                        .detach();
5407                }
5408            }
5409        });
5410
5411        Ok(response)
5412    }
5413
5414    async fn handle_format_buffers(
5415        this: ModelHandle<Self>,
5416        envelope: TypedEnvelope<proto::FormatBuffers>,
5417        _: Arc<Client>,
5418        mut cx: AsyncAppContext,
5419    ) -> Result<proto::FormatBuffersResponse> {
5420        let sender_id = envelope.original_sender_id()?;
5421        let format = this.update(&mut cx, |this, cx| {
5422            let mut buffers = HashSet::default();
5423            for buffer_id in &envelope.payload.buffer_ids {
5424                buffers.insert(
5425                    this.opened_buffers
5426                        .get(buffer_id)
5427                        .and_then(|buffer| buffer.upgrade(cx))
5428                        .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))?,
5429                );
5430            }
5431            let trigger = FormatTrigger::from_proto(envelope.payload.trigger);
5432            Ok::<_, anyhow::Error>(this.format(buffers, false, trigger, cx))
5433        })?;
5434
5435        let project_transaction = format.await?;
5436        let project_transaction = this.update(&mut cx, |this, cx| {
5437            this.serialize_project_transaction_for_peer(project_transaction, sender_id, cx)
5438        });
5439        Ok(proto::FormatBuffersResponse {
5440            transaction: Some(project_transaction),
5441        })
5442    }
5443
5444    async fn handle_get_completions(
5445        this: ModelHandle<Self>,
5446        envelope: TypedEnvelope<proto::GetCompletions>,
5447        _: Arc<Client>,
5448        mut cx: AsyncAppContext,
5449    ) -> Result<proto::GetCompletionsResponse> {
5450        let buffer = this.read_with(&cx, |this, cx| {
5451            this.opened_buffers
5452                .get(&envelope.payload.buffer_id)
5453                .and_then(|buffer| buffer.upgrade(cx))
5454                .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))
5455        })?;
5456
5457        let position = envelope
5458            .payload
5459            .position
5460            .and_then(language::proto::deserialize_anchor)
5461            .map(|p| {
5462                buffer.read_with(&cx, |buffer, _| {
5463                    buffer.clip_point_utf16(Unclipped(p.to_point_utf16(buffer)), Bias::Left)
5464                })
5465            })
5466            .ok_or_else(|| anyhow!("invalid position"))?;
5467
5468        let version = deserialize_version(envelope.payload.version);
5469        buffer
5470            .update(&mut cx, |buffer, _| buffer.wait_for_version(version))
5471            .await;
5472        let version = buffer.read_with(&cx, |buffer, _| buffer.version());
5473
5474        let completions = this
5475            .update(&mut cx, |this, cx| this.completions(&buffer, position, cx))
5476            .await?;
5477
5478        Ok(proto::GetCompletionsResponse {
5479            completions: completions
5480                .iter()
5481                .map(language::proto::serialize_completion)
5482                .collect(),
5483            version: serialize_version(&version),
5484        })
5485    }
5486
5487    async fn handle_apply_additional_edits_for_completion(
5488        this: ModelHandle<Self>,
5489        envelope: TypedEnvelope<proto::ApplyCompletionAdditionalEdits>,
5490        _: Arc<Client>,
5491        mut cx: AsyncAppContext,
5492    ) -> Result<proto::ApplyCompletionAdditionalEditsResponse> {
5493        let (buffer, completion) = this.update(&mut cx, |this, cx| {
5494            let buffer = this
5495                .opened_buffers
5496                .get(&envelope.payload.buffer_id)
5497                .and_then(|buffer| buffer.upgrade(cx))
5498                .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))?;
5499            let language = buffer.read(cx).language();
5500            let completion = language::proto::deserialize_completion(
5501                envelope
5502                    .payload
5503                    .completion
5504                    .ok_or_else(|| anyhow!("invalid completion"))?,
5505                language.cloned(),
5506            );
5507            Ok::<_, anyhow::Error>((buffer, completion))
5508        })?;
5509
5510        let completion = completion.await?;
5511
5512        let apply_additional_edits = this.update(&mut cx, |this, cx| {
5513            this.apply_additional_edits_for_completion(buffer, completion, false, cx)
5514        });
5515
5516        Ok(proto::ApplyCompletionAdditionalEditsResponse {
5517            transaction: apply_additional_edits
5518                .await?
5519                .as_ref()
5520                .map(language::proto::serialize_transaction),
5521        })
5522    }
5523
5524    async fn handle_get_code_actions(
5525        this: ModelHandle<Self>,
5526        envelope: TypedEnvelope<proto::GetCodeActions>,
5527        _: Arc<Client>,
5528        mut cx: AsyncAppContext,
5529    ) -> Result<proto::GetCodeActionsResponse> {
5530        let start = envelope
5531            .payload
5532            .start
5533            .and_then(language::proto::deserialize_anchor)
5534            .ok_or_else(|| anyhow!("invalid start"))?;
5535        let end = envelope
5536            .payload
5537            .end
5538            .and_then(language::proto::deserialize_anchor)
5539            .ok_or_else(|| anyhow!("invalid end"))?;
5540        let buffer = this.update(&mut cx, |this, cx| {
5541            this.opened_buffers
5542                .get(&envelope.payload.buffer_id)
5543                .and_then(|buffer| buffer.upgrade(cx))
5544                .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))
5545        })?;
5546        buffer
5547            .update(&mut cx, |buffer, _| {
5548                buffer.wait_for_version(deserialize_version(envelope.payload.version))
5549            })
5550            .await;
5551
5552        let version = buffer.read_with(&cx, |buffer, _| buffer.version());
5553        let code_actions = this.update(&mut cx, |this, cx| {
5554            Ok::<_, anyhow::Error>(this.code_actions(&buffer, start..end, cx))
5555        })?;
5556
5557        Ok(proto::GetCodeActionsResponse {
5558            actions: code_actions
5559                .await?
5560                .iter()
5561                .map(language::proto::serialize_code_action)
5562                .collect(),
5563            version: serialize_version(&version),
5564        })
5565    }
5566
5567    async fn handle_apply_code_action(
5568        this: ModelHandle<Self>,
5569        envelope: TypedEnvelope<proto::ApplyCodeAction>,
5570        _: Arc<Client>,
5571        mut cx: AsyncAppContext,
5572    ) -> Result<proto::ApplyCodeActionResponse> {
5573        let sender_id = envelope.original_sender_id()?;
5574        let action = language::proto::deserialize_code_action(
5575            envelope
5576                .payload
5577                .action
5578                .ok_or_else(|| anyhow!("invalid action"))?,
5579        )?;
5580        let apply_code_action = this.update(&mut cx, |this, cx| {
5581            let buffer = this
5582                .opened_buffers
5583                .get(&envelope.payload.buffer_id)
5584                .and_then(|buffer| buffer.upgrade(cx))
5585                .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))?;
5586            Ok::<_, anyhow::Error>(this.apply_code_action(buffer, action, false, cx))
5587        })?;
5588
5589        let project_transaction = apply_code_action.await?;
5590        let project_transaction = this.update(&mut cx, |this, cx| {
5591            this.serialize_project_transaction_for_peer(project_transaction, sender_id, cx)
5592        });
5593        Ok(proto::ApplyCodeActionResponse {
5594            transaction: Some(project_transaction),
5595        })
5596    }
5597
5598    async fn handle_lsp_command<T: LspCommand>(
5599        this: ModelHandle<Self>,
5600        envelope: TypedEnvelope<T::ProtoRequest>,
5601        _: Arc<Client>,
5602        mut cx: AsyncAppContext,
5603    ) -> Result<<T::ProtoRequest as proto::RequestMessage>::Response>
5604    where
5605        <T::LspRequest as lsp::request::Request>::Result: Send,
5606    {
5607        let sender_id = envelope.original_sender_id()?;
5608        let buffer_id = T::buffer_id_from_proto(&envelope.payload);
5609        let buffer_handle = this.read_with(&cx, |this, _| {
5610            this.opened_buffers
5611                .get(&buffer_id)
5612                .and_then(|buffer| buffer.upgrade(&cx))
5613                .ok_or_else(|| anyhow!("unknown buffer id {}", buffer_id))
5614        })?;
5615        let request = T::from_proto(
5616            envelope.payload,
5617            this.clone(),
5618            buffer_handle.clone(),
5619            cx.clone(),
5620        )
5621        .await?;
5622        let buffer_version = buffer_handle.read_with(&cx, |buffer, _| buffer.version());
5623        let response = this
5624            .update(&mut cx, |this, cx| {
5625                this.request_lsp(buffer_handle, request, cx)
5626            })
5627            .await?;
5628        this.update(&mut cx, |this, cx| {
5629            Ok(T::response_to_proto(
5630                response,
5631                this,
5632                sender_id,
5633                &buffer_version,
5634                cx,
5635            ))
5636        })
5637    }
5638
5639    async fn handle_get_project_symbols(
5640        this: ModelHandle<Self>,
5641        envelope: TypedEnvelope<proto::GetProjectSymbols>,
5642        _: Arc<Client>,
5643        mut cx: AsyncAppContext,
5644    ) -> Result<proto::GetProjectSymbolsResponse> {
5645        let symbols = this
5646            .update(&mut cx, |this, cx| {
5647                this.symbols(&envelope.payload.query, cx)
5648            })
5649            .await?;
5650
5651        Ok(proto::GetProjectSymbolsResponse {
5652            symbols: symbols.iter().map(serialize_symbol).collect(),
5653        })
5654    }
5655
5656    async fn handle_search_project(
5657        this: ModelHandle<Self>,
5658        envelope: TypedEnvelope<proto::SearchProject>,
5659        _: Arc<Client>,
5660        mut cx: AsyncAppContext,
5661    ) -> Result<proto::SearchProjectResponse> {
5662        let peer_id = envelope.original_sender_id()?;
5663        let query = SearchQuery::from_proto(envelope.payload)?;
5664        let result = this
5665            .update(&mut cx, |this, cx| this.search(query, cx))
5666            .await?;
5667
5668        this.update(&mut cx, |this, cx| {
5669            let mut locations = Vec::new();
5670            for (buffer, ranges) in result {
5671                for range in ranges {
5672                    let start = serialize_anchor(&range.start);
5673                    let end = serialize_anchor(&range.end);
5674                    let buffer_id = this.create_buffer_for_peer(&buffer, peer_id, cx);
5675                    locations.push(proto::Location {
5676                        buffer_id,
5677                        start: Some(start),
5678                        end: Some(end),
5679                    });
5680                }
5681            }
5682            Ok(proto::SearchProjectResponse { locations })
5683        })
5684    }
5685
5686    async fn handle_open_buffer_for_symbol(
5687        this: ModelHandle<Self>,
5688        envelope: TypedEnvelope<proto::OpenBufferForSymbol>,
5689        _: Arc<Client>,
5690        mut cx: AsyncAppContext,
5691    ) -> Result<proto::OpenBufferForSymbolResponse> {
5692        let peer_id = envelope.original_sender_id()?;
5693        let symbol = envelope
5694            .payload
5695            .symbol
5696            .ok_or_else(|| anyhow!("invalid symbol"))?;
5697        let symbol = this
5698            .read_with(&cx, |this, _| this.deserialize_symbol(symbol))
5699            .await?;
5700        let symbol = this.read_with(&cx, |this, _| {
5701            let signature = this.symbol_signature(&symbol.path);
5702            if signature == symbol.signature {
5703                Ok(symbol)
5704            } else {
5705                Err(anyhow!("invalid symbol signature"))
5706            }
5707        })?;
5708        let buffer = this
5709            .update(&mut cx, |this, cx| this.open_buffer_for_symbol(&symbol, cx))
5710            .await?;
5711
5712        Ok(proto::OpenBufferForSymbolResponse {
5713            buffer_id: this.update(&mut cx, |this, cx| {
5714                this.create_buffer_for_peer(&buffer, peer_id, cx)
5715            }),
5716        })
5717    }
5718
5719    fn symbol_signature(&self, project_path: &ProjectPath) -> [u8; 32] {
5720        let mut hasher = Sha256::new();
5721        hasher.update(project_path.worktree_id.to_proto().to_be_bytes());
5722        hasher.update(project_path.path.to_string_lossy().as_bytes());
5723        hasher.update(self.nonce.to_be_bytes());
5724        hasher.finalize().as_slice().try_into().unwrap()
5725    }
5726
5727    async fn handle_open_buffer_by_id(
5728        this: ModelHandle<Self>,
5729        envelope: TypedEnvelope<proto::OpenBufferById>,
5730        _: Arc<Client>,
5731        mut cx: AsyncAppContext,
5732    ) -> Result<proto::OpenBufferResponse> {
5733        let peer_id = envelope.original_sender_id()?;
5734        let buffer = this
5735            .update(&mut cx, |this, cx| {
5736                this.open_buffer_by_id(envelope.payload.id, cx)
5737            })
5738            .await?;
5739        this.update(&mut cx, |this, cx| {
5740            Ok(proto::OpenBufferResponse {
5741                buffer_id: this.create_buffer_for_peer(&buffer, peer_id, cx),
5742            })
5743        })
5744    }
5745
5746    async fn handle_open_buffer_by_path(
5747        this: ModelHandle<Self>,
5748        envelope: TypedEnvelope<proto::OpenBufferByPath>,
5749        _: Arc<Client>,
5750        mut cx: AsyncAppContext,
5751    ) -> Result<proto::OpenBufferResponse> {
5752        let peer_id = envelope.original_sender_id()?;
5753        let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
5754        let open_buffer = this.update(&mut cx, |this, cx| {
5755            this.open_buffer(
5756                ProjectPath {
5757                    worktree_id,
5758                    path: PathBuf::from(envelope.payload.path).into(),
5759                },
5760                cx,
5761            )
5762        });
5763
5764        let buffer = open_buffer.await?;
5765        this.update(&mut cx, |this, cx| {
5766            Ok(proto::OpenBufferResponse {
5767                buffer_id: this.create_buffer_for_peer(&buffer, peer_id, cx),
5768            })
5769        })
5770    }
5771
5772    fn serialize_project_transaction_for_peer(
5773        &mut self,
5774        project_transaction: ProjectTransaction,
5775        peer_id: proto::PeerId,
5776        cx: &AppContext,
5777    ) -> proto::ProjectTransaction {
5778        let mut serialized_transaction = proto::ProjectTransaction {
5779            buffer_ids: Default::default(),
5780            transactions: Default::default(),
5781        };
5782        for (buffer, transaction) in project_transaction.0 {
5783            serialized_transaction
5784                .buffer_ids
5785                .push(self.create_buffer_for_peer(&buffer, peer_id, cx));
5786            serialized_transaction
5787                .transactions
5788                .push(language::proto::serialize_transaction(&transaction));
5789        }
5790        serialized_transaction
5791    }
5792
5793    fn deserialize_project_transaction(
5794        &mut self,
5795        message: proto::ProjectTransaction,
5796        push_to_history: bool,
5797        cx: &mut ModelContext<Self>,
5798    ) -> Task<Result<ProjectTransaction>> {
5799        cx.spawn(|this, mut cx| async move {
5800            let mut project_transaction = ProjectTransaction::default();
5801            for (buffer_id, transaction) in message.buffer_ids.into_iter().zip(message.transactions)
5802            {
5803                let buffer = this
5804                    .update(&mut cx, |this, cx| {
5805                        this.wait_for_remote_buffer(buffer_id, cx)
5806                    })
5807                    .await?;
5808                let transaction = language::proto::deserialize_transaction(transaction)?;
5809                project_transaction.0.insert(buffer, transaction);
5810            }
5811
5812            for (buffer, transaction) in &project_transaction.0 {
5813                buffer
5814                    .update(&mut cx, |buffer, _| {
5815                        buffer.wait_for_edits(transaction.edit_ids.iter().copied())
5816                    })
5817                    .await;
5818
5819                if push_to_history {
5820                    buffer.update(&mut cx, |buffer, _| {
5821                        buffer.push_transaction(transaction.clone(), Instant::now());
5822                    });
5823                }
5824            }
5825
5826            Ok(project_transaction)
5827        })
5828    }
5829
5830    fn create_buffer_for_peer(
5831        &mut self,
5832        buffer: &ModelHandle<Buffer>,
5833        peer_id: proto::PeerId,
5834        cx: &AppContext,
5835    ) -> u64 {
5836        let buffer_id = buffer.read(cx).remote_id();
5837        if let Some(project_id) = self.remote_id() {
5838            let shared_buffers = self.shared_buffers.entry(peer_id).or_default();
5839            if shared_buffers.insert(buffer_id) {
5840                let buffer = buffer.read(cx);
5841                let state = buffer.to_proto();
5842                let operations = buffer.serialize_ops(None, cx);
5843                let client = self.client.clone();
5844                cx.background()
5845                    .spawn(
5846                        async move {
5847                            let operations = operations.await;
5848
5849                            client.send(proto::CreateBufferForPeer {
5850                                project_id,
5851                                peer_id: Some(peer_id),
5852                                variant: Some(proto::create_buffer_for_peer::Variant::State(state)),
5853                            })?;
5854
5855                            let mut chunks = split_operations(operations).peekable();
5856                            while let Some(chunk) = chunks.next() {
5857                                let is_last = chunks.peek().is_none();
5858                                client.send(proto::CreateBufferForPeer {
5859                                    project_id,
5860                                    peer_id: Some(peer_id),
5861                                    variant: Some(proto::create_buffer_for_peer::Variant::Chunk(
5862                                        proto::BufferChunk {
5863                                            buffer_id,
5864                                            operations: chunk,
5865                                            is_last,
5866                                        },
5867                                    )),
5868                                })?;
5869                            }
5870
5871                            anyhow::Ok(())
5872                        }
5873                        .log_err(),
5874                    )
5875                    .detach();
5876            }
5877        }
5878
5879        buffer_id
5880    }
5881
5882    fn wait_for_remote_buffer(
5883        &mut self,
5884        id: u64,
5885        cx: &mut ModelContext<Self>,
5886    ) -> Task<Result<ModelHandle<Buffer>>> {
5887        let mut opened_buffer_rx = self.opened_buffer.1.clone();
5888
5889        cx.spawn_weak(|this, mut cx| async move {
5890            let buffer = loop {
5891                let Some(this) = this.upgrade(&cx) else {
5892                    return Err(anyhow!("project dropped"));
5893                };
5894                let buffer = this.read_with(&cx, |this, cx| {
5895                    this.opened_buffers
5896                        .get(&id)
5897                        .and_then(|buffer| buffer.upgrade(cx))
5898                });
5899                if let Some(buffer) = buffer {
5900                    break buffer;
5901                } else if this.read_with(&cx, |this, _| this.is_read_only()) {
5902                    return Err(anyhow!("disconnected before buffer {} could be opened", id));
5903                }
5904
5905                this.update(&mut cx, |this, _| {
5906                    this.incomplete_remote_buffers.entry(id).or_default();
5907                });
5908                drop(this);
5909                opened_buffer_rx
5910                    .next()
5911                    .await
5912                    .ok_or_else(|| anyhow!("project dropped while waiting for buffer"))?;
5913            };
5914            buffer.update(&mut cx, |buffer, cx| buffer.git_diff_recalc(cx));
5915            Ok(buffer)
5916        })
5917    }
5918
5919    fn synchronize_remote_buffers(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
5920        let project_id = match self.client_state.as_ref() {
5921            Some(ProjectClientState::Remote {
5922                sharing_has_stopped,
5923                remote_id,
5924                ..
5925            }) => {
5926                if *sharing_has_stopped {
5927                    return Task::ready(Err(anyhow!(
5928                        "can't synchronize remote buffers on a readonly project"
5929                    )));
5930                } else {
5931                    *remote_id
5932                }
5933            }
5934            Some(ProjectClientState::Local { .. }) | None => {
5935                return Task::ready(Err(anyhow!(
5936                    "can't synchronize remote buffers on a local project"
5937                )))
5938            }
5939        };
5940
5941        let client = self.client.clone();
5942        cx.spawn(|this, cx| async move {
5943            let (buffers, incomplete_buffer_ids) = this.read_with(&cx, |this, cx| {
5944                let buffers = this
5945                    .opened_buffers
5946                    .iter()
5947                    .filter_map(|(id, buffer)| {
5948                        let buffer = buffer.upgrade(cx)?;
5949                        Some(proto::BufferVersion {
5950                            id: *id,
5951                            version: language::proto::serialize_version(&buffer.read(cx).version),
5952                        })
5953                    })
5954                    .collect();
5955                let incomplete_buffer_ids = this
5956                    .incomplete_remote_buffers
5957                    .keys()
5958                    .copied()
5959                    .collect::<Vec<_>>();
5960
5961                (buffers, incomplete_buffer_ids)
5962            });
5963            let response = client
5964                .request(proto::SynchronizeBuffers {
5965                    project_id,
5966                    buffers,
5967                })
5968                .await?;
5969
5970            let send_updates_for_buffers = response.buffers.into_iter().map(|buffer| {
5971                let client = client.clone();
5972                let buffer_id = buffer.id;
5973                let remote_version = language::proto::deserialize_version(buffer.version);
5974                this.read_with(&cx, |this, cx| {
5975                    if let Some(buffer) = this.buffer_for_id(buffer_id, cx) {
5976                        let operations = buffer.read(cx).serialize_ops(Some(remote_version), cx);
5977                        cx.background().spawn(async move {
5978                            let operations = operations.await;
5979                            for chunk in split_operations(operations) {
5980                                client
5981                                    .request(proto::UpdateBuffer {
5982                                        project_id,
5983                                        buffer_id,
5984                                        operations: chunk,
5985                                    })
5986                                    .await?;
5987                            }
5988                            anyhow::Ok(())
5989                        })
5990                    } else {
5991                        Task::ready(Ok(()))
5992                    }
5993                })
5994            });
5995
5996            // Any incomplete buffers have open requests waiting. Request that the host sends
5997            // creates these buffers for us again to unblock any waiting futures.
5998            for id in incomplete_buffer_ids {
5999                cx.background()
6000                    .spawn(client.request(proto::OpenBufferById { project_id, id }))
6001                    .detach();
6002            }
6003
6004            futures::future::join_all(send_updates_for_buffers)
6005                .await
6006                .into_iter()
6007                .collect()
6008        })
6009    }
6010
6011    pub fn worktree_metadata_protos(&self, cx: &AppContext) -> Vec<proto::WorktreeMetadata> {
6012        self.worktrees(cx)
6013            .map(|worktree| {
6014                let worktree = worktree.read(cx);
6015                proto::WorktreeMetadata {
6016                    id: worktree.id().to_proto(),
6017                    root_name: worktree.root_name().into(),
6018                    visible: worktree.is_visible(),
6019                    abs_path: worktree.abs_path().to_string_lossy().into(),
6020                }
6021            })
6022            .collect()
6023    }
6024
6025    fn set_worktrees_from_proto(
6026        &mut self,
6027        worktrees: Vec<proto::WorktreeMetadata>,
6028        cx: &mut ModelContext<Project>,
6029    ) -> Result<()> {
6030        let replica_id = self.replica_id();
6031        let remote_id = self.remote_id().ok_or_else(|| anyhow!("invalid project"))?;
6032
6033        let mut old_worktrees_by_id = self
6034            .worktrees
6035            .drain(..)
6036            .filter_map(|worktree| {
6037                let worktree = worktree.upgrade(cx)?;
6038                Some((worktree.read(cx).id(), worktree))
6039            })
6040            .collect::<HashMap<_, _>>();
6041
6042        for worktree in worktrees {
6043            if let Some(old_worktree) =
6044                old_worktrees_by_id.remove(&WorktreeId::from_proto(worktree.id))
6045            {
6046                self.worktrees.push(WorktreeHandle::Strong(old_worktree));
6047            } else {
6048                let worktree =
6049                    Worktree::remote(remote_id, replica_id, worktree, self.client.clone(), cx);
6050                let _ = self.add_worktree(&worktree, cx);
6051            }
6052        }
6053
6054        let _ = self.metadata_changed(cx);
6055        for (id, _) in old_worktrees_by_id {
6056            cx.emit(Event::WorktreeRemoved(id));
6057        }
6058
6059        Ok(())
6060    }
6061
6062    fn set_collaborators_from_proto(
6063        &mut self,
6064        messages: Vec<proto::Collaborator>,
6065        cx: &mut ModelContext<Self>,
6066    ) -> Result<()> {
6067        let mut collaborators = HashMap::default();
6068        for message in messages {
6069            let collaborator = Collaborator::from_proto(message)?;
6070            collaborators.insert(collaborator.peer_id, collaborator);
6071        }
6072        for old_peer_id in self.collaborators.keys() {
6073            if !collaborators.contains_key(old_peer_id) {
6074                cx.emit(Event::CollaboratorLeft(*old_peer_id));
6075            }
6076        }
6077        self.collaborators = collaborators;
6078        Ok(())
6079    }
6080
6081    fn deserialize_symbol(
6082        &self,
6083        serialized_symbol: proto::Symbol,
6084    ) -> impl Future<Output = Result<Symbol>> {
6085        let languages = self.languages.clone();
6086        async move {
6087            let source_worktree_id = WorktreeId::from_proto(serialized_symbol.source_worktree_id);
6088            let worktree_id = WorktreeId::from_proto(serialized_symbol.worktree_id);
6089            let start = serialized_symbol
6090                .start
6091                .ok_or_else(|| anyhow!("invalid start"))?;
6092            let end = serialized_symbol
6093                .end
6094                .ok_or_else(|| anyhow!("invalid end"))?;
6095            let kind = unsafe { mem::transmute(serialized_symbol.kind) };
6096            let path = ProjectPath {
6097                worktree_id,
6098                path: PathBuf::from(serialized_symbol.path).into(),
6099            };
6100            let language = languages.language_for_path(&path.path).await.log_err();
6101            Ok(Symbol {
6102                language_server_name: LanguageServerName(
6103                    serialized_symbol.language_server_name.into(),
6104                ),
6105                source_worktree_id,
6106                path,
6107                label: {
6108                    match language {
6109                        Some(language) => {
6110                            language
6111                                .label_for_symbol(&serialized_symbol.name, kind)
6112                                .await
6113                        }
6114                        None => None,
6115                    }
6116                    .unwrap_or_else(|| CodeLabel::plain(serialized_symbol.name.clone(), None))
6117                },
6118
6119                name: serialized_symbol.name,
6120                range: Unclipped(PointUtf16::new(start.row, start.column))
6121                    ..Unclipped(PointUtf16::new(end.row, end.column)),
6122                kind,
6123                signature: serialized_symbol
6124                    .signature
6125                    .try_into()
6126                    .map_err(|_| anyhow!("invalid signature"))?,
6127            })
6128        }
6129    }
6130
6131    async fn handle_buffer_saved(
6132        this: ModelHandle<Self>,
6133        envelope: TypedEnvelope<proto::BufferSaved>,
6134        _: Arc<Client>,
6135        mut cx: AsyncAppContext,
6136    ) -> Result<()> {
6137        let fingerprint = deserialize_fingerprint(&envelope.payload.fingerprint)?;
6138        let version = deserialize_version(envelope.payload.version);
6139        let mtime = envelope
6140            .payload
6141            .mtime
6142            .ok_or_else(|| anyhow!("missing mtime"))?
6143            .into();
6144
6145        this.update(&mut cx, |this, cx| {
6146            let buffer = this
6147                .opened_buffers
6148                .get(&envelope.payload.buffer_id)
6149                .and_then(|buffer| buffer.upgrade(cx));
6150            if let Some(buffer) = buffer {
6151                buffer.update(cx, |buffer, cx| {
6152                    buffer.did_save(version, fingerprint, mtime, cx);
6153                });
6154            }
6155            Ok(())
6156        })
6157    }
6158
6159    async fn handle_buffer_reloaded(
6160        this: ModelHandle<Self>,
6161        envelope: TypedEnvelope<proto::BufferReloaded>,
6162        _: Arc<Client>,
6163        mut cx: AsyncAppContext,
6164    ) -> Result<()> {
6165        let payload = envelope.payload;
6166        let version = deserialize_version(payload.version);
6167        let fingerprint = deserialize_fingerprint(&payload.fingerprint)?;
6168        let line_ending = deserialize_line_ending(
6169            proto::LineEnding::from_i32(payload.line_ending)
6170                .ok_or_else(|| anyhow!("missing line ending"))?,
6171        );
6172        let mtime = payload
6173            .mtime
6174            .ok_or_else(|| anyhow!("missing mtime"))?
6175            .into();
6176        this.update(&mut cx, |this, cx| {
6177            let buffer = this
6178                .opened_buffers
6179                .get(&payload.buffer_id)
6180                .and_then(|buffer| buffer.upgrade(cx));
6181            if let Some(buffer) = buffer {
6182                buffer.update(cx, |buffer, cx| {
6183                    buffer.did_reload(version, fingerprint, line_ending, mtime, cx);
6184                });
6185            }
6186            Ok(())
6187        })
6188    }
6189
6190    #[allow(clippy::type_complexity)]
6191    fn edits_from_lsp(
6192        &mut self,
6193        buffer: &ModelHandle<Buffer>,
6194        lsp_edits: impl 'static + Send + IntoIterator<Item = lsp::TextEdit>,
6195        version: Option<i32>,
6196        cx: &mut ModelContext<Self>,
6197    ) -> Task<Result<Vec<(Range<Anchor>, String)>>> {
6198        let snapshot = self.buffer_snapshot_for_lsp_version(buffer, version, cx);
6199        cx.background().spawn(async move {
6200            let snapshot = snapshot?;
6201            let mut lsp_edits = lsp_edits
6202                .into_iter()
6203                .map(|edit| (range_from_lsp(edit.range), edit.new_text))
6204                .collect::<Vec<_>>();
6205            lsp_edits.sort_by_key(|(range, _)| range.start);
6206
6207            let mut lsp_edits = lsp_edits.into_iter().peekable();
6208            let mut edits = Vec::new();
6209            while let Some((range, mut new_text)) = lsp_edits.next() {
6210                // Clip invalid ranges provided by the language server.
6211                let mut range = snapshot.clip_point_utf16(range.start, Bias::Left)
6212                    ..snapshot.clip_point_utf16(range.end, Bias::Left);
6213
6214                // Combine any LSP edits that are adjacent.
6215                //
6216                // Also, combine LSP edits that are separated from each other by only
6217                // a newline. This is important because for some code actions,
6218                // Rust-analyzer rewrites the entire buffer via a series of edits that
6219                // are separated by unchanged newline characters.
6220                //
6221                // In order for the diffing logic below to work properly, any edits that
6222                // cancel each other out must be combined into one.
6223                while let Some((next_range, next_text)) = lsp_edits.peek() {
6224                    if next_range.start.0 > range.end {
6225                        if next_range.start.0.row > range.end.row + 1
6226                            || next_range.start.0.column > 0
6227                            || snapshot.clip_point_utf16(
6228                                Unclipped(PointUtf16::new(range.end.row, u32::MAX)),
6229                                Bias::Left,
6230                            ) > range.end
6231                        {
6232                            break;
6233                        }
6234                        new_text.push('\n');
6235                    }
6236                    range.end = snapshot.clip_point_utf16(next_range.end, Bias::Left);
6237                    new_text.push_str(next_text);
6238                    lsp_edits.next();
6239                }
6240
6241                // For multiline edits, perform a diff of the old and new text so that
6242                // we can identify the changes more precisely, preserving the locations
6243                // of any anchors positioned in the unchanged regions.
6244                if range.end.row > range.start.row {
6245                    let mut offset = range.start.to_offset(&snapshot);
6246                    let old_text = snapshot.text_for_range(range).collect::<String>();
6247
6248                    let diff = TextDiff::from_lines(old_text.as_str(), &new_text);
6249                    let mut moved_since_edit = true;
6250                    for change in diff.iter_all_changes() {
6251                        let tag = change.tag();
6252                        let value = change.value();
6253                        match tag {
6254                            ChangeTag::Equal => {
6255                                offset += value.len();
6256                                moved_since_edit = true;
6257                            }
6258                            ChangeTag::Delete => {
6259                                let start = snapshot.anchor_after(offset);
6260                                let end = snapshot.anchor_before(offset + value.len());
6261                                if moved_since_edit {
6262                                    edits.push((start..end, String::new()));
6263                                } else {
6264                                    edits.last_mut().unwrap().0.end = end;
6265                                }
6266                                offset += value.len();
6267                                moved_since_edit = false;
6268                            }
6269                            ChangeTag::Insert => {
6270                                if moved_since_edit {
6271                                    let anchor = snapshot.anchor_after(offset);
6272                                    edits.push((anchor..anchor, value.to_string()));
6273                                } else {
6274                                    edits.last_mut().unwrap().1.push_str(value);
6275                                }
6276                                moved_since_edit = false;
6277                            }
6278                        }
6279                    }
6280                } else if range.end == range.start {
6281                    let anchor = snapshot.anchor_after(range.start);
6282                    edits.push((anchor..anchor, new_text));
6283                } else {
6284                    let edit_start = snapshot.anchor_after(range.start);
6285                    let edit_end = snapshot.anchor_before(range.end);
6286                    edits.push((edit_start..edit_end, new_text));
6287                }
6288            }
6289
6290            Ok(edits)
6291        })
6292    }
6293
6294    fn buffer_snapshot_for_lsp_version(
6295        &mut self,
6296        buffer: &ModelHandle<Buffer>,
6297        version: Option<i32>,
6298        cx: &AppContext,
6299    ) -> Result<TextBufferSnapshot> {
6300        const OLD_VERSIONS_TO_RETAIN: i32 = 10;
6301
6302        if let Some(version) = version {
6303            let buffer_id = buffer.read(cx).remote_id();
6304            let snapshots = self
6305                .buffer_snapshots
6306                .get_mut(&buffer_id)
6307                .ok_or_else(|| anyhow!("no snapshot found for buffer {}", buffer_id))?;
6308            let found_snapshot = snapshots
6309                .binary_search_by_key(&version, |e| e.0)
6310                .map(|ix| snapshots[ix].1.clone())
6311                .map_err(|_| {
6312                    anyhow!(
6313                        "snapshot not found for buffer {} at version {}",
6314                        buffer_id,
6315                        version
6316                    )
6317                })?;
6318            snapshots.retain(|(snapshot_version, _)| {
6319                snapshot_version + OLD_VERSIONS_TO_RETAIN >= version
6320            });
6321            Ok(found_snapshot)
6322        } else {
6323            Ok((buffer.read(cx)).text_snapshot())
6324        }
6325    }
6326
6327    fn language_server_for_buffer(
6328        &self,
6329        buffer: &Buffer,
6330        cx: &AppContext,
6331    ) -> Option<(&Arc<CachedLspAdapter>, &Arc<LanguageServer>)> {
6332        let server_id = self.language_server_id_for_buffer(buffer, cx)?;
6333        let server = self.language_servers.get(&server_id)?;
6334        if let LanguageServerState::Running {
6335            adapter, server, ..
6336        } = server
6337        {
6338            Some((adapter, server))
6339        } else {
6340            None
6341        }
6342    }
6343
6344    fn language_server_id_for_buffer(&self, buffer: &Buffer, cx: &AppContext) -> Option<usize> {
6345        if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) {
6346            let name = language.lsp_adapter()?.name.clone();
6347            let worktree_id = file.worktree_id(cx);
6348            let key = (worktree_id, name);
6349            self.language_server_ids.get(&key).copied()
6350        } else {
6351            None
6352        }
6353    }
6354}
6355
6356impl WorktreeHandle {
6357    pub fn upgrade(&self, cx: &AppContext) -> Option<ModelHandle<Worktree>> {
6358        match self {
6359            WorktreeHandle::Strong(handle) => Some(handle.clone()),
6360            WorktreeHandle::Weak(handle) => handle.upgrade(cx),
6361        }
6362    }
6363}
6364
6365impl OpenBuffer {
6366    pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<ModelHandle<Buffer>> {
6367        match self {
6368            OpenBuffer::Strong(handle) => Some(handle.clone()),
6369            OpenBuffer::Weak(handle) => handle.upgrade(cx),
6370            OpenBuffer::Operations(_) => None,
6371        }
6372    }
6373}
6374
6375pub struct PathMatchCandidateSet {
6376    pub snapshot: Snapshot,
6377    pub include_ignored: bool,
6378    pub include_root_name: bool,
6379}
6380
6381impl<'a> fuzzy::PathMatchCandidateSet<'a> for PathMatchCandidateSet {
6382    type Candidates = PathMatchCandidateSetIter<'a>;
6383
6384    fn id(&self) -> usize {
6385        self.snapshot.id().to_usize()
6386    }
6387
6388    fn len(&self) -> usize {
6389        if self.include_ignored {
6390            self.snapshot.file_count()
6391        } else {
6392            self.snapshot.visible_file_count()
6393        }
6394    }
6395
6396    fn prefix(&self) -> Arc<str> {
6397        if self.snapshot.root_entry().map_or(false, |e| e.is_file()) {
6398            self.snapshot.root_name().into()
6399        } else if self.include_root_name {
6400            format!("{}/", self.snapshot.root_name()).into()
6401        } else {
6402            "".into()
6403        }
6404    }
6405
6406    fn candidates(&'a self, start: usize) -> Self::Candidates {
6407        PathMatchCandidateSetIter {
6408            traversal: self.snapshot.files(self.include_ignored, start),
6409        }
6410    }
6411}
6412
6413pub struct PathMatchCandidateSetIter<'a> {
6414    traversal: Traversal<'a>,
6415}
6416
6417impl<'a> Iterator for PathMatchCandidateSetIter<'a> {
6418    type Item = fuzzy::PathMatchCandidate<'a>;
6419
6420    fn next(&mut self) -> Option<Self::Item> {
6421        self.traversal.next().map(|entry| {
6422            if let EntryKind::File(char_bag) = entry.kind {
6423                fuzzy::PathMatchCandidate {
6424                    path: &entry.path,
6425                    char_bag,
6426                }
6427            } else {
6428                unreachable!()
6429            }
6430        })
6431    }
6432}
6433
6434impl Entity for Project {
6435    type Event = Event;
6436
6437    fn release(&mut self, _: &mut gpui::MutableAppContext) {
6438        match &self.client_state {
6439            Some(ProjectClientState::Local { remote_id, .. }) => {
6440                let _ = self.client.send(proto::UnshareProject {
6441                    project_id: *remote_id,
6442                });
6443            }
6444            Some(ProjectClientState::Remote { remote_id, .. }) => {
6445                let _ = self.client.send(proto::LeaveProject {
6446                    project_id: *remote_id,
6447                });
6448            }
6449            _ => {}
6450        }
6451    }
6452
6453    fn app_will_quit(
6454        &mut self,
6455        _: &mut MutableAppContext,
6456    ) -> Option<std::pin::Pin<Box<dyn 'static + Future<Output = ()>>>> {
6457        let shutdown_futures = self
6458            .language_servers
6459            .drain()
6460            .map(|(_, server_state)| async {
6461                match server_state {
6462                    LanguageServerState::Running { server, .. } => server.shutdown()?.await,
6463                    LanguageServerState::Starting(starting_server) => {
6464                        starting_server.await?.shutdown()?.await
6465                    }
6466                }
6467            })
6468            .collect::<Vec<_>>();
6469
6470        Some(
6471            async move {
6472                futures::future::join_all(shutdown_futures).await;
6473            }
6474            .boxed(),
6475        )
6476    }
6477}
6478
6479impl Collaborator {
6480    fn from_proto(message: proto::Collaborator) -> Result<Self> {
6481        Ok(Self {
6482            peer_id: message.peer_id.ok_or_else(|| anyhow!("invalid peer id"))?,
6483            replica_id: message.replica_id as ReplicaId,
6484        })
6485    }
6486}
6487
6488impl<P: AsRef<Path>> From<(WorktreeId, P)> for ProjectPath {
6489    fn from((worktree_id, path): (WorktreeId, P)) -> Self {
6490        Self {
6491            worktree_id,
6492            path: path.as_ref().into(),
6493        }
6494    }
6495}
6496
6497fn split_operations(
6498    mut operations: Vec<proto::Operation>,
6499) -> impl Iterator<Item = Vec<proto::Operation>> {
6500    #[cfg(any(test, feature = "test-support"))]
6501    const CHUNK_SIZE: usize = 5;
6502
6503    #[cfg(not(any(test, feature = "test-support")))]
6504    const CHUNK_SIZE: usize = 100;
6505
6506    let mut done = false;
6507    std::iter::from_fn(move || {
6508        if done {
6509            return None;
6510        }
6511
6512        let operations = operations
6513            .drain(..cmp::min(CHUNK_SIZE, operations.len()))
6514            .collect::<Vec<_>>();
6515        if operations.is_empty() {
6516            done = true;
6517        }
6518        Some(operations)
6519    })
6520}
6521
6522fn serialize_symbol(symbol: &Symbol) -> proto::Symbol {
6523    proto::Symbol {
6524        language_server_name: symbol.language_server_name.0.to_string(),
6525        source_worktree_id: symbol.source_worktree_id.to_proto(),
6526        worktree_id: symbol.path.worktree_id.to_proto(),
6527        path: symbol.path.path.to_string_lossy().to_string(),
6528        name: symbol.name.clone(),
6529        kind: unsafe { mem::transmute(symbol.kind) },
6530        start: Some(proto::PointUtf16 {
6531            row: symbol.range.start.0.row,
6532            column: symbol.range.start.0.column,
6533        }),
6534        end: Some(proto::PointUtf16 {
6535            row: symbol.range.end.0.row,
6536            column: symbol.range.end.0.column,
6537        }),
6538        signature: symbol.signature.to_vec(),
6539    }
6540}
6541
6542fn relativize_path(base: &Path, path: &Path) -> PathBuf {
6543    let mut path_components = path.components();
6544    let mut base_components = base.components();
6545    let mut components: Vec<Component> = Vec::new();
6546    loop {
6547        match (path_components.next(), base_components.next()) {
6548            (None, None) => break,
6549            (Some(a), None) => {
6550                components.push(a);
6551                components.extend(path_components.by_ref());
6552                break;
6553            }
6554            (None, _) => components.push(Component::ParentDir),
6555            (Some(a), Some(b)) if components.is_empty() && a == b => (),
6556            (Some(a), Some(b)) if b == Component::CurDir => components.push(a),
6557            (Some(a), Some(_)) => {
6558                components.push(Component::ParentDir);
6559                for _ in base_components {
6560                    components.push(Component::ParentDir);
6561                }
6562                components.push(a);
6563                components.extend(path_components.by_ref());
6564                break;
6565            }
6566        }
6567    }
6568    components.iter().map(|c| c.as_os_str()).collect()
6569}
6570
6571impl Item for Buffer {
6572    fn entry_id(&self, cx: &AppContext) -> Option<ProjectEntryId> {
6573        File::from_dyn(self.file()).and_then(|file| file.project_entry_id(cx))
6574    }
6575
6576    fn project_path(&self, cx: &AppContext) -> Option<ProjectPath> {
6577        File::from_dyn(self.file()).map(|file| ProjectPath {
6578            worktree_id: file.worktree_id(cx),
6579            path: file.path().clone(),
6580        })
6581    }
6582}