lsp_store.rs

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