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