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