project.rs

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