lsp_store.rs

   1use crate::{
   2    buffer_store::{BufferStore, BufferStoreEvent},
   3    environment::ProjectEnvironment,
   4    lsp_command::{self, *},
   5    lsp_ext_command,
   6    project_settings::{LspSettings, ProjectSettings},
   7    relativize_path, resolve_path,
   8    worktree_store::{WorktreeStore, WorktreeStoreEvent},
   9    yarn::YarnPathStore,
  10    CodeAction, Completion, CoreCompletion, Hover, InlayHint, Item as _, ProjectPath,
  11    ProjectTransaction, ResolveState, Symbol,
  12};
  13use anyhow::{anyhow, Context as _, Result};
  14use async_trait::async_trait;
  15use client::{proto, TypedEnvelope};
  16use collections::{btree_map, BTreeMap, HashMap, HashSet};
  17use futures::{
  18    future::{join_all, BoxFuture, Shared},
  19    select,
  20    stream::FuturesUnordered,
  21    Future, FutureExt, StreamExt,
  22};
  23use globset::{Glob, GlobSet, GlobSetBuilder};
  24use gpui::{
  25    AppContext, AsyncAppContext, Context, Entity, EventEmitter, Model, ModelContext, PromptLevel,
  26    Task, WeakModel,
  27};
  28use http_client::{AsyncBody, Error, HttpClient, Request, Response, Uri};
  29use language::{
  30    language_settings::{
  31        all_language_settings, language_settings, AllLanguageSettings, LanguageSettings,
  32    },
  33    markdown, point_to_lsp, prepare_completion_documentation,
  34    proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
  35    range_from_lsp, Bias, Buffer, BufferSnapshot, CachedLspAdapter, CodeLabel, Diagnostic,
  36    DiagnosticEntry, DiagnosticSet, Documentation, File as _, Language, LanguageConfig,
  37    LanguageMatcher, LanguageName, LanguageRegistry, LanguageServerName, LocalFile, LspAdapter,
  38    LspAdapterDelegate, Patch, PendingLanguageServer, PointUtf16, TextBufferSnapshot, ToOffset,
  39    ToPointUtf16, Transaction, Unclipped,
  40};
  41use lsp::{
  42    CodeActionKind, CompletionContext, DiagnosticSeverity, DiagnosticTag,
  43    DidChangeWatchedFilesRegistrationOptions, Edit, FileSystemWatcher, InsertTextFormat,
  44    LanguageServer, LanguageServerBinary, LanguageServerId, LspRequestFuture, MessageActionItem,
  45    MessageType, OneOf, ServerHealthStatus, ServerStatus, SymbolKind, TextEdit, Url,
  46    WorkDoneProgressCancelParams, WorkspaceFolder,
  47};
  48use parking_lot::{Mutex, RwLock};
  49use postage::watch;
  50use rand::prelude::*;
  51
  52use rpc::proto::AnyProtoClient;
  53use serde::Serialize;
  54use settings::{Settings, SettingsLocation, SettingsStore};
  55use sha2::{Digest, Sha256};
  56use similar::{ChangeTag, TextDiff};
  57use smol::channel::Sender;
  58use snippet::Snippet;
  59use std::{
  60    any::Any,
  61    cmp::Ordering,
  62    convert::TryInto,
  63    ffi::OsStr,
  64    iter, mem,
  65    ops::{ControlFlow, Range},
  66    path::{self, Path, PathBuf},
  67    process::Stdio,
  68    str,
  69    sync::{atomic::Ordering::SeqCst, Arc},
  70    time::{Duration, Instant},
  71};
  72use text::{Anchor, BufferId, LineEnding};
  73use util::{
  74    debug_panic, defer, maybe, merge_json_value_into, post_inc, ResultExt, TryFutureExt as _,
  75};
  76
  77pub use fs::*;
  78pub use language::Location;
  79#[cfg(any(test, feature = "test-support"))]
  80pub use prettier::FORMAT_SUFFIX as TEST_PRETTIER_FORMAT_SUFFIX;
  81pub use worktree::{
  82    Entry, EntryKind, File, LocalWorktree, PathChange, ProjectEntryId, RepositoryEntry,
  83    UpdatedEntriesSet, UpdatedGitRepositoriesSet, Worktree, WorktreeId, WorktreeSettings,
  84    FS_WATCH_LATENCY,
  85};
  86
  87const MAX_SERVER_REINSTALL_ATTEMPT_COUNT: u64 = 4;
  88const SERVER_REINSTALL_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
  89const SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
  90pub const SERVER_PROGRESS_THROTTLE_TIMEOUT: Duration = Duration::from_millis(100);
  91
  92pub struct LocalLspStore {
  93    http_client: Option<Arc<dyn HttpClient>>,
  94    environment: Model<ProjectEnvironment>,
  95    fs: Arc<dyn Fs>,
  96    yarn: Model<YarnPathStore>,
  97    pub language_servers: HashMap<LanguageServerId, LanguageServerState>,
  98    last_workspace_edits_by_language_server: HashMap<LanguageServerId, ProjectTransaction>,
  99    language_server_watched_paths: HashMap<LanguageServerId, Model<LanguageServerWatchedPaths>>,
 100    language_server_watcher_registrations:
 101        HashMap<LanguageServerId, HashMap<String, Vec<FileSystemWatcher>>>,
 102    supplementary_language_servers:
 103        HashMap<LanguageServerId, (LanguageServerName, Arc<LanguageServer>)>,
 104    _subscription: gpui::Subscription,
 105}
 106
 107impl LocalLspStore {
 108    fn shutdown_language_servers(
 109        &mut self,
 110        _cx: &mut ModelContext<LspStore>,
 111    ) -> impl Future<Output = ()> {
 112        let shutdown_futures = self
 113            .language_servers
 114            .drain()
 115            .map(|(_, server_state)| async {
 116                use LanguageServerState::*;
 117                match server_state {
 118                    Running { server, .. } => server.shutdown()?.await,
 119                    Starting(task) => task.await?.shutdown()?.await,
 120                }
 121            })
 122            .collect::<Vec<_>>();
 123
 124        async move {
 125            futures::future::join_all(shutdown_futures).await;
 126        }
 127    }
 128}
 129
 130pub struct RemoteLspStore {
 131    upstream_client: AnyProtoClient,
 132}
 133
 134impl RemoteLspStore {}
 135
 136pub struct SshLspStore {
 137    upstream_client: AnyProtoClient,
 138}
 139
 140#[allow(clippy::large_enum_variant)]
 141pub enum LspStoreMode {
 142    Local(LocalLspStore),   // ssh host and collab host
 143    Remote(RemoteLspStore), // collab guest
 144    Ssh(SshLspStore),       // ssh client
 145}
 146
 147impl LspStoreMode {
 148    fn is_local(&self) -> bool {
 149        matches!(self, LspStoreMode::Local(_))
 150    }
 151
 152    fn is_ssh(&self) -> bool {
 153        matches!(self, LspStoreMode::Ssh(_))
 154    }
 155
 156    fn is_remote(&self) -> bool {
 157        matches!(self, LspStoreMode::Remote(_))
 158    }
 159}
 160
 161pub struct LspStore {
 162    mode: LspStoreMode,
 163    downstream_client: Option<AnyProtoClient>,
 164    project_id: u64,
 165    nonce: u128,
 166    buffer_store: Model<BufferStore>,
 167    worktree_store: Model<WorktreeStore>,
 168    buffer_snapshots: HashMap<BufferId, HashMap<LanguageServerId, Vec<LspBufferSnapshot>>>, // buffer_id -> server_id -> vec of snapshots
 169    pub languages: Arc<LanguageRegistry>,
 170    language_server_ids: HashMap<(WorktreeId, LanguageServerName), LanguageServerId>,
 171    pub language_server_statuses: BTreeMap<LanguageServerId, LanguageServerStatus>,
 172    active_entry: Option<ProjectEntryId>,
 173    _maintain_workspace_config: Task<Result<()>>,
 174    _maintain_buffer_languages: Task<()>,
 175    next_diagnostic_group_id: usize,
 176    diagnostic_summaries:
 177        HashMap<WorktreeId, HashMap<Arc<Path>, HashMap<LanguageServerId, DiagnosticSummary>>>,
 178    diagnostics: HashMap<
 179        WorktreeId,
 180        HashMap<
 181            Arc<Path>,
 182            Vec<(
 183                LanguageServerId,
 184                Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
 185            )>,
 186        >,
 187    >,
 188}
 189
 190pub enum LspStoreEvent {
 191    LanguageServerAdded(LanguageServerId),
 192    LanguageServerRemoved(LanguageServerId),
 193    LanguageServerUpdate {
 194        language_server_id: LanguageServerId,
 195        message: proto::update_language_server::Variant,
 196    },
 197    LanguageServerLog(LanguageServerId, LanguageServerLogType, String),
 198    LanguageServerPrompt(LanguageServerPromptRequest),
 199    LanguageDetected {
 200        buffer: Model<Buffer>,
 201        new_language: Option<Arc<Language>>,
 202    },
 203    Notification(String),
 204    RefreshInlayHints,
 205    DiagnosticsUpdated {
 206        language_server_id: LanguageServerId,
 207        path: ProjectPath,
 208    },
 209    DiskBasedDiagnosticsStarted {
 210        language_server_id: LanguageServerId,
 211    },
 212    DiskBasedDiagnosticsFinished {
 213        language_server_id: LanguageServerId,
 214    },
 215    SnippetEdit {
 216        buffer_id: BufferId,
 217        edits: Vec<(lsp::Range, Snippet)>,
 218        most_recent_edit: clock::Lamport,
 219    },
 220    StartFormattingLocalBuffer(BufferId),
 221    FinishFormattingLocalBuffer(BufferId),
 222}
 223
 224#[derive(Clone, Debug, Serialize)]
 225pub struct LanguageServerStatus {
 226    pub name: String,
 227    pub pending_work: BTreeMap<String, LanguageServerProgress>,
 228    pub has_pending_diagnostic_updates: bool,
 229    progress_tokens: HashSet<String>,
 230}
 231
 232#[derive(Clone, Debug)]
 233struct CoreSymbol {
 234    pub language_server_name: LanguageServerName,
 235    pub source_worktree_id: WorktreeId,
 236    pub path: ProjectPath,
 237    pub name: String,
 238    pub kind: lsp::SymbolKind,
 239    pub range: Range<Unclipped<PointUtf16>>,
 240    pub signature: [u8; 32],
 241}
 242
 243impl LspStore {
 244    pub fn init(client: &AnyProtoClient) {
 245        client.add_model_request_handler(Self::handle_multi_lsp_query);
 246        client.add_model_request_handler(Self::handle_restart_language_servers);
 247        client.add_model_message_handler(Self::handle_start_language_server);
 248        client.add_model_message_handler(Self::handle_update_language_server);
 249        client.add_model_message_handler(Self::handle_update_diagnostic_summary);
 250        client.add_model_request_handler(Self::handle_resolve_completion_documentation);
 251        client.add_model_request_handler(Self::handle_apply_code_action);
 252        client.add_model_request_handler(Self::handle_inlay_hints);
 253        client.add_model_request_handler(Self::handle_get_project_symbols);
 254        client.add_model_request_handler(Self::handle_resolve_inlay_hint);
 255        client.add_model_request_handler(Self::handle_open_buffer_for_symbol);
 256        client.add_model_request_handler(Self::handle_refresh_inlay_hints);
 257        client.add_model_request_handler(Self::handle_on_type_formatting);
 258        client.add_model_request_handler(Self::handle_apply_additional_edits_for_completion);
 259        client.add_model_request_handler(Self::handle_lsp_command::<GetCodeActions>);
 260        client.add_model_request_handler(Self::handle_lsp_command::<GetCompletions>);
 261        client.add_model_request_handler(Self::handle_lsp_command::<GetHover>);
 262        client.add_model_request_handler(Self::handle_lsp_command::<GetDefinition>);
 263        client.add_model_request_handler(Self::handle_lsp_command::<GetDeclaration>);
 264        client.add_model_request_handler(Self::handle_lsp_command::<GetTypeDefinition>);
 265        client.add_model_request_handler(Self::handle_lsp_command::<GetDocumentHighlights>);
 266        client.add_model_request_handler(Self::handle_lsp_command::<GetReferences>);
 267        client.add_model_request_handler(Self::handle_lsp_command::<PrepareRename>);
 268        client.add_model_request_handler(Self::handle_lsp_command::<PerformRename>);
 269        client.add_model_request_handler(Self::handle_lsp_command::<lsp_ext_command::ExpandMacro>);
 270        client.add_model_request_handler(Self::handle_lsp_command::<LinkedEditingRange>);
 271    }
 272
 273    pub fn as_remote(&self) -> Option<&RemoteLspStore> {
 274        match &self.mode {
 275            LspStoreMode::Remote(remote_lsp_store) => Some(remote_lsp_store),
 276            _ => None,
 277        }
 278    }
 279
 280    pub fn as_ssh(&self) -> Option<&SshLspStore> {
 281        match &self.mode {
 282            LspStoreMode::Ssh(ssh_lsp_store) => Some(ssh_lsp_store),
 283            _ => None,
 284        }
 285    }
 286
 287    pub fn as_local(&self) -> Option<&LocalLspStore> {
 288        match &self.mode {
 289            LspStoreMode::Local(local_lsp_store) => Some(local_lsp_store),
 290            _ => None,
 291        }
 292    }
 293
 294    pub fn as_local_mut(&mut self) -> Option<&mut LocalLspStore> {
 295        match &mut self.mode {
 296            LspStoreMode::Local(local_lsp_store) => Some(local_lsp_store),
 297            _ => None,
 298        }
 299    }
 300
 301    pub fn upstream_client(&self) -> Option<AnyProtoClient> {
 302        match &self.mode {
 303            LspStoreMode::Ssh(SshLspStore {
 304                upstream_client, ..
 305            })
 306            | LspStoreMode::Remote(RemoteLspStore {
 307                upstream_client, ..
 308            }) => Some(upstream_client.clone()),
 309            LspStoreMode::Local(_) => None,
 310        }
 311    }
 312
 313    pub fn new_local(
 314        buffer_store: Model<BufferStore>,
 315        worktree_store: Model<WorktreeStore>,
 316        environment: Model<ProjectEnvironment>,
 317        languages: Arc<LanguageRegistry>,
 318        http_client: Option<Arc<dyn HttpClient>>,
 319        fs: Arc<dyn Fs>,
 320        cx: &mut ModelContext<Self>,
 321    ) -> Self {
 322        let yarn = YarnPathStore::new(fs.clone(), cx);
 323        cx.subscribe(&buffer_store, Self::on_buffer_store_event)
 324            .detach();
 325        cx.subscribe(&worktree_store, Self::on_worktree_store_event)
 326            .detach();
 327
 328        Self {
 329            mode: LspStoreMode::Local(LocalLspStore {
 330                supplementary_language_servers: Default::default(),
 331                language_servers: Default::default(),
 332                last_workspace_edits_by_language_server: Default::default(),
 333                language_server_watched_paths: Default::default(),
 334                language_server_watcher_registrations: Default::default(),
 335                environment,
 336                http_client,
 337                fs,
 338                yarn,
 339                _subscription: cx.on_app_quit(|this, cx| {
 340                    this.as_local_mut().unwrap().shutdown_language_servers(cx)
 341                }),
 342            }),
 343            downstream_client: None,
 344            project_id: 0,
 345            buffer_store,
 346            worktree_store,
 347            languages: languages.clone(),
 348            language_server_ids: Default::default(),
 349            language_server_statuses: Default::default(),
 350            nonce: StdRng::from_entropy().gen(),
 351            buffer_snapshots: Default::default(),
 352            next_diagnostic_group_id: Default::default(),
 353            diagnostic_summaries: Default::default(),
 354            diagnostics: Default::default(),
 355            active_entry: None,
 356            _maintain_workspace_config: Self::maintain_workspace_config(cx),
 357            _maintain_buffer_languages: Self::maintain_buffer_languages(languages.clone(), cx),
 358        }
 359    }
 360
 361    fn send_lsp_proto_request<R: LspCommand>(
 362        &self,
 363        buffer: Model<Buffer>,
 364        client: AnyProtoClient,
 365        request: R,
 366        cx: &mut ModelContext<'_, LspStore>,
 367    ) -> Task<anyhow::Result<<R as LspCommand>::Response>> {
 368        let message = request.to_proto(self.project_id, buffer.read(cx));
 369        cx.spawn(move |this, cx| async move {
 370            let response = client.request(message).await?;
 371            let this = this.upgrade().context("project dropped")?;
 372            request
 373                .response_from_proto(response, this, buffer, cx)
 374                .await
 375        })
 376    }
 377
 378    pub fn new_ssh(
 379        buffer_store: Model<BufferStore>,
 380        worktree_store: Model<WorktreeStore>,
 381        languages: Arc<LanguageRegistry>,
 382        upstream_client: AnyProtoClient,
 383        project_id: u64,
 384        cx: &mut ModelContext<Self>,
 385    ) -> Self {
 386        cx.subscribe(&buffer_store, Self::on_buffer_store_event)
 387            .detach();
 388        cx.subscribe(&worktree_store, Self::on_worktree_store_event)
 389            .detach();
 390
 391        Self {
 392            mode: LspStoreMode::Ssh(SshLspStore { upstream_client }),
 393            downstream_client: None,
 394            project_id,
 395            buffer_store,
 396            worktree_store,
 397            languages: languages.clone(),
 398            language_server_ids: Default::default(),
 399            language_server_statuses: Default::default(),
 400            nonce: StdRng::from_entropy().gen(),
 401            buffer_snapshots: Default::default(),
 402            next_diagnostic_group_id: Default::default(),
 403            diagnostic_summaries: Default::default(),
 404            diagnostics: Default::default(),
 405            active_entry: None,
 406            _maintain_workspace_config: Self::maintain_workspace_config(cx),
 407            _maintain_buffer_languages: Self::maintain_buffer_languages(languages.clone(), cx),
 408        }
 409    }
 410
 411    pub fn new_remote(
 412        buffer_store: Model<BufferStore>,
 413        worktree_store: Model<WorktreeStore>,
 414        languages: Arc<LanguageRegistry>,
 415        upstream_client: AnyProtoClient,
 416        project_id: u64,
 417        cx: &mut ModelContext<Self>,
 418    ) -> Self {
 419        cx.subscribe(&buffer_store, Self::on_buffer_store_event)
 420            .detach();
 421        cx.subscribe(&worktree_store, Self::on_worktree_store_event)
 422            .detach();
 423
 424        Self {
 425            mode: LspStoreMode::Remote(RemoteLspStore { upstream_client }),
 426            downstream_client: None,
 427            project_id,
 428            buffer_store,
 429            worktree_store,
 430            languages: languages.clone(),
 431            language_server_ids: Default::default(),
 432            language_server_statuses: Default::default(),
 433            nonce: StdRng::from_entropy().gen(),
 434            buffer_snapshots: Default::default(),
 435            next_diagnostic_group_id: Default::default(),
 436            diagnostic_summaries: Default::default(),
 437            diagnostics: Default::default(),
 438            active_entry: None,
 439            _maintain_workspace_config: Self::maintain_workspace_config(cx),
 440            _maintain_buffer_languages: Self::maintain_buffer_languages(languages.clone(), cx),
 441        }
 442    }
 443
 444    fn worktree_for_id(
 445        &self,
 446        worktree_id: WorktreeId,
 447        cx: &ModelContext<Self>,
 448    ) -> Result<Model<Worktree>> {
 449        self.worktree_store
 450            .read(cx)
 451            .worktree_for_id(worktree_id, cx)
 452            .ok_or_else(|| anyhow!("worktree not found"))
 453    }
 454
 455    fn on_buffer_store_event(
 456        &mut self,
 457        _: Model<BufferStore>,
 458        event: &BufferStoreEvent,
 459        cx: &mut ModelContext<Self>,
 460    ) {
 461        match event {
 462            BufferStoreEvent::BufferAdded(buffer) => {
 463                self.register_buffer(buffer, cx).log_err();
 464            }
 465            BufferStoreEvent::BufferChangedFilePath { buffer, old_file } => {
 466                if let Some(old_file) = File::from_dyn(old_file.as_ref()) {
 467                    self.unregister_buffer_from_language_servers(buffer, old_file, cx);
 468                }
 469
 470                self.register_buffer_with_language_servers(buffer, cx);
 471            }
 472            BufferStoreEvent::BufferDropped(_) => {}
 473        }
 474    }
 475
 476    fn on_worktree_store_event(
 477        &mut self,
 478        _: Model<WorktreeStore>,
 479        event: &WorktreeStoreEvent,
 480        cx: &mut ModelContext<Self>,
 481    ) {
 482        match event {
 483            WorktreeStoreEvent::WorktreeAdded(worktree) => {
 484                if !worktree.read(cx).is_local() {
 485                    return;
 486                }
 487                cx.subscribe(worktree, |this, worktree, event, cx| match event {
 488                    worktree::Event::UpdatedEntries(changes) => {
 489                        this.update_local_worktree_language_servers(&worktree, changes, cx);
 490                    }
 491                    worktree::Event::UpdatedGitRepositories(_)
 492                    | worktree::Event::DeletedEntry(_) => {}
 493                })
 494                .detach()
 495            }
 496            WorktreeStoreEvent::WorktreeRemoved(_, id) => self.remove_worktree(*id, cx),
 497            WorktreeStoreEvent::WorktreeOrderChanged => {}
 498        }
 499    }
 500
 501    fn on_buffer_event(
 502        &mut self,
 503        buffer: Model<Buffer>,
 504        event: &language::Event,
 505        cx: &mut ModelContext<Self>,
 506    ) {
 507        match event {
 508            language::Event::Edited { .. } => {
 509                self.on_buffer_edited(buffer, cx);
 510            }
 511
 512            language::Event::Saved => {
 513                self.on_buffer_saved(buffer, cx);
 514            }
 515
 516            _ => {}
 517        }
 518    }
 519
 520    fn register_buffer(
 521        &mut self,
 522        buffer: &Model<Buffer>,
 523        cx: &mut ModelContext<Self>,
 524    ) -> Result<()> {
 525        buffer.update(cx, |buffer, _| {
 526            buffer.set_language_registry(self.languages.clone())
 527        });
 528
 529        cx.subscribe(buffer, |this, buffer, event, cx| {
 530            this.on_buffer_event(buffer, event, cx);
 531        })
 532        .detach();
 533
 534        self.register_buffer_with_language_servers(buffer, cx);
 535        cx.observe_release(buffer, |this, buffer, cx| {
 536            if let Some(file) = File::from_dyn(buffer.file()) {
 537                if file.is_local() {
 538                    let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap();
 539                    for server in this.language_servers_for_buffer(buffer, cx) {
 540                        server
 541                            .1
 542                            .notify::<lsp::notification::DidCloseTextDocument>(
 543                                lsp::DidCloseTextDocumentParams {
 544                                    text_document: lsp::TextDocumentIdentifier::new(uri.clone()),
 545                                },
 546                            )
 547                            .log_err();
 548                    }
 549                }
 550            }
 551        })
 552        .detach();
 553
 554        Ok(())
 555    }
 556
 557    fn maintain_buffer_languages(
 558        languages: Arc<LanguageRegistry>,
 559        cx: &mut ModelContext<Self>,
 560    ) -> Task<()> {
 561        let mut subscription = languages.subscribe();
 562        let mut prev_reload_count = languages.reload_count();
 563        cx.spawn(move |this, mut cx| async move {
 564            while let Some(()) = subscription.next().await {
 565                if let Some(this) = this.upgrade() {
 566                    // If the language registry has been reloaded, then remove and
 567                    // re-assign the languages on all open buffers.
 568                    let reload_count = languages.reload_count();
 569                    if reload_count > prev_reload_count {
 570                        prev_reload_count = reload_count;
 571                        this.update(&mut cx, |this, cx| {
 572                            this.buffer_store.clone().update(cx, |buffer_store, cx| {
 573                                for buffer in buffer_store.buffers() {
 574                                    if let Some(f) = File::from_dyn(buffer.read(cx).file()).cloned()
 575                                    {
 576                                        this.unregister_buffer_from_language_servers(
 577                                            &buffer, &f, cx,
 578                                        );
 579                                        buffer
 580                                            .update(cx, |buffer, cx| buffer.set_language(None, cx));
 581                                    }
 582                                }
 583                            });
 584                        })
 585                        .ok();
 586                    }
 587
 588                    this.update(&mut cx, |this, cx| {
 589                        let mut plain_text_buffers = Vec::new();
 590                        let mut buffers_with_unknown_injections = Vec::new();
 591                        for handle in this.buffer_store.read(cx).buffers() {
 592                            let buffer = handle.read(cx);
 593                            if buffer.language().is_none()
 594                                || buffer.language() == Some(&*language::PLAIN_TEXT)
 595                            {
 596                                plain_text_buffers.push(handle);
 597                            } else if buffer.contains_unknown_injections() {
 598                                buffers_with_unknown_injections.push(handle);
 599                            }
 600                        }
 601                        for buffer in plain_text_buffers {
 602                            this.register_buffer_with_language_servers(&buffer, cx);
 603                        }
 604
 605                        for buffer in buffers_with_unknown_injections {
 606                            buffer.update(cx, |buffer, cx| buffer.reparse(cx));
 607                        }
 608                    })
 609                    .ok();
 610                }
 611            }
 612        })
 613    }
 614
 615    fn detect_language_for_buffer(
 616        &mut self,
 617        buffer_handle: &Model<Buffer>,
 618        cx: &mut ModelContext<Self>,
 619    ) -> Option<language::AvailableLanguage> {
 620        // If the buffer has a language, set it and start the language server if we haven't already.
 621        let buffer = buffer_handle.read(cx);
 622        let file = buffer.file()?;
 623
 624        let content = buffer.as_rope();
 625        let available_language = self.languages.language_for_file(file, Some(content), cx);
 626        if let Some(available_language) = &available_language {
 627            if let Some(Ok(Ok(new_language))) = self
 628                .languages
 629                .load_language(available_language)
 630                .now_or_never()
 631            {
 632                self.set_language_for_buffer(buffer_handle, new_language, cx);
 633            }
 634        } else {
 635            cx.emit(LspStoreEvent::LanguageDetected {
 636                buffer: buffer_handle.clone(),
 637                new_language: None,
 638            });
 639        }
 640
 641        available_language
 642    }
 643
 644    pub fn set_language_for_buffer(
 645        &mut self,
 646        buffer: &Model<Buffer>,
 647        new_language: Arc<Language>,
 648        cx: &mut ModelContext<Self>,
 649    ) {
 650        buffer.update(cx, |buffer, cx| {
 651            if buffer.language().map_or(true, |old_language| {
 652                !Arc::ptr_eq(old_language, &new_language)
 653            }) {
 654                buffer.set_language(Some(new_language.clone()), cx);
 655            }
 656        });
 657
 658        let buffer_file = buffer.read(cx).file().cloned();
 659        let buffer_file = File::from_dyn(buffer_file.as_ref());
 660
 661        if let Some(file) = buffer_file {
 662            let worktree = file.worktree.clone();
 663            self.start_language_servers(&worktree, new_language.name(), cx)
 664        }
 665
 666        cx.emit(LspStoreEvent::LanguageDetected {
 667            buffer: buffer.clone(),
 668            new_language: Some(new_language),
 669        })
 670    }
 671
 672    pub fn buffer_store(&self) -> Model<BufferStore> {
 673        self.buffer_store.clone()
 674    }
 675
 676    pub fn set_active_entry(&mut self, active_entry: Option<ProjectEntryId>) {
 677        self.active_entry = active_entry;
 678    }
 679
 680    pub(crate) fn send_diagnostic_summaries(
 681        &self,
 682        worktree: &mut Worktree,
 683    ) -> Result<(), anyhow::Error> {
 684        if let Some(client) = self.downstream_client.clone() {
 685            if let Some(summaries) = self.diagnostic_summaries.get(&worktree.id()) {
 686                for (path, summaries) in summaries {
 687                    for (&server_id, summary) in summaries {
 688                        client.send(proto::UpdateDiagnosticSummary {
 689                            project_id: self.project_id,
 690                            worktree_id: worktree.id().to_proto(),
 691                            summary: Some(summary.to_proto(server_id, path)),
 692                        })?;
 693                    }
 694                }
 695            }
 696        }
 697        Ok(())
 698    }
 699
 700    pub fn request_lsp<R: LspCommand>(
 701        &self,
 702        buffer_handle: Model<Buffer>,
 703        server: LanguageServerToQuery,
 704        request: R,
 705        cx: &mut ModelContext<Self>,
 706    ) -> Task<Result<R::Response>>
 707    where
 708        <R::LspRequest as lsp::request::Request>::Result: Send,
 709        <R::LspRequest as lsp::request::Request>::Params: Send,
 710    {
 711        let buffer = buffer_handle.read(cx);
 712
 713        if let Some(upstream_client) = self.upstream_client() {
 714            return self.send_lsp_proto_request(buffer_handle, upstream_client, request, cx);
 715        }
 716
 717        let language_server = match server {
 718            LanguageServerToQuery::Primary => {
 719                match self.primary_language_server_for_buffer(buffer, cx) {
 720                    Some((_, server)) => Some(Arc::clone(server)),
 721                    None => return Task::ready(Ok(Default::default())),
 722                }
 723            }
 724            LanguageServerToQuery::Other(id) => self
 725                .language_server_for_buffer(buffer, id, cx)
 726                .map(|(_, server)| Arc::clone(server)),
 727        };
 728        let file = File::from_dyn(buffer.file()).and_then(File::as_local);
 729        if let (Some(file), Some(language_server)) = (file, language_server) {
 730            let lsp_params = request.to_lsp(&file.abs_path(cx), buffer, &language_server, cx);
 731            let status = request.status();
 732            return cx.spawn(move |this, cx| async move {
 733                if !request.check_capabilities(language_server.adapter_server_capabilities()) {
 734                    return Ok(Default::default());
 735                }
 736
 737                let lsp_request = language_server.request::<R::LspRequest>(lsp_params);
 738
 739                let id = lsp_request.id();
 740                let _cleanup = if status.is_some() {
 741                    cx.update(|cx| {
 742                        this.update(cx, |this, cx| {
 743                            this.on_lsp_work_start(
 744                                language_server.server_id(),
 745                                id.to_string(),
 746                                LanguageServerProgress {
 747                                    is_disk_based_diagnostics_progress: false,
 748                                    is_cancellable: false,
 749                                    title: None,
 750                                    message: status.clone(),
 751                                    percentage: None,
 752                                    last_update_at: cx.background_executor().now(),
 753                                },
 754                                cx,
 755                            );
 756                        })
 757                    })
 758                    .log_err();
 759
 760                    Some(defer(|| {
 761                        cx.update(|cx| {
 762                            this.update(cx, |this, cx| {
 763                                this.on_lsp_work_end(
 764                                    language_server.server_id(),
 765                                    id.to_string(),
 766                                    cx,
 767                                );
 768                            })
 769                        })
 770                        .log_err();
 771                    }))
 772                } else {
 773                    None
 774                };
 775
 776                let result = lsp_request.await;
 777
 778                let response = result.map_err(|err| {
 779                    log::warn!(
 780                        "Generic lsp request to {} failed: {}",
 781                        language_server.name(),
 782                        err
 783                    );
 784                    err
 785                })?;
 786
 787                request
 788                    .response_from_lsp(
 789                        response,
 790                        this.upgrade().ok_or_else(|| anyhow!("no app context"))?,
 791                        buffer_handle,
 792                        language_server.server_id(),
 793                        cx.clone(),
 794                    )
 795                    .await
 796            });
 797        }
 798
 799        Task::ready(Ok(Default::default()))
 800    }
 801
 802    pub async fn execute_code_actions_on_servers(
 803        this: &WeakModel<LspStore>,
 804        adapters_and_servers: &[(Arc<CachedLspAdapter>, Arc<LanguageServer>)],
 805        code_actions: Vec<lsp::CodeActionKind>,
 806        buffer: &Model<Buffer>,
 807        push_to_history: bool,
 808        project_transaction: &mut ProjectTransaction,
 809        cx: &mut AsyncAppContext,
 810    ) -> Result<(), anyhow::Error> {
 811        for (lsp_adapter, language_server) in adapters_and_servers.iter() {
 812            let code_actions = code_actions.clone();
 813
 814            let actions = this
 815                .update(cx, move |this, cx| {
 816                    let request = GetCodeActions {
 817                        range: text::Anchor::MIN..text::Anchor::MAX,
 818                        kinds: Some(code_actions),
 819                    };
 820                    let server = LanguageServerToQuery::Other(language_server.server_id());
 821                    this.request_lsp(buffer.clone(), server, request, cx)
 822                })?
 823                .await?;
 824
 825            for mut action in actions {
 826                Self::try_resolve_code_action(language_server, &mut action)
 827                    .await
 828                    .context("resolving a formatting code action")?;
 829
 830                if let Some(edit) = action.lsp_action.edit {
 831                    if edit.changes.is_none() && edit.document_changes.is_none() {
 832                        continue;
 833                    }
 834
 835                    let new = Self::deserialize_workspace_edit(
 836                        this.upgrade().ok_or_else(|| anyhow!("project dropped"))?,
 837                        edit,
 838                        push_to_history,
 839                        lsp_adapter.clone(),
 840                        language_server.clone(),
 841                        cx,
 842                    )
 843                    .await?;
 844                    project_transaction.0.extend(new.0);
 845                }
 846
 847                if let Some(command) = action.lsp_action.command {
 848                    this.update(cx, |this, _| {
 849                        if let LspStoreMode::Local(mode) = &mut this.mode {
 850                            mode.last_workspace_edits_by_language_server
 851                                .remove(&language_server.server_id());
 852                        }
 853                    })?;
 854
 855                    language_server
 856                        .request::<lsp::request::ExecuteCommand>(lsp::ExecuteCommandParams {
 857                            command: command.command,
 858                            arguments: command.arguments.unwrap_or_default(),
 859                            ..Default::default()
 860                        })
 861                        .await?;
 862
 863                    this.update(cx, |this, _| {
 864                        if let LspStoreMode::Local(mode) = &mut this.mode {
 865                            project_transaction.0.extend(
 866                                mode.last_workspace_edits_by_language_server
 867                                    .remove(&language_server.server_id())
 868                                    .unwrap_or_default()
 869                                    .0,
 870                            )
 871                        }
 872                    })?;
 873                }
 874            }
 875        }
 876
 877        Ok(())
 878    }
 879
 880    async fn try_resolve_code_action(
 881        lang_server: &LanguageServer,
 882        action: &mut CodeAction,
 883    ) -> anyhow::Result<()> {
 884        if GetCodeActions::can_resolve_actions(&lang_server.capabilities())
 885            && action.lsp_action.data.is_some()
 886            && (action.lsp_action.command.is_none() || action.lsp_action.edit.is_none())
 887        {
 888            action.lsp_action = lang_server
 889                .request::<lsp::request::CodeActionResolveRequest>(action.lsp_action.clone())
 890                .await?;
 891        }
 892
 893        anyhow::Ok(())
 894    }
 895
 896    pub fn apply_code_action(
 897        &self,
 898        buffer_handle: Model<Buffer>,
 899        mut action: CodeAction,
 900        push_to_history: bool,
 901        cx: &mut ModelContext<Self>,
 902    ) -> Task<Result<ProjectTransaction>> {
 903        if let Some(upstream_client) = self.upstream_client() {
 904            let request = proto::ApplyCodeAction {
 905                project_id: self.project_id,
 906                buffer_id: buffer_handle.read(cx).remote_id().into(),
 907                action: Some(Self::serialize_code_action(&action)),
 908            };
 909            cx.spawn(move |this, cx| async move {
 910                let response = upstream_client
 911                    .request(request)
 912                    .await?
 913                    .transaction
 914                    .ok_or_else(|| anyhow!("missing transaction"))?;
 915                BufferStore::deserialize_project_transaction(
 916                    this.read_with(&cx, |this, _| this.buffer_store.downgrade())?,
 917                    response,
 918                    push_to_history,
 919                    cx,
 920                )
 921                .await
 922            })
 923        } else {
 924            let buffer = buffer_handle.read(cx);
 925            let (lsp_adapter, lang_server) = if let Some((adapter, server)) =
 926                self.language_server_for_buffer(buffer, action.server_id, cx)
 927            {
 928                (adapter.clone(), server.clone())
 929            } else {
 930                return Task::ready(Ok(Default::default()));
 931            };
 932            cx.spawn(move |this, mut cx| async move {
 933                Self::try_resolve_code_action(&lang_server, &mut action)
 934                    .await
 935                    .context("resolving a code action")?;
 936                if let Some(edit) = action.lsp_action.edit {
 937                    if edit.changes.is_some() || edit.document_changes.is_some() {
 938                        return Self::deserialize_workspace_edit(
 939                            this.upgrade().ok_or_else(|| anyhow!("no app present"))?,
 940                            edit,
 941                            push_to_history,
 942                            lsp_adapter.clone(),
 943                            lang_server.clone(),
 944                            &mut cx,
 945                        )
 946                        .await;
 947                    }
 948                }
 949
 950                if let Some(command) = action.lsp_action.command {
 951                    this.update(&mut cx, |this, _| {
 952                        this.as_local_mut()
 953                            .unwrap()
 954                            .last_workspace_edits_by_language_server
 955                            .remove(&lang_server.server_id());
 956                    })?;
 957
 958                    let result = lang_server
 959                        .request::<lsp::request::ExecuteCommand>(lsp::ExecuteCommandParams {
 960                            command: command.command,
 961                            arguments: command.arguments.unwrap_or_default(),
 962                            ..Default::default()
 963                        })
 964                        .await;
 965
 966                    result?;
 967
 968                    return this.update(&mut cx, |this, _| {
 969                        this.as_local_mut()
 970                            .unwrap()
 971                            .last_workspace_edits_by_language_server
 972                            .remove(&lang_server.server_id())
 973                            .unwrap_or_default()
 974                    });
 975                }
 976
 977                Ok(ProjectTransaction::default())
 978            })
 979        }
 980    }
 981
 982    pub fn resolve_inlay_hint(
 983        &self,
 984        hint: InlayHint,
 985        buffer_handle: Model<Buffer>,
 986        server_id: LanguageServerId,
 987        cx: &mut ModelContext<Self>,
 988    ) -> Task<anyhow::Result<InlayHint>> {
 989        if let Some(upstream_client) = self.upstream_client() {
 990            let request = proto::ResolveInlayHint {
 991                project_id: self.project_id,
 992                buffer_id: buffer_handle.read(cx).remote_id().into(),
 993                language_server_id: server_id.0 as u64,
 994                hint: Some(InlayHints::project_to_proto_hint(hint.clone())),
 995            };
 996            cx.spawn(move |_, _| async move {
 997                let response = upstream_client
 998                    .request(request)
 999                    .await
1000                    .context("inlay hints proto request")?;
1001                match response.hint {
1002                    Some(resolved_hint) => InlayHints::proto_to_project_hint(resolved_hint)
1003                        .context("inlay hints proto resolve response conversion"),
1004                    None => Ok(hint),
1005                }
1006            })
1007        } else {
1008            let buffer = buffer_handle.read(cx);
1009            let (_, lang_server) = if let Some((adapter, server)) =
1010                self.language_server_for_buffer(buffer, server_id, cx)
1011            {
1012                (adapter.clone(), server.clone())
1013            } else {
1014                return Task::ready(Ok(hint));
1015            };
1016            if !InlayHints::can_resolve_inlays(&lang_server.capabilities()) {
1017                return Task::ready(Ok(hint));
1018            }
1019
1020            let buffer_snapshot = buffer.snapshot();
1021            cx.spawn(move |_, mut cx| async move {
1022                let resolve_task = lang_server.request::<lsp::request::InlayHintResolveRequest>(
1023                    InlayHints::project_to_lsp_hint(hint, &buffer_snapshot),
1024                );
1025                let resolved_hint = resolve_task
1026                    .await
1027                    .context("inlay hint resolve LSP request")?;
1028                let resolved_hint = InlayHints::lsp_to_project_hint(
1029                    resolved_hint,
1030                    &buffer_handle,
1031                    server_id,
1032                    ResolveState::Resolved,
1033                    false,
1034                    &mut cx,
1035                )
1036                .await?;
1037                Ok(resolved_hint)
1038            })
1039        }
1040    }
1041
1042    pub(crate) fn linked_edit(
1043        &self,
1044        buffer: &Model<Buffer>,
1045        position: Anchor,
1046        cx: &mut ModelContext<Self>,
1047    ) -> Task<Result<Vec<Range<Anchor>>>> {
1048        let snapshot = buffer.read(cx).snapshot();
1049        let scope = snapshot.language_scope_at(position);
1050        let Some(server_id) = self
1051            .language_servers_for_buffer(buffer.read(cx), cx)
1052            .filter(|(_, server)| {
1053                server
1054                    .capabilities()
1055                    .linked_editing_range_provider
1056                    .is_some()
1057            })
1058            .filter(|(adapter, _)| {
1059                scope
1060                    .as_ref()
1061                    .map(|scope| scope.language_allowed(&adapter.name))
1062                    .unwrap_or(true)
1063            })
1064            .map(|(_, server)| LanguageServerToQuery::Other(server.server_id()))
1065            .next()
1066            .or_else(|| {
1067                self.upstream_client()
1068                    .is_some()
1069                    .then_some(LanguageServerToQuery::Primary)
1070            })
1071            .filter(|_| {
1072                maybe!({
1073                    let language_name = buffer.read(cx).language_at(position)?.name();
1074                    Some(
1075                        AllLanguageSettings::get_global(cx)
1076                            .language(Some(&language_name))
1077                            .linked_edits,
1078                    )
1079                }) == Some(true)
1080            })
1081        else {
1082            return Task::ready(Ok(vec![]));
1083        };
1084
1085        self.request_lsp(
1086            buffer.clone(),
1087            server_id,
1088            LinkedEditingRange { position },
1089            cx,
1090        )
1091    }
1092
1093    fn apply_on_type_formatting(
1094        &self,
1095        buffer: Model<Buffer>,
1096        position: Anchor,
1097        trigger: String,
1098        cx: &mut ModelContext<Self>,
1099    ) -> Task<Result<Option<Transaction>>> {
1100        if let Some(client) = self.upstream_client() {
1101            let request = proto::OnTypeFormatting {
1102                project_id: self.project_id,
1103                buffer_id: buffer.read(cx).remote_id().into(),
1104                position: Some(serialize_anchor(&position)),
1105                trigger,
1106                version: serialize_version(&buffer.read(cx).version()),
1107            };
1108            cx.spawn(move |_, _| async move {
1109                client
1110                    .request(request)
1111                    .await?
1112                    .transaction
1113                    .map(language::proto::deserialize_transaction)
1114                    .transpose()
1115            })
1116        } else {
1117            cx.spawn(move |this, mut cx| async move {
1118                // Do not allow multiple concurrent formatting requests for the
1119                // same buffer.
1120                this.update(&mut cx, |_, cx| {
1121                    cx.emit(LspStoreEvent::StartFormattingLocalBuffer(
1122                        buffer.read(cx).remote_id(),
1123                    ));
1124                })?;
1125
1126                let _cleanup = defer({
1127                    let this = this.clone();
1128                    let mut cx = cx.clone();
1129                    let closure_buffer = buffer.clone();
1130                    move || {
1131                        this.update(&mut cx, |_, cx| {
1132                            cx.emit(LspStoreEvent::FinishFormattingLocalBuffer(
1133                                closure_buffer.read(cx).remote_id(),
1134                            ))
1135                        })
1136                        .ok();
1137                    }
1138                });
1139
1140                buffer
1141                    .update(&mut cx, |buffer, _| {
1142                        buffer.wait_for_edits(Some(position.timestamp))
1143                    })?
1144                    .await?;
1145                this.update(&mut cx, |this, cx| {
1146                    let position = position.to_point_utf16(buffer.read(cx));
1147                    this.on_type_format(buffer, position, trigger, false, cx)
1148                })?
1149                .await
1150            })
1151        }
1152    }
1153
1154    pub fn on_type_format<T: ToPointUtf16>(
1155        &mut self,
1156        buffer: Model<Buffer>,
1157        position: T,
1158        trigger: String,
1159        push_to_history: bool,
1160        cx: &mut ModelContext<Self>,
1161    ) -> Task<Result<Option<Transaction>>> {
1162        let position = position.to_point_utf16(buffer.read(cx));
1163        self.on_type_format_impl(buffer, position, trigger, push_to_history, cx)
1164    }
1165
1166    fn on_type_format_impl(
1167        &mut self,
1168        buffer: Model<Buffer>,
1169        position: PointUtf16,
1170        trigger: String,
1171        push_to_history: bool,
1172        cx: &mut ModelContext<Self>,
1173    ) -> Task<Result<Option<Transaction>>> {
1174        let options = buffer.update(cx, |buffer, cx| {
1175            lsp_command::lsp_formatting_options(language_settings(
1176                buffer.language_at(position).as_ref(),
1177                buffer.file(),
1178                cx,
1179            ))
1180        });
1181        self.request_lsp(
1182            buffer.clone(),
1183            LanguageServerToQuery::Primary,
1184            OnTypeFormatting {
1185                position,
1186                trigger,
1187                options,
1188                push_to_history,
1189            },
1190            cx,
1191        )
1192    }
1193
1194    pub async fn format_via_lsp(
1195        this: &WeakModel<Self>,
1196        buffer: &Model<Buffer>,
1197        abs_path: &Path,
1198        language_server: &Arc<LanguageServer>,
1199        settings: &LanguageSettings,
1200        cx: &mut AsyncAppContext,
1201    ) -> Result<Vec<(Range<Anchor>, String)>> {
1202        let uri = lsp::Url::from_file_path(abs_path)
1203            .map_err(|_| anyhow!("failed to convert abs path to uri"))?;
1204        let text_document = lsp::TextDocumentIdentifier::new(uri);
1205        let capabilities = &language_server.capabilities();
1206
1207        let formatting_provider = capabilities.document_formatting_provider.as_ref();
1208        let range_formatting_provider = capabilities.document_range_formatting_provider.as_ref();
1209
1210        let lsp_edits = if matches!(formatting_provider, Some(p) if *p != OneOf::Left(false)) {
1211            language_server
1212                .request::<lsp::request::Formatting>(lsp::DocumentFormattingParams {
1213                    text_document,
1214                    options: lsp_command::lsp_formatting_options(settings),
1215                    work_done_progress_params: Default::default(),
1216                })
1217                .await?
1218        } else if matches!(range_formatting_provider, Some(p) if *p != OneOf::Left(false)) {
1219            let buffer_start = lsp::Position::new(0, 0);
1220            let buffer_end = buffer.update(cx, |b, _| point_to_lsp(b.max_point_utf16()))?;
1221
1222            language_server
1223                .request::<lsp::request::RangeFormatting>(lsp::DocumentRangeFormattingParams {
1224                    text_document,
1225                    range: lsp::Range::new(buffer_start, buffer_end),
1226                    options: lsp_command::lsp_formatting_options(settings),
1227                    work_done_progress_params: Default::default(),
1228                })
1229                .await?
1230        } else {
1231            None
1232        };
1233
1234        if let Some(lsp_edits) = lsp_edits {
1235            this.update(cx, |this, cx| {
1236                this.edits_from_lsp(buffer, lsp_edits, language_server.server_id(), None, cx)
1237            })?
1238            .await
1239        } else {
1240            Ok(Vec::new())
1241        }
1242    }
1243
1244    pub fn code_actions(
1245        &mut self,
1246        buffer_handle: &Model<Buffer>,
1247        range: Range<Anchor>,
1248        cx: &mut ModelContext<Self>,
1249    ) -> Task<Vec<CodeAction>> {
1250        if let Some(upstream_client) = self.upstream_client() {
1251            let request_task = upstream_client.request(proto::MultiLspQuery {
1252                buffer_id: buffer_handle.read(cx).remote_id().into(),
1253                version: serialize_version(&buffer_handle.read(cx).version()),
1254                project_id: self.project_id,
1255                strategy: Some(proto::multi_lsp_query::Strategy::All(
1256                    proto::AllLanguageServers {},
1257                )),
1258                request: Some(proto::multi_lsp_query::Request::GetCodeActions(
1259                    GetCodeActions {
1260                        range: range.clone(),
1261                        kinds: None,
1262                    }
1263                    .to_proto(self.project_id, buffer_handle.read(cx)),
1264                )),
1265            });
1266            let buffer = buffer_handle.clone();
1267            cx.spawn(|weak_project, cx| async move {
1268                let Some(project) = weak_project.upgrade() else {
1269                    return Vec::new();
1270                };
1271                join_all(
1272                    request_task
1273                        .await
1274                        .log_err()
1275                        .map(|response| response.responses)
1276                        .unwrap_or_default()
1277                        .into_iter()
1278                        .filter_map(|lsp_response| match lsp_response.response? {
1279                            proto::lsp_response::Response::GetCodeActionsResponse(response) => {
1280                                Some(response)
1281                            }
1282                            unexpected => {
1283                                debug_panic!("Unexpected response: {unexpected:?}");
1284                                None
1285                            }
1286                        })
1287                        .map(|code_actions_response| {
1288                            let response = GetCodeActions {
1289                                range: range.clone(),
1290                                kinds: None,
1291                            }
1292                            .response_from_proto(
1293                                code_actions_response,
1294                                project.clone(),
1295                                buffer.clone(),
1296                                cx.clone(),
1297                            );
1298                            async move { response.await.log_err().unwrap_or_default() }
1299                        }),
1300                )
1301                .await
1302                .into_iter()
1303                .flatten()
1304                .collect()
1305            })
1306        } else {
1307            let all_actions_task = self.request_multiple_lsp_locally(
1308                buffer_handle,
1309                Some(range.start),
1310                GetCodeActions {
1311                    range: range.clone(),
1312                    kinds: None,
1313                },
1314                cx,
1315            );
1316            cx.spawn(|_, _| async move { all_actions_task.await.into_iter().flatten().collect() })
1317        }
1318    }
1319
1320    #[inline(never)]
1321    pub fn completions(
1322        &self,
1323        buffer: &Model<Buffer>,
1324        position: PointUtf16,
1325        context: CompletionContext,
1326        cx: &mut ModelContext<Self>,
1327    ) -> Task<Result<Vec<Completion>>> {
1328        let language_registry = self.languages.clone();
1329
1330        if let Some(upstream_client) = self.upstream_client() {
1331            let task = self.send_lsp_proto_request(
1332                buffer.clone(),
1333                upstream_client,
1334                GetCompletions { position, context },
1335                cx,
1336            );
1337            let language = buffer.read(cx).language().cloned();
1338
1339            // In the future, we should provide project guests with the names of LSP adapters,
1340            // so that they can use the correct LSP adapter when computing labels. For now,
1341            // guests just use the first LSP adapter associated with the buffer's language.
1342            let lsp_adapter = language.as_ref().and_then(|language| {
1343                language_registry
1344                    .lsp_adapters(&language.name())
1345                    .first()
1346                    .cloned()
1347            });
1348
1349            cx.foreground_executor().spawn(async move {
1350                let completions = task.await?;
1351                let mut result = Vec::new();
1352                populate_labels_for_completions(
1353                    completions,
1354                    &language_registry,
1355                    language,
1356                    lsp_adapter,
1357                    &mut result,
1358                )
1359                .await;
1360                Ok(result)
1361            })
1362        } else {
1363            let snapshot = buffer.read(cx).snapshot();
1364            let offset = position.to_offset(&snapshot);
1365            let scope = snapshot.language_scope_at(offset);
1366            let language = snapshot.language().cloned();
1367
1368            let server_ids: Vec<_> = self
1369                .language_servers_for_buffer(buffer.read(cx), cx)
1370                .filter(|(_, server)| server.capabilities().completion_provider.is_some())
1371                .filter(|(adapter, _)| {
1372                    scope
1373                        .as_ref()
1374                        .map(|scope| scope.language_allowed(&adapter.name))
1375                        .unwrap_or(true)
1376                })
1377                .map(|(_, server)| server.server_id())
1378                .collect();
1379
1380            let buffer = buffer.clone();
1381            cx.spawn(move |this, mut cx| async move {
1382                let mut tasks = Vec::with_capacity(server_ids.len());
1383                this.update(&mut cx, |this, cx| {
1384                    for server_id in server_ids {
1385                        let lsp_adapter = this.language_server_adapter_for_id(server_id);
1386                        tasks.push((
1387                            lsp_adapter,
1388                            this.request_lsp(
1389                                buffer.clone(),
1390                                LanguageServerToQuery::Other(server_id),
1391                                GetCompletions {
1392                                    position,
1393                                    context: context.clone(),
1394                                },
1395                                cx,
1396                            ),
1397                        ));
1398                    }
1399                })?;
1400
1401                let mut completions = Vec::new();
1402                for (lsp_adapter, task) in tasks {
1403                    if let Ok(new_completions) = task.await {
1404                        populate_labels_for_completions(
1405                            new_completions,
1406                            &language_registry,
1407                            language.clone(),
1408                            lsp_adapter,
1409                            &mut completions,
1410                        )
1411                        .await;
1412                    }
1413                }
1414
1415                Ok(completions)
1416            })
1417        }
1418    }
1419
1420    pub fn resolve_completions(
1421        &self,
1422        buffer: Model<Buffer>,
1423        completion_indices: Vec<usize>,
1424        completions: Arc<RwLock<Box<[Completion]>>>,
1425        cx: &mut ModelContext<Self>,
1426    ) -> Task<Result<bool>> {
1427        let client = self.upstream_client();
1428        let language_registry = self.languages.clone();
1429        let project_id = self.project_id;
1430
1431        let buffer_id = buffer.read(cx).remote_id();
1432        let buffer_snapshot = buffer.read(cx).snapshot();
1433
1434        cx.spawn(move |this, cx| async move {
1435            let mut did_resolve = false;
1436            if let Some(client) = client {
1437                for completion_index in completion_indices {
1438                    let (server_id, completion) = {
1439                        let completions_guard = completions.read();
1440                        let completion = &completions_guard[completion_index];
1441                        if completion.documentation.is_some() {
1442                            continue;
1443                        }
1444
1445                        did_resolve = true;
1446                        let server_id = completion.server_id;
1447                        let completion = completion.lsp_completion.clone();
1448
1449                        (server_id, completion)
1450                    };
1451
1452                    Self::resolve_completion_remote(
1453                        project_id,
1454                        server_id,
1455                        buffer_id,
1456                        completions.clone(),
1457                        completion_index,
1458                        completion,
1459                        client.clone(),
1460                        language_registry.clone(),
1461                    )
1462                    .await;
1463                }
1464            } else {
1465                for completion_index in completion_indices {
1466                    let (server_id, completion) = {
1467                        let completions_guard = completions.read();
1468                        let completion = &completions_guard[completion_index];
1469                        if completion.documentation.is_some() {
1470                            continue;
1471                        }
1472
1473                        let server_id = completion.server_id;
1474                        let completion = completion.lsp_completion.clone();
1475
1476                        (server_id, completion)
1477                    };
1478
1479                    let server = this
1480                        .read_with(&cx, |this, _| this.language_server_for_id(server_id))
1481                        .ok()
1482                        .flatten();
1483                    let Some(server) = server else {
1484                        continue;
1485                    };
1486
1487                    did_resolve = true;
1488                    Self::resolve_completion_local(
1489                        server,
1490                        &buffer_snapshot,
1491                        completions.clone(),
1492                        completion_index,
1493                        completion,
1494                        language_registry.clone(),
1495                    )
1496                    .await;
1497                }
1498            }
1499
1500            Ok(did_resolve)
1501        })
1502    }
1503
1504    async fn resolve_completion_local(
1505        server: Arc<lsp::LanguageServer>,
1506        snapshot: &BufferSnapshot,
1507        completions: Arc<RwLock<Box<[Completion]>>>,
1508        completion_index: usize,
1509        completion: lsp::CompletionItem,
1510        language_registry: Arc<LanguageRegistry>,
1511    ) {
1512        let can_resolve = server
1513            .capabilities()
1514            .completion_provider
1515            .as_ref()
1516            .and_then(|options| options.resolve_provider)
1517            .unwrap_or(false);
1518        if !can_resolve {
1519            return;
1520        }
1521
1522        let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
1523        let Some(completion_item) = request.await.log_err() else {
1524            return;
1525        };
1526
1527        if let Some(lsp_documentation) = completion_item.documentation.as_ref() {
1528            let documentation = language::prepare_completion_documentation(
1529                lsp_documentation,
1530                &language_registry,
1531                None, // TODO: Try to reasonably work out which language the completion is for
1532            )
1533            .await;
1534
1535            let mut completions = completions.write();
1536            let completion = &mut completions[completion_index];
1537            completion.documentation = Some(documentation);
1538        } else {
1539            let mut completions = completions.write();
1540            let completion = &mut completions[completion_index];
1541            completion.documentation = Some(Documentation::Undocumented);
1542        }
1543
1544        if let Some(text_edit) = completion_item.text_edit.as_ref() {
1545            // Technically we don't have to parse the whole `text_edit`, since the only
1546            // language server we currently use that does update `text_edit` in `completionItem/resolve`
1547            // is `typescript-language-server` and they only update `text_edit.new_text`.
1548            // But we should not rely on that.
1549            let edit = parse_completion_text_edit(text_edit, snapshot);
1550
1551            if let Some((old_range, mut new_text)) = edit {
1552                LineEnding::normalize(&mut new_text);
1553
1554                let mut completions = completions.write();
1555                let completion = &mut completions[completion_index];
1556
1557                completion.new_text = new_text;
1558                completion.old_range = old_range;
1559            }
1560        }
1561        if completion_item.insert_text_format == Some(InsertTextFormat::SNIPPET) {
1562            // vtsls might change the type of completion after resolution.
1563            let mut completions = completions.write();
1564            let completion = &mut completions[completion_index];
1565            if completion_item.insert_text_format != completion.lsp_completion.insert_text_format {
1566                completion.lsp_completion.insert_text_format = completion_item.insert_text_format;
1567            }
1568        }
1569    }
1570
1571    #[allow(clippy::too_many_arguments)]
1572    async fn resolve_completion_remote(
1573        project_id: u64,
1574        server_id: LanguageServerId,
1575        buffer_id: BufferId,
1576        completions: Arc<RwLock<Box<[Completion]>>>,
1577        completion_index: usize,
1578        completion: lsp::CompletionItem,
1579        client: AnyProtoClient,
1580        language_registry: Arc<LanguageRegistry>,
1581    ) {
1582        let request = proto::ResolveCompletionDocumentation {
1583            project_id,
1584            language_server_id: server_id.0 as u64,
1585            lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
1586            buffer_id: buffer_id.into(),
1587        };
1588
1589        let Some(response) = client
1590            .request(request)
1591            .await
1592            .context("completion documentation resolve proto request")
1593            .log_err()
1594        else {
1595            return;
1596        };
1597
1598        let documentation = if response.documentation.is_empty() {
1599            Documentation::Undocumented
1600        } else if response.documentation_is_markdown {
1601            Documentation::MultiLineMarkdown(
1602                markdown::parse_markdown(&response.documentation, &language_registry, None).await,
1603            )
1604        } else if response.documentation.lines().count() <= 1 {
1605            Documentation::SingleLine(response.documentation)
1606        } else {
1607            Documentation::MultiLinePlainText(response.documentation)
1608        };
1609
1610        let mut completions = completions.write();
1611        let completion = &mut completions[completion_index];
1612        completion.documentation = Some(documentation);
1613
1614        let old_range = response
1615            .old_start
1616            .and_then(deserialize_anchor)
1617            .zip(response.old_end.and_then(deserialize_anchor));
1618        if let Some((old_start, old_end)) = old_range {
1619            if !response.new_text.is_empty() {
1620                completion.new_text = response.new_text;
1621                completion.old_range = old_start..old_end;
1622            }
1623        }
1624    }
1625
1626    pub fn apply_additional_edits_for_completion(
1627        &self,
1628        buffer_handle: Model<Buffer>,
1629        completion: Completion,
1630        push_to_history: bool,
1631        cx: &mut ModelContext<Self>,
1632    ) -> Task<Result<Option<Transaction>>> {
1633        let buffer = buffer_handle.read(cx);
1634        let buffer_id = buffer.remote_id();
1635
1636        if let Some(client) = self.upstream_client() {
1637            let project_id = self.project_id;
1638            cx.spawn(move |_, mut cx| async move {
1639                let response = client
1640                    .request(proto::ApplyCompletionAdditionalEdits {
1641                        project_id,
1642                        buffer_id: buffer_id.into(),
1643                        completion: Some(Self::serialize_completion(&CoreCompletion {
1644                            old_range: completion.old_range,
1645                            new_text: completion.new_text,
1646                            server_id: completion.server_id,
1647                            lsp_completion: completion.lsp_completion,
1648                        })),
1649                    })
1650                    .await?;
1651
1652                if let Some(transaction) = response.transaction {
1653                    let transaction = language::proto::deserialize_transaction(transaction)?;
1654                    buffer_handle
1655                        .update(&mut cx, |buffer, _| {
1656                            buffer.wait_for_edits(transaction.edit_ids.iter().copied())
1657                        })?
1658                        .await?;
1659                    if push_to_history {
1660                        buffer_handle.update(&mut cx, |buffer, _| {
1661                            buffer.push_transaction(transaction.clone(), Instant::now());
1662                        })?;
1663                    }
1664                    Ok(Some(transaction))
1665                } else {
1666                    Ok(None)
1667                }
1668            })
1669        } else {
1670            let server_id = completion.server_id;
1671            let lang_server = match self.language_server_for_buffer(buffer, server_id, cx) {
1672                Some((_, server)) => server.clone(),
1673                _ => return Task::ready(Ok(Default::default())),
1674            };
1675
1676            cx.spawn(move |this, mut cx| async move {
1677                let can_resolve = lang_server
1678                    .capabilities()
1679                    .completion_provider
1680                    .as_ref()
1681                    .and_then(|options| options.resolve_provider)
1682                    .unwrap_or(false);
1683                let additional_text_edits = if can_resolve {
1684                    lang_server
1685                        .request::<lsp::request::ResolveCompletionItem>(completion.lsp_completion)
1686                        .await?
1687                        .additional_text_edits
1688                } else {
1689                    completion.lsp_completion.additional_text_edits
1690                };
1691                if let Some(edits) = additional_text_edits {
1692                    let edits = this
1693                        .update(&mut cx, |this, cx| {
1694                            this.edits_from_lsp(
1695                                &buffer_handle,
1696                                edits,
1697                                lang_server.server_id(),
1698                                None,
1699                                cx,
1700                            )
1701                        })?
1702                        .await?;
1703
1704                    buffer_handle.update(&mut cx, |buffer, cx| {
1705                        buffer.finalize_last_transaction();
1706                        buffer.start_transaction();
1707
1708                        for (range, text) in edits {
1709                            let primary = &completion.old_range;
1710                            let start_within = primary.start.cmp(&range.start, buffer).is_le()
1711                                && primary.end.cmp(&range.start, buffer).is_ge();
1712                            let end_within = range.start.cmp(&primary.end, buffer).is_le()
1713                                && range.end.cmp(&primary.end, buffer).is_ge();
1714
1715                            //Skip additional edits which overlap with the primary completion edit
1716                            //https://github.com/zed-industries/zed/pull/1871
1717                            if !start_within && !end_within {
1718                                buffer.edit([(range, text)], None, cx);
1719                            }
1720                        }
1721
1722                        let transaction = if buffer.end_transaction(cx).is_some() {
1723                            let transaction = buffer.finalize_last_transaction().unwrap().clone();
1724                            if !push_to_history {
1725                                buffer.forget_transaction(transaction.id);
1726                            }
1727                            Some(transaction)
1728                        } else {
1729                            None
1730                        };
1731                        Ok(transaction)
1732                    })?
1733                } else {
1734                    Ok(None)
1735                }
1736            })
1737        }
1738    }
1739
1740    pub fn inlay_hints(
1741        &mut self,
1742        buffer_handle: Model<Buffer>,
1743        range: Range<Anchor>,
1744        cx: &mut ModelContext<Self>,
1745    ) -> Task<anyhow::Result<Vec<InlayHint>>> {
1746        let buffer = buffer_handle.read(cx);
1747        let range_start = range.start;
1748        let range_end = range.end;
1749        let buffer_id = buffer.remote_id().into();
1750        let lsp_request = InlayHints { range };
1751
1752        if let Some(client) = self.upstream_client() {
1753            let request = proto::InlayHints {
1754                project_id: self.project_id,
1755                buffer_id,
1756                start: Some(serialize_anchor(&range_start)),
1757                end: Some(serialize_anchor(&range_end)),
1758                version: serialize_version(&buffer_handle.read(cx).version()),
1759            };
1760            cx.spawn(move |project, cx| async move {
1761                let response = client
1762                    .request(request)
1763                    .await
1764                    .context("inlay hints proto request")?;
1765                LspCommand::response_from_proto(
1766                    lsp_request,
1767                    response,
1768                    project.upgrade().ok_or_else(|| anyhow!("No project"))?,
1769                    buffer_handle.clone(),
1770                    cx.clone(),
1771                )
1772                .await
1773                .context("inlay hints proto response conversion")
1774            })
1775        } else {
1776            let lsp_request_task = self.request_lsp(
1777                buffer_handle.clone(),
1778                LanguageServerToQuery::Primary,
1779                lsp_request,
1780                cx,
1781            );
1782            cx.spawn(move |_, mut cx| async move {
1783                buffer_handle
1784                    .update(&mut cx, |buffer, _| {
1785                        buffer.wait_for_edits(vec![range_start.timestamp, range_end.timestamp])
1786                    })?
1787                    .await
1788                    .context("waiting for inlay hint request range edits")?;
1789                lsp_request_task.await.context("inlay hints LSP request")
1790            })
1791        }
1792    }
1793
1794    pub fn signature_help<T: ToPointUtf16>(
1795        &self,
1796        buffer: &Model<Buffer>,
1797        position: T,
1798        cx: &mut ModelContext<Self>,
1799    ) -> Task<Vec<SignatureHelp>> {
1800        let position = position.to_point_utf16(buffer.read(cx));
1801
1802        if let Some(client) = self.upstream_client() {
1803            let request_task = client.request(proto::MultiLspQuery {
1804                buffer_id: buffer.read(cx).remote_id().into(),
1805                version: serialize_version(&buffer.read(cx).version()),
1806                project_id: self.project_id,
1807                strategy: Some(proto::multi_lsp_query::Strategy::All(
1808                    proto::AllLanguageServers {},
1809                )),
1810                request: Some(proto::multi_lsp_query::Request::GetSignatureHelp(
1811                    GetSignatureHelp { position }.to_proto(self.project_id, buffer.read(cx)),
1812                )),
1813            });
1814            let buffer = buffer.clone();
1815            cx.spawn(|weak_project, cx| async move {
1816                let Some(project) = weak_project.upgrade() else {
1817                    return Vec::new();
1818                };
1819                join_all(
1820                    request_task
1821                        .await
1822                        .log_err()
1823                        .map(|response| response.responses)
1824                        .unwrap_or_default()
1825                        .into_iter()
1826                        .filter_map(|lsp_response| match lsp_response.response? {
1827                            proto::lsp_response::Response::GetSignatureHelpResponse(response) => {
1828                                Some(response)
1829                            }
1830                            unexpected => {
1831                                debug_panic!("Unexpected response: {unexpected:?}");
1832                                None
1833                            }
1834                        })
1835                        .map(|signature_response| {
1836                            let response = GetSignatureHelp { position }.response_from_proto(
1837                                signature_response,
1838                                project.clone(),
1839                                buffer.clone(),
1840                                cx.clone(),
1841                            );
1842                            async move { response.await.log_err().flatten() }
1843                        }),
1844                )
1845                .await
1846                .into_iter()
1847                .flatten()
1848                .collect()
1849            })
1850        } else {
1851            let all_actions_task = self.request_multiple_lsp_locally(
1852                buffer,
1853                Some(position),
1854                GetSignatureHelp { position },
1855                cx,
1856            );
1857            cx.spawn(|_, _| async move {
1858                all_actions_task
1859                    .await
1860                    .into_iter()
1861                    .flatten()
1862                    .filter(|help| !help.markdown.is_empty())
1863                    .collect::<Vec<_>>()
1864            })
1865        }
1866    }
1867
1868    pub fn hover(
1869        &self,
1870        buffer: &Model<Buffer>,
1871        position: PointUtf16,
1872        cx: &mut ModelContext<Self>,
1873    ) -> Task<Vec<Hover>> {
1874        if let Some(client) = self.upstream_client() {
1875            let request_task = client.request(proto::MultiLspQuery {
1876                buffer_id: buffer.read(cx).remote_id().into(),
1877                version: serialize_version(&buffer.read(cx).version()),
1878                project_id: self.project_id,
1879                strategy: Some(proto::multi_lsp_query::Strategy::All(
1880                    proto::AllLanguageServers {},
1881                )),
1882                request: Some(proto::multi_lsp_query::Request::GetHover(
1883                    GetHover { position }.to_proto(self.project_id, buffer.read(cx)),
1884                )),
1885            });
1886            let buffer = buffer.clone();
1887            cx.spawn(|weak_project, cx| async move {
1888                let Some(project) = weak_project.upgrade() else {
1889                    return Vec::new();
1890                };
1891                join_all(
1892                    request_task
1893                        .await
1894                        .log_err()
1895                        .map(|response| response.responses)
1896                        .unwrap_or_default()
1897                        .into_iter()
1898                        .filter_map(|lsp_response| match lsp_response.response? {
1899                            proto::lsp_response::Response::GetHoverResponse(response) => {
1900                                Some(response)
1901                            }
1902                            unexpected => {
1903                                debug_panic!("Unexpected response: {unexpected:?}");
1904                                None
1905                            }
1906                        })
1907                        .map(|hover_response| {
1908                            let response = GetHover { position }.response_from_proto(
1909                                hover_response,
1910                                project.clone(),
1911                                buffer.clone(),
1912                                cx.clone(),
1913                            );
1914                            async move {
1915                                response
1916                                    .await
1917                                    .log_err()
1918                                    .flatten()
1919                                    .and_then(remove_empty_hover_blocks)
1920                            }
1921                        }),
1922                )
1923                .await
1924                .into_iter()
1925                .flatten()
1926                .collect()
1927            })
1928        } else {
1929            let all_actions_task = self.request_multiple_lsp_locally(
1930                buffer,
1931                Some(position),
1932                GetHover { position },
1933                cx,
1934            );
1935            cx.spawn(|_, _| async move {
1936                all_actions_task
1937                    .await
1938                    .into_iter()
1939                    .filter_map(|hover| remove_empty_hover_blocks(hover?))
1940                    .collect::<Vec<Hover>>()
1941            })
1942        }
1943    }
1944
1945    pub fn symbols(&self, query: &str, cx: &mut ModelContext<Self>) -> Task<Result<Vec<Symbol>>> {
1946        let language_registry = self.languages.clone();
1947
1948        if let Some(upstream_client) = self.upstream_client().as_ref() {
1949            let request = upstream_client.request(proto::GetProjectSymbols {
1950                project_id: self.project_id,
1951                query: query.to_string(),
1952            });
1953            cx.foreground_executor().spawn(async move {
1954                let response = request.await?;
1955                let mut symbols = Vec::new();
1956                let core_symbols = response
1957                    .symbols
1958                    .into_iter()
1959                    .filter_map(|symbol| Self::deserialize_symbol(symbol).log_err())
1960                    .collect::<Vec<_>>();
1961                populate_labels_for_symbols(
1962                    core_symbols,
1963                    &language_registry,
1964                    None,
1965                    None,
1966                    &mut symbols,
1967                )
1968                .await;
1969                Ok(symbols)
1970            })
1971        } else {
1972            struct WorkspaceSymbolsResult {
1973                lsp_adapter: Arc<CachedLspAdapter>,
1974                language: LanguageName,
1975                worktree: WeakModel<Worktree>,
1976                worktree_abs_path: Arc<Path>,
1977                lsp_symbols: Vec<(String, SymbolKind, lsp::Location)>,
1978            }
1979
1980            let mut requests = Vec::new();
1981            for ((worktree_id, _), server_id) in self.language_server_ids.iter() {
1982                let Some(worktree_handle) = self
1983                    .worktree_store
1984                    .read(cx)
1985                    .worktree_for_id(*worktree_id, cx)
1986                else {
1987                    continue;
1988                };
1989                let worktree = worktree_handle.read(cx);
1990                if !worktree.is_visible() {
1991                    continue;
1992                }
1993                let worktree_abs_path = worktree.abs_path().clone();
1994
1995                let (lsp_adapter, language, server) =
1996                    match self.as_local().unwrap().language_servers.get(server_id) {
1997                        Some(LanguageServerState::Running {
1998                            adapter,
1999                            language,
2000                            server,
2001                            ..
2002                        }) => (adapter.clone(), language.clone(), server),
2003
2004                        _ => continue,
2005                    };
2006
2007                requests.push(
2008                    server
2009                        .request::<lsp::request::WorkspaceSymbolRequest>(
2010                            lsp::WorkspaceSymbolParams {
2011                                query: query.to_string(),
2012                                ..Default::default()
2013                            },
2014                        )
2015                        .log_err()
2016                        .map(move |response| {
2017                            let lsp_symbols = response.flatten().map(|symbol_response| match symbol_response {
2018                                lsp::WorkspaceSymbolResponse::Flat(flat_responses) => {
2019                                    flat_responses.into_iter().map(|lsp_symbol| {
2020                                        (lsp_symbol.name, lsp_symbol.kind, lsp_symbol.location)
2021                                    }).collect::<Vec<_>>()
2022                                }
2023                                lsp::WorkspaceSymbolResponse::Nested(nested_responses) => {
2024                                    nested_responses.into_iter().filter_map(|lsp_symbol| {
2025                                        let location = match lsp_symbol.location {
2026                                            OneOf::Left(location) => location,
2027                                            OneOf::Right(_) => {
2028                                                log::error!("Unexpected: client capabilities forbid symbol resolutions in workspace.symbol.resolveSupport");
2029                                                return None
2030                                            }
2031                                        };
2032                                        Some((lsp_symbol.name, lsp_symbol.kind, location))
2033                                    }).collect::<Vec<_>>()
2034                                }
2035                            }).unwrap_or_default();
2036
2037                            WorkspaceSymbolsResult {
2038                                lsp_adapter,
2039                                language,
2040                                worktree: worktree_handle.downgrade(),
2041                                worktree_abs_path,
2042                                lsp_symbols,
2043                            }
2044                        }),
2045                );
2046            }
2047
2048            cx.spawn(move |this, mut cx| async move {
2049                let responses = futures::future::join_all(requests).await;
2050                let this = match this.upgrade() {
2051                    Some(this) => this,
2052                    None => return Ok(Vec::new()),
2053                };
2054
2055                let mut symbols = Vec::new();
2056                for result in responses {
2057                    let core_symbols = this.update(&mut cx, |this, cx| {
2058                        result
2059                            .lsp_symbols
2060                            .into_iter()
2061                            .filter_map(|(symbol_name, symbol_kind, symbol_location)| {
2062                                let abs_path = symbol_location.uri.to_file_path().ok()?;
2063                                let source_worktree = result.worktree.upgrade()?;
2064                                let source_worktree_id = source_worktree.read(cx).id();
2065
2066                                let path;
2067                                let worktree;
2068                                if let Some((tree, rel_path)) =
2069                                    this.worktree_store.read(cx).find_worktree(&abs_path, cx)
2070                                {
2071                                    worktree = tree;
2072                                    path = rel_path;
2073                                } else {
2074                                    worktree = source_worktree.clone();
2075                                    path = relativize_path(&result.worktree_abs_path, &abs_path);
2076                                }
2077
2078                                let worktree_id = worktree.read(cx).id();
2079                                let project_path = ProjectPath {
2080                                    worktree_id,
2081                                    path: path.into(),
2082                                };
2083                                let signature = this.symbol_signature(&project_path);
2084                                Some(CoreSymbol {
2085                                    language_server_name: result.lsp_adapter.name.clone(),
2086                                    source_worktree_id,
2087                                    path: project_path,
2088                                    kind: symbol_kind,
2089                                    name: symbol_name,
2090                                    range: range_from_lsp(symbol_location.range),
2091                                    signature,
2092                                })
2093                            })
2094                            .collect()
2095                    })?;
2096
2097                    populate_labels_for_symbols(
2098                        core_symbols,
2099                        &language_registry,
2100                        Some(result.language),
2101                        Some(result.lsp_adapter),
2102                        &mut symbols,
2103                    )
2104                    .await;
2105                }
2106
2107                Ok(symbols)
2108            })
2109        }
2110    }
2111
2112    pub fn diagnostic_summaries<'a>(
2113        &'a self,
2114        include_ignored: bool,
2115        cx: &'a AppContext,
2116    ) -> impl Iterator<Item = (ProjectPath, LanguageServerId, DiagnosticSummary)> + 'a {
2117        self.worktree_store
2118            .read(cx)
2119            .visible_worktrees(cx)
2120            .filter_map(|worktree| {
2121                let worktree = worktree.read(cx);
2122                Some((worktree, self.diagnostic_summaries.get(&worktree.id())?))
2123            })
2124            .flat_map(move |(worktree, summaries)| {
2125                let worktree_id = worktree.id();
2126                summaries
2127                    .iter()
2128                    .filter(move |(path, _)| {
2129                        include_ignored
2130                            || worktree
2131                                .entry_for_path(path.as_ref())
2132                                .map_or(false, |entry| !entry.is_ignored)
2133                    })
2134                    .flat_map(move |(path, summaries)| {
2135                        summaries.iter().map(move |(server_id, summary)| {
2136                            (
2137                                ProjectPath {
2138                                    worktree_id,
2139                                    path: path.clone(),
2140                                },
2141                                *server_id,
2142                                *summary,
2143                            )
2144                        })
2145                    })
2146            })
2147    }
2148
2149    pub fn started_language_servers(&self) -> Vec<(WorktreeId, LanguageServerName)> {
2150        self.language_server_ids.keys().cloned().collect()
2151    }
2152
2153    pub fn on_buffer_edited(
2154        &mut self,
2155        buffer: Model<Buffer>,
2156        cx: &mut ModelContext<Self>,
2157    ) -> Option<()> {
2158        let buffer = buffer.read(cx);
2159        let file = File::from_dyn(buffer.file())?;
2160        let abs_path = file.as_local()?.abs_path(cx);
2161        let uri = lsp::Url::from_file_path(abs_path).unwrap();
2162        let next_snapshot = buffer.text_snapshot();
2163
2164        let language_servers: Vec<_> = self
2165            .language_servers_for_buffer(buffer, cx)
2166            .map(|i| i.1.clone())
2167            .collect();
2168
2169        for language_server in language_servers {
2170            let language_server = language_server.clone();
2171
2172            let buffer_snapshots = self
2173                .buffer_snapshots
2174                .get_mut(&buffer.remote_id())
2175                .and_then(|m| m.get_mut(&language_server.server_id()))?;
2176            let previous_snapshot = buffer_snapshots.last()?;
2177
2178            let build_incremental_change = || {
2179                buffer
2180                    .edits_since::<(PointUtf16, usize)>(previous_snapshot.snapshot.version())
2181                    .map(|edit| {
2182                        let edit_start = edit.new.start.0;
2183                        let edit_end = edit_start + (edit.old.end.0 - edit.old.start.0);
2184                        let new_text = next_snapshot
2185                            .text_for_range(edit.new.start.1..edit.new.end.1)
2186                            .collect();
2187                        lsp::TextDocumentContentChangeEvent {
2188                            range: Some(lsp::Range::new(
2189                                point_to_lsp(edit_start),
2190                                point_to_lsp(edit_end),
2191                            )),
2192                            range_length: None,
2193                            text: new_text,
2194                        }
2195                    })
2196                    .collect()
2197            };
2198
2199            let document_sync_kind = language_server
2200                .capabilities()
2201                .text_document_sync
2202                .as_ref()
2203                .and_then(|sync| match sync {
2204                    lsp::TextDocumentSyncCapability::Kind(kind) => Some(*kind),
2205                    lsp::TextDocumentSyncCapability::Options(options) => options.change,
2206                });
2207
2208            let content_changes: Vec<_> = match document_sync_kind {
2209                Some(lsp::TextDocumentSyncKind::FULL) => {
2210                    vec![lsp::TextDocumentContentChangeEvent {
2211                        range: None,
2212                        range_length: None,
2213                        text: next_snapshot.text(),
2214                    }]
2215                }
2216                Some(lsp::TextDocumentSyncKind::INCREMENTAL) => build_incremental_change(),
2217                _ => {
2218                    #[cfg(any(test, feature = "test-support"))]
2219                    {
2220                        build_incremental_change()
2221                    }
2222
2223                    #[cfg(not(any(test, feature = "test-support")))]
2224                    {
2225                        continue;
2226                    }
2227                }
2228            };
2229
2230            let next_version = previous_snapshot.version + 1;
2231            buffer_snapshots.push(LspBufferSnapshot {
2232                version: next_version,
2233                snapshot: next_snapshot.clone(),
2234            });
2235
2236            language_server
2237                .notify::<lsp::notification::DidChangeTextDocument>(
2238                    lsp::DidChangeTextDocumentParams {
2239                        text_document: lsp::VersionedTextDocumentIdentifier::new(
2240                            uri.clone(),
2241                            next_version,
2242                        ),
2243                        content_changes,
2244                    },
2245                )
2246                .log_err();
2247        }
2248
2249        None
2250    }
2251
2252    pub fn on_buffer_saved(
2253        &mut self,
2254        buffer: Model<Buffer>,
2255        cx: &mut ModelContext<Self>,
2256    ) -> Option<()> {
2257        let file = File::from_dyn(buffer.read(cx).file())?;
2258        let worktree_id = file.worktree_id(cx);
2259        let abs_path = file.as_local()?.abs_path(cx);
2260        let text_document = lsp::TextDocumentIdentifier {
2261            uri: lsp::Url::from_file_path(abs_path).log_err()?,
2262        };
2263
2264        for server in self.language_servers_for_worktree(worktree_id) {
2265            if let Some(include_text) = include_text(server.as_ref()) {
2266                let text = if include_text {
2267                    Some(buffer.read(cx).text())
2268                } else {
2269                    None
2270                };
2271                server
2272                    .notify::<lsp::notification::DidSaveTextDocument>(
2273                        lsp::DidSaveTextDocumentParams {
2274                            text_document: text_document.clone(),
2275                            text,
2276                        },
2277                    )
2278                    .log_err();
2279            }
2280        }
2281
2282        for language_server_id in self.language_server_ids_for_buffer(buffer.read(cx), cx) {
2283            self.simulate_disk_based_diagnostics_events_if_needed(language_server_id, cx);
2284        }
2285
2286        None
2287    }
2288
2289    fn maintain_workspace_config(cx: &mut ModelContext<Self>) -> Task<Result<()>> {
2290        let (mut settings_changed_tx, mut settings_changed_rx) = watch::channel();
2291        let _ = postage::stream::Stream::try_recv(&mut settings_changed_rx);
2292
2293        let settings_observation = cx.observe_global::<SettingsStore>(move |_, _| {
2294            *settings_changed_tx.borrow_mut() = ();
2295        });
2296
2297        cx.spawn(move |this, mut cx| async move {
2298            while let Some(()) = settings_changed_rx.next().await {
2299                let servers = this.update(&mut cx, |this, cx| {
2300                    this.language_server_ids
2301                        .iter()
2302                        .filter_map(|((worktree_id, _), server_id)| {
2303                            let worktree = this
2304                                .worktree_store
2305                                .read(cx)
2306                                .worktree_for_id(*worktree_id, cx)?;
2307                            let state = this.as_local()?.language_servers.get(server_id)?;
2308                            let delegate =
2309                                ProjectLspAdapterDelegate::for_local(this, &worktree, cx);
2310                            match state {
2311                                LanguageServerState::Starting(_) => None,
2312                                LanguageServerState::Running {
2313                                    adapter, server, ..
2314                                } => Some((
2315                                    adapter.adapter.clone(),
2316                                    server.clone(),
2317                                    delegate as Arc<dyn LspAdapterDelegate>,
2318                                )),
2319                            }
2320                        })
2321                        .collect::<Vec<_>>()
2322                })?;
2323
2324                for (adapter, server, delegate) in servers {
2325                    let settings = adapter.workspace_configuration(&delegate, &mut cx).await?;
2326
2327                    server
2328                        .notify::<lsp::notification::DidChangeConfiguration>(
2329                            lsp::DidChangeConfigurationParams { settings },
2330                        )
2331                        .ok();
2332                }
2333            }
2334
2335            drop(settings_observation);
2336            anyhow::Ok(())
2337        })
2338    }
2339
2340    pub fn primary_language_server_for_buffer<'a>(
2341        &'a self,
2342        buffer: &'a Buffer,
2343        cx: &'a AppContext,
2344    ) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
2345        // The list of language servers is ordered based on the `language_servers` setting
2346        // for each language, thus we can consider the first one in the list to be the
2347        // primary one.
2348        self.language_servers_for_buffer(buffer, cx).next()
2349    }
2350
2351    pub fn language_server_for_buffer<'a>(
2352        &'a self,
2353        buffer: &'a Buffer,
2354        server_id: LanguageServerId,
2355        cx: &'a AppContext,
2356    ) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
2357        self.language_servers_for_buffer(buffer, cx)
2358            .find(|(_, s)| s.server_id() == server_id)
2359    }
2360
2361    fn language_servers_for_worktree(
2362        &self,
2363        worktree_id: WorktreeId,
2364    ) -> impl Iterator<Item = &Arc<LanguageServer>> {
2365        self.language_server_ids
2366            .iter()
2367            .filter_map(move |((language_server_worktree_id, _), id)| {
2368                if *language_server_worktree_id == worktree_id {
2369                    if let Some(LanguageServerState::Running { server, .. }) =
2370                        self.as_local()?.language_servers.get(id)
2371                    {
2372                        return Some(server);
2373                    }
2374                }
2375                None
2376            })
2377    }
2378
2379    pub fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut ModelContext<Self>) {
2380        self.diagnostics.remove(&id_to_remove);
2381        self.diagnostic_summaries.remove(&id_to_remove);
2382
2383        let mut servers_to_remove = HashMap::default();
2384        let mut servers_to_preserve = HashSet::default();
2385        for ((worktree_id, server_name), &server_id) in &self.language_server_ids {
2386            if worktree_id == &id_to_remove {
2387                servers_to_remove.insert(server_id, server_name.clone());
2388            } else {
2389                servers_to_preserve.insert(server_id);
2390            }
2391        }
2392        servers_to_remove.retain(|server_id, _| !servers_to_preserve.contains(server_id));
2393        for (server_id_to_remove, server_name) in servers_to_remove {
2394            self.language_server_ids
2395                .remove(&(id_to_remove, server_name));
2396            self.language_server_statuses.remove(&server_id_to_remove);
2397            if let Some(local_lsp_store) = self.as_local_mut() {
2398                local_lsp_store
2399                    .language_server_watched_paths
2400                    .remove(&server_id_to_remove);
2401                local_lsp_store
2402                    .last_workspace_edits_by_language_server
2403                    .remove(&server_id_to_remove);
2404                local_lsp_store
2405                    .language_servers
2406                    .remove(&server_id_to_remove);
2407            }
2408            cx.emit(LspStoreEvent::LanguageServerRemoved(server_id_to_remove));
2409        }
2410    }
2411
2412    pub fn shared(
2413        &mut self,
2414        project_id: u64,
2415        downstream_client: AnyProtoClient,
2416        _: &mut ModelContext<Self>,
2417    ) {
2418        self.project_id = project_id;
2419        self.downstream_client = Some(downstream_client.clone());
2420
2421        for (server_id, status) in &self.language_server_statuses {
2422            downstream_client
2423                .send(proto::StartLanguageServer {
2424                    project_id,
2425                    server: Some(proto::LanguageServer {
2426                        id: server_id.0 as u64,
2427                        name: status.name.clone(),
2428                    }),
2429                })
2430                .log_err();
2431        }
2432    }
2433
2434    pub fn disconnected_from_host(&mut self) {
2435        self.downstream_client.take();
2436    }
2437
2438    pub(crate) fn set_language_server_statuses_from_proto(
2439        &mut self,
2440        language_servers: Vec<proto::LanguageServer>,
2441    ) {
2442        self.language_server_statuses = language_servers
2443            .into_iter()
2444            .map(|server| {
2445                (
2446                    LanguageServerId(server.id as usize),
2447                    LanguageServerStatus {
2448                        name: server.name,
2449                        pending_work: Default::default(),
2450                        has_pending_diagnostic_updates: false,
2451                        progress_tokens: Default::default(),
2452                    },
2453                )
2454            })
2455            .collect();
2456    }
2457
2458    pub(crate) fn register_language_server(
2459        &mut self,
2460        worktree_id: WorktreeId,
2461        language_server_name: LanguageServerName,
2462        language_server_id: LanguageServerId,
2463    ) {
2464        self.language_server_ids
2465            .insert((worktree_id, language_server_name), language_server_id);
2466    }
2467
2468    #[track_caller]
2469    pub(crate) fn register_buffer_with_language_servers(
2470        &mut self,
2471        buffer_handle: &Model<Buffer>,
2472        cx: &mut ModelContext<Self>,
2473    ) {
2474        let available_language = self.detect_language_for_buffer(buffer_handle, cx);
2475
2476        let buffer = buffer_handle.read(cx);
2477        let buffer_id = buffer.remote_id();
2478
2479        if let Some(file) = File::from_dyn(buffer.file()) {
2480            if !file.is_local() {
2481                return;
2482            }
2483
2484            let abs_path = file.abs_path(cx);
2485            let Some(uri) = lsp::Url::from_file_path(&abs_path).log_err() else {
2486                return;
2487            };
2488            let initial_snapshot = buffer.text_snapshot();
2489            let worktree_id = file.worktree_id(cx);
2490
2491            if let Some(diagnostics) = self.diagnostics.get(&worktree_id) {
2492                for (server_id, diagnostics) in
2493                    diagnostics.get(file.path()).cloned().unwrap_or_default()
2494                {
2495                    self.update_buffer_diagnostics(buffer_handle, server_id, None, diagnostics, cx)
2496                        .log_err();
2497                }
2498            }
2499
2500            if let Some(language) = available_language {
2501                for adapter in self.languages.lsp_adapters(&language.name()) {
2502                    let server = self
2503                        .language_server_ids
2504                        .get(&(worktree_id, adapter.name.clone()))
2505                        .and_then(|id| self.as_local()?.language_servers.get(id))
2506                        .and_then(|server_state| {
2507                            if let LanguageServerState::Running { server, .. } = server_state {
2508                                Some(server.clone())
2509                            } else {
2510                                None
2511                            }
2512                        });
2513                    let server = match server {
2514                        Some(server) => server,
2515                        None => continue,
2516                    };
2517
2518                    server
2519                        .notify::<lsp::notification::DidOpenTextDocument>(
2520                            lsp::DidOpenTextDocumentParams {
2521                                text_document: lsp::TextDocumentItem::new(
2522                                    uri.clone(),
2523                                    adapter.language_id(&language.name()),
2524                                    0,
2525                                    initial_snapshot.text(),
2526                                ),
2527                            },
2528                        )
2529                        .log_err();
2530
2531                    buffer_handle.update(cx, |buffer, cx| {
2532                        buffer.set_completion_triggers(
2533                            server
2534                                .capabilities()
2535                                .completion_provider
2536                                .as_ref()
2537                                .and_then(|provider| provider.trigger_characters.clone())
2538                                .unwrap_or_default(),
2539                            cx,
2540                        );
2541                    });
2542
2543                    let snapshot = LspBufferSnapshot {
2544                        version: 0,
2545                        snapshot: initial_snapshot.clone(),
2546                    };
2547                    self.buffer_snapshots
2548                        .entry(buffer_id)
2549                        .or_default()
2550                        .insert(server.server_id(), vec![snapshot]);
2551                }
2552            }
2553        }
2554    }
2555
2556    pub(crate) fn unregister_buffer_from_language_servers(
2557        &mut self,
2558        buffer: &Model<Buffer>,
2559        old_file: &File,
2560        cx: &mut AppContext,
2561    ) {
2562        let old_path = match old_file.as_local() {
2563            Some(local) => local.abs_path(cx),
2564            None => return,
2565        };
2566
2567        buffer.update(cx, |buffer, cx| {
2568            let worktree_id = old_file.worktree_id(cx);
2569
2570            let ids = &self.language_server_ids;
2571
2572            if let Some(language) = buffer.language().cloned() {
2573                for adapter in self.languages.lsp_adapters(&language.name()) {
2574                    if let Some(server_id) = ids.get(&(worktree_id, adapter.name.clone())) {
2575                        buffer.update_diagnostics(*server_id, Default::default(), cx);
2576                    }
2577                }
2578            }
2579
2580            self.buffer_snapshots.remove(&buffer.remote_id());
2581            let file_url = lsp::Url::from_file_path(old_path).unwrap();
2582            for (_, language_server) in self.language_servers_for_buffer(buffer, cx) {
2583                language_server
2584                    .notify::<lsp::notification::DidCloseTextDocument>(
2585                        lsp::DidCloseTextDocumentParams {
2586                            text_document: lsp::TextDocumentIdentifier::new(file_url.clone()),
2587                        },
2588                    )
2589                    .log_err();
2590            }
2591        });
2592    }
2593
2594    pub fn update_diagnostic_entries(
2595        &mut self,
2596        server_id: LanguageServerId,
2597        abs_path: PathBuf,
2598        version: Option<i32>,
2599        diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
2600        cx: &mut ModelContext<Self>,
2601    ) -> Result<(), anyhow::Error> {
2602        let (worktree, relative_path) =
2603            self.worktree_store
2604                .read(cx)
2605                .find_worktree(&abs_path, cx)
2606                .ok_or_else(|| anyhow!("no worktree found for diagnostics path {abs_path:?}"))?;
2607
2608        let project_path = ProjectPath {
2609            worktree_id: worktree.read(cx).id(),
2610            path: relative_path.into(),
2611        };
2612
2613        if let Some(buffer) = self.buffer_store.read(cx).get_by_path(&project_path, cx) {
2614            self.update_buffer_diagnostics(&buffer, server_id, version, diagnostics.clone(), cx)?;
2615        }
2616
2617        let updated = worktree.update(cx, |worktree, cx| {
2618            self.update_worktree_diagnostics(
2619                worktree.id(),
2620                server_id,
2621                project_path.path.clone(),
2622                diagnostics,
2623                cx,
2624            )
2625        })?;
2626        if updated {
2627            cx.emit(LspStoreEvent::DiagnosticsUpdated {
2628                language_server_id: server_id,
2629                path: project_path,
2630            })
2631        }
2632        Ok(())
2633    }
2634
2635    pub fn update_worktree_diagnostics(
2636        &mut self,
2637        worktree_id: WorktreeId,
2638        server_id: LanguageServerId,
2639        worktree_path: Arc<Path>,
2640        diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
2641        _: &mut ModelContext<Worktree>,
2642    ) -> Result<bool> {
2643        let summaries_for_tree = self.diagnostic_summaries.entry(worktree_id).or_default();
2644        let diagnostics_for_tree = self.diagnostics.entry(worktree_id).or_default();
2645        let summaries_by_server_id = summaries_for_tree.entry(worktree_path.clone()).or_default();
2646
2647        let old_summary = summaries_by_server_id
2648            .remove(&server_id)
2649            .unwrap_or_default();
2650
2651        let new_summary = DiagnosticSummary::new(&diagnostics);
2652        if new_summary.is_empty() {
2653            if let Some(diagnostics_by_server_id) = diagnostics_for_tree.get_mut(&worktree_path) {
2654                if let Ok(ix) = diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0) {
2655                    diagnostics_by_server_id.remove(ix);
2656                }
2657                if diagnostics_by_server_id.is_empty() {
2658                    diagnostics_for_tree.remove(&worktree_path);
2659                }
2660            }
2661        } else {
2662            summaries_by_server_id.insert(server_id, new_summary);
2663            let diagnostics_by_server_id = diagnostics_for_tree
2664                .entry(worktree_path.clone())
2665                .or_default();
2666            match diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0) {
2667                Ok(ix) => {
2668                    diagnostics_by_server_id[ix] = (server_id, diagnostics);
2669                }
2670                Err(ix) => {
2671                    diagnostics_by_server_id.insert(ix, (server_id, diagnostics));
2672                }
2673            }
2674        }
2675
2676        if !old_summary.is_empty() || !new_summary.is_empty() {
2677            if let Some(downstream_client) = &self.downstream_client {
2678                downstream_client
2679                    .send(proto::UpdateDiagnosticSummary {
2680                        project_id: self.project_id,
2681                        worktree_id: worktree_id.to_proto(),
2682                        summary: Some(proto::DiagnosticSummary {
2683                            path: worktree_path.to_string_lossy().to_string(),
2684                            language_server_id: server_id.0 as u64,
2685                            error_count: new_summary.error_count as u32,
2686                            warning_count: new_summary.warning_count as u32,
2687                        }),
2688                    })
2689                    .log_err();
2690            }
2691        }
2692
2693        Ok(!old_summary.is_empty() || !new_summary.is_empty())
2694    }
2695
2696    pub fn open_buffer_for_symbol(
2697        &mut self,
2698        symbol: &Symbol,
2699        cx: &mut ModelContext<Self>,
2700    ) -> Task<Result<Model<Buffer>>> {
2701        if let Some(client) = self.upstream_client() {
2702            let request = client.request(proto::OpenBufferForSymbol {
2703                project_id: self.project_id,
2704                symbol: Some(Self::serialize_symbol(symbol)),
2705            });
2706            cx.spawn(move |this, mut cx| async move {
2707                let response = request.await?;
2708                let buffer_id = BufferId::new(response.buffer_id)?;
2709                this.update(&mut cx, |this, cx| {
2710                    this.wait_for_remote_buffer(buffer_id, cx)
2711                })?
2712                .await
2713            })
2714        } else {
2715            let Some(&language_server_id) = self.language_server_ids.get(&(
2716                symbol.source_worktree_id,
2717                symbol.language_server_name.clone(),
2718            )) else {
2719                return Task::ready(Err(anyhow!(
2720                    "language server for worktree and language not found"
2721                )));
2722            };
2723
2724            let worktree_abs_path = if let Some(worktree_abs_path) = self
2725                .worktree_store
2726                .read(cx)
2727                .worktree_for_id(symbol.path.worktree_id, cx)
2728                .map(|worktree| worktree.read(cx).abs_path())
2729            {
2730                worktree_abs_path
2731            } else {
2732                return Task::ready(Err(anyhow!("worktree not found for symbol")));
2733            };
2734
2735            let symbol_abs_path = resolve_path(&worktree_abs_path, &symbol.path.path);
2736            let symbol_uri = if let Ok(uri) = lsp::Url::from_file_path(symbol_abs_path) {
2737                uri
2738            } else {
2739                return Task::ready(Err(anyhow!("invalid symbol path")));
2740            };
2741
2742            self.open_local_buffer_via_lsp(
2743                symbol_uri,
2744                language_server_id,
2745                symbol.language_server_name.clone(),
2746                cx,
2747            )
2748        }
2749    }
2750
2751    pub fn open_local_buffer_via_lsp(
2752        &mut self,
2753        mut abs_path: lsp::Url,
2754        language_server_id: LanguageServerId,
2755        language_server_name: LanguageServerName,
2756        cx: &mut ModelContext<Self>,
2757    ) -> Task<Result<Model<Buffer>>> {
2758        cx.spawn(move |this, mut cx| async move {
2759            // Escape percent-encoded string.
2760            let current_scheme = abs_path.scheme().to_owned();
2761            let _ = abs_path.set_scheme("file");
2762
2763            let abs_path = abs_path
2764                .to_file_path()
2765                .map_err(|_| anyhow!("can't convert URI to path"))?;
2766            let p = abs_path.clone();
2767            let yarn_worktree = this
2768                .update(&mut cx, move |this, cx| {
2769                    this.as_local().unwrap().yarn.update(cx, |_, cx| {
2770                        cx.spawn(|this, mut cx| async move {
2771                            let t = this
2772                                .update(&mut cx, |this, cx| {
2773                                    this.process_path(&p, &current_scheme, cx)
2774                                })
2775                                .ok()?;
2776                            t.await
2777                        })
2778                    })
2779                })?
2780                .await;
2781            let (worktree_root_target, known_relative_path) =
2782                if let Some((zip_root, relative_path)) = yarn_worktree {
2783                    (zip_root, Some(relative_path))
2784                } else {
2785                    (Arc::<Path>::from(abs_path.as_path()), None)
2786                };
2787            let (worktree, relative_path) = if let Some(result) =
2788                this.update(&mut cx, |this, cx| {
2789                    this.worktree_store.update(cx, |worktree_store, cx| {
2790                        worktree_store.find_worktree(&worktree_root_target, cx)
2791                    })
2792                })? {
2793                let relative_path =
2794                    known_relative_path.unwrap_or_else(|| Arc::<Path>::from(result.1));
2795                (result.0, relative_path)
2796            } else {
2797                let worktree = this
2798                    .update(&mut cx, |this, cx| {
2799                        this.worktree_store.update(cx, |worktree_store, cx| {
2800                            worktree_store.create_worktree(&worktree_root_target, false, cx)
2801                        })
2802                    })?
2803                    .await?;
2804                this.update(&mut cx, |this, cx| {
2805                    this.register_language_server(
2806                        worktree.read(cx).id(),
2807                        language_server_name,
2808                        language_server_id,
2809                    )
2810                })
2811                .ok();
2812                let worktree_root = worktree.update(&mut cx, |this, _| this.abs_path())?;
2813                let relative_path = if let Some(known_path) = known_relative_path {
2814                    known_path
2815                } else {
2816                    abs_path.strip_prefix(worktree_root)?.into()
2817                };
2818                (worktree, relative_path)
2819            };
2820            let project_path = ProjectPath {
2821                worktree_id: worktree.update(&mut cx, |worktree, _| worktree.id())?,
2822                path: relative_path,
2823            };
2824            this.update(&mut cx, |this, cx| {
2825                this.buffer_store().update(cx, |buffer_store, cx| {
2826                    buffer_store.open_buffer(project_path, cx)
2827                })
2828            })?
2829            .await
2830        })
2831    }
2832
2833    pub(crate) fn update_buffer_diagnostics(
2834        &mut self,
2835        buffer: &Model<Buffer>,
2836        server_id: LanguageServerId,
2837        version: Option<i32>,
2838        mut diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
2839        cx: &mut ModelContext<Self>,
2840    ) -> Result<()> {
2841        fn compare_diagnostics(a: &Diagnostic, b: &Diagnostic) -> Ordering {
2842            Ordering::Equal
2843                .then_with(|| b.is_primary.cmp(&a.is_primary))
2844                .then_with(|| a.is_disk_based.cmp(&b.is_disk_based))
2845                .then_with(|| a.severity.cmp(&b.severity))
2846                .then_with(|| a.message.cmp(&b.message))
2847        }
2848
2849        let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx)?;
2850
2851        diagnostics.sort_unstable_by(|a, b| {
2852            Ordering::Equal
2853                .then_with(|| a.range.start.cmp(&b.range.start))
2854                .then_with(|| b.range.end.cmp(&a.range.end))
2855                .then_with(|| compare_diagnostics(&a.diagnostic, &b.diagnostic))
2856        });
2857
2858        let mut sanitized_diagnostics = Vec::new();
2859        let edits_since_save = Patch::new(
2860            snapshot
2861                .edits_since::<Unclipped<PointUtf16>>(buffer.read(cx).saved_version())
2862                .collect(),
2863        );
2864        for entry in diagnostics {
2865            let start;
2866            let end;
2867            if entry.diagnostic.is_disk_based {
2868                // Some diagnostics are based on files on disk instead of buffers'
2869                // current contents. Adjust these diagnostics' ranges to reflect
2870                // any unsaved edits.
2871                start = edits_since_save.old_to_new(entry.range.start);
2872                end = edits_since_save.old_to_new(entry.range.end);
2873            } else {
2874                start = entry.range.start;
2875                end = entry.range.end;
2876            }
2877
2878            let mut range = snapshot.clip_point_utf16(start, Bias::Left)
2879                ..snapshot.clip_point_utf16(end, Bias::Right);
2880
2881            // Expand empty ranges by one codepoint
2882            if range.start == range.end {
2883                // This will be go to the next boundary when being clipped
2884                range.end.column += 1;
2885                range.end = snapshot.clip_point_utf16(Unclipped(range.end), Bias::Right);
2886                if range.start == range.end && range.end.column > 0 {
2887                    range.start.column -= 1;
2888                    range.start = snapshot.clip_point_utf16(Unclipped(range.start), Bias::Left);
2889                }
2890            }
2891
2892            sanitized_diagnostics.push(DiagnosticEntry {
2893                range,
2894                diagnostic: entry.diagnostic,
2895            });
2896        }
2897        drop(edits_since_save);
2898
2899        let set = DiagnosticSet::new(sanitized_diagnostics, &snapshot);
2900        buffer.update(cx, |buffer, cx| {
2901            buffer.update_diagnostics(server_id, set, cx)
2902        });
2903        Ok(())
2904    }
2905
2906    fn request_multiple_lsp_locally<P, R>(
2907        &self,
2908        buffer: &Model<Buffer>,
2909        position: Option<P>,
2910        request: R,
2911        cx: &mut ModelContext<'_, Self>,
2912    ) -> Task<Vec<R::Response>>
2913    where
2914        P: ToOffset,
2915        R: LspCommand + Clone,
2916        <R::LspRequest as lsp::request::Request>::Result: Send,
2917        <R::LspRequest as lsp::request::Request>::Params: Send,
2918    {
2919        debug_assert!(self.upstream_client().is_none());
2920
2921        let snapshot = buffer.read(cx).snapshot();
2922        let scope = position.and_then(|position| snapshot.language_scope_at(position));
2923        let server_ids = self
2924            .language_servers_for_buffer(buffer.read(cx), cx)
2925            .filter(|(adapter, _)| {
2926                scope
2927                    .as_ref()
2928                    .map(|scope| scope.language_allowed(&adapter.name))
2929                    .unwrap_or(true)
2930            })
2931            .map(|(_, server)| server.server_id())
2932            .collect::<Vec<_>>();
2933        let mut response_results = server_ids
2934            .into_iter()
2935            .map(|server_id| {
2936                self.request_lsp(
2937                    buffer.clone(),
2938                    LanguageServerToQuery::Other(server_id),
2939                    request.clone(),
2940                    cx,
2941                )
2942            })
2943            .collect::<FuturesUnordered<_>>();
2944
2945        cx.spawn(|_, _| async move {
2946            let mut responses = Vec::with_capacity(response_results.len());
2947            while let Some(response_result) = response_results.next().await {
2948                if let Some(response) = response_result.log_err() {
2949                    responses.push(response);
2950                }
2951            }
2952            responses
2953        })
2954    }
2955
2956    async fn handle_lsp_command<T: LspCommand>(
2957        this: Model<Self>,
2958        envelope: TypedEnvelope<T::ProtoRequest>,
2959        mut cx: AsyncAppContext,
2960    ) -> Result<<T::ProtoRequest as proto::RequestMessage>::Response>
2961    where
2962        <T::LspRequest as lsp::request::Request>::Params: Send,
2963        <T::LspRequest as lsp::request::Request>::Result: Send,
2964    {
2965        let sender_id = envelope.original_sender_id().unwrap_or_default();
2966        let buffer_id = T::buffer_id_from_proto(&envelope.payload)?;
2967        let buffer_handle = this.update(&mut cx, |this, cx| {
2968            this.buffer_store.read(cx).get_existing(buffer_id)
2969        })??;
2970        let request = T::from_proto(
2971            envelope.payload,
2972            this.clone(),
2973            buffer_handle.clone(),
2974            cx.clone(),
2975        )
2976        .await?;
2977        let response = this
2978            .update(&mut cx, |this, cx| {
2979                this.request_lsp(
2980                    buffer_handle.clone(),
2981                    LanguageServerToQuery::Primary,
2982                    request,
2983                    cx,
2984                )
2985            })?
2986            .await?;
2987        this.update(&mut cx, |this, cx| {
2988            Ok(T::response_to_proto(
2989                response,
2990                this,
2991                sender_id,
2992                &buffer_handle.read(cx).version(),
2993                cx,
2994            ))
2995        })?
2996    }
2997
2998    async fn handle_multi_lsp_query(
2999        this: Model<Self>,
3000        envelope: TypedEnvelope<proto::MultiLspQuery>,
3001        mut cx: AsyncAppContext,
3002    ) -> Result<proto::MultiLspQueryResponse> {
3003        let sender_id = envelope.original_sender_id().unwrap_or_default();
3004        let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
3005        let version = deserialize_version(&envelope.payload.version);
3006        let buffer = this.update(&mut cx, |this, cx| {
3007            this.buffer_store.read(cx).get_existing(buffer_id)
3008        })??;
3009        buffer
3010            .update(&mut cx, |buffer, _| {
3011                buffer.wait_for_version(version.clone())
3012            })?
3013            .await?;
3014        let buffer_version = buffer.update(&mut cx, |buffer, _| buffer.version())?;
3015        match envelope
3016            .payload
3017            .strategy
3018            .context("invalid request without the strategy")?
3019        {
3020            proto::multi_lsp_query::Strategy::All(_) => {
3021                // currently, there's only one multiple language servers query strategy,
3022                // so just ensure it's specified correctly
3023            }
3024        }
3025        match envelope.payload.request {
3026            Some(proto::multi_lsp_query::Request::GetHover(get_hover)) => {
3027                let get_hover =
3028                    GetHover::from_proto(get_hover, this.clone(), buffer.clone(), cx.clone())
3029                        .await?;
3030                let all_hovers = this
3031                    .update(&mut cx, |this, cx| {
3032                        this.request_multiple_lsp_locally(
3033                            &buffer,
3034                            Some(get_hover.position),
3035                            get_hover,
3036                            cx,
3037                        )
3038                    })?
3039                    .await
3040                    .into_iter()
3041                    .filter_map(|hover| remove_empty_hover_blocks(hover?));
3042                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
3043                    responses: all_hovers
3044                        .map(|hover| proto::LspResponse {
3045                            response: Some(proto::lsp_response::Response::GetHoverResponse(
3046                                GetHover::response_to_proto(
3047                                    Some(hover),
3048                                    project,
3049                                    sender_id,
3050                                    &buffer_version,
3051                                    cx,
3052                                ),
3053                            )),
3054                        })
3055                        .collect(),
3056                })
3057            }
3058            Some(proto::multi_lsp_query::Request::GetCodeActions(get_code_actions)) => {
3059                let get_code_actions = GetCodeActions::from_proto(
3060                    get_code_actions,
3061                    this.clone(),
3062                    buffer.clone(),
3063                    cx.clone(),
3064                )
3065                .await?;
3066
3067                let all_actions = this
3068                    .update(&mut cx, |project, cx| {
3069                        project.request_multiple_lsp_locally(
3070                            &buffer,
3071                            Some(get_code_actions.range.start),
3072                            get_code_actions,
3073                            cx,
3074                        )
3075                    })?
3076                    .await
3077                    .into_iter();
3078
3079                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
3080                    responses: all_actions
3081                        .map(|code_actions| proto::LspResponse {
3082                            response: Some(proto::lsp_response::Response::GetCodeActionsResponse(
3083                                GetCodeActions::response_to_proto(
3084                                    code_actions,
3085                                    project,
3086                                    sender_id,
3087                                    &buffer_version,
3088                                    cx,
3089                                ),
3090                            )),
3091                        })
3092                        .collect(),
3093                })
3094            }
3095            Some(proto::multi_lsp_query::Request::GetSignatureHelp(get_signature_help)) => {
3096                let get_signature_help = GetSignatureHelp::from_proto(
3097                    get_signature_help,
3098                    this.clone(),
3099                    buffer.clone(),
3100                    cx.clone(),
3101                )
3102                .await?;
3103
3104                let all_signatures = this
3105                    .update(&mut cx, |project, cx| {
3106                        project.request_multiple_lsp_locally(
3107                            &buffer,
3108                            Some(get_signature_help.position),
3109                            get_signature_help,
3110                            cx,
3111                        )
3112                    })?
3113                    .await
3114                    .into_iter();
3115
3116                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
3117                    responses: all_signatures
3118                        .map(|signature_help| proto::LspResponse {
3119                            response: Some(
3120                                proto::lsp_response::Response::GetSignatureHelpResponse(
3121                                    GetSignatureHelp::response_to_proto(
3122                                        signature_help,
3123                                        project,
3124                                        sender_id,
3125                                        &buffer_version,
3126                                        cx,
3127                                    ),
3128                                ),
3129                            ),
3130                        })
3131                        .collect(),
3132                })
3133            }
3134            None => anyhow::bail!("empty multi lsp query request"),
3135        }
3136    }
3137
3138    async fn handle_apply_code_action(
3139        this: Model<Self>,
3140        envelope: TypedEnvelope<proto::ApplyCodeAction>,
3141        mut cx: AsyncAppContext,
3142    ) -> Result<proto::ApplyCodeActionResponse> {
3143        let sender_id = envelope.original_sender_id().unwrap_or_default();
3144        let action = Self::deserialize_code_action(
3145            envelope
3146                .payload
3147                .action
3148                .ok_or_else(|| anyhow!("invalid action"))?,
3149        )?;
3150        let apply_code_action = this.update(&mut cx, |this, cx| {
3151            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
3152            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
3153            anyhow::Ok(this.apply_code_action(buffer, action, false, cx))
3154        })??;
3155
3156        let project_transaction = apply_code_action.await?;
3157        let project_transaction = this.update(&mut cx, |this, cx| {
3158            this.buffer_store.update(cx, |buffer_store, cx| {
3159                buffer_store.serialize_project_transaction_for_peer(
3160                    project_transaction,
3161                    sender_id,
3162                    cx,
3163                )
3164            })
3165        })?;
3166        Ok(proto::ApplyCodeActionResponse {
3167            transaction: Some(project_transaction),
3168        })
3169    }
3170
3171    async fn handle_update_diagnostic_summary(
3172        this: Model<Self>,
3173        envelope: TypedEnvelope<proto::UpdateDiagnosticSummary>,
3174        mut cx: AsyncAppContext,
3175    ) -> Result<()> {
3176        this.update(&mut cx, |this, cx| {
3177            let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
3178            if let Some(message) = envelope.payload.summary {
3179                let project_path = ProjectPath {
3180                    worktree_id,
3181                    path: Path::new(&message.path).into(),
3182                };
3183                let path = project_path.path.clone();
3184                let server_id = LanguageServerId(message.language_server_id as usize);
3185                let summary = DiagnosticSummary {
3186                    error_count: message.error_count as usize,
3187                    warning_count: message.warning_count as usize,
3188                };
3189
3190                if summary.is_empty() {
3191                    if let Some(worktree_summaries) =
3192                        this.diagnostic_summaries.get_mut(&worktree_id)
3193                    {
3194                        if let Some(summaries) = worktree_summaries.get_mut(&path) {
3195                            summaries.remove(&server_id);
3196                            if summaries.is_empty() {
3197                                worktree_summaries.remove(&path);
3198                            }
3199                        }
3200                    }
3201                } else {
3202                    this.diagnostic_summaries
3203                        .entry(worktree_id)
3204                        .or_default()
3205                        .entry(path)
3206                        .or_default()
3207                        .insert(server_id, summary);
3208                }
3209                cx.emit(LspStoreEvent::DiagnosticsUpdated {
3210                    language_server_id: LanguageServerId(message.language_server_id as usize),
3211                    path: project_path,
3212                });
3213            }
3214            Ok(())
3215        })?
3216    }
3217
3218    async fn handle_start_language_server(
3219        this: Model<Self>,
3220        envelope: TypedEnvelope<proto::StartLanguageServer>,
3221        mut cx: AsyncAppContext,
3222    ) -> Result<()> {
3223        let server = envelope
3224            .payload
3225            .server
3226            .ok_or_else(|| anyhow!("invalid server"))?;
3227        this.update(&mut cx, |this, cx| {
3228            this.language_server_statuses.insert(
3229                LanguageServerId(server.id as usize),
3230                LanguageServerStatus {
3231                    name: server.name,
3232                    pending_work: Default::default(),
3233                    has_pending_diagnostic_updates: false,
3234                    progress_tokens: Default::default(),
3235                },
3236            );
3237            cx.notify();
3238        })?;
3239        Ok(())
3240    }
3241
3242    async fn handle_update_language_server(
3243        this: Model<Self>,
3244        envelope: TypedEnvelope<proto::UpdateLanguageServer>,
3245        mut cx: AsyncAppContext,
3246    ) -> Result<()> {
3247        this.update(&mut cx, |this, cx| {
3248            let language_server_id = LanguageServerId(envelope.payload.language_server_id as usize);
3249
3250            match envelope
3251                .payload
3252                .variant
3253                .ok_or_else(|| anyhow!("invalid variant"))?
3254            {
3255                proto::update_language_server::Variant::WorkStart(payload) => {
3256                    this.on_lsp_work_start(
3257                        language_server_id,
3258                        payload.token,
3259                        LanguageServerProgress {
3260                            title: payload.title,
3261                            is_disk_based_diagnostics_progress: false,
3262                            is_cancellable: false,
3263                            message: payload.message,
3264                            percentage: payload.percentage.map(|p| p as usize),
3265                            last_update_at: cx.background_executor().now(),
3266                        },
3267                        cx,
3268                    );
3269                }
3270
3271                proto::update_language_server::Variant::WorkProgress(payload) => {
3272                    this.on_lsp_work_progress(
3273                        language_server_id,
3274                        payload.token,
3275                        LanguageServerProgress {
3276                            title: None,
3277                            is_disk_based_diagnostics_progress: false,
3278                            is_cancellable: false,
3279                            message: payload.message,
3280                            percentage: payload.percentage.map(|p| p as usize),
3281                            last_update_at: cx.background_executor().now(),
3282                        },
3283                        cx,
3284                    );
3285                }
3286
3287                proto::update_language_server::Variant::WorkEnd(payload) => {
3288                    this.on_lsp_work_end(language_server_id, payload.token, cx);
3289                }
3290
3291                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(_) => {
3292                    this.disk_based_diagnostics_started(language_server_id, cx);
3293                }
3294
3295                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(_) => {
3296                    this.disk_based_diagnostics_finished(language_server_id, cx)
3297                }
3298            }
3299
3300            Ok(())
3301        })?
3302    }
3303
3304    pub fn disk_based_diagnostics_started(
3305        &mut self,
3306        language_server_id: LanguageServerId,
3307        cx: &mut ModelContext<Self>,
3308    ) {
3309        if let Some(language_server_status) =
3310            self.language_server_statuses.get_mut(&language_server_id)
3311        {
3312            language_server_status.has_pending_diagnostic_updates = true;
3313        }
3314
3315        cx.emit(LspStoreEvent::DiskBasedDiagnosticsStarted { language_server_id });
3316    }
3317
3318    pub fn disk_based_diagnostics_finished(
3319        &mut self,
3320        language_server_id: LanguageServerId,
3321        cx: &mut ModelContext<Self>,
3322    ) {
3323        if let Some(language_server_status) =
3324            self.language_server_statuses.get_mut(&language_server_id)
3325        {
3326            language_server_status.has_pending_diagnostic_updates = false;
3327        }
3328
3329        cx.emit(LspStoreEvent::DiskBasedDiagnosticsFinished { language_server_id });
3330    }
3331
3332    // After saving a buffer using a language server that doesn't provide a disk-based progress token,
3333    // kick off a timer that will reset every time the buffer is saved. If the timer eventually fires,
3334    // simulate disk-based diagnostics being finished so that other pieces of UI (e.g., project
3335    // diagnostics view, diagnostic status bar) can update. We don't emit an event right away because
3336    // the language server might take some time to publish diagnostics.
3337    fn simulate_disk_based_diagnostics_events_if_needed(
3338        &mut self,
3339        language_server_id: LanguageServerId,
3340        cx: &mut ModelContext<Self>,
3341    ) {
3342        const DISK_BASED_DIAGNOSTICS_DEBOUNCE: Duration = Duration::from_secs(1);
3343
3344        let Some(LanguageServerState::Running {
3345            simulate_disk_based_diagnostics_completion,
3346            adapter,
3347            ..
3348        }) = self
3349            .as_local_mut()
3350            .and_then(|local_store| local_store.language_servers.get_mut(&language_server_id))
3351        else {
3352            return;
3353        };
3354
3355        if adapter.disk_based_diagnostics_progress_token.is_some() {
3356            return;
3357        }
3358
3359        let prev_task = simulate_disk_based_diagnostics_completion.replace(cx.spawn(
3360            move |this, mut cx| async move {
3361                cx.background_executor()
3362                    .timer(DISK_BASED_DIAGNOSTICS_DEBOUNCE)
3363                    .await;
3364
3365                this.update(&mut cx, |this, cx| {
3366                    this.disk_based_diagnostics_finished(language_server_id, cx);
3367
3368                    if let Some(LanguageServerState::Running {
3369                        simulate_disk_based_diagnostics_completion,
3370                        ..
3371                    }) = this.as_local_mut().and_then(|local_store| {
3372                        local_store.language_servers.get_mut(&language_server_id)
3373                    }) {
3374                        *simulate_disk_based_diagnostics_completion = None;
3375                    }
3376                })
3377                .ok();
3378            },
3379        ));
3380
3381        if prev_task.is_none() {
3382            self.disk_based_diagnostics_started(language_server_id, cx);
3383        }
3384    }
3385
3386    pub fn language_server_statuses(
3387        &self,
3388    ) -> impl DoubleEndedIterator<Item = (LanguageServerId, &LanguageServerStatus)> {
3389        self.language_server_statuses
3390            .iter()
3391            .map(|(key, value)| (*key, value))
3392    }
3393
3394    fn lsp_notify_abs_paths_changed(
3395        &mut self,
3396        server_id: LanguageServerId,
3397        changes: Vec<PathEvent>,
3398    ) {
3399        maybe!({
3400            let server = self.language_server_for_id(server_id)?;
3401            let changes = changes
3402                .into_iter()
3403                .filter_map(|event| {
3404                    let typ = match event.kind? {
3405                        PathEventKind::Created => lsp::FileChangeType::CREATED,
3406                        PathEventKind::Removed => lsp::FileChangeType::DELETED,
3407                        PathEventKind::Changed => lsp::FileChangeType::CHANGED,
3408                    };
3409                    Some(lsp::FileEvent {
3410                        uri: lsp::Url::from_file_path(&event.path).ok()?,
3411                        typ,
3412                    })
3413                })
3414                .collect::<Vec<_>>();
3415            if !changes.is_empty() {
3416                server
3417                    .notify::<lsp::notification::DidChangeWatchedFiles>(
3418                        lsp::DidChangeWatchedFilesParams { changes },
3419                    )
3420                    .log_err();
3421            }
3422            Some(())
3423        });
3424    }
3425
3426    fn rebuild_watched_paths(
3427        &mut self,
3428        language_server_id: LanguageServerId,
3429        cx: &mut ModelContext<Self>,
3430    ) {
3431        let worktrees = self
3432            .worktree_store
3433            .read(cx)
3434            .worktrees()
3435            .filter_map(|worktree| {
3436                self.language_servers_for_worktree(worktree.read(cx).id())
3437                    .find(|server| server.server_id() == language_server_id)
3438                    .map(|_| worktree)
3439            })
3440            .collect::<Vec<_>>();
3441
3442        let local_lsp_store = self.as_local_mut().unwrap();
3443
3444        let Some(watchers) = local_lsp_store
3445            .language_server_watcher_registrations
3446            .get(&language_server_id)
3447        else {
3448            return;
3449        };
3450
3451        let mut worktree_globs = HashMap::default();
3452        let mut abs_globs = HashMap::default();
3453        log::trace!(
3454            "Processing new watcher paths for language server with id {}",
3455            language_server_id
3456        );
3457
3458        enum PathToWatch {
3459            Worktree {
3460                literal_prefix: Arc<Path>,
3461                pattern: String,
3462            },
3463            Absolute {
3464                path: Arc<Path>,
3465                pattern: String,
3466            },
3467        }
3468        for watcher in watchers.values().flatten() {
3469            let mut found_host = false;
3470            for worktree in &worktrees {
3471                let glob_is_inside_worktree = worktree.update(cx, |tree, _| {
3472                    if let Some(worktree_root_path) = tree.abs_path().to_str() {
3473                        let path_to_watch = match &watcher.glob_pattern {
3474                            lsp::GlobPattern::String(s) => {
3475                                match s.strip_prefix(worktree_root_path) {
3476                                    Some(relative) => {
3477                                        let pattern = relative
3478                                            .strip_prefix(std::path::MAIN_SEPARATOR)
3479                                            .unwrap_or(relative)
3480                                            .to_owned();
3481                                        let literal_prefix = glob_literal_prefix(&pattern);
3482
3483                                        let literal_prefix = Arc::from(PathBuf::from(
3484                                            literal_prefix
3485                                                .strip_prefix(std::path::MAIN_SEPARATOR)
3486                                                .unwrap_or(literal_prefix),
3487                                        ));
3488                                        PathToWatch::Worktree {
3489                                            literal_prefix,
3490                                            pattern,
3491                                        }
3492                                    }
3493                                    None => {
3494                                        let path = glob_literal_prefix(s);
3495                                        let glob = &s[path.len()..];
3496                                        let pattern = glob
3497                                            .strip_prefix(std::path::MAIN_SEPARATOR)
3498                                            .unwrap_or(glob)
3499                                            .to_owned();
3500                                        let path = if Path::new(path).components().next().is_none()
3501                                        {
3502                                            Arc::from(Path::new(worktree_root_path))
3503                                        } else {
3504                                            PathBuf::from(path).into()
3505                                        };
3506
3507                                        PathToWatch::Absolute { path, pattern }
3508                                    }
3509                                }
3510                            }
3511                            lsp::GlobPattern::Relative(rp) => {
3512                                let Ok(mut base_uri) = match &rp.base_uri {
3513                                    lsp::OneOf::Left(workspace_folder) => &workspace_folder.uri,
3514                                    lsp::OneOf::Right(base_uri) => base_uri,
3515                                }
3516                                .to_file_path() else {
3517                                    return false;
3518                                };
3519
3520                                match base_uri.strip_prefix(worktree_root_path) {
3521                                    Ok(relative) => {
3522                                        let mut literal_prefix = relative.to_owned();
3523                                        literal_prefix.push(glob_literal_prefix(&rp.pattern));
3524
3525                                        PathToWatch::Worktree {
3526                                            literal_prefix: literal_prefix.into(),
3527                                            pattern: rp.pattern.clone(),
3528                                        }
3529                                    }
3530                                    Err(_) => {
3531                                        let path = glob_literal_prefix(&rp.pattern);
3532                                        let glob = &rp.pattern[path.len()..];
3533                                        let pattern = glob
3534                                            .strip_prefix(std::path::MAIN_SEPARATOR)
3535                                            .unwrap_or(glob)
3536                                            .to_owned();
3537                                        base_uri.push(path);
3538
3539                                        let path = if base_uri.components().next().is_none() {
3540                                            Arc::from(Path::new("/"))
3541                                        } else {
3542                                            base_uri.into()
3543                                        };
3544                                        PathToWatch::Absolute { path, pattern }
3545                                    }
3546                                }
3547                            }
3548                        };
3549                        match path_to_watch {
3550                            PathToWatch::Worktree {
3551                                literal_prefix,
3552                                pattern,
3553                            } => {
3554                                if let Some((tree, glob)) =
3555                                    tree.as_local_mut().zip(Glob::new(&pattern).log_err())
3556                                {
3557                                    tree.add_path_prefix_to_scan(literal_prefix);
3558                                    worktree_globs
3559                                        .entry(tree.id())
3560                                        .or_insert_with(GlobSetBuilder::new)
3561                                        .add(glob);
3562                                } else {
3563                                    return false;
3564                                }
3565                            }
3566                            PathToWatch::Absolute { path, pattern } => {
3567                                if let Some(glob) = Glob::new(&pattern).log_err() {
3568                                    abs_globs
3569                                        .entry(path)
3570                                        .or_insert_with(GlobSetBuilder::new)
3571                                        .add(glob);
3572                                }
3573                            }
3574                        }
3575                        return true;
3576                    }
3577                    false
3578                });
3579                if glob_is_inside_worktree {
3580                    log::trace!(
3581                        "Watcher pattern `{}` has been attached to the worktree at `{}`",
3582                        serde_json::to_string(&watcher.glob_pattern).unwrap(),
3583                        worktree.read(cx).abs_path().display()
3584                    );
3585                    found_host = true;
3586                }
3587            }
3588            if !found_host {
3589                log::error!(
3590                    "Watcher pattern `{}` has not been attached to any worktree or absolute path",
3591                    serde_json::to_string(&watcher.glob_pattern).unwrap()
3592                )
3593            }
3594        }
3595
3596        let mut watch_builder = LanguageServerWatchedPathsBuilder::default();
3597        for (worktree_id, builder) in worktree_globs {
3598            if let Ok(globset) = builder.build() {
3599                watch_builder.watch_worktree(worktree_id, globset);
3600            }
3601        }
3602        for (abs_path, builder) in abs_globs {
3603            if let Ok(globset) = builder.build() {
3604                watch_builder.watch_abs_path(abs_path, globset);
3605            }
3606        }
3607        let watcher = watch_builder.build(local_lsp_store.fs.clone(), language_server_id, cx);
3608        local_lsp_store
3609            .language_server_watched_paths
3610            .insert(language_server_id, watcher);
3611
3612        cx.notify();
3613    }
3614
3615    pub fn language_server_for_id(&self, id: LanguageServerId) -> Option<Arc<LanguageServer>> {
3616        if let Some(local_lsp_store) = self.as_local() {
3617            if let Some(LanguageServerState::Running { server, .. }) =
3618                local_lsp_store.language_servers.get(&id)
3619            {
3620                Some(server.clone())
3621            } else if let Some((_, server)) =
3622                local_lsp_store.supplementary_language_servers.get(&id)
3623            {
3624                Some(Arc::clone(server))
3625            } else {
3626                None
3627            }
3628        } else {
3629            None
3630        }
3631    }
3632
3633    async fn on_lsp_workspace_edit(
3634        this: WeakModel<Self>,
3635        params: lsp::ApplyWorkspaceEditParams,
3636        server_id: LanguageServerId,
3637        adapter: Arc<CachedLspAdapter>,
3638        mut cx: AsyncAppContext,
3639    ) -> Result<lsp::ApplyWorkspaceEditResponse> {
3640        let this = this
3641            .upgrade()
3642            .ok_or_else(|| anyhow!("project project closed"))?;
3643        let language_server = this
3644            .update(&mut cx, |this, _| this.language_server_for_id(server_id))?
3645            .ok_or_else(|| anyhow!("language server not found"))?;
3646        let transaction = Self::deserialize_workspace_edit(
3647            this.clone(),
3648            params.edit,
3649            true,
3650            adapter.clone(),
3651            language_server.clone(),
3652            &mut cx,
3653        )
3654        .await
3655        .log_err();
3656        this.update(&mut cx, |this, _| {
3657            if let Some(transaction) = transaction {
3658                this.as_local_mut()
3659                    .unwrap()
3660                    .last_workspace_edits_by_language_server
3661                    .insert(server_id, transaction);
3662            }
3663        })?;
3664        Ok(lsp::ApplyWorkspaceEditResponse {
3665            applied: true,
3666            failed_change: None,
3667            failure_reason: None,
3668        })
3669    }
3670
3671    fn on_lsp_progress(
3672        &mut self,
3673        progress: lsp::ProgressParams,
3674        language_server_id: LanguageServerId,
3675        disk_based_diagnostics_progress_token: Option<String>,
3676        cx: &mut ModelContext<Self>,
3677    ) {
3678        let token = match progress.token {
3679            lsp::NumberOrString::String(token) => token,
3680            lsp::NumberOrString::Number(token) => {
3681                log::info!("skipping numeric progress token {}", token);
3682                return;
3683            }
3684        };
3685
3686        let lsp::ProgressParamsValue::WorkDone(progress) = progress.value;
3687        let language_server_status =
3688            if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
3689                status
3690            } else {
3691                return;
3692            };
3693
3694        if !language_server_status.progress_tokens.contains(&token) {
3695            return;
3696        }
3697
3698        let is_disk_based_diagnostics_progress = disk_based_diagnostics_progress_token
3699            .as_ref()
3700            .map_or(false, |disk_based_token| {
3701                token.starts_with(disk_based_token)
3702            });
3703
3704        match progress {
3705            lsp::WorkDoneProgress::Begin(report) => {
3706                if is_disk_based_diagnostics_progress {
3707                    self.disk_based_diagnostics_started(language_server_id, cx);
3708                }
3709                self.on_lsp_work_start(
3710                    language_server_id,
3711                    token.clone(),
3712                    LanguageServerProgress {
3713                        title: Some(report.title),
3714                        is_disk_based_diagnostics_progress,
3715                        is_cancellable: report.cancellable.unwrap_or(false),
3716                        message: report.message.clone(),
3717                        percentage: report.percentage.map(|p| p as usize),
3718                        last_update_at: cx.background_executor().now(),
3719                    },
3720                    cx,
3721                );
3722            }
3723            lsp::WorkDoneProgress::Report(report) => {
3724                if self.on_lsp_work_progress(
3725                    language_server_id,
3726                    token.clone(),
3727                    LanguageServerProgress {
3728                        title: None,
3729                        is_disk_based_diagnostics_progress,
3730                        is_cancellable: report.cancellable.unwrap_or(false),
3731                        message: report.message.clone(),
3732                        percentage: report.percentage.map(|p| p as usize),
3733                        last_update_at: cx.background_executor().now(),
3734                    },
3735                    cx,
3736                ) {
3737                    cx.emit(LspStoreEvent::LanguageServerUpdate {
3738                        language_server_id,
3739                        message: proto::update_language_server::Variant::WorkProgress(
3740                            proto::LspWorkProgress {
3741                                token,
3742                                message: report.message,
3743                                percentage: report.percentage,
3744                            },
3745                        ),
3746                    })
3747                }
3748            }
3749            lsp::WorkDoneProgress::End(_) => {
3750                language_server_status.progress_tokens.remove(&token);
3751                self.on_lsp_work_end(language_server_id, token.clone(), cx);
3752                if is_disk_based_diagnostics_progress {
3753                    self.disk_based_diagnostics_finished(language_server_id, cx);
3754                }
3755            }
3756        }
3757    }
3758
3759    fn on_lsp_work_start(
3760        &mut self,
3761        language_server_id: LanguageServerId,
3762        token: String,
3763        progress: LanguageServerProgress,
3764        cx: &mut ModelContext<Self>,
3765    ) {
3766        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
3767            status.pending_work.insert(token.clone(), progress.clone());
3768            cx.notify();
3769        }
3770        cx.emit(LspStoreEvent::LanguageServerUpdate {
3771            language_server_id,
3772            message: proto::update_language_server::Variant::WorkStart(proto::LspWorkStart {
3773                token,
3774                title: progress.title,
3775                message: progress.message,
3776                percentage: progress.percentage.map(|p| p as u32),
3777            }),
3778        })
3779    }
3780
3781    fn on_lsp_work_progress(
3782        &mut self,
3783        language_server_id: LanguageServerId,
3784        token: String,
3785        progress: LanguageServerProgress,
3786        cx: &mut ModelContext<Self>,
3787    ) -> bool {
3788        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
3789            match status.pending_work.entry(token) {
3790                btree_map::Entry::Vacant(entry) => {
3791                    entry.insert(progress);
3792                    cx.notify();
3793                    return true;
3794                }
3795                btree_map::Entry::Occupied(mut entry) => {
3796                    let entry = entry.get_mut();
3797                    if (progress.last_update_at - entry.last_update_at)
3798                        >= SERVER_PROGRESS_THROTTLE_TIMEOUT
3799                    {
3800                        entry.last_update_at = progress.last_update_at;
3801                        if progress.message.is_some() {
3802                            entry.message = progress.message;
3803                        }
3804                        if progress.percentage.is_some() {
3805                            entry.percentage = progress.percentage;
3806                        }
3807                        cx.notify();
3808                        return true;
3809                    }
3810                }
3811            }
3812        }
3813
3814        false
3815    }
3816
3817    fn on_lsp_work_end(
3818        &mut self,
3819        language_server_id: LanguageServerId,
3820        token: String,
3821        cx: &mut ModelContext<Self>,
3822    ) {
3823        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
3824            if let Some(work) = status.pending_work.remove(&token) {
3825                if !work.is_disk_based_diagnostics_progress {
3826                    cx.emit(LspStoreEvent::RefreshInlayHints);
3827                }
3828            }
3829            cx.notify();
3830        }
3831
3832        cx.emit(LspStoreEvent::LanguageServerUpdate {
3833            language_server_id,
3834            message: proto::update_language_server::Variant::WorkEnd(proto::LspWorkEnd { token }),
3835        })
3836    }
3837
3838    fn on_lsp_did_change_watched_files(
3839        &mut self,
3840        language_server_id: LanguageServerId,
3841        registration_id: &str,
3842        params: DidChangeWatchedFilesRegistrationOptions,
3843        cx: &mut ModelContext<Self>,
3844    ) {
3845        if let Some(local) = self.as_local_mut() {
3846            let registrations = local
3847                .language_server_watcher_registrations
3848                .entry(language_server_id)
3849                .or_default();
3850
3851            registrations.insert(registration_id.to_string(), params.watchers);
3852
3853            self.rebuild_watched_paths(language_server_id, cx);
3854        }
3855    }
3856
3857    fn on_lsp_unregister_did_change_watched_files(
3858        &mut self,
3859        language_server_id: LanguageServerId,
3860        registration_id: &str,
3861        cx: &mut ModelContext<Self>,
3862    ) {
3863        if let Some(local) = self.as_local_mut() {
3864            let registrations = local
3865                .language_server_watcher_registrations
3866                .entry(language_server_id)
3867                .or_default();
3868
3869            if registrations.remove(registration_id).is_some() {
3870                log::info!(
3871                "language server {}: unregistered workspace/DidChangeWatchedFiles capability with id {}",
3872                language_server_id,
3873                registration_id
3874            );
3875            } else {
3876                log::warn!(
3877                "language server {}: failed to unregister workspace/DidChangeWatchedFiles capability with id {}. not registered.",
3878                language_server_id,
3879                registration_id
3880            );
3881            }
3882
3883            self.rebuild_watched_paths(language_server_id, cx);
3884        }
3885    }
3886
3887    #[allow(clippy::type_complexity)]
3888    pub(crate) fn edits_from_lsp(
3889        &mut self,
3890        buffer: &Model<Buffer>,
3891        lsp_edits: impl 'static + Send + IntoIterator<Item = lsp::TextEdit>,
3892        server_id: LanguageServerId,
3893        version: Option<i32>,
3894        cx: &mut ModelContext<Self>,
3895    ) -> Task<Result<Vec<(Range<Anchor>, String)>>> {
3896        let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx);
3897        cx.background_executor().spawn(async move {
3898            let snapshot = snapshot?;
3899            let mut lsp_edits = lsp_edits
3900                .into_iter()
3901                .map(|edit| (range_from_lsp(edit.range), edit.new_text))
3902                .collect::<Vec<_>>();
3903            lsp_edits.sort_by_key(|(range, _)| range.start);
3904
3905            let mut lsp_edits = lsp_edits.into_iter().peekable();
3906            let mut edits = Vec::new();
3907            while let Some((range, mut new_text)) = lsp_edits.next() {
3908                // Clip invalid ranges provided by the language server.
3909                let mut range = snapshot.clip_point_utf16(range.start, Bias::Left)
3910                    ..snapshot.clip_point_utf16(range.end, Bias::Left);
3911
3912                // Combine any LSP edits that are adjacent.
3913                //
3914                // Also, combine LSP edits that are separated from each other by only
3915                // a newline. This is important because for some code actions,
3916                // Rust-analyzer rewrites the entire buffer via a series of edits that
3917                // are separated by unchanged newline characters.
3918                //
3919                // In order for the diffing logic below to work properly, any edits that
3920                // cancel each other out must be combined into one.
3921                while let Some((next_range, next_text)) = lsp_edits.peek() {
3922                    if next_range.start.0 > range.end {
3923                        if next_range.start.0.row > range.end.row + 1
3924                            || next_range.start.0.column > 0
3925                            || snapshot.clip_point_utf16(
3926                                Unclipped(PointUtf16::new(range.end.row, u32::MAX)),
3927                                Bias::Left,
3928                            ) > range.end
3929                        {
3930                            break;
3931                        }
3932                        new_text.push('\n');
3933                    }
3934                    range.end = snapshot.clip_point_utf16(next_range.end, Bias::Left);
3935                    new_text.push_str(next_text);
3936                    lsp_edits.next();
3937                }
3938
3939                // For multiline edits, perform a diff of the old and new text so that
3940                // we can identify the changes more precisely, preserving the locations
3941                // of any anchors positioned in the unchanged regions.
3942                if range.end.row > range.start.row {
3943                    let mut offset = range.start.to_offset(&snapshot);
3944                    let old_text = snapshot.text_for_range(range).collect::<String>();
3945
3946                    let diff = TextDiff::from_lines(old_text.as_str(), &new_text);
3947                    let mut moved_since_edit = true;
3948                    for change in diff.iter_all_changes() {
3949                        let tag = change.tag();
3950                        let value = change.value();
3951                        match tag {
3952                            ChangeTag::Equal => {
3953                                offset += value.len();
3954                                moved_since_edit = true;
3955                            }
3956                            ChangeTag::Delete => {
3957                                let start = snapshot.anchor_after(offset);
3958                                let end = snapshot.anchor_before(offset + value.len());
3959                                if moved_since_edit {
3960                                    edits.push((start..end, String::new()));
3961                                } else {
3962                                    edits.last_mut().unwrap().0.end = end;
3963                                }
3964                                offset += value.len();
3965                                moved_since_edit = false;
3966                            }
3967                            ChangeTag::Insert => {
3968                                if moved_since_edit {
3969                                    let anchor = snapshot.anchor_after(offset);
3970                                    edits.push((anchor..anchor, value.to_string()));
3971                                } else {
3972                                    edits.last_mut().unwrap().1.push_str(value);
3973                                }
3974                                moved_since_edit = false;
3975                            }
3976                        }
3977                    }
3978                } else if range.end == range.start {
3979                    let anchor = snapshot.anchor_after(range.start);
3980                    edits.push((anchor..anchor, new_text));
3981                } else {
3982                    let edit_start = snapshot.anchor_after(range.start);
3983                    let edit_end = snapshot.anchor_before(range.end);
3984                    edits.push((edit_start..edit_end, new_text));
3985                }
3986            }
3987
3988            Ok(edits)
3989        })
3990    }
3991
3992    pub async fn handle_resolve_completion_documentation(
3993        this: Model<Self>,
3994        envelope: TypedEnvelope<proto::ResolveCompletionDocumentation>,
3995        mut cx: AsyncAppContext,
3996    ) -> Result<proto::ResolveCompletionDocumentationResponse> {
3997        let lsp_completion = serde_json::from_slice(&envelope.payload.lsp_completion)?;
3998
3999        let completion = this
4000            .read_with(&cx, |this, _| {
4001                let id = LanguageServerId(envelope.payload.language_server_id as usize);
4002                let Some(server) = this.language_server_for_id(id) else {
4003                    return Err(anyhow!("No language server {id}"));
4004                };
4005
4006                Ok(server.request::<lsp::request::ResolveCompletionItem>(lsp_completion))
4007            })??
4008            .await?;
4009
4010        let mut documentation_is_markdown = false;
4011        let documentation = match completion.documentation {
4012            Some(lsp::Documentation::String(text)) => text,
4013
4014            Some(lsp::Documentation::MarkupContent(lsp::MarkupContent { kind, value })) => {
4015                documentation_is_markdown = kind == lsp::MarkupKind::Markdown;
4016                value
4017            }
4018
4019            _ => String::new(),
4020        };
4021
4022        // If we have a new buffer_id, that means we're talking to a new client
4023        // and want to check for new text_edits in the completion too.
4024        let mut old_start = None;
4025        let mut old_end = None;
4026        let mut new_text = String::default();
4027        if let Ok(buffer_id) = BufferId::new(envelope.payload.buffer_id) {
4028            let buffer_snapshot = this.update(&mut cx, |this, cx| {
4029                let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
4030                anyhow::Ok(buffer.read(cx).snapshot())
4031            })??;
4032
4033            if let Some(text_edit) = completion.text_edit.as_ref() {
4034                let edit = parse_completion_text_edit(text_edit, &buffer_snapshot);
4035
4036                if let Some((old_range, mut text_edit_new_text)) = edit {
4037                    LineEnding::normalize(&mut text_edit_new_text);
4038
4039                    new_text = text_edit_new_text;
4040                    old_start = Some(serialize_anchor(&old_range.start));
4041                    old_end = Some(serialize_anchor(&old_range.end));
4042                }
4043            }
4044        }
4045
4046        Ok(proto::ResolveCompletionDocumentationResponse {
4047            documentation,
4048            documentation_is_markdown,
4049            old_start,
4050            old_end,
4051            new_text,
4052        })
4053    }
4054
4055    async fn handle_on_type_formatting(
4056        this: Model<Self>,
4057        envelope: TypedEnvelope<proto::OnTypeFormatting>,
4058        mut cx: AsyncAppContext,
4059    ) -> Result<proto::OnTypeFormattingResponse> {
4060        let on_type_formatting = this.update(&mut cx, |this, cx| {
4061            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
4062            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
4063            let position = envelope
4064                .payload
4065                .position
4066                .and_then(deserialize_anchor)
4067                .ok_or_else(|| anyhow!("invalid position"))?;
4068            Ok::<_, anyhow::Error>(this.apply_on_type_formatting(
4069                buffer,
4070                position,
4071                envelope.payload.trigger.clone(),
4072                cx,
4073            ))
4074        })??;
4075
4076        let transaction = on_type_formatting
4077            .await?
4078            .as_ref()
4079            .map(language::proto::serialize_transaction);
4080        Ok(proto::OnTypeFormattingResponse { transaction })
4081    }
4082
4083    async fn handle_refresh_inlay_hints(
4084        this: Model<Self>,
4085        _: TypedEnvelope<proto::RefreshInlayHints>,
4086        mut cx: AsyncAppContext,
4087    ) -> Result<proto::Ack> {
4088        this.update(&mut cx, |_, cx| {
4089            cx.emit(LspStoreEvent::RefreshInlayHints);
4090        })?;
4091        Ok(proto::Ack {})
4092    }
4093
4094    async fn handle_inlay_hints(
4095        this: Model<Self>,
4096        envelope: TypedEnvelope<proto::InlayHints>,
4097        mut cx: AsyncAppContext,
4098    ) -> Result<proto::InlayHintsResponse> {
4099        let sender_id = envelope.original_sender_id().unwrap_or_default();
4100        let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
4101        let buffer = this.update(&mut cx, |this, cx| {
4102            this.buffer_store.read(cx).get_existing(buffer_id)
4103        })??;
4104        buffer
4105            .update(&mut cx, |buffer, _| {
4106                buffer.wait_for_version(deserialize_version(&envelope.payload.version))
4107            })?
4108            .await
4109            .with_context(|| format!("waiting for version for buffer {}", buffer.entity_id()))?;
4110
4111        let start = envelope
4112            .payload
4113            .start
4114            .and_then(deserialize_anchor)
4115            .context("missing range start")?;
4116        let end = envelope
4117            .payload
4118            .end
4119            .and_then(deserialize_anchor)
4120            .context("missing range end")?;
4121        let buffer_hints = this
4122            .update(&mut cx, |lsp_store, cx| {
4123                lsp_store.inlay_hints(buffer.clone(), start..end, cx)
4124            })?
4125            .await
4126            .context("inlay hints fetch")?;
4127
4128        this.update(&mut cx, |project, cx| {
4129            InlayHints::response_to_proto(
4130                buffer_hints,
4131                project,
4132                sender_id,
4133                &buffer.read(cx).version(),
4134                cx,
4135            )
4136        })
4137    }
4138
4139    async fn handle_resolve_inlay_hint(
4140        this: Model<Self>,
4141        envelope: TypedEnvelope<proto::ResolveInlayHint>,
4142        mut cx: AsyncAppContext,
4143    ) -> Result<proto::ResolveInlayHintResponse> {
4144        let proto_hint = envelope
4145            .payload
4146            .hint
4147            .expect("incorrect protobuf resolve inlay hint message: missing the inlay hint");
4148        let hint = InlayHints::proto_to_project_hint(proto_hint)
4149            .context("resolved proto inlay hint conversion")?;
4150        let buffer = this.update(&mut cx, |this, cx| {
4151            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
4152            this.buffer_store.read(cx).get_existing(buffer_id)
4153        })??;
4154        let response_hint = this
4155            .update(&mut cx, |this, cx| {
4156                this.resolve_inlay_hint(
4157                    hint,
4158                    buffer,
4159                    LanguageServerId(envelope.payload.language_server_id as usize),
4160                    cx,
4161                )
4162            })?
4163            .await
4164            .context("inlay hints fetch")?;
4165        Ok(proto::ResolveInlayHintResponse {
4166            hint: Some(InlayHints::project_to_proto_hint(response_hint)),
4167        })
4168    }
4169
4170    async fn handle_open_buffer_for_symbol(
4171        this: Model<Self>,
4172        envelope: TypedEnvelope<proto::OpenBufferForSymbol>,
4173        mut cx: AsyncAppContext,
4174    ) -> Result<proto::OpenBufferForSymbolResponse> {
4175        let peer_id = envelope.original_sender_id().unwrap_or_default();
4176        let symbol = envelope
4177            .payload
4178            .symbol
4179            .ok_or_else(|| anyhow!("invalid symbol"))?;
4180        let symbol = Self::deserialize_symbol(symbol)?;
4181        let symbol = this.update(&mut cx, |this, _| {
4182            let signature = this.symbol_signature(&symbol.path);
4183            if signature == symbol.signature {
4184                Ok(symbol)
4185            } else {
4186                Err(anyhow!("invalid symbol signature"))
4187            }
4188        })??;
4189        let buffer = this
4190            .update(&mut cx, |this, cx| {
4191                this.open_buffer_for_symbol(
4192                    &Symbol {
4193                        language_server_name: symbol.language_server_name,
4194                        source_worktree_id: symbol.source_worktree_id,
4195                        path: symbol.path,
4196                        name: symbol.name,
4197                        kind: symbol.kind,
4198                        range: symbol.range,
4199                        signature: symbol.signature,
4200                        label: CodeLabel {
4201                            text: Default::default(),
4202                            runs: Default::default(),
4203                            filter_range: Default::default(),
4204                        },
4205                    },
4206                    cx,
4207                )
4208            })?
4209            .await?;
4210
4211        this.update(&mut cx, |this, cx| {
4212            let is_private = buffer
4213                .read(cx)
4214                .file()
4215                .map(|f| f.is_private())
4216                .unwrap_or_default();
4217            if is_private {
4218                Err(anyhow!(rpc::ErrorCode::UnsharedItem))
4219            } else {
4220                this.buffer_store
4221                    .update(cx, |buffer_store, cx| {
4222                        buffer_store.create_buffer_for_peer(&buffer, peer_id, cx)
4223                    })
4224                    .detach_and_log_err(cx);
4225                let buffer_id = buffer.read(cx).remote_id().to_proto();
4226                Ok(proto::OpenBufferForSymbolResponse { buffer_id })
4227            }
4228        })?
4229    }
4230
4231    fn symbol_signature(&self, project_path: &ProjectPath) -> [u8; 32] {
4232        let mut hasher = Sha256::new();
4233        hasher.update(project_path.worktree_id.to_proto().to_be_bytes());
4234        hasher.update(project_path.path.to_string_lossy().as_bytes());
4235        hasher.update(self.nonce.to_be_bytes());
4236        hasher.finalize().as_slice().try_into().unwrap()
4237    }
4238
4239    pub async fn handle_get_project_symbols(
4240        this: Model<Self>,
4241        envelope: TypedEnvelope<proto::GetProjectSymbols>,
4242        mut cx: AsyncAppContext,
4243    ) -> Result<proto::GetProjectSymbolsResponse> {
4244        let symbols = this
4245            .update(&mut cx, |this, cx| {
4246                this.symbols(&envelope.payload.query, cx)
4247            })?
4248            .await?;
4249
4250        Ok(proto::GetProjectSymbolsResponse {
4251            symbols: symbols.iter().map(Self::serialize_symbol).collect(),
4252        })
4253    }
4254
4255    pub async fn handle_restart_language_servers(
4256        this: Model<Self>,
4257        envelope: TypedEnvelope<proto::RestartLanguageServers>,
4258        mut cx: AsyncAppContext,
4259    ) -> Result<proto::Ack> {
4260        this.update(&mut cx, |this, cx| {
4261            let buffers: Vec<_> = envelope
4262                .payload
4263                .buffer_ids
4264                .into_iter()
4265                .flat_map(|buffer_id| {
4266                    this.buffer_store
4267                        .read(cx)
4268                        .get(BufferId::new(buffer_id).log_err()?)
4269                })
4270                .collect();
4271            this.restart_language_servers_for_buffers(buffers, cx)
4272        })?;
4273
4274        Ok(proto::Ack {})
4275    }
4276
4277    pub async fn handle_create_language_server(
4278        this: Model<Self>,
4279        envelope: TypedEnvelope<proto::CreateLanguageServer>,
4280        mut cx: AsyncAppContext,
4281    ) -> Result<proto::Ack> {
4282        let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
4283        let name = LanguageServerName::from_proto(envelope.payload.name);
4284
4285        let binary = envelope
4286            .payload
4287            .binary
4288            .ok_or_else(|| anyhow!("missing binary"))?;
4289        let binary = LanguageServerBinary {
4290            path: PathBuf::from(binary.path),
4291            env: None,
4292            arguments: binary.arguments.into_iter().map(Into::into).collect(),
4293        };
4294        let language = envelope
4295            .payload
4296            .language
4297            .ok_or_else(|| anyhow!("missing language"))?;
4298        let language_name = LanguageName::from_proto(language.name);
4299        let matcher: LanguageMatcher = serde_json::from_str(&language.matcher)?;
4300
4301        this.update(&mut cx, |this, cx| {
4302            this.languages
4303                .register_language(language_name.clone(), None, matcher.clone(), {
4304                    let language_name = language_name.clone();
4305                    move || {
4306                        Ok((
4307                            LanguageConfig {
4308                                name: language_name.clone(),
4309                                matcher: matcher.clone(),
4310                                ..Default::default()
4311                            },
4312                            Default::default(),
4313                            Default::default(),
4314                        ))
4315                    }
4316                });
4317            cx.background_executor()
4318                .spawn(this.languages.language_for_name(language_name.0.as_ref()))
4319                .detach();
4320
4321            let adapter = Arc::new(SshLspAdapter::new(
4322                name,
4323                binary,
4324                envelope.payload.initialization_options,
4325                envelope.payload.code_action_kinds,
4326            ));
4327
4328            this.languages
4329                .register_lsp_adapter(language_name.clone(), adapter.clone());
4330            let Some(worktree) = this
4331                .worktree_store
4332                .read(cx)
4333                .worktree_for_id(worktree_id, cx)
4334            else {
4335                return Err(anyhow!("worktree not found"));
4336            };
4337            this.start_language_server(
4338                &worktree,
4339                CachedLspAdapter::new(adapter),
4340                language_name,
4341                cx,
4342            );
4343            Ok(())
4344        })??;
4345        Ok(proto::Ack {})
4346    }
4347
4348    pub async fn handle_which_command(
4349        this: Model<Self>,
4350        envelope: TypedEnvelope<proto::WhichCommand>,
4351        mut cx: AsyncAppContext,
4352    ) -> Result<proto::WhichCommandResponse> {
4353        let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
4354        let command = PathBuf::from(envelope.payload.command);
4355        let response = this
4356            .update(&mut cx, |this, cx| {
4357                let worktree = this.worktree_for_id(worktree_id, cx)?;
4358                let delegate = ProjectLspAdapterDelegate::for_local(this, &worktree, cx);
4359                anyhow::Ok(
4360                    cx.spawn(|_, _| async move { delegate.which(command.as_os_str()).await }),
4361                )
4362            })??
4363            .await;
4364
4365        Ok(proto::WhichCommandResponse {
4366            path: response.map(|path| path.to_string_lossy().to_string()),
4367        })
4368    }
4369
4370    pub async fn handle_shell_env(
4371        this: Model<Self>,
4372        envelope: TypedEnvelope<proto::ShellEnv>,
4373        mut cx: AsyncAppContext,
4374    ) -> Result<proto::ShellEnvResponse> {
4375        let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
4376        let response = this
4377            .update(&mut cx, |this, cx| {
4378                let worktree = this.worktree_for_id(worktree_id, cx)?;
4379                let delegate = ProjectLspAdapterDelegate::for_local(this, &worktree, cx);
4380                anyhow::Ok(cx.spawn(|_, _| async move { delegate.shell_env().await }))
4381            })??
4382            .await;
4383
4384        Ok(proto::ShellEnvResponse {
4385            env: response.into_iter().collect(),
4386        })
4387    }
4388
4389    async fn handle_apply_additional_edits_for_completion(
4390        this: Model<Self>,
4391        envelope: TypedEnvelope<proto::ApplyCompletionAdditionalEdits>,
4392        mut cx: AsyncAppContext,
4393    ) -> Result<proto::ApplyCompletionAdditionalEditsResponse> {
4394        let (buffer, completion) = this.update(&mut cx, |this, cx| {
4395            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
4396            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
4397            let completion = Self::deserialize_completion(
4398                envelope
4399                    .payload
4400                    .completion
4401                    .ok_or_else(|| anyhow!("invalid completion"))?,
4402            )?;
4403            anyhow::Ok((buffer, completion))
4404        })??;
4405
4406        let apply_additional_edits = this.update(&mut cx, |this, cx| {
4407            this.apply_additional_edits_for_completion(
4408                buffer,
4409                Completion {
4410                    old_range: completion.old_range,
4411                    new_text: completion.new_text,
4412                    lsp_completion: completion.lsp_completion,
4413                    server_id: completion.server_id,
4414                    documentation: None,
4415                    label: CodeLabel {
4416                        text: Default::default(),
4417                        runs: Default::default(),
4418                        filter_range: Default::default(),
4419                    },
4420                    confirm: None,
4421                },
4422                false,
4423                cx,
4424            )
4425        })?;
4426
4427        Ok(proto::ApplyCompletionAdditionalEditsResponse {
4428            transaction: apply_additional_edits
4429                .await?
4430                .as_ref()
4431                .map(language::proto::serialize_transaction),
4432        })
4433    }
4434
4435    fn language_settings<'a>(
4436        &'a self,
4437        worktree: &'a Model<Worktree>,
4438        language: &LanguageName,
4439        cx: &'a mut ModelContext<Self>,
4440    ) -> &'a LanguageSettings {
4441        let root_file = worktree.update(cx, |tree, cx| tree.root_file(cx));
4442        all_language_settings(root_file.map(|f| f as _).as_ref(), cx).language(Some(language))
4443    }
4444
4445    pub fn start_language_servers(
4446        &mut self,
4447        worktree: &Model<Worktree>,
4448        language: LanguageName,
4449        cx: &mut ModelContext<Self>,
4450    ) {
4451        let settings = self.language_settings(worktree, &language, cx);
4452        if !settings.enable_language_server || self.mode.is_remote() {
4453            return;
4454        }
4455
4456        let available_lsp_adapters = self.languages.clone().lsp_adapters(&language);
4457        let available_language_servers = available_lsp_adapters
4458            .iter()
4459            .map(|lsp_adapter| lsp_adapter.name.clone())
4460            .collect::<Vec<_>>();
4461
4462        let desired_language_servers =
4463            settings.customized_language_servers(&available_language_servers);
4464
4465        let mut enabled_lsp_adapters: Vec<Arc<CachedLspAdapter>> = Vec::new();
4466        for desired_language_server in desired_language_servers {
4467            if let Some(adapter) = available_lsp_adapters
4468                .iter()
4469                .find(|adapter| adapter.name == desired_language_server)
4470            {
4471                enabled_lsp_adapters.push(adapter.clone());
4472                continue;
4473            }
4474
4475            if let Some(adapter) = self
4476                .languages
4477                .load_available_lsp_adapter(&desired_language_server)
4478            {
4479                self.languages
4480                    .register_lsp_adapter(language.clone(), adapter.adapter.clone());
4481                enabled_lsp_adapters.push(adapter);
4482                continue;
4483            }
4484
4485            log::warn!(
4486                "no language server found matching '{}'",
4487                desired_language_server.0
4488            );
4489        }
4490
4491        for adapter in &enabled_lsp_adapters {
4492            self.start_language_server(worktree, adapter.clone(), language.clone(), cx);
4493        }
4494
4495        // After starting all the language servers, reorder them to reflect the desired order
4496        // based on the settings.
4497        //
4498        // This is done, in part, to ensure that language servers loaded at different points
4499        // (e.g., native vs extension) still end up in the right order at the end, rather than
4500        // it being based on which language server happened to be loaded in first.
4501        self.languages
4502            .reorder_language_servers(&language, enabled_lsp_adapters);
4503    }
4504
4505    /*
4506    ssh client owns the lifecycle of the language servers
4507    ssh host actually runs the binaries
4508
4509    in the future: ssh client will use the local extensions to get the downloads etc.
4510        and send them up over the ssh connection (but today) we'll just the static config
4511
4512        languages::() <-- registers lsp adapters
4513        on the ssh host we won't have adapters for the LSPs
4514    */
4515
4516    fn start_language_server_on_ssh_host(
4517        &mut self,
4518        worktree: &Model<Worktree>,
4519        adapter: Arc<CachedLspAdapter>,
4520        language: LanguageName,
4521        cx: &mut ModelContext<Self>,
4522    ) {
4523        let ssh = self.as_ssh().unwrap();
4524
4525        let delegate =
4526            ProjectLspAdapterDelegate::for_ssh(self, worktree, ssh.upstream_client.clone(), cx)
4527                as Arc<dyn LspAdapterDelegate>;
4528
4529        // TODO: We should use `adapter` here instead of reaching through the `CachedLspAdapter`.
4530        let lsp_adapter = adapter.adapter.clone();
4531
4532        let project_id = self.project_id;
4533        let worktree_id = worktree.read(cx).id().to_proto();
4534        let upstream_client = ssh.upstream_client.clone();
4535        let name = adapter.name().to_string();
4536
4537        let Some(available_language) = self.languages.available_language_for_name(&language) else {
4538            log::error!("failed to find available language {language}");
4539            return;
4540        };
4541
4542        let task = cx.spawn(|_, cx| async move {
4543            let user_binary_task = lsp_adapter.check_if_user_installed(delegate.as_ref(), &cx);
4544            let binary = match user_binary_task.await {
4545                Some(binary) => binary,
4546                None => {
4547                    return Err(anyhow!(
4548                        "Downloading language server for ssh host is not supported yet"
4549                    ))
4550                }
4551            };
4552
4553            let name = adapter.name().to_string();
4554            let code_action_kinds = adapter
4555                .adapter
4556                .code_action_kinds()
4557                .map(|kinds| serde_json::to_string(&kinds))
4558                .transpose()?;
4559            let get_options = adapter.adapter.clone().initialization_options(&delegate);
4560            let initialization_options = get_options
4561                .await?
4562                .map(|options| serde_json::to_string(&options))
4563                .transpose()?;
4564
4565            let language_server_command = proto::LanguageServerCommand {
4566                path: binary.path.to_string_lossy().to_string(),
4567                arguments: binary
4568                    .arguments
4569                    .iter()
4570                    .map(|args| args.to_string_lossy().to_string())
4571                    .collect(),
4572                env: binary.env.unwrap_or_default().into_iter().collect(),
4573            };
4574
4575            upstream_client
4576                .request(proto::CreateLanguageServer {
4577                    project_id,
4578                    worktree_id,
4579                    name,
4580                    binary: Some(language_server_command),
4581                    initialization_options,
4582                    code_action_kinds,
4583                    language: Some(proto::AvailableLanguage {
4584                        name: language.to_proto(),
4585                        matcher: serde_json::to_string(&available_language.matcher())?,
4586                    }),
4587                })
4588                .await
4589        });
4590        cx.spawn(|this, mut cx| async move {
4591            if let Err(e) = task.await {
4592                this.update(&mut cx, |_this, cx| {
4593                    cx.emit(LspStoreEvent::Notification(format!(
4594                        "failed to start {}: {}",
4595                        name, e
4596                    )))
4597                })
4598                .ok();
4599            }
4600        })
4601        .detach();
4602    }
4603
4604    fn start_language_server(
4605        &mut self,
4606        worktree_handle: &Model<Worktree>,
4607        adapter: Arc<CachedLspAdapter>,
4608        language: LanguageName,
4609        cx: &mut ModelContext<Self>,
4610    ) {
4611        if self.mode.is_remote() {
4612            return;
4613        }
4614
4615        let worktree = worktree_handle.read(cx);
4616        let worktree_id = worktree.id();
4617        let worktree_path = worktree.abs_path();
4618        let key = (worktree_id, adapter.name.clone());
4619        if self.language_server_ids.contains_key(&key) {
4620            return;
4621        }
4622
4623        if self.mode.is_ssh() {
4624            self.start_language_server_on_ssh_host(worktree_handle, adapter, language, cx);
4625            return;
4626        }
4627
4628        if adapter.reinstall_attempt_count.load(SeqCst) > MAX_SERVER_REINSTALL_ATTEMPT_COUNT {
4629            return;
4630        }
4631
4632        let stderr_capture = Arc::new(Mutex::new(Some(String::new())));
4633        let lsp_adapter_delegate = ProjectLspAdapterDelegate::for_local(self, worktree_handle, cx);
4634        let cli_environment = self
4635            .as_local()
4636            .unwrap()
4637            .environment
4638            .read(cx)
4639            .get_cli_environment();
4640
4641        let pending_server = match self.languages.create_pending_language_server(
4642            stderr_capture.clone(),
4643            language.clone(),
4644            adapter.clone(),
4645            Arc::clone(&worktree_path),
4646            lsp_adapter_delegate.clone(),
4647            cli_environment,
4648            cx,
4649        ) {
4650            Some(pending_server) => pending_server,
4651            None => return,
4652        };
4653
4654        let project_settings = ProjectSettings::get(
4655            Some(SettingsLocation {
4656                worktree_id,
4657                path: Path::new(""),
4658            }),
4659            cx,
4660        );
4661
4662        // We need some on the SSH client, and some on SSH host
4663        let lsp = project_settings.lsp.get(&adapter.name.0);
4664        let override_options = lsp.and_then(|s| s.initialization_options.clone());
4665
4666        let server_id = pending_server.server_id;
4667        let container_dir = pending_server.container_dir.clone();
4668        let state = LanguageServerState::Starting({
4669            let adapter = adapter.clone();
4670            let server_name = adapter.name.0.clone();
4671            let language = language.clone();
4672            let key = key.clone();
4673
4674            cx.spawn(move |this, mut cx| async move {
4675                let result = Self::setup_and_insert_language_server(
4676                    this.clone(),
4677                    lsp_adapter_delegate,
4678                    override_options,
4679                    pending_server,
4680                    adapter.clone(),
4681                    language.clone(),
4682                    server_id,
4683                    key,
4684                    &mut cx,
4685                )
4686                .await;
4687
4688                match result {
4689                    Ok(server) => {
4690                        stderr_capture.lock().take();
4691                        server
4692                    }
4693
4694                    Err(err) => {
4695                        log::error!("failed to start language server {server_name:?}: {err}");
4696                        log::error!("server stderr: {:?}", stderr_capture.lock().take());
4697
4698                        let this = this.upgrade()?;
4699                        let container_dir = container_dir?;
4700
4701                        let attempt_count = adapter.reinstall_attempt_count.fetch_add(1, SeqCst);
4702                        if attempt_count >= MAX_SERVER_REINSTALL_ATTEMPT_COUNT {
4703                            let max = MAX_SERVER_REINSTALL_ATTEMPT_COUNT;
4704                            log::error!("Hit {max} reinstallation attempts for {server_name:?}");
4705                            return None;
4706                        }
4707
4708                        log::info!(
4709                            "retrying installation of language server {server_name:?} in {}s",
4710                            SERVER_REINSTALL_DEBOUNCE_TIMEOUT.as_secs()
4711                        );
4712                        cx.background_executor()
4713                            .timer(SERVER_REINSTALL_DEBOUNCE_TIMEOUT)
4714                            .await;
4715
4716                        let installation_test_binary = adapter
4717                            .installation_test_binary(container_dir.to_path_buf())
4718                            .await;
4719
4720                        this.update(&mut cx, |_, cx| {
4721                            Self::check_errored_server(
4722                                language,
4723                                adapter,
4724                                server_id,
4725                                installation_test_binary,
4726                                cx,
4727                            )
4728                        })
4729                        .ok();
4730
4731                        None
4732                    }
4733                }
4734            })
4735        });
4736
4737        self.as_local_mut()
4738            .unwrap()
4739            .language_servers
4740            .insert(server_id, state);
4741        self.language_server_ids.insert(key, server_id);
4742    }
4743
4744    #[allow(clippy::too_many_arguments)]
4745    async fn setup_and_insert_language_server(
4746        this: WeakModel<Self>,
4747        delegate: Arc<dyn LspAdapterDelegate>,
4748        override_initialization_options: Option<serde_json::Value>,
4749        pending_server: PendingLanguageServer,
4750        adapter: Arc<CachedLspAdapter>,
4751        language: LanguageName,
4752        server_id: LanguageServerId,
4753        key: (WorktreeId, LanguageServerName),
4754        cx: &mut AsyncAppContext,
4755    ) -> Result<Option<Arc<LanguageServer>>> {
4756        let language_server = Self::setup_pending_language_server(
4757            this.clone(),
4758            override_initialization_options,
4759            pending_server,
4760            delegate,
4761            adapter.clone(),
4762            server_id,
4763            cx,
4764        )
4765        .await?;
4766
4767        let this = match this.upgrade() {
4768            Some(this) => this,
4769            None => return Err(anyhow!("failed to upgrade project handle")),
4770        };
4771
4772        this.update(cx, |this, cx| {
4773            this.insert_newly_running_language_server(
4774                language,
4775                adapter,
4776                language_server.clone(),
4777                server_id,
4778                key,
4779                cx,
4780            )
4781        })??;
4782
4783        Ok(Some(language_server))
4784    }
4785
4786    fn reinstall_language_server(
4787        &mut self,
4788        language: LanguageName,
4789        adapter: Arc<CachedLspAdapter>,
4790        server_id: LanguageServerId,
4791        cx: &mut ModelContext<Self>,
4792    ) -> Option<Task<()>> {
4793        log::info!("beginning to reinstall server");
4794
4795        if let Some(local) = self.as_local_mut() {
4796            let existing_server = match local.language_servers.remove(&server_id) {
4797                Some(LanguageServerState::Running { server, .. }) => Some(server),
4798                _ => None,
4799            };
4800
4801            self.worktree_store.update(cx, |store, cx| {
4802                for worktree in store.worktrees() {
4803                    let key = (worktree.read(cx).id(), adapter.name.clone());
4804                    self.language_server_ids.remove(&key);
4805                }
4806            });
4807
4808            Some(cx.spawn(move |this, mut cx| async move {
4809                if let Some(task) = existing_server.and_then(|server| server.shutdown()) {
4810                    log::info!("shutting down existing server");
4811                    task.await;
4812                }
4813
4814                // TODO: This is race-safe with regards to preventing new instances from
4815                // starting while deleting, but existing instances in other projects are going
4816                // to be very confused and messed up
4817                let Some(task) = this
4818                    .update(&mut cx, |this, cx| {
4819                        this.languages.delete_server_container(adapter.clone(), cx)
4820                    })
4821                    .log_err()
4822                else {
4823                    return;
4824                };
4825                task.await;
4826
4827                this.update(&mut cx, |this, cx| {
4828                    for worktree in this.worktree_store.read(cx).worktrees().collect::<Vec<_>>() {
4829                        this.start_language_server(
4830                            &worktree,
4831                            adapter.clone(),
4832                            language.clone(),
4833                            cx,
4834                        );
4835                    }
4836                })
4837                .ok();
4838            }))
4839        } else if let Some(_ssh_store) = self.as_ssh() {
4840            // TODO
4841            None
4842        } else {
4843            None
4844        }
4845    }
4846
4847    async fn shutdown_language_server(
4848        server_state: Option<LanguageServerState>,
4849        name: Arc<str>,
4850        cx: AsyncAppContext,
4851    ) {
4852        let server = match server_state {
4853            Some(LanguageServerState::Starting(task)) => {
4854                let mut timer = cx
4855                    .background_executor()
4856                    .timer(SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT)
4857                    .fuse();
4858
4859                select! {
4860                    server = task.fuse() => server,
4861                    _ = timer => {
4862                        log::info!(
4863                            "timeout waiting for language server {} to finish launching before stopping",
4864                            name
4865                        );
4866                        None
4867                    },
4868                }
4869            }
4870
4871            Some(LanguageServerState::Running { server, .. }) => Some(server),
4872
4873            None => None,
4874        };
4875
4876        if let Some(server) = server {
4877            if let Some(shutdown) = server.shutdown() {
4878                shutdown.await;
4879            }
4880        }
4881    }
4882
4883    // Returns a list of all of the worktrees which no longer have a language server and the root path
4884    // for the stopped server
4885    pub fn stop_language_server(
4886        &mut self,
4887        worktree_id: WorktreeId,
4888        adapter_name: LanguageServerName,
4889        cx: &mut ModelContext<Self>,
4890    ) -> Task<Vec<WorktreeId>> {
4891        let key = (worktree_id, adapter_name);
4892        if self.mode.is_local() {
4893            if let Some(server_id) = self.language_server_ids.remove(&key) {
4894                let name = key.1 .0;
4895                log::info!("stopping language server {name}");
4896
4897                // Remove other entries for this language server as well
4898                let mut orphaned_worktrees = vec![worktree_id];
4899                let other_keys = self.language_server_ids.keys().cloned().collect::<Vec<_>>();
4900                for other_key in other_keys {
4901                    if self.language_server_ids.get(&other_key) == Some(&server_id) {
4902                        self.language_server_ids.remove(&other_key);
4903                        orphaned_worktrees.push(other_key.0);
4904                    }
4905                }
4906
4907                self.buffer_store.update(cx, |buffer_store, cx| {
4908                    for buffer in buffer_store.buffers() {
4909                        buffer.update(cx, |buffer, cx| {
4910                            buffer.update_diagnostics(server_id, Default::default(), cx);
4911                        });
4912                    }
4913                });
4914
4915                let project_id = self.project_id;
4916                for (worktree_id, summaries) in self.diagnostic_summaries.iter_mut() {
4917                    summaries.retain(|path, summaries_by_server_id| {
4918                        if summaries_by_server_id.remove(&server_id).is_some() {
4919                            if let Some(downstream_client) = self.downstream_client.clone() {
4920                                downstream_client
4921                                    .send(proto::UpdateDiagnosticSummary {
4922                                        project_id,
4923                                        worktree_id: worktree_id.to_proto(),
4924                                        summary: Some(proto::DiagnosticSummary {
4925                                            path: path.to_string_lossy().to_string(),
4926                                            language_server_id: server_id.0 as u64,
4927                                            error_count: 0,
4928                                            warning_count: 0,
4929                                        }),
4930                                    })
4931                                    .log_err();
4932                            }
4933                            !summaries_by_server_id.is_empty()
4934                        } else {
4935                            true
4936                        }
4937                    });
4938                }
4939
4940                for diagnostics in self.diagnostics.values_mut() {
4941                    diagnostics.retain(|_, diagnostics_by_server_id| {
4942                        if let Ok(ix) =
4943                            diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0)
4944                        {
4945                            diagnostics_by_server_id.remove(ix);
4946                            !diagnostics_by_server_id.is_empty()
4947                        } else {
4948                            true
4949                        }
4950                    });
4951                }
4952
4953                self.as_local_mut()
4954                    .unwrap()
4955                    .language_server_watched_paths
4956                    .remove(&server_id);
4957                self.language_server_statuses.remove(&server_id);
4958                cx.notify();
4959
4960                let server_state = self
4961                    .as_local_mut()
4962                    .unwrap()
4963                    .language_servers
4964                    .remove(&server_id);
4965                cx.emit(LspStoreEvent::LanguageServerRemoved(server_id));
4966                cx.spawn(move |_, cx| async move {
4967                    Self::shutdown_language_server(server_state, name, cx).await;
4968                    orphaned_worktrees
4969                })
4970            } else {
4971                Task::ready(Vec::new())
4972            }
4973        } else if self.mode.is_ssh() {
4974            // TODO ssh
4975            Task::ready(Vec::new())
4976        } else {
4977            Task::ready(Vec::new())
4978        }
4979    }
4980
4981    pub fn restart_language_servers_for_buffers(
4982        &mut self,
4983        buffers: impl IntoIterator<Item = Model<Buffer>>,
4984        cx: &mut ModelContext<Self>,
4985    ) {
4986        if let Some(client) = self.upstream_client() {
4987            let request = client.request(proto::RestartLanguageServers {
4988                project_id: self.project_id,
4989                buffer_ids: buffers
4990                    .into_iter()
4991                    .map(|b| b.read(cx).remote_id().to_proto())
4992                    .collect(),
4993            });
4994            cx.background_executor()
4995                .spawn(request)
4996                .detach_and_log_err(cx);
4997        } else {
4998            #[allow(clippy::mutable_key_type)]
4999            let language_server_lookup_info: HashSet<(Model<Worktree>, LanguageName)> = buffers
5000                .into_iter()
5001                .filter_map(|buffer| {
5002                    let buffer = buffer.read(cx);
5003                    let file = buffer.file()?;
5004                    let worktree = File::from_dyn(Some(file))?.worktree.clone();
5005                    let language =
5006                        self.languages
5007                            .language_for_file(file, Some(buffer.as_rope()), cx)?;
5008
5009                    Some((worktree, language.name()))
5010                })
5011                .collect();
5012
5013            for (worktree, language) in language_server_lookup_info {
5014                self.restart_language_servers(worktree, language, cx);
5015            }
5016        }
5017    }
5018
5019    pub fn restart_language_servers(
5020        &mut self,
5021        worktree: Model<Worktree>,
5022        language: LanguageName,
5023        cx: &mut ModelContext<Self>,
5024    ) {
5025        let worktree_id = worktree.read(cx).id();
5026
5027        let stop_tasks = self
5028            .languages
5029            .clone()
5030            .lsp_adapters(&language)
5031            .iter()
5032            .map(|adapter| {
5033                let stop_task = self.stop_language_server(worktree_id, adapter.name.clone(), cx);
5034                (stop_task, adapter.name.clone())
5035            })
5036            .collect::<Vec<_>>();
5037        if stop_tasks.is_empty() {
5038            return;
5039        }
5040
5041        cx.spawn(move |this, mut cx| async move {
5042            // For each stopped language server, record all of the worktrees with which
5043            // it was associated.
5044            let mut affected_worktrees = Vec::new();
5045            for (stop_task, language_server_name) in stop_tasks {
5046                for affected_worktree_id in stop_task.await {
5047                    affected_worktrees.push((affected_worktree_id, language_server_name.clone()));
5048                }
5049            }
5050
5051            this.update(&mut cx, |this, cx| {
5052                // Restart the language server for the given worktree.
5053                this.start_language_servers(&worktree, language.clone(), cx);
5054
5055                // Lookup new server ids and set them for each of the orphaned worktrees
5056                for (affected_worktree_id, language_server_name) in affected_worktrees {
5057                    if let Some(new_server_id) = this
5058                        .language_server_ids
5059                        .get(&(worktree_id, language_server_name.clone()))
5060                        .cloned()
5061                    {
5062                        this.language_server_ids
5063                            .insert((affected_worktree_id, language_server_name), new_server_id);
5064                    }
5065                }
5066            })
5067            .ok();
5068        })
5069        .detach();
5070    }
5071
5072    fn check_errored_server(
5073        language: LanguageName,
5074        adapter: Arc<CachedLspAdapter>,
5075        server_id: LanguageServerId,
5076        installation_test_binary: Option<LanguageServerBinary>,
5077        cx: &mut ModelContext<Self>,
5078    ) {
5079        if !adapter.can_be_reinstalled() {
5080            log::info!(
5081                "Validation check requested for {:?} but it cannot be reinstalled",
5082                adapter.name.0
5083            );
5084            return;
5085        }
5086
5087        cx.spawn(move |this, mut cx| async move {
5088            log::info!("About to spawn test binary");
5089
5090            // A lack of test binary counts as a failure
5091            let process = installation_test_binary.and_then(|binary| {
5092                smol::process::Command::new(&binary.path)
5093                    .current_dir(&binary.path)
5094                    .args(binary.arguments)
5095                    .stdin(Stdio::piped())
5096                    .stdout(Stdio::piped())
5097                    .stderr(Stdio::inherit())
5098                    .kill_on_drop(true)
5099                    .spawn()
5100                    .ok()
5101            });
5102
5103            const PROCESS_TIMEOUT: Duration = Duration::from_secs(5);
5104            let mut timeout = cx.background_executor().timer(PROCESS_TIMEOUT).fuse();
5105
5106            let mut errored = false;
5107            if let Some(mut process) = process {
5108                futures::select! {
5109                    status = process.status().fuse() => match status {
5110                        Ok(status) => errored = !status.success(),
5111                        Err(_) => errored = true,
5112                    },
5113
5114                    _ = timeout => {
5115                        log::info!("test binary time-ed out, this counts as a success");
5116                        _ = process.kill();
5117                    }
5118                }
5119            } else {
5120                log::warn!("test binary failed to launch");
5121                errored = true;
5122            }
5123
5124            if errored {
5125                log::warn!("test binary check failed");
5126                let task = this
5127                    .update(&mut cx, move |this, cx| {
5128                        this.reinstall_language_server(language, adapter, server_id, cx)
5129                    })
5130                    .ok()
5131                    .flatten();
5132
5133                if let Some(task) = task {
5134                    task.await;
5135                }
5136            }
5137        })
5138        .detach();
5139    }
5140
5141    async fn setup_pending_language_server(
5142        this: WeakModel<Self>,
5143        override_options: Option<serde_json::Value>,
5144        pending_server: PendingLanguageServer,
5145        delegate: Arc<dyn LspAdapterDelegate>,
5146        adapter: Arc<CachedLspAdapter>,
5147        server_id: LanguageServerId,
5148        cx: &mut AsyncAppContext,
5149    ) -> Result<Arc<LanguageServer>> {
5150        let workspace_config = adapter
5151            .adapter
5152            .clone()
5153            .workspace_configuration(&delegate, cx)
5154            .await?;
5155        // This has to come from the server
5156        let (language_server, mut initialization_options) = pending_server.task.await?;
5157
5158        let name = language_server.name();
5159        language_server
5160            .on_notification::<lsp::notification::PublishDiagnostics, _>({
5161                let adapter = adapter.clone();
5162                let this = this.clone();
5163                move |mut params, mut cx| {
5164                    let adapter = adapter.clone();
5165                    if let Some(this) = this.upgrade() {
5166                        adapter.process_diagnostics(&mut params);
5167                        // Everything else has to be on the server, Can we make it on the client?
5168                        this.update(&mut cx, |this, cx| {
5169                            this.update_diagnostics(
5170                                server_id,
5171                                params,
5172                                &adapter.disk_based_diagnostic_sources,
5173                                cx,
5174                            )
5175                            .log_err();
5176                        })
5177                        .ok();
5178                    }
5179                }
5180            })
5181            .detach();
5182
5183        language_server
5184            .on_request::<lsp::request::WorkspaceConfiguration, _, _>({
5185                let adapter = adapter.adapter.clone();
5186                let delegate = delegate.clone();
5187                move |params, mut cx| {
5188                    let adapter = adapter.clone();
5189                    let delegate = delegate.clone();
5190                    async move {
5191                        let workspace_config =
5192                            adapter.workspace_configuration(&delegate, &mut cx).await?;
5193                        Ok(params
5194                            .items
5195                            .into_iter()
5196                            .map(|item| {
5197                                if let Some(section) = &item.section {
5198                                    workspace_config
5199                                        .get(section)
5200                                        .cloned()
5201                                        .unwrap_or(serde_json::Value::Null)
5202                                } else {
5203                                    workspace_config.clone()
5204                                }
5205                            })
5206                            .collect())
5207                    }
5208                }
5209            })
5210            .detach();
5211
5212        let id = language_server.server_id();
5213        language_server
5214            .on_request::<lsp::request::WorkspaceFoldersRequest, _, _>({
5215                let this = this.clone();
5216                move |_, mut cx| {
5217                    let this = this.clone();
5218                    async move {
5219                        let Some(server) =
5220                            this.update(&mut cx, |this, _| this.language_server_for_id(id))?
5221                        else {
5222                            return Ok(None);
5223                        };
5224                        let root = server.root_path();
5225                        let Ok(uri) = Url::from_file_path(&root) else {
5226                            return Ok(None);
5227                        };
5228                        Ok(Some(vec![WorkspaceFolder {
5229                            uri,
5230                            name: Default::default(),
5231                        }]))
5232                    }
5233                }
5234            })
5235            .detach();
5236        // Even though we don't have handling for these requests, respond to them to
5237        // avoid stalling any language server like `gopls` which waits for a response
5238        // to these requests when initializing.
5239        language_server
5240            .on_request::<lsp::request::WorkDoneProgressCreate, _, _>({
5241                let this = this.clone();
5242                move |params, mut cx| {
5243                    let this = this.clone();
5244                    async move {
5245                        this.update(&mut cx, |this, _| {
5246                            if let Some(status) = this.language_server_statuses.get_mut(&server_id)
5247                            {
5248                                if let lsp::NumberOrString::String(token) = params.token {
5249                                    status.progress_tokens.insert(token);
5250                                }
5251                            }
5252                        })?;
5253
5254                        Ok(())
5255                    }
5256                }
5257            })
5258            .detach();
5259
5260        language_server
5261            .on_request::<lsp::request::RegisterCapability, _, _>({
5262                let this = this.clone();
5263                move |params, mut cx| {
5264                    let this = this.clone();
5265                    async move {
5266                        for reg in params.registrations {
5267                            match reg.method.as_str() {
5268                                "workspace/didChangeWatchedFiles" => {
5269                                    if let Some(options) = reg.register_options {
5270                                        let options = serde_json::from_value(options)?;
5271                                        this.update(&mut cx, |this, cx| {
5272                                            this.on_lsp_did_change_watched_files(
5273                                                server_id, &reg.id, options, cx,
5274                                            );
5275                                        })?;
5276                                    }
5277                                }
5278                                "textDocument/rangeFormatting" => {
5279                                    this.update(&mut cx, |this, _| {
5280                                        if let Some(server) = this.language_server_for_id(server_id)
5281                                        {
5282                                            let options = reg
5283                                                .register_options
5284                                                .map(|options| {
5285                                                    serde_json::from_value::<
5286                                                        lsp::DocumentRangeFormattingOptions,
5287                                                    >(
5288                                                        options
5289                                                    )
5290                                                })
5291                                                .transpose()?;
5292                                            let provider = match options {
5293                                                None => OneOf::Left(true),
5294                                                Some(options) => OneOf::Right(options),
5295                                            };
5296                                            server.update_capabilities(|capabilities| {
5297                                                capabilities.document_range_formatting_provider =
5298                                                    Some(provider);
5299                                            })
5300                                        }
5301                                        anyhow::Ok(())
5302                                    })??;
5303                                }
5304                                "textDocument/onTypeFormatting" => {
5305                                    this.update(&mut cx, |this, _| {
5306                                        if let Some(server) = this.language_server_for_id(server_id)
5307                                        {
5308                                            let options = reg
5309                                                .register_options
5310                                                .map(|options| {
5311                                                    serde_json::from_value::<
5312                                                        lsp::DocumentOnTypeFormattingOptions,
5313                                                    >(
5314                                                        options
5315                                                    )
5316                                                })
5317                                                .transpose()?;
5318                                            if let Some(options) = options {
5319                                                server.update_capabilities(|capabilities| {
5320                                                    capabilities
5321                                                        .document_on_type_formatting_provider =
5322                                                        Some(options);
5323                                                })
5324                                            }
5325                                        }
5326                                        anyhow::Ok(())
5327                                    })??;
5328                                }
5329                                "textDocument/formatting" => {
5330                                    this.update(&mut cx, |this, _| {
5331                                        if let Some(server) = this.language_server_for_id(server_id)
5332                                        {
5333                                            let options = reg
5334                                                .register_options
5335                                                .map(|options| {
5336                                                    serde_json::from_value::<
5337                                                        lsp::DocumentFormattingOptions,
5338                                                    >(
5339                                                        options
5340                                                    )
5341                                                })
5342                                                .transpose()?;
5343                                            let provider = match options {
5344                                                None => OneOf::Left(true),
5345                                                Some(options) => OneOf::Right(options),
5346                                            };
5347                                            server.update_capabilities(|capabilities| {
5348                                                capabilities.document_formatting_provider =
5349                                                    Some(provider);
5350                                            })
5351                                        }
5352                                        anyhow::Ok(())
5353                                    })??;
5354                                }
5355                                _ => log::warn!("unhandled capability registration: {reg:?}"),
5356                            }
5357                        }
5358                        Ok(())
5359                    }
5360                }
5361            })
5362            .detach();
5363
5364        language_server
5365            .on_request::<lsp::request::UnregisterCapability, _, _>({
5366                let this = this.clone();
5367                move |params, mut cx| {
5368                    let this = this.clone();
5369                    async move {
5370                        for unreg in params.unregisterations.iter() {
5371                            match unreg.method.as_str() {
5372                                "workspace/didChangeWatchedFiles" => {
5373                                    this.update(&mut cx, |this, cx| {
5374                                        this.on_lsp_unregister_did_change_watched_files(
5375                                            server_id, &unreg.id, cx,
5376                                        );
5377                                    })?;
5378                                }
5379                                "textDocument/rangeFormatting" => {
5380                                    this.update(&mut cx, |this, _| {
5381                                        if let Some(server) = this.language_server_for_id(server_id)
5382                                        {
5383                                            server.update_capabilities(|capabilities| {
5384                                                capabilities.document_range_formatting_provider =
5385                                                    None
5386                                            })
5387                                        }
5388                                    })?;
5389                                }
5390                                "textDocument/onTypeFormatting" => {
5391                                    this.update(&mut cx, |this, _| {
5392                                        if let Some(server) = this.language_server_for_id(server_id)
5393                                        {
5394                                            server.update_capabilities(|capabilities| {
5395                                                capabilities.document_on_type_formatting_provider =
5396                                                    None;
5397                                            })
5398                                        }
5399                                    })?;
5400                                }
5401                                "textDocument/formatting" => {
5402                                    this.update(&mut cx, |this, _| {
5403                                        if let Some(server) = this.language_server_for_id(server_id)
5404                                        {
5405                                            server.update_capabilities(|capabilities| {
5406                                                capabilities.document_formatting_provider = None;
5407                                            })
5408                                        }
5409                                    })?;
5410                                }
5411                                _ => log::warn!("unhandled capability unregistration: {unreg:?}"),
5412                            }
5413                        }
5414                        Ok(())
5415                    }
5416                }
5417            })
5418            .detach();
5419
5420        language_server
5421            .on_request::<lsp::request::ApplyWorkspaceEdit, _, _>({
5422                let adapter = adapter.clone();
5423                let this = this.clone();
5424                move |params, cx| {
5425                    Self::on_lsp_workspace_edit(
5426                        this.clone(),
5427                        params,
5428                        server_id,
5429                        adapter.clone(),
5430                        cx,
5431                    )
5432                }
5433            })
5434            .detach();
5435
5436        language_server
5437            .on_request::<lsp::request::InlayHintRefreshRequest, _, _>({
5438                let this = this.clone();
5439                move |(), mut cx| {
5440                    let this = this.clone();
5441                    async move {
5442                        this.update(&mut cx, |this, cx| {
5443                            cx.emit(LspStoreEvent::RefreshInlayHints);
5444                            this.downstream_client.as_ref().map(|client| {
5445                                client.send(proto::RefreshInlayHints {
5446                                    project_id: this.project_id,
5447                                })
5448                            })
5449                        })?
5450                        .transpose()?;
5451                        Ok(())
5452                    }
5453                }
5454            })
5455            .detach();
5456
5457        language_server
5458            .on_request::<lsp::request::ShowMessageRequest, _, _>({
5459                let this = this.clone();
5460                let name = name.to_string();
5461                move |params, mut cx| {
5462                    let this = this.clone();
5463                    let name = name.to_string();
5464                    async move {
5465                        let actions = params.actions.unwrap_or_default();
5466                        let (tx, mut rx) = smol::channel::bounded(1);
5467                        let request = LanguageServerPromptRequest {
5468                            level: match params.typ {
5469                                lsp::MessageType::ERROR => PromptLevel::Critical,
5470                                lsp::MessageType::WARNING => PromptLevel::Warning,
5471                                _ => PromptLevel::Info,
5472                            },
5473                            message: params.message,
5474                            actions,
5475                            response_channel: tx,
5476                            lsp_name: name.clone(),
5477                        };
5478
5479                        let did_update = this
5480                            .update(&mut cx, |_, cx| {
5481                                cx.emit(LspStoreEvent::LanguageServerPrompt(request));
5482                            })
5483                            .is_ok();
5484                        if did_update {
5485                            let response = rx.next().await;
5486
5487                            Ok(response)
5488                        } else {
5489                            Ok(None)
5490                        }
5491                    }
5492                }
5493            })
5494            .detach();
5495
5496        let disk_based_diagnostics_progress_token =
5497            adapter.disk_based_diagnostics_progress_token.clone();
5498
5499        language_server
5500            .on_notification::<ServerStatus, _>({
5501                let this = this.clone();
5502                let name = name.to_string();
5503                move |params, mut cx| {
5504                    let this = this.clone();
5505                    let name = name.to_string();
5506                    if let Some(ref message) = params.message {
5507                        let message = message.trim();
5508                        if !message.is_empty() {
5509                            let formatted_message = format!(
5510                                "Language server {name} (id {server_id}) status update: {message}"
5511                            );
5512                            match params.health {
5513                                ServerHealthStatus::Ok => log::info!("{}", formatted_message),
5514                                ServerHealthStatus::Warning => log::warn!("{}", formatted_message),
5515                                ServerHealthStatus::Error => {
5516                                    log::error!("{}", formatted_message);
5517                                    let (tx, _rx) = smol::channel::bounded(1);
5518                                    let request = LanguageServerPromptRequest {
5519                                        level: PromptLevel::Critical,
5520                                        message: params.message.unwrap_or_default(),
5521                                        actions: Vec::new(),
5522                                        response_channel: tx,
5523                                        lsp_name: name.clone(),
5524                                    };
5525                                    let _ = this
5526                                        .update(&mut cx, |_, cx| {
5527                                            cx.emit(LspStoreEvent::LanguageServerPrompt(request));
5528                                        })
5529                                        .ok();
5530                                }
5531                                ServerHealthStatus::Other(status) => {
5532                                    log::info!(
5533                                        "Unknown server health: {status}\n{formatted_message}"
5534                                    )
5535                                }
5536                            }
5537                        }
5538                    }
5539                }
5540            })
5541            .detach();
5542        language_server
5543            .on_notification::<lsp::notification::ShowMessage, _>({
5544                let this = this.clone();
5545                let name = name.to_string();
5546                move |params, mut cx| {
5547                    let this = this.clone();
5548                    let name = name.to_string();
5549
5550                    let (tx, _) = smol::channel::bounded(1);
5551                    let request = LanguageServerPromptRequest {
5552                        level: match params.typ {
5553                            lsp::MessageType::ERROR => PromptLevel::Critical,
5554                            lsp::MessageType::WARNING => PromptLevel::Warning,
5555                            _ => PromptLevel::Info,
5556                        },
5557                        message: params.message,
5558                        actions: vec![],
5559                        response_channel: tx,
5560                        lsp_name: name.clone(),
5561                    };
5562
5563                    let _ = this.update(&mut cx, |_, cx| {
5564                        cx.emit(LspStoreEvent::LanguageServerPrompt(request));
5565                    });
5566                }
5567            })
5568            .detach();
5569        language_server
5570            .on_notification::<lsp::notification::Progress, _>({
5571                let this = this.clone();
5572                move |params, mut cx| {
5573                    if let Some(this) = this.upgrade() {
5574                        this.update(&mut cx, |this, cx| {
5575                            this.on_lsp_progress(
5576                                params,
5577                                server_id,
5578                                disk_based_diagnostics_progress_token.clone(),
5579                                cx,
5580                            );
5581                        })
5582                        .ok();
5583                    }
5584                }
5585            })
5586            .detach();
5587
5588        language_server
5589            .on_notification::<lsp::notification::LogMessage, _>({
5590                let this = this.clone();
5591                move |params, mut cx| {
5592                    if let Some(this) = this.upgrade() {
5593                        this.update(&mut cx, |_, cx| {
5594                            cx.emit(LspStoreEvent::LanguageServerLog(
5595                                server_id,
5596                                LanguageServerLogType::Log(params.typ),
5597                                params.message,
5598                            ));
5599                        })
5600                        .ok();
5601                    }
5602                }
5603            })
5604            .detach();
5605
5606        language_server
5607            .on_notification::<lsp::notification::LogTrace, _>({
5608                let this = this.clone();
5609                move |params, mut cx| {
5610                    if let Some(this) = this.upgrade() {
5611                        this.update(&mut cx, |_, cx| {
5612                            cx.emit(LspStoreEvent::LanguageServerLog(
5613                                server_id,
5614                                LanguageServerLogType::Trace(params.verbose),
5615                                params.message,
5616                            ));
5617                        })
5618                        .ok();
5619                    }
5620                }
5621            })
5622            .detach();
5623
5624        match (&mut initialization_options, override_options) {
5625            (Some(initialization_options), Some(override_options)) => {
5626                merge_json_value_into(override_options, initialization_options);
5627            }
5628            (None, override_options) => initialization_options = override_options,
5629            _ => {}
5630        }
5631
5632        let language_server = cx
5633            .update(|cx| language_server.initialize(initialization_options, cx))?
5634            .await
5635            .inspect_err(|_| {
5636                if let Some(this) = this.upgrade() {
5637                    this.update(cx, |_, cx| {
5638                        cx.emit(LspStoreEvent::LanguageServerRemoved(server_id))
5639                    })
5640                    .ok();
5641                }
5642            })?;
5643
5644        language_server
5645            .notify::<lsp::notification::DidChangeConfiguration>(
5646                lsp::DidChangeConfigurationParams {
5647                    settings: workspace_config,
5648                },
5649            )
5650            .ok();
5651
5652        Ok(language_server)
5653    }
5654
5655    pub fn update_diagnostics(
5656        &mut self,
5657        language_server_id: LanguageServerId,
5658        mut params: lsp::PublishDiagnosticsParams,
5659        disk_based_sources: &[String],
5660        cx: &mut ModelContext<Self>,
5661    ) -> Result<()> {
5662        let abs_path = params
5663            .uri
5664            .to_file_path()
5665            .map_err(|_| anyhow!("URI is not a file"))?;
5666        let mut diagnostics = Vec::default();
5667        let mut primary_diagnostic_group_ids = HashMap::default();
5668        let mut sources_by_group_id = HashMap::default();
5669        let mut supporting_diagnostics = HashMap::default();
5670
5671        // Ensure that primary diagnostics are always the most severe
5672        params.diagnostics.sort_by_key(|item| item.severity);
5673
5674        for diagnostic in &params.diagnostics {
5675            let source = diagnostic.source.as_ref();
5676            let code = diagnostic.code.as_ref().map(|code| match code {
5677                lsp::NumberOrString::Number(code) => code.to_string(),
5678                lsp::NumberOrString::String(code) => code.clone(),
5679            });
5680            let range = range_from_lsp(diagnostic.range);
5681            let is_supporting = diagnostic
5682                .related_information
5683                .as_ref()
5684                .map_or(false, |infos| {
5685                    infos.iter().any(|info| {
5686                        primary_diagnostic_group_ids.contains_key(&(
5687                            source,
5688                            code.clone(),
5689                            range_from_lsp(info.location.range),
5690                        ))
5691                    })
5692                });
5693
5694            let is_unnecessary = diagnostic.tags.as_ref().map_or(false, |tags| {
5695                tags.iter().any(|tag| *tag == DiagnosticTag::UNNECESSARY)
5696            });
5697
5698            if is_supporting {
5699                supporting_diagnostics.insert(
5700                    (source, code.clone(), range),
5701                    (diagnostic.severity, is_unnecessary),
5702                );
5703            } else {
5704                let group_id = post_inc(&mut self.next_diagnostic_group_id);
5705                let is_disk_based =
5706                    source.map_or(false, |source| disk_based_sources.contains(source));
5707
5708                sources_by_group_id.insert(group_id, source);
5709                primary_diagnostic_group_ids
5710                    .insert((source, code.clone(), range.clone()), group_id);
5711
5712                diagnostics.push(DiagnosticEntry {
5713                    range,
5714                    diagnostic: Diagnostic {
5715                        source: diagnostic.source.clone(),
5716                        code: code.clone(),
5717                        severity: diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR),
5718                        message: diagnostic.message.trim().to_string(),
5719                        group_id,
5720                        is_primary: true,
5721                        is_disk_based,
5722                        is_unnecessary,
5723                        data: diagnostic.data.clone(),
5724                    },
5725                });
5726                if let Some(infos) = &diagnostic.related_information {
5727                    for info in infos {
5728                        if info.location.uri == params.uri && !info.message.is_empty() {
5729                            let range = range_from_lsp(info.location.range);
5730                            diagnostics.push(DiagnosticEntry {
5731                                range,
5732                                diagnostic: Diagnostic {
5733                                    source: diagnostic.source.clone(),
5734                                    code: code.clone(),
5735                                    severity: DiagnosticSeverity::INFORMATION,
5736                                    message: info.message.trim().to_string(),
5737                                    group_id,
5738                                    is_primary: false,
5739                                    is_disk_based,
5740                                    is_unnecessary: false,
5741                                    data: diagnostic.data.clone(),
5742                                },
5743                            });
5744                        }
5745                    }
5746                }
5747            }
5748        }
5749
5750        for entry in &mut diagnostics {
5751            let diagnostic = &mut entry.diagnostic;
5752            if !diagnostic.is_primary {
5753                let source = *sources_by_group_id.get(&diagnostic.group_id).unwrap();
5754                if let Some(&(severity, is_unnecessary)) = supporting_diagnostics.get(&(
5755                    source,
5756                    diagnostic.code.clone(),
5757                    entry.range.clone(),
5758                )) {
5759                    if let Some(severity) = severity {
5760                        diagnostic.severity = severity;
5761                    }
5762                    diagnostic.is_unnecessary = is_unnecessary;
5763                }
5764            }
5765        }
5766
5767        self.update_diagnostic_entries(
5768            language_server_id,
5769            abs_path,
5770            params.version,
5771            diagnostics,
5772            cx,
5773        )?;
5774        Ok(())
5775    }
5776
5777    fn insert_newly_running_language_server(
5778        &mut self,
5779        language: LanguageName,
5780        adapter: Arc<CachedLspAdapter>,
5781        language_server: Arc<LanguageServer>,
5782        server_id: LanguageServerId,
5783        key: (WorktreeId, LanguageServerName),
5784        cx: &mut ModelContext<Self>,
5785    ) -> Result<()> {
5786        // If the language server for this key doesn't match the server id, don't store the
5787        // server. Which will cause it to be dropped, killing the process
5788        if self
5789            .language_server_ids
5790            .get(&key)
5791            .map(|id| id != &server_id)
5792            .unwrap_or(false)
5793        {
5794            return Ok(());
5795        }
5796
5797        // Update language_servers collection with Running variant of LanguageServerState
5798        // indicating that the server is up and running and ready
5799        if let Some(local) = self.as_local_mut() {
5800            local.language_servers.insert(
5801                server_id,
5802                LanguageServerState::Running {
5803                    adapter: adapter.clone(),
5804                    language: language.clone(),
5805                    server: language_server.clone(),
5806                    simulate_disk_based_diagnostics_completion: None,
5807                },
5808            );
5809        }
5810
5811        self.language_server_statuses.insert(
5812            server_id,
5813            LanguageServerStatus {
5814                name: language_server.name().to_string(),
5815                pending_work: Default::default(),
5816                has_pending_diagnostic_updates: false,
5817                progress_tokens: Default::default(),
5818            },
5819        );
5820
5821        cx.emit(LspStoreEvent::LanguageServerAdded(server_id));
5822
5823        if let Some(downstream_client) = self.downstream_client.as_ref() {
5824            downstream_client.send(proto::StartLanguageServer {
5825                project_id: self.project_id,
5826                server: Some(proto::LanguageServer {
5827                    id: server_id.0 as u64,
5828                    name: language_server.name().to_string(),
5829                }),
5830            })?;
5831        }
5832
5833        // Tell the language server about every open buffer in the worktree that matches the language.
5834        self.buffer_store.update(cx, |buffer_store, cx| {
5835            for buffer_handle in buffer_store.buffers() {
5836                let buffer = buffer_handle.read(cx);
5837                let file = match File::from_dyn(buffer.file()) {
5838                    Some(file) => file,
5839                    None => continue,
5840                };
5841                let language = match buffer.language() {
5842                    Some(language) => language,
5843                    None => continue,
5844                };
5845
5846                if file.worktree.read(cx).id() != key.0
5847                    || !self
5848                        .languages
5849                        .lsp_adapters(&language.name())
5850                        .iter()
5851                        .any(|a| a.name == key.1)
5852                {
5853                    continue;
5854                }
5855
5856                let file = match file.as_local() {
5857                    Some(file) => file,
5858                    None => continue,
5859                };
5860
5861                let versions = self
5862                    .buffer_snapshots
5863                    .entry(buffer.remote_id())
5864                    .or_default()
5865                    .entry(server_id)
5866                    .or_insert_with(|| {
5867                        vec![LspBufferSnapshot {
5868                            version: 0,
5869                            snapshot: buffer.text_snapshot(),
5870                        }]
5871                    });
5872
5873                let snapshot = versions.last().unwrap();
5874                let version = snapshot.version;
5875                let initial_snapshot = &snapshot.snapshot;
5876                let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap();
5877                language_server.notify::<lsp::notification::DidOpenTextDocument>(
5878                    lsp::DidOpenTextDocumentParams {
5879                        text_document: lsp::TextDocumentItem::new(
5880                            uri,
5881                            adapter.language_id(&language.name()),
5882                            version,
5883                            initial_snapshot.text(),
5884                        ),
5885                    },
5886                )?;
5887
5888                buffer_handle.update(cx, |buffer, cx| {
5889                    buffer.set_completion_triggers(
5890                        language_server
5891                            .capabilities()
5892                            .completion_provider
5893                            .as_ref()
5894                            .and_then(|provider| provider.trigger_characters.clone())
5895                            .unwrap_or_default(),
5896                        cx,
5897                    )
5898                });
5899            }
5900            anyhow::Ok(())
5901        })?;
5902
5903        cx.notify();
5904        Ok(())
5905    }
5906
5907    fn buffer_snapshot_for_lsp_version(
5908        &mut self,
5909        buffer: &Model<Buffer>,
5910        server_id: LanguageServerId,
5911        version: Option<i32>,
5912        cx: &AppContext,
5913    ) -> Result<TextBufferSnapshot> {
5914        const OLD_VERSIONS_TO_RETAIN: i32 = 10;
5915
5916        if let Some(version) = version {
5917            let buffer_id = buffer.read(cx).remote_id();
5918            let snapshots = self
5919                .buffer_snapshots
5920                .get_mut(&buffer_id)
5921                .and_then(|m| m.get_mut(&server_id))
5922                .ok_or_else(|| {
5923                    anyhow!("no snapshots found for buffer {buffer_id} and server {server_id}")
5924                })?;
5925
5926            let found_snapshot = snapshots
5927                .binary_search_by_key(&version, |e| e.version)
5928                .map(|ix| snapshots[ix].snapshot.clone())
5929                .map_err(|_| {
5930                    anyhow!("snapshot not found for buffer {buffer_id} server {server_id} at version {version}")
5931                })?;
5932
5933            snapshots.retain(|snapshot| snapshot.version + OLD_VERSIONS_TO_RETAIN >= version);
5934            Ok(found_snapshot)
5935        } else {
5936            Ok((buffer.read(cx)).text_snapshot())
5937        }
5938    }
5939
5940    pub fn language_servers_running_disk_based_diagnostics(
5941        &self,
5942    ) -> impl Iterator<Item = LanguageServerId> + '_ {
5943        self.language_server_statuses
5944            .iter()
5945            .filter_map(|(id, status)| {
5946                if status.has_pending_diagnostic_updates {
5947                    Some(*id)
5948                } else {
5949                    None
5950                }
5951            })
5952    }
5953
5954    pub(crate) fn language_servers_for_buffer<'a>(
5955        &'a self,
5956        buffer: &'a Buffer,
5957        cx: &'a AppContext,
5958    ) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
5959        self.language_server_ids_for_buffer(buffer, cx)
5960            .into_iter()
5961            .filter_map(
5962                |server_id| match self.as_local()?.language_servers.get(&server_id)? {
5963                    LanguageServerState::Running {
5964                        adapter, server, ..
5965                    } => Some((adapter, server)),
5966                    _ => None,
5967                },
5968            )
5969    }
5970
5971    pub(crate) fn cancel_language_server_work_for_buffers(
5972        &mut self,
5973        buffers: impl IntoIterator<Item = Model<Buffer>>,
5974        cx: &mut ModelContext<Self>,
5975    ) {
5976        let servers = buffers
5977            .into_iter()
5978            .flat_map(|buffer| {
5979                self.language_server_ids_for_buffer(buffer.read(cx), cx)
5980                    .into_iter()
5981            })
5982            .collect::<HashSet<_>>();
5983
5984        for server_id in servers {
5985            self.cancel_language_server_work(server_id, None, cx);
5986        }
5987    }
5988
5989    pub fn language_servers(
5990        &self,
5991    ) -> impl '_ + Iterator<Item = (LanguageServerId, LanguageServerName, WorktreeId)> {
5992        self.language_server_ids
5993            .iter()
5994            .map(|((worktree_id, server_name), server_id)| {
5995                (*server_id, server_name.clone(), *worktree_id)
5996            })
5997    }
5998
5999    pub fn register_supplementary_language_server(
6000        &mut self,
6001        id: LanguageServerId,
6002        name: LanguageServerName,
6003        server: Arc<LanguageServer>,
6004        cx: &mut ModelContext<Self>,
6005    ) {
6006        if let Some(local) = self.as_local_mut() {
6007            local
6008                .supplementary_language_servers
6009                .insert(id, (name, server));
6010            cx.emit(LspStoreEvent::LanguageServerAdded(id));
6011        }
6012    }
6013
6014    pub fn unregister_supplementary_language_server(
6015        &mut self,
6016        id: LanguageServerId,
6017        cx: &mut ModelContext<Self>,
6018    ) {
6019        if let Some(local) = self.as_local_mut() {
6020            local.supplementary_language_servers.remove(&id);
6021            cx.emit(LspStoreEvent::LanguageServerRemoved(id));
6022        }
6023    }
6024
6025    pub fn supplementary_language_servers(
6026        &self,
6027    ) -> impl '_ + Iterator<Item = (LanguageServerId, LanguageServerName)> {
6028        self.as_local().into_iter().flat_map(|local| {
6029            local
6030                .supplementary_language_servers
6031                .iter()
6032                .map(|(id, (name, _))| (*id, name.clone()))
6033        })
6034    }
6035
6036    pub fn language_server_adapter_for_id(
6037        &self,
6038        id: LanguageServerId,
6039    ) -> Option<Arc<CachedLspAdapter>> {
6040        self.as_local()
6041            .and_then(|local| local.language_servers.get(&id))
6042            .and_then(|language_server_state| match language_server_state {
6043                LanguageServerState::Running { adapter, .. } => Some(adapter.clone()),
6044                _ => None,
6045            })
6046    }
6047
6048    pub(super) fn update_local_worktree_language_servers(
6049        &mut self,
6050        worktree_handle: &Model<Worktree>,
6051        changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
6052        cx: &mut ModelContext<Self>,
6053    ) {
6054        if changes.is_empty() {
6055            return;
6056        }
6057
6058        let Some(local) = self.as_local() else { return };
6059
6060        let worktree_id = worktree_handle.read(cx).id();
6061        let mut language_server_ids = self
6062            .language_server_ids
6063            .iter()
6064            .filter_map(|((server_worktree_id, _), server_id)| {
6065                (*server_worktree_id == worktree_id).then_some(*server_id)
6066            })
6067            .collect::<Vec<_>>();
6068        language_server_ids.sort();
6069        language_server_ids.dedup();
6070
6071        let abs_path = worktree_handle.read(cx).abs_path();
6072        for server_id in &language_server_ids {
6073            if let Some(LanguageServerState::Running { server, .. }) =
6074                local.language_servers.get(server_id)
6075            {
6076                if let Some(watched_paths) = local
6077                    .language_server_watched_paths
6078                    .get(server_id)
6079                    .and_then(|paths| paths.read(cx).worktree_paths.get(&worktree_id))
6080                {
6081                    let params = lsp::DidChangeWatchedFilesParams {
6082                        changes: changes
6083                            .iter()
6084                            .filter_map(|(path, _, change)| {
6085                                if !watched_paths.is_match(path) {
6086                                    return None;
6087                                }
6088                                let typ = match change {
6089                                    PathChange::Loaded => return None,
6090                                    PathChange::Added => lsp::FileChangeType::CREATED,
6091                                    PathChange::Removed => lsp::FileChangeType::DELETED,
6092                                    PathChange::Updated => lsp::FileChangeType::CHANGED,
6093                                    PathChange::AddedOrUpdated => lsp::FileChangeType::CHANGED,
6094                                };
6095                                Some(lsp::FileEvent {
6096                                    uri: lsp::Url::from_file_path(abs_path.join(path)).unwrap(),
6097                                    typ,
6098                                })
6099                            })
6100                            .collect(),
6101                    };
6102                    if !params.changes.is_empty() {
6103                        server
6104                            .notify::<lsp::notification::DidChangeWatchedFiles>(params)
6105                            .log_err();
6106                    }
6107                }
6108            }
6109        }
6110    }
6111
6112    pub(crate) fn cancel_language_server_work(
6113        &mut self,
6114        server_id: LanguageServerId,
6115        token_to_cancel: Option<String>,
6116        _cx: &mut ModelContext<Self>,
6117    ) {
6118        let Some(local) = self.as_local() else {
6119            return;
6120        };
6121        let status = self.language_server_statuses.get(&server_id);
6122        let server = local.language_servers.get(&server_id);
6123        if let Some((LanguageServerState::Running { server, .. }, status)) = server.zip(status) {
6124            for (token, progress) in &status.pending_work {
6125                if let Some(token_to_cancel) = token_to_cancel.as_ref() {
6126                    if token != token_to_cancel {
6127                        continue;
6128                    }
6129                }
6130                if progress.is_cancellable {
6131                    server
6132                        .notify::<lsp::notification::WorkDoneProgressCancel>(
6133                            WorkDoneProgressCancelParams {
6134                                token: lsp::NumberOrString::String(token.clone()),
6135                            },
6136                        )
6137                        .ok();
6138                }
6139
6140                if progress.is_cancellable {
6141                    server
6142                        .notify::<lsp::notification::WorkDoneProgressCancel>(
6143                            WorkDoneProgressCancelParams {
6144                                token: lsp::NumberOrString::String(token.clone()),
6145                            },
6146                        )
6147                        .ok();
6148                }
6149            }
6150        }
6151    }
6152
6153    pub fn wait_for_remote_buffer(
6154        &mut self,
6155        id: BufferId,
6156        cx: &mut ModelContext<Self>,
6157    ) -> Task<Result<Model<Buffer>>> {
6158        self.buffer_store.update(cx, |buffer_store, cx| {
6159            buffer_store.wait_for_remote_buffer(id, cx)
6160        })
6161    }
6162
6163    pub(crate) fn language_server_ids_for_buffer(
6164        &self,
6165        buffer: &Buffer,
6166        cx: &AppContext,
6167    ) -> Vec<LanguageServerId> {
6168        if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) {
6169            let worktree_id = file.worktree_id(cx);
6170            self.languages
6171                .lsp_adapters(&language.name())
6172                .iter()
6173                .flat_map(|adapter| {
6174                    let key = (worktree_id, adapter.name.clone());
6175                    self.language_server_ids.get(&key).copied()
6176                })
6177                .collect()
6178        } else {
6179            Vec::new()
6180        }
6181    }
6182
6183    pub async fn deserialize_text_edits(
6184        this: Model<Self>,
6185        buffer_to_edit: Model<Buffer>,
6186        edits: Vec<lsp::TextEdit>,
6187        push_to_history: bool,
6188        _: Arc<CachedLspAdapter>,
6189        language_server: Arc<LanguageServer>,
6190        cx: &mut AsyncAppContext,
6191    ) -> Result<Option<Transaction>> {
6192        let edits = this
6193            .update(cx, |this, cx| {
6194                this.edits_from_lsp(
6195                    &buffer_to_edit,
6196                    edits,
6197                    language_server.server_id(),
6198                    None,
6199                    cx,
6200                )
6201            })?
6202            .await?;
6203
6204        let transaction = buffer_to_edit.update(cx, |buffer, cx| {
6205            buffer.finalize_last_transaction();
6206            buffer.start_transaction();
6207            for (range, text) in edits {
6208                buffer.edit([(range, text)], None, cx);
6209            }
6210
6211            if buffer.end_transaction(cx).is_some() {
6212                let transaction = buffer.finalize_last_transaction().unwrap().clone();
6213                if !push_to_history {
6214                    buffer.forget_transaction(transaction.id);
6215                }
6216                Some(transaction)
6217            } else {
6218                None
6219            }
6220        })?;
6221
6222        Ok(transaction)
6223    }
6224
6225    pub async fn deserialize_workspace_edit(
6226        this: Model<Self>,
6227        edit: lsp::WorkspaceEdit,
6228        push_to_history: bool,
6229        lsp_adapter: Arc<CachedLspAdapter>,
6230        language_server: Arc<LanguageServer>,
6231        cx: &mut AsyncAppContext,
6232    ) -> Result<ProjectTransaction> {
6233        let fs = this.read_with(cx, |this, _| this.as_local().unwrap().fs.clone())?;
6234
6235        let mut operations = Vec::new();
6236        if let Some(document_changes) = edit.document_changes {
6237            match document_changes {
6238                lsp::DocumentChanges::Edits(edits) => {
6239                    operations.extend(edits.into_iter().map(lsp::DocumentChangeOperation::Edit))
6240                }
6241                lsp::DocumentChanges::Operations(ops) => operations = ops,
6242            }
6243        } else if let Some(changes) = edit.changes {
6244            operations.extend(changes.into_iter().map(|(uri, edits)| {
6245                lsp::DocumentChangeOperation::Edit(lsp::TextDocumentEdit {
6246                    text_document: lsp::OptionalVersionedTextDocumentIdentifier {
6247                        uri,
6248                        version: None,
6249                    },
6250                    edits: edits.into_iter().map(Edit::Plain).collect(),
6251                })
6252            }));
6253        }
6254
6255        let mut project_transaction = ProjectTransaction::default();
6256        for operation in operations {
6257            match operation {
6258                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Create(op)) => {
6259                    let abs_path = op
6260                        .uri
6261                        .to_file_path()
6262                        .map_err(|_| anyhow!("can't convert URI to path"))?;
6263
6264                    if let Some(parent_path) = abs_path.parent() {
6265                        fs.create_dir(parent_path).await?;
6266                    }
6267                    if abs_path.ends_with("/") {
6268                        fs.create_dir(&abs_path).await?;
6269                    } else {
6270                        fs.create_file(
6271                            &abs_path,
6272                            op.options
6273                                .map(|options| fs::CreateOptions {
6274                                    overwrite: options.overwrite.unwrap_or(false),
6275                                    ignore_if_exists: options.ignore_if_exists.unwrap_or(false),
6276                                })
6277                                .unwrap_or_default(),
6278                        )
6279                        .await?;
6280                    }
6281                }
6282
6283                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Rename(op)) => {
6284                    let source_abs_path = op
6285                        .old_uri
6286                        .to_file_path()
6287                        .map_err(|_| anyhow!("can't convert URI to path"))?;
6288                    let target_abs_path = op
6289                        .new_uri
6290                        .to_file_path()
6291                        .map_err(|_| anyhow!("can't convert URI to path"))?;
6292                    fs.rename(
6293                        &source_abs_path,
6294                        &target_abs_path,
6295                        op.options
6296                            .map(|options| fs::RenameOptions {
6297                                overwrite: options.overwrite.unwrap_or(false),
6298                                ignore_if_exists: options.ignore_if_exists.unwrap_or(false),
6299                            })
6300                            .unwrap_or_default(),
6301                    )
6302                    .await?;
6303                }
6304
6305                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Delete(op)) => {
6306                    let abs_path = op
6307                        .uri
6308                        .to_file_path()
6309                        .map_err(|_| anyhow!("can't convert URI to path"))?;
6310                    let options = op
6311                        .options
6312                        .map(|options| fs::RemoveOptions {
6313                            recursive: options.recursive.unwrap_or(false),
6314                            ignore_if_not_exists: options.ignore_if_not_exists.unwrap_or(false),
6315                        })
6316                        .unwrap_or_default();
6317                    if abs_path.ends_with("/") {
6318                        fs.remove_dir(&abs_path, options).await?;
6319                    } else {
6320                        fs.remove_file(&abs_path, options).await?;
6321                    }
6322                }
6323
6324                lsp::DocumentChangeOperation::Edit(op) => {
6325                    let buffer_to_edit = this
6326                        .update(cx, |this, cx| {
6327                            this.open_local_buffer_via_lsp(
6328                                op.text_document.uri.clone(),
6329                                language_server.server_id(),
6330                                lsp_adapter.name.clone(),
6331                                cx,
6332                            )
6333                        })?
6334                        .await?;
6335
6336                    let edits = this
6337                        .update(cx, |this, cx| {
6338                            let path = buffer_to_edit.read(cx).project_path(cx);
6339                            let active_entry = this.active_entry;
6340                            let is_active_entry = path.clone().map_or(false, |project_path| {
6341                                this.worktree_store
6342                                    .read(cx)
6343                                    .entry_for_path(&project_path, cx)
6344                                    .map_or(false, |entry| Some(entry.id) == active_entry)
6345                            });
6346
6347                            let (mut edits, mut snippet_edits) = (vec![], vec![]);
6348                            for edit in op.edits {
6349                                match edit {
6350                                    Edit::Plain(edit) => edits.push(edit),
6351                                    Edit::Annotated(edit) => edits.push(edit.text_edit),
6352                                    Edit::Snippet(edit) => {
6353                                        let Ok(snippet) = Snippet::parse(&edit.snippet.value)
6354                                        else {
6355                                            continue;
6356                                        };
6357
6358                                        if is_active_entry {
6359                                            snippet_edits.push((edit.range, snippet));
6360                                        } else {
6361                                            // Since this buffer is not focused, apply a normal edit.
6362                                            edits.push(TextEdit {
6363                                                range: edit.range,
6364                                                new_text: snippet.text,
6365                                            });
6366                                        }
6367                                    }
6368                                }
6369                            }
6370                            if !snippet_edits.is_empty() {
6371                                let buffer_id = buffer_to_edit.read(cx).remote_id();
6372                                let version = if let Some(buffer_version) = op.text_document.version
6373                                {
6374                                    this.buffer_snapshots
6375                                        .get(&buffer_id)
6376                                        .and_then(|server_to_snapshots| {
6377                                            let all_snapshots = server_to_snapshots
6378                                                .get(&language_server.server_id())?;
6379                                            all_snapshots
6380                                                .binary_search_by_key(&buffer_version, |snapshot| {
6381                                                    snapshot.version
6382                                                })
6383                                                .ok()
6384                                                .and_then(|index| all_snapshots.get(index))
6385                                        })
6386                                        .map(|lsp_snapshot| lsp_snapshot.snapshot.version())
6387                                } else {
6388                                    Some(buffer_to_edit.read(cx).saved_version())
6389                                };
6390
6391                                let most_recent_edit = version.and_then(|version| {
6392                                    version.iter().max_by_key(|timestamp| timestamp.value)
6393                                });
6394                                // Check if the edit that triggered that edit has been made by this participant.
6395
6396                                if let Some(most_recent_edit) = most_recent_edit {
6397                                    cx.emit(LspStoreEvent::SnippetEdit {
6398                                        buffer_id,
6399                                        edits: snippet_edits,
6400                                        most_recent_edit,
6401                                    });
6402                                }
6403                            }
6404
6405                            this.edits_from_lsp(
6406                                &buffer_to_edit,
6407                                edits,
6408                                language_server.server_id(),
6409                                op.text_document.version,
6410                                cx,
6411                            )
6412                        })?
6413                        .await?;
6414
6415                    let transaction = buffer_to_edit.update(cx, |buffer, cx| {
6416                        buffer.finalize_last_transaction();
6417                        buffer.start_transaction();
6418                        for (range, text) in edits {
6419                            buffer.edit([(range, text)], None, cx);
6420                        }
6421                        let transaction = if buffer.end_transaction(cx).is_some() {
6422                            let transaction = buffer.finalize_last_transaction().unwrap().clone();
6423                            if !push_to_history {
6424                                buffer.forget_transaction(transaction.id);
6425                            }
6426                            Some(transaction)
6427                        } else {
6428                            None
6429                        };
6430
6431                        transaction
6432                    })?;
6433                    if let Some(transaction) = transaction {
6434                        project_transaction.0.insert(buffer_to_edit, transaction);
6435                    }
6436                }
6437            }
6438        }
6439
6440        Ok(project_transaction)
6441    }
6442
6443    fn serialize_symbol(symbol: &Symbol) -> proto::Symbol {
6444        proto::Symbol {
6445            language_server_name: symbol.language_server_name.0.to_string(),
6446            source_worktree_id: symbol.source_worktree_id.to_proto(),
6447            worktree_id: symbol.path.worktree_id.to_proto(),
6448            path: symbol.path.path.to_string_lossy().to_string(),
6449            name: symbol.name.clone(),
6450            kind: unsafe { mem::transmute::<lsp::SymbolKind, i32>(symbol.kind) },
6451            start: Some(proto::PointUtf16 {
6452                row: symbol.range.start.0.row,
6453                column: symbol.range.start.0.column,
6454            }),
6455            end: Some(proto::PointUtf16 {
6456                row: symbol.range.end.0.row,
6457                column: symbol.range.end.0.column,
6458            }),
6459            signature: symbol.signature.to_vec(),
6460        }
6461    }
6462
6463    fn deserialize_symbol(serialized_symbol: proto::Symbol) -> Result<CoreSymbol> {
6464        let source_worktree_id = WorktreeId::from_proto(serialized_symbol.source_worktree_id);
6465        let worktree_id = WorktreeId::from_proto(serialized_symbol.worktree_id);
6466        let kind = unsafe { mem::transmute::<i32, lsp::SymbolKind>(serialized_symbol.kind) };
6467        let path = ProjectPath {
6468            worktree_id,
6469            path: PathBuf::from(serialized_symbol.path).into(),
6470        };
6471
6472        let start = serialized_symbol
6473            .start
6474            .ok_or_else(|| anyhow!("invalid start"))?;
6475        let end = serialized_symbol
6476            .end
6477            .ok_or_else(|| anyhow!("invalid end"))?;
6478        Ok(CoreSymbol {
6479            language_server_name: LanguageServerName(serialized_symbol.language_server_name.into()),
6480            source_worktree_id,
6481            path,
6482            name: serialized_symbol.name,
6483            range: Unclipped(PointUtf16::new(start.row, start.column))
6484                ..Unclipped(PointUtf16::new(end.row, end.column)),
6485            kind,
6486            signature: serialized_symbol
6487                .signature
6488                .try_into()
6489                .map_err(|_| anyhow!("invalid signature"))?,
6490        })
6491    }
6492
6493    pub(crate) fn serialize_completion(completion: &CoreCompletion) -> proto::Completion {
6494        proto::Completion {
6495            old_start: Some(serialize_anchor(&completion.old_range.start)),
6496            old_end: Some(serialize_anchor(&completion.old_range.end)),
6497            new_text: completion.new_text.clone(),
6498            server_id: completion.server_id.0 as u64,
6499            lsp_completion: serde_json::to_vec(&completion.lsp_completion).unwrap(),
6500        }
6501    }
6502
6503    pub(crate) fn deserialize_completion(completion: proto::Completion) -> Result<CoreCompletion> {
6504        let old_start = completion
6505            .old_start
6506            .and_then(deserialize_anchor)
6507            .ok_or_else(|| anyhow!("invalid old start"))?;
6508        let old_end = completion
6509            .old_end
6510            .and_then(deserialize_anchor)
6511            .ok_or_else(|| anyhow!("invalid old end"))?;
6512        let lsp_completion = serde_json::from_slice(&completion.lsp_completion)?;
6513
6514        Ok(CoreCompletion {
6515            old_range: old_start..old_end,
6516            new_text: completion.new_text,
6517            server_id: LanguageServerId(completion.server_id as usize),
6518            lsp_completion,
6519        })
6520    }
6521
6522    pub(crate) fn serialize_code_action(action: &CodeAction) -> proto::CodeAction {
6523        proto::CodeAction {
6524            server_id: action.server_id.0 as u64,
6525            start: Some(serialize_anchor(&action.range.start)),
6526            end: Some(serialize_anchor(&action.range.end)),
6527            lsp_action: serde_json::to_vec(&action.lsp_action).unwrap(),
6528        }
6529    }
6530
6531    pub(crate) fn deserialize_code_action(action: proto::CodeAction) -> Result<CodeAction> {
6532        let start = action
6533            .start
6534            .and_then(deserialize_anchor)
6535            .ok_or_else(|| anyhow!("invalid start"))?;
6536        let end = action
6537            .end
6538            .and_then(deserialize_anchor)
6539            .ok_or_else(|| anyhow!("invalid end"))?;
6540        let lsp_action = serde_json::from_slice(&action.lsp_action)?;
6541        Ok(CodeAction {
6542            server_id: LanguageServerId(action.server_id as usize),
6543            range: start..end,
6544            lsp_action,
6545        })
6546    }
6547}
6548
6549impl EventEmitter<LspStoreEvent> for LspStore {}
6550
6551fn remove_empty_hover_blocks(mut hover: Hover) -> Option<Hover> {
6552    hover
6553        .contents
6554        .retain(|hover_block| !hover_block.text.trim().is_empty());
6555    if hover.contents.is_empty() {
6556        None
6557    } else {
6558        Some(hover)
6559    }
6560}
6561
6562async fn populate_labels_for_completions(
6563    mut new_completions: Vec<CoreCompletion>,
6564    language_registry: &Arc<LanguageRegistry>,
6565    language: Option<Arc<Language>>,
6566    lsp_adapter: Option<Arc<CachedLspAdapter>>,
6567    completions: &mut Vec<Completion>,
6568) {
6569    let lsp_completions = new_completions
6570        .iter_mut()
6571        .map(|completion| mem::take(&mut completion.lsp_completion))
6572        .collect::<Vec<_>>();
6573
6574    let labels = if let Some((language, lsp_adapter)) = language.as_ref().zip(lsp_adapter) {
6575        lsp_adapter
6576            .labels_for_completions(&lsp_completions, language)
6577            .await
6578            .log_err()
6579            .unwrap_or_default()
6580    } else {
6581        Vec::new()
6582    };
6583
6584    for ((completion, lsp_completion), label) in new_completions
6585        .into_iter()
6586        .zip(lsp_completions)
6587        .zip(labels.into_iter().chain(iter::repeat(None)))
6588    {
6589        let documentation = if let Some(docs) = &lsp_completion.documentation {
6590            Some(prepare_completion_documentation(docs, language_registry, language.clone()).await)
6591        } else {
6592            None
6593        };
6594
6595        completions.push(Completion {
6596            old_range: completion.old_range,
6597            new_text: completion.new_text,
6598            label: label.unwrap_or_else(|| {
6599                CodeLabel::plain(
6600                    lsp_completion.label.clone(),
6601                    lsp_completion.filter_text.as_deref(),
6602                )
6603            }),
6604            server_id: completion.server_id,
6605            documentation,
6606            lsp_completion,
6607            confirm: None,
6608        })
6609    }
6610}
6611
6612#[derive(Debug)]
6613pub enum LanguageServerToQuery {
6614    Primary,
6615    Other(LanguageServerId),
6616}
6617
6618#[derive(Default)]
6619struct LanguageServerWatchedPaths {
6620    worktree_paths: HashMap<WorktreeId, GlobSet>,
6621    abs_paths: HashMap<Arc<Path>, (GlobSet, Task<()>)>,
6622}
6623
6624#[derive(Default)]
6625struct LanguageServerWatchedPathsBuilder {
6626    worktree_paths: HashMap<WorktreeId, GlobSet>,
6627    abs_paths: HashMap<Arc<Path>, GlobSet>,
6628}
6629
6630impl LanguageServerWatchedPathsBuilder {
6631    fn watch_worktree(&mut self, worktree_id: WorktreeId, glob_set: GlobSet) {
6632        self.worktree_paths.insert(worktree_id, glob_set);
6633    }
6634    fn watch_abs_path(&mut self, path: Arc<Path>, glob_set: GlobSet) {
6635        self.abs_paths.insert(path, glob_set);
6636    }
6637    fn build(
6638        self,
6639        fs: Arc<dyn Fs>,
6640        language_server_id: LanguageServerId,
6641        cx: &mut ModelContext<LspStore>,
6642    ) -> Model<LanguageServerWatchedPaths> {
6643        let project = cx.weak_model();
6644
6645        cx.new_model(|cx| {
6646            let this_id = cx.entity_id();
6647            const LSP_ABS_PATH_OBSERVE: Duration = Duration::from_millis(100);
6648            let abs_paths = self
6649                .abs_paths
6650                .into_iter()
6651                .map(|(abs_path, globset)| {
6652                    let task = cx.spawn({
6653                        let abs_path = abs_path.clone();
6654                        let fs = fs.clone();
6655
6656                        let lsp_store = project.clone();
6657                        |_, mut cx| async move {
6658                            maybe!(async move {
6659                                let mut push_updates =
6660                                    fs.watch(&abs_path, LSP_ABS_PATH_OBSERVE).await;
6661                                while let Some(update) = push_updates.0.next().await {
6662                                    let action = lsp_store
6663                                        .update(&mut cx, |this, cx| {
6664                                            let Some(local) = this.as_local() else {
6665                                                return ControlFlow::Break(());
6666                                            };
6667                                            let Some(watcher) = local
6668                                                .language_server_watched_paths
6669                                                .get(&language_server_id)
6670                                            else {
6671                                                return ControlFlow::Break(());
6672                                            };
6673                                            if watcher.entity_id() != this_id {
6674                                                // This watcher is no longer registered on the project, which means that we should
6675                                                // cease operations.
6676                                                return ControlFlow::Break(());
6677                                            }
6678                                            let (globs, _) = watcher
6679                                                .read(cx)
6680                                                .abs_paths
6681                                                .get(&abs_path)
6682                                                .expect(
6683                                                "Watched abs path is not registered with a watcher",
6684                                            );
6685                                            let matching_entries = update
6686                                                .into_iter()
6687                                                .filter(|event| globs.is_match(&event.path))
6688                                                .collect::<Vec<_>>();
6689                                            this.lsp_notify_abs_paths_changed(
6690                                                language_server_id,
6691                                                matching_entries,
6692                                            );
6693                                            ControlFlow::Continue(())
6694                                        })
6695                                        .ok()?;
6696
6697                                    if action.is_break() {
6698                                        break;
6699                                    }
6700                                }
6701                                Some(())
6702                            })
6703                            .await;
6704                        }
6705                    });
6706                    (abs_path, (globset, task))
6707                })
6708                .collect();
6709            LanguageServerWatchedPaths {
6710                worktree_paths: self.worktree_paths,
6711                abs_paths,
6712            }
6713        })
6714    }
6715}
6716
6717struct LspBufferSnapshot {
6718    version: i32,
6719    snapshot: TextBufferSnapshot,
6720}
6721
6722/// A prompt requested by LSP server.
6723#[derive(Clone, Debug)]
6724pub struct LanguageServerPromptRequest {
6725    pub level: PromptLevel,
6726    pub message: String,
6727    pub actions: Vec<MessageActionItem>,
6728    pub lsp_name: String,
6729    pub(crate) response_channel: Sender<MessageActionItem>,
6730}
6731
6732impl LanguageServerPromptRequest {
6733    pub async fn respond(self, index: usize) -> Option<()> {
6734        if let Some(response) = self.actions.into_iter().nth(index) {
6735            self.response_channel.send(response).await.ok()
6736        } else {
6737            None
6738        }
6739    }
6740}
6741impl PartialEq for LanguageServerPromptRequest {
6742    fn eq(&self, other: &Self) -> bool {
6743        self.message == other.message && self.actions == other.actions
6744    }
6745}
6746
6747#[derive(Clone, Debug, PartialEq)]
6748pub enum LanguageServerLogType {
6749    Log(MessageType),
6750    Trace(Option<String>),
6751}
6752
6753pub enum LanguageServerState {
6754    Starting(Task<Option<Arc<LanguageServer>>>),
6755
6756    Running {
6757        language: LanguageName,
6758        adapter: Arc<CachedLspAdapter>,
6759        server: Arc<LanguageServer>,
6760        simulate_disk_based_diagnostics_completion: Option<Task<()>>,
6761    },
6762}
6763
6764impl std::fmt::Debug for LanguageServerState {
6765    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6766        match self {
6767            LanguageServerState::Starting(_) => {
6768                f.debug_struct("LanguageServerState::Starting").finish()
6769            }
6770            LanguageServerState::Running { language, .. } => f
6771                .debug_struct("LanguageServerState::Running")
6772                .field("language", &language)
6773                .finish(),
6774        }
6775    }
6776}
6777
6778#[derive(Clone, Debug, Serialize)]
6779pub struct LanguageServerProgress {
6780    pub is_disk_based_diagnostics_progress: bool,
6781    pub is_cancellable: bool,
6782    pub title: Option<String>,
6783    pub message: Option<String>,
6784    pub percentage: Option<usize>,
6785    #[serde(skip_serializing)]
6786    pub last_update_at: Instant,
6787}
6788
6789#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize)]
6790pub struct DiagnosticSummary {
6791    pub error_count: usize,
6792    pub warning_count: usize,
6793}
6794
6795impl DiagnosticSummary {
6796    pub fn new<'a, T: 'a>(diagnostics: impl IntoIterator<Item = &'a DiagnosticEntry<T>>) -> Self {
6797        let mut this = Self {
6798            error_count: 0,
6799            warning_count: 0,
6800        };
6801
6802        for entry in diagnostics {
6803            if entry.diagnostic.is_primary {
6804                match entry.diagnostic.severity {
6805                    DiagnosticSeverity::ERROR => this.error_count += 1,
6806                    DiagnosticSeverity::WARNING => this.warning_count += 1,
6807                    _ => {}
6808                }
6809            }
6810        }
6811
6812        this
6813    }
6814
6815    pub fn is_empty(&self) -> bool {
6816        self.error_count == 0 && self.warning_count == 0
6817    }
6818
6819    pub fn to_proto(
6820        &self,
6821        language_server_id: LanguageServerId,
6822        path: &Path,
6823    ) -> proto::DiagnosticSummary {
6824        proto::DiagnosticSummary {
6825            path: path.to_string_lossy().to_string(),
6826            language_server_id: language_server_id.0 as u64,
6827            error_count: self.error_count as u32,
6828            warning_count: self.warning_count as u32,
6829        }
6830    }
6831}
6832
6833fn glob_literal_prefix(glob: &str) -> &str {
6834    let is_absolute = glob.starts_with(path::MAIN_SEPARATOR);
6835
6836    let mut literal_end = is_absolute as usize;
6837    for (i, part) in glob.split(path::MAIN_SEPARATOR).enumerate() {
6838        if part.contains(['*', '?', '{', '}']) {
6839            break;
6840        } else {
6841            if i > 0 {
6842                // Account for separator prior to this part
6843                literal_end += path::MAIN_SEPARATOR.len_utf8();
6844            }
6845            literal_end += part.len();
6846        }
6847    }
6848    let literal_end = literal_end.min(glob.len());
6849    &glob[..literal_end]
6850}
6851
6852pub struct SshLspAdapter {
6853    name: LanguageServerName,
6854    binary: LanguageServerBinary,
6855    initialization_options: Option<String>,
6856    code_action_kinds: Option<Vec<CodeActionKind>>,
6857}
6858
6859impl SshLspAdapter {
6860    pub fn new(
6861        name: LanguageServerName,
6862        binary: LanguageServerBinary,
6863        initialization_options: Option<String>,
6864        code_action_kinds: Option<String>,
6865    ) -> Self {
6866        Self {
6867            name,
6868            binary,
6869            initialization_options,
6870            code_action_kinds: code_action_kinds
6871                .as_ref()
6872                .and_then(|c| serde_json::from_str(c).ok()),
6873        }
6874    }
6875}
6876
6877#[async_trait(?Send)]
6878impl LspAdapter for SshLspAdapter {
6879    fn name(&self) -> LanguageServerName {
6880        self.name.clone()
6881    }
6882
6883    async fn initialization_options(
6884        self: Arc<Self>,
6885        _: &Arc<dyn LspAdapterDelegate>,
6886    ) -> Result<Option<serde_json::Value>> {
6887        let Some(options) = &self.initialization_options else {
6888            return Ok(None);
6889        };
6890        let result = serde_json::from_str(options)?;
6891        Ok(result)
6892    }
6893
6894    fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
6895        self.code_action_kinds.clone()
6896    }
6897
6898    async fn check_if_user_installed(
6899        &self,
6900        _: &dyn LspAdapterDelegate,
6901        _: &AsyncAppContext,
6902    ) -> Option<LanguageServerBinary> {
6903        Some(self.binary.clone())
6904    }
6905
6906    async fn cached_server_binary(
6907        &self,
6908        _: PathBuf,
6909        _: &dyn LspAdapterDelegate,
6910    ) -> Option<LanguageServerBinary> {
6911        None
6912    }
6913
6914    async fn fetch_latest_server_version(
6915        &self,
6916        _: &dyn LspAdapterDelegate,
6917    ) -> Result<Box<dyn 'static + Send + Any>> {
6918        anyhow::bail!("SshLspAdapter does not support fetch_latest_server_version")
6919    }
6920
6921    async fn fetch_server_binary(
6922        &self,
6923        _: Box<dyn 'static + Send + Any>,
6924        _: PathBuf,
6925        _: &dyn LspAdapterDelegate,
6926    ) -> Result<LanguageServerBinary> {
6927        anyhow::bail!("SshLspAdapter does not support fetch_server_binary")
6928    }
6929
6930    async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
6931        None
6932    }
6933}
6934
6935pub struct ProjectLspAdapterDelegate {
6936    lsp_store: WeakModel<LspStore>,
6937    worktree: worktree::Snapshot,
6938    fs: Option<Arc<dyn Fs>>,
6939    http_client: Arc<dyn HttpClient>,
6940    language_registry: Arc<LanguageRegistry>,
6941    load_shell_env_task: Shared<Task<Option<HashMap<String, String>>>>,
6942    upstream_client: Option<AnyProtoClient>,
6943}
6944
6945impl ProjectLspAdapterDelegate {
6946    fn for_local(
6947        lsp_store: &LspStore,
6948        worktree: &Model<Worktree>,
6949        cx: &mut ModelContext<LspStore>,
6950    ) -> Arc<Self> {
6951        let local = lsp_store
6952            .as_local()
6953            .expect("ProjectLspAdapterDelegate cannot be constructed on a remote");
6954
6955        let http_client = local
6956            .http_client
6957            .clone()
6958            .unwrap_or_else(|| Arc::new(BlockedHttpClient));
6959
6960        Self::new(
6961            lsp_store,
6962            worktree,
6963            http_client,
6964            Some(local.fs.clone()),
6965            None,
6966            cx,
6967        )
6968    }
6969
6970    fn for_ssh(
6971        lsp_store: &LspStore,
6972        worktree: &Model<Worktree>,
6973        upstream_client: AnyProtoClient,
6974        cx: &mut ModelContext<LspStore>,
6975    ) -> Arc<Self> {
6976        Self::new(
6977            lsp_store,
6978            worktree,
6979            Arc::new(BlockedHttpClient),
6980            None,
6981            Some(upstream_client),
6982            cx,
6983        )
6984    }
6985
6986    pub fn new(
6987        lsp_store: &LspStore,
6988        worktree: &Model<Worktree>,
6989        http_client: Arc<dyn HttpClient>,
6990        fs: Option<Arc<dyn Fs>>,
6991        upstream_client: Option<AnyProtoClient>,
6992        cx: &mut ModelContext<LspStore>,
6993    ) -> Arc<Self> {
6994        let worktree_id = worktree.read(cx).id();
6995        let worktree_abs_path = worktree.read(cx).abs_path();
6996        let load_shell_env_task = if let Some(environment) =
6997            &lsp_store.as_local().map(|local| local.environment.clone())
6998        {
6999            environment.update(cx, |env, cx| {
7000                env.get_environment(Some(worktree_id), Some(worktree_abs_path), cx)
7001            })
7002        } else {
7003            Task::ready(None).shared()
7004        };
7005
7006        Arc::new(Self {
7007            lsp_store: cx.weak_model(),
7008            worktree: worktree.read(cx).snapshot(),
7009            fs,
7010            http_client,
7011            upstream_client,
7012            language_registry: lsp_store.languages.clone(),
7013            load_shell_env_task,
7014        })
7015    }
7016}
7017
7018struct BlockedHttpClient;
7019
7020impl HttpClient for BlockedHttpClient {
7021    fn send(
7022        &self,
7023        _req: Request<AsyncBody>,
7024    ) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
7025        Box::pin(async {
7026            Err(std::io::Error::new(
7027                std::io::ErrorKind::PermissionDenied,
7028                "ssh host blocked http connection",
7029            )
7030            .into())
7031        })
7032    }
7033
7034    fn proxy(&self) -> Option<&Uri> {
7035        None
7036    }
7037}
7038
7039pub fn language_server_settings<'a, 'b: 'a>(
7040    delegate: &'a dyn LspAdapterDelegate,
7041    language: &str,
7042    cx: &'b AppContext,
7043) -> Option<&'a LspSettings> {
7044    ProjectSettings::get(
7045        Some(SettingsLocation {
7046            worktree_id: delegate.worktree_id(),
7047            path: delegate.worktree_root_path(),
7048        }),
7049        cx,
7050    )
7051    .lsp
7052    .get(language)
7053}
7054
7055#[async_trait]
7056impl LspAdapterDelegate for ProjectLspAdapterDelegate {
7057    fn show_notification(&self, message: &str, cx: &mut AppContext) {
7058        self.lsp_store
7059            .update(cx, |_, cx| {
7060                cx.emit(LspStoreEvent::Notification(message.to_owned()))
7061            })
7062            .ok();
7063    }
7064
7065    fn http_client(&self) -> Arc<dyn HttpClient> {
7066        self.http_client.clone()
7067    }
7068
7069    fn worktree_id(&self) -> WorktreeId {
7070        self.worktree.id()
7071    }
7072
7073    fn worktree_root_path(&self) -> &Path {
7074        self.worktree.abs_path().as_ref()
7075    }
7076
7077    async fn shell_env(&self) -> HashMap<String, String> {
7078        if let Some(upstream_client) = &self.upstream_client {
7079            use rpc::proto::SSH_PROJECT_ID;
7080
7081            return upstream_client
7082                .request(proto::ShellEnv {
7083                    project_id: SSH_PROJECT_ID,
7084                    worktree_id: self.worktree_id().to_proto(),
7085                })
7086                .await
7087                .map(|response| response.env.into_iter().collect())
7088                .unwrap_or_default();
7089        }
7090
7091        let task = self.load_shell_env_task.clone();
7092        task.await.unwrap_or_default()
7093    }
7094
7095    #[cfg(not(target_os = "windows"))]
7096    async fn which(&self, command: &OsStr) -> Option<PathBuf> {
7097        if let Some(upstream_client) = &self.upstream_client {
7098            use rpc::proto::SSH_PROJECT_ID;
7099
7100            return upstream_client
7101                .request(proto::WhichCommand {
7102                    project_id: SSH_PROJECT_ID,
7103                    worktree_id: self.worktree_id().to_proto(),
7104                    command: command.to_string_lossy().to_string(),
7105                })
7106                .await
7107                .log_err()
7108                .and_then(|response| response.path)
7109                .map(PathBuf::from);
7110        }
7111
7112        self.fs.as_ref()?;
7113
7114        let worktree_abs_path = self.worktree.abs_path();
7115        let shell_path = self.shell_env().await.get("PATH").cloned();
7116        which::which_in(command, shell_path.as_ref(), worktree_abs_path).ok()
7117    }
7118
7119    #[cfg(target_os = "windows")]
7120    async fn which(&self, command: &OsStr) -> Option<PathBuf> {
7121        self.fs.as_ref()?;
7122
7123        // todo(windows) Getting the shell env variables in a current directory on Windows is more complicated than other platforms
7124        //               there isn't a 'default shell' necessarily. The closest would be the default profile on the windows terminal
7125        //               SEE: https://learn.microsoft.com/en-us/windows/terminal/customize-settings/startup
7126        which::which(command).ok()
7127    }
7128
7129    fn update_status(
7130        &self,
7131        server_name: LanguageServerName,
7132        status: language::LanguageServerBinaryStatus,
7133    ) {
7134        self.language_registry
7135            .update_lsp_status(server_name, status);
7136    }
7137
7138    async fn read_text_file(&self, path: PathBuf) -> Result<String> {
7139        if self.worktree.entry_for_path(&path).is_none() {
7140            return Err(anyhow!("no such path {path:?}"));
7141        };
7142        if let Some(fs) = &self.fs {
7143            let content = fs.load(&path).await?;
7144            Ok(content)
7145        } else {
7146            return Err(anyhow!("cannot open {path:?} on ssh host (yet!)"));
7147        }
7148    }
7149}
7150
7151async fn populate_labels_for_symbols(
7152    symbols: Vec<CoreSymbol>,
7153    language_registry: &Arc<LanguageRegistry>,
7154    default_language: Option<LanguageName>,
7155    lsp_adapter: Option<Arc<CachedLspAdapter>>,
7156    output: &mut Vec<Symbol>,
7157) {
7158    #[allow(clippy::mutable_key_type)]
7159    let mut symbols_by_language = HashMap::<Option<Arc<Language>>, Vec<CoreSymbol>>::default();
7160
7161    let mut unknown_path = None;
7162    for symbol in symbols {
7163        let language = language_registry
7164            .language_for_file_path(&symbol.path.path)
7165            .await
7166            .ok()
7167            .or_else(|| {
7168                unknown_path.get_or_insert(symbol.path.path.clone());
7169                default_language.as_ref().and_then(|name| {
7170                    language_registry
7171                        .language_for_name(&name.0)
7172                        .now_or_never()?
7173                        .ok()
7174                })
7175            });
7176        symbols_by_language
7177            .entry(language)
7178            .or_default()
7179            .push(symbol);
7180    }
7181
7182    if let Some(unknown_path) = unknown_path {
7183        log::info!(
7184            "no language found for symbol path {}",
7185            unknown_path.display()
7186        );
7187    }
7188
7189    let mut label_params = Vec::new();
7190    for (language, mut symbols) in symbols_by_language {
7191        label_params.clear();
7192        label_params.extend(
7193            symbols
7194                .iter_mut()
7195                .map(|symbol| (mem::take(&mut symbol.name), symbol.kind)),
7196        );
7197
7198        let mut labels = Vec::new();
7199        if let Some(language) = language {
7200            let lsp_adapter = lsp_adapter.clone().or_else(|| {
7201                language_registry
7202                    .lsp_adapters(&language.name())
7203                    .first()
7204                    .cloned()
7205            });
7206            if let Some(lsp_adapter) = lsp_adapter {
7207                labels = lsp_adapter
7208                    .labels_for_symbols(&label_params, &language)
7209                    .await
7210                    .log_err()
7211                    .unwrap_or_default();
7212            }
7213        }
7214
7215        for ((symbol, (name, _)), label) in symbols
7216            .into_iter()
7217            .zip(label_params.drain(..))
7218            .zip(labels.into_iter().chain(iter::repeat(None)))
7219        {
7220            output.push(Symbol {
7221                language_server_name: symbol.language_server_name,
7222                source_worktree_id: symbol.source_worktree_id,
7223                path: symbol.path,
7224                label: label.unwrap_or_else(|| CodeLabel::plain(name.clone(), None)),
7225                name,
7226                kind: symbol.kind,
7227                range: symbol.range,
7228                signature: symbol.signature,
7229            });
7230        }
7231    }
7232}
7233
7234fn include_text(server: &lsp::LanguageServer) -> Option<bool> {
7235    match server.capabilities().text_document_sync.as_ref()? {
7236        lsp::TextDocumentSyncCapability::Kind(kind) => match *kind {
7237            lsp::TextDocumentSyncKind::NONE => None,
7238            lsp::TextDocumentSyncKind::FULL => Some(true),
7239            lsp::TextDocumentSyncKind::INCREMENTAL => Some(false),
7240            _ => None,
7241        },
7242        lsp::TextDocumentSyncCapability::Options(options) => match options.save.as_ref()? {
7243            lsp::TextDocumentSyncSaveOptions::Supported(supported) => {
7244                if *supported {
7245                    Some(true)
7246                } else {
7247                    None
7248                }
7249            }
7250            lsp::TextDocumentSyncSaveOptions::SaveOptions(save_options) => {
7251                Some(save_options.include_text.unwrap_or(false))
7252            }
7253        },
7254    }
7255}
7256
7257#[cfg(test)]
7258#[test]
7259fn test_glob_literal_prefix() {
7260    assert_eq!(glob_literal_prefix("**/*.js"), "");
7261    assert_eq!(glob_literal_prefix("node_modules/**/*.js"), "node_modules");
7262    assert_eq!(glob_literal_prefix("foo/{bar,baz}.js"), "foo");
7263    assert_eq!(glob_literal_prefix("foo/bar/baz.js"), "foo/bar/baz.js");
7264}