lsp_command.rs

   1pub mod signature_help;
   2
   3use crate::{
   4    CodeAction, CompletionSource, CoreCompletion, CoreCompletionResponse, DocumentColor,
   5    DocumentHighlight, DocumentSymbol, Hover, HoverBlock, HoverBlockKind, InlayHint,
   6    InlayHintLabel, InlayHintLabelPart, InlayHintLabelPartTooltip, InlayHintTooltip, Location,
   7    LocationLink, LspAction, LspPullDiagnostics, MarkupContent, PrepareRenameResponse,
   8    ProjectTransaction, PulledDiagnostics, ResolveState,
   9    lsp_store::{LocalLspStore, LspFoldingRange, LspStore},
  10};
  11use anyhow::{Context as _, Result};
  12use async_trait::async_trait;
  13use client::proto::{self, PeerId};
  14use clock::Global;
  15use collections::HashMap;
  16use futures::future;
  17use gpui::{App, AsyncApp, Entity, SharedString, Task, prelude::FluentBuilder};
  18use language::{
  19    Anchor, Bias, Buffer, BufferSnapshot, CachedLspAdapter, CharKind, CharScopeContext,
  20    OffsetRangeExt, PointUtf16, ToOffset, ToPointUtf16, Transaction, Unclipped,
  21    language_settings::{InlayHintKind, LanguageSettings, language_settings},
  22    point_from_lsp, point_to_lsp,
  23    proto::{
  24        deserialize_anchor, deserialize_anchor_range, deserialize_version, serialize_anchor,
  25        serialize_anchor_range, serialize_version,
  26    },
  27    range_from_lsp, range_to_lsp,
  28};
  29use lsp::{
  30    AdapterServerCapabilities, CodeActionKind, CodeActionOptions, CodeDescription,
  31    CompletionContext, CompletionListItemDefaultsEditRange, CompletionTriggerKind,
  32    DocumentHighlightKind, LanguageServer, LanguageServerId, LinkedEditingRangeServerCapabilities,
  33    OneOf, RenameOptions, ServerCapabilities,
  34};
  35use serde_json::Value;
  36use signature_help::{lsp_to_proto_signature, proto_to_lsp_signature};
  37use std::{
  38    cmp::Reverse, collections::hash_map, mem, ops::Range, path::Path, str::FromStr, sync::Arc,
  39};
  40use text::{BufferId, LineEnding};
  41use util::{ResultExt as _, debug_panic};
  42
  43pub use signature_help::SignatureHelp;
  44
  45fn code_action_kind_matches(requested: &lsp::CodeActionKind, actual: &lsp::CodeActionKind) -> bool {
  46    let requested_str = requested.as_str();
  47    let actual_str = actual.as_str();
  48
  49    // Exact match or hierarchical match
  50    actual_str == requested_str
  51        || actual_str
  52            .strip_prefix(requested_str)
  53            .is_some_and(|suffix| suffix.starts_with('.'))
  54}
  55
  56pub fn lsp_formatting_options(settings: &LanguageSettings) -> lsp::FormattingOptions {
  57    lsp::FormattingOptions {
  58        tab_size: settings.tab_size.into(),
  59        insert_spaces: !settings.hard_tabs,
  60        trim_trailing_whitespace: Some(settings.remove_trailing_whitespace_on_save),
  61        trim_final_newlines: Some(settings.ensure_final_newline_on_save),
  62        insert_final_newline: Some(settings.ensure_final_newline_on_save),
  63        ..lsp::FormattingOptions::default()
  64    }
  65}
  66
  67pub fn file_path_to_lsp_url(path: &Path) -> Result<lsp::Uri> {
  68    match lsp::Uri::from_file_path(path) {
  69        Ok(url) => Ok(url),
  70        Err(()) => anyhow::bail!("Invalid file path provided to LSP request: {path:?}"),
  71    }
  72}
  73
  74pub(crate) fn make_text_document_identifier(path: &Path) -> Result<lsp::TextDocumentIdentifier> {
  75    Ok(lsp::TextDocumentIdentifier {
  76        uri: file_path_to_lsp_url(path)?,
  77    })
  78}
  79
  80pub(crate) fn make_lsp_text_document_position(
  81    path: &Path,
  82    position: PointUtf16,
  83) -> Result<lsp::TextDocumentPositionParams> {
  84    Ok(lsp::TextDocumentPositionParams {
  85        text_document: make_text_document_identifier(path)?,
  86        position: point_to_lsp(position),
  87    })
  88}
  89
  90#[async_trait(?Send)]
  91pub trait LspCommand: 'static + Sized + Send + std::fmt::Debug {
  92    type Response: 'static + Default + Send + std::fmt::Debug;
  93    type LspRequest: 'static + Send + lsp::request::Request;
  94    type ProtoRequest: 'static + Send + proto::RequestMessage;
  95
  96    fn display_name(&self) -> &str;
  97
  98    fn status(&self) -> Option<String> {
  99        None
 100    }
 101
 102    fn to_lsp_params_or_response(
 103        &self,
 104        path: &Path,
 105        buffer: &Buffer,
 106        language_server: &Arc<LanguageServer>,
 107        cx: &App,
 108    ) -> Result<
 109        LspParamsOrResponse<<Self::LspRequest as lsp::request::Request>::Params, Self::Response>,
 110    > {
 111        if self.check_capabilities(language_server.adapter_server_capabilities()) {
 112            Ok(LspParamsOrResponse::Params(self.to_lsp(
 113                path,
 114                buffer,
 115                language_server,
 116                cx,
 117            )?))
 118        } else {
 119            Ok(LspParamsOrResponse::Response(Default::default()))
 120        }
 121    }
 122
 123    /// When false, `to_lsp_params_or_response` default implementation will return the default response.
 124    fn check_capabilities(&self, _: AdapterServerCapabilities) -> bool;
 125
 126    fn to_lsp(
 127        &self,
 128        path: &Path,
 129        buffer: &Buffer,
 130        language_server: &Arc<LanguageServer>,
 131        cx: &App,
 132    ) -> Result<<Self::LspRequest as lsp::request::Request>::Params>;
 133
 134    async fn response_from_lsp(
 135        self,
 136        message: <Self::LspRequest as lsp::request::Request>::Result,
 137        lsp_store: Entity<LspStore>,
 138        buffer: Entity<Buffer>,
 139        server_id: LanguageServerId,
 140        cx: AsyncApp,
 141    ) -> Result<Self::Response>;
 142
 143    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest;
 144
 145    async fn from_proto(
 146        message: Self::ProtoRequest,
 147        lsp_store: Entity<LspStore>,
 148        buffer: Entity<Buffer>,
 149        cx: AsyncApp,
 150    ) -> Result<Self>;
 151
 152    fn response_to_proto(
 153        response: Self::Response,
 154        lsp_store: &mut LspStore,
 155        peer_id: PeerId,
 156        buffer_version: &clock::Global,
 157        cx: &mut App,
 158    ) -> <Self::ProtoRequest as proto::RequestMessage>::Response;
 159
 160    async fn response_from_proto(
 161        self,
 162        message: <Self::ProtoRequest as proto::RequestMessage>::Response,
 163        lsp_store: Entity<LspStore>,
 164        buffer: Entity<Buffer>,
 165        cx: AsyncApp,
 166    ) -> Result<Self::Response>;
 167
 168    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId>;
 169}
 170
 171pub enum LspParamsOrResponse<P, R> {
 172    Params(P),
 173    Response(R),
 174}
 175
 176#[derive(Debug)]
 177pub(crate) struct PrepareRename {
 178    pub position: PointUtf16,
 179}
 180
 181#[derive(Debug)]
 182pub(crate) struct PerformRename {
 183    pub position: PointUtf16,
 184    pub new_name: String,
 185    pub push_to_history: bool,
 186}
 187
 188#[derive(Debug, Clone, Copy)]
 189pub struct GetDefinitions {
 190    pub position: PointUtf16,
 191}
 192
 193#[derive(Debug, Clone, Copy)]
 194pub(crate) struct GetDeclarations {
 195    pub position: PointUtf16,
 196}
 197
 198#[derive(Debug, Clone, Copy)]
 199pub(crate) struct GetTypeDefinitions {
 200    pub position: PointUtf16,
 201}
 202
 203#[derive(Debug, Clone, Copy)]
 204pub(crate) struct GetImplementations {
 205    pub position: PointUtf16,
 206}
 207
 208#[derive(Debug, Clone, Copy)]
 209pub(crate) struct GetReferences {
 210    pub position: PointUtf16,
 211}
 212
 213#[derive(Debug)]
 214pub(crate) struct GetDocumentHighlights {
 215    pub position: PointUtf16,
 216}
 217
 218#[derive(Debug, Copy, Clone)]
 219pub(crate) struct GetDocumentSymbols;
 220
 221#[derive(Clone, Debug)]
 222pub(crate) struct GetSignatureHelp {
 223    pub position: PointUtf16,
 224}
 225
 226#[derive(Clone, Debug)]
 227pub(crate) struct GetHover {
 228    pub position: PointUtf16,
 229}
 230
 231#[derive(Debug)]
 232pub(crate) struct GetCompletions {
 233    pub position: PointUtf16,
 234    pub context: CompletionContext,
 235    pub server_id: Option<lsp::LanguageServerId>,
 236}
 237
 238#[derive(Clone, Debug)]
 239pub(crate) struct GetCodeActions {
 240    pub range: Range<Anchor>,
 241    pub kinds: Option<Vec<lsp::CodeActionKind>>,
 242}
 243
 244#[derive(Debug)]
 245pub(crate) struct OnTypeFormatting {
 246    pub position: PointUtf16,
 247    pub trigger: String,
 248    pub options: lsp::FormattingOptions,
 249    pub push_to_history: bool,
 250}
 251
 252#[derive(Clone, Debug)]
 253pub(crate) struct InlayHints {
 254    pub range: Range<Anchor>,
 255}
 256
 257#[derive(Debug, Clone, Copy)]
 258pub(crate) struct SemanticTokensFull {
 259    pub for_server: Option<LanguageServerId>,
 260}
 261
 262#[derive(Debug, Clone)]
 263pub(crate) struct SemanticTokensDelta {
 264    pub previous_result_id: SharedString,
 265}
 266
 267#[derive(Debug)]
 268pub(crate) enum SemanticTokensResponse {
 269    Full {
 270        data: Vec<u32>,
 271        result_id: Option<SharedString>,
 272    },
 273    Delta {
 274        edits: Vec<SemanticTokensEdit>,
 275        result_id: Option<SharedString>,
 276    },
 277}
 278
 279impl Default for SemanticTokensResponse {
 280    fn default() -> Self {
 281        Self::Delta {
 282            edits: Vec::new(),
 283            result_id: None,
 284        }
 285    }
 286}
 287
 288#[derive(Debug)]
 289pub(crate) struct SemanticTokensEdit {
 290    pub start: u32,
 291    pub delete_count: u32,
 292    pub data: Vec<u32>,
 293}
 294
 295#[derive(Debug, Copy, Clone)]
 296pub(crate) struct GetCodeLens;
 297
 298#[derive(Debug, Copy, Clone)]
 299pub(crate) struct GetDocumentColor;
 300
 301#[derive(Debug, Copy, Clone)]
 302pub(crate) struct GetFoldingRanges;
 303
 304impl GetCodeLens {
 305    pub(crate) fn can_resolve_lens(capabilities: &ServerCapabilities) -> bool {
 306        capabilities
 307            .code_lens_provider
 308            .as_ref()
 309            .and_then(|code_lens_options| code_lens_options.resolve_provider)
 310            .unwrap_or(false)
 311    }
 312}
 313
 314#[derive(Debug)]
 315pub(crate) struct LinkedEditingRange {
 316    pub position: Anchor,
 317}
 318
 319#[derive(Clone, Debug)]
 320pub struct GetDocumentDiagnostics {
 321    /// We cannot blindly rely on server's capabilities.diagnostic_provider, as they're a singular field, whereas
 322    /// a server can register multiple diagnostic providers post-mortem.
 323    pub registration_id: Option<SharedString>,
 324    pub identifier: Option<SharedString>,
 325    pub previous_result_id: Option<SharedString>,
 326}
 327
 328#[async_trait(?Send)]
 329impl LspCommand for PrepareRename {
 330    type Response = PrepareRenameResponse;
 331    type LspRequest = lsp::request::PrepareRenameRequest;
 332    type ProtoRequest = proto::PrepareRename;
 333
 334    fn display_name(&self) -> &str {
 335        "Prepare rename"
 336    }
 337
 338    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 339        capabilities
 340            .server_capabilities
 341            .rename_provider
 342            .is_some_and(|capability| match capability {
 343                OneOf::Left(enabled) => enabled,
 344                OneOf::Right(options) => options.prepare_provider.unwrap_or(false),
 345            })
 346    }
 347
 348    fn to_lsp_params_or_response(
 349        &self,
 350        path: &Path,
 351        buffer: &Buffer,
 352        language_server: &Arc<LanguageServer>,
 353        cx: &App,
 354    ) -> Result<LspParamsOrResponse<lsp::TextDocumentPositionParams, PrepareRenameResponse>> {
 355        let rename_provider = language_server
 356            .adapter_server_capabilities()
 357            .server_capabilities
 358            .rename_provider;
 359        match rename_provider {
 360            Some(lsp::OneOf::Right(RenameOptions {
 361                prepare_provider: Some(true),
 362                ..
 363            })) => Ok(LspParamsOrResponse::Params(self.to_lsp(
 364                path,
 365                buffer,
 366                language_server,
 367                cx,
 368            )?)),
 369            Some(lsp::OneOf::Right(_)) => Ok(LspParamsOrResponse::Response(
 370                PrepareRenameResponse::OnlyUnpreparedRenameSupported,
 371            )),
 372            Some(lsp::OneOf::Left(true)) => Ok(LspParamsOrResponse::Response(
 373                PrepareRenameResponse::OnlyUnpreparedRenameSupported,
 374            )),
 375            _ => anyhow::bail!("Rename not supported"),
 376        }
 377    }
 378
 379    fn to_lsp(
 380        &self,
 381        path: &Path,
 382        _: &Buffer,
 383        _: &Arc<LanguageServer>,
 384        _: &App,
 385    ) -> Result<lsp::TextDocumentPositionParams> {
 386        make_lsp_text_document_position(path, self.position)
 387    }
 388
 389    async fn response_from_lsp(
 390        self,
 391        message: Option<lsp::PrepareRenameResponse>,
 392        _: Entity<LspStore>,
 393        buffer: Entity<Buffer>,
 394        _: LanguageServerId,
 395        cx: AsyncApp,
 396    ) -> Result<PrepareRenameResponse> {
 397        buffer.read_with(&cx, |buffer, _| match message {
 398            Some(lsp::PrepareRenameResponse::Range(range))
 399            | Some(lsp::PrepareRenameResponse::RangeWithPlaceholder { range, .. }) => {
 400                let Range { start, end } = range_from_lsp(range);
 401                if buffer.clip_point_utf16(start, Bias::Left) == start.0
 402                    && buffer.clip_point_utf16(end, Bias::Left) == end.0
 403                {
 404                    Ok(PrepareRenameResponse::Success(
 405                        buffer.anchor_after(start)..buffer.anchor_before(end),
 406                    ))
 407                } else {
 408                    Ok(PrepareRenameResponse::InvalidPosition)
 409                }
 410            }
 411            Some(lsp::PrepareRenameResponse::DefaultBehavior { .. }) => {
 412                let snapshot = buffer.snapshot();
 413                let (range, _) = snapshot.surrounding_word(self.position, None);
 414                let range = snapshot.anchor_after(range.start)..snapshot.anchor_before(range.end);
 415                Ok(PrepareRenameResponse::Success(range))
 416            }
 417            None => Ok(PrepareRenameResponse::InvalidPosition),
 418        })
 419    }
 420
 421    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::PrepareRename {
 422        proto::PrepareRename {
 423            project_id,
 424            buffer_id: buffer.remote_id().into(),
 425            position: Some(language::proto::serialize_anchor(
 426                &buffer.anchor_before(self.position),
 427            )),
 428            version: serialize_version(&buffer.version()),
 429        }
 430    }
 431
 432    async fn from_proto(
 433        message: proto::PrepareRename,
 434        _: Entity<LspStore>,
 435        buffer: Entity<Buffer>,
 436        mut cx: AsyncApp,
 437    ) -> Result<Self> {
 438        let position = message
 439            .position
 440            .and_then(deserialize_anchor)
 441            .context("invalid position")?;
 442        buffer
 443            .update(&mut cx, |buffer, _| {
 444                buffer.wait_for_version(deserialize_version(&message.version))
 445            })
 446            .await?;
 447
 448        Ok(Self {
 449            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 450        })
 451    }
 452
 453    fn response_to_proto(
 454        response: PrepareRenameResponse,
 455        _: &mut LspStore,
 456        _: PeerId,
 457        buffer_version: &clock::Global,
 458        _: &mut App,
 459    ) -> proto::PrepareRenameResponse {
 460        match response {
 461            PrepareRenameResponse::Success(range) => proto::PrepareRenameResponse {
 462                can_rename: true,
 463                only_unprepared_rename_supported: false,
 464                start: Some(language::proto::serialize_anchor(&range.start)),
 465                end: Some(language::proto::serialize_anchor(&range.end)),
 466                version: serialize_version(buffer_version),
 467            },
 468            PrepareRenameResponse::OnlyUnpreparedRenameSupported => proto::PrepareRenameResponse {
 469                can_rename: false,
 470                only_unprepared_rename_supported: true,
 471                start: None,
 472                end: None,
 473                version: vec![],
 474            },
 475            PrepareRenameResponse::InvalidPosition => proto::PrepareRenameResponse {
 476                can_rename: false,
 477                only_unprepared_rename_supported: false,
 478                start: None,
 479                end: None,
 480                version: vec![],
 481            },
 482        }
 483    }
 484
 485    async fn response_from_proto(
 486        self,
 487        message: proto::PrepareRenameResponse,
 488        _: Entity<LspStore>,
 489        buffer: Entity<Buffer>,
 490        mut cx: AsyncApp,
 491    ) -> Result<PrepareRenameResponse> {
 492        if message.can_rename {
 493            buffer
 494                .update(&mut cx, |buffer, _| {
 495                    buffer.wait_for_version(deserialize_version(&message.version))
 496                })
 497                .await?;
 498            if let (Some(start), Some(end)) = (
 499                message.start.and_then(deserialize_anchor),
 500                message.end.and_then(deserialize_anchor),
 501            ) {
 502                Ok(PrepareRenameResponse::Success(start..end))
 503            } else {
 504                anyhow::bail!(
 505                    "Missing start or end position in remote project PrepareRenameResponse"
 506                );
 507            }
 508        } else if message.only_unprepared_rename_supported {
 509            Ok(PrepareRenameResponse::OnlyUnpreparedRenameSupported)
 510        } else {
 511            Ok(PrepareRenameResponse::InvalidPosition)
 512        }
 513    }
 514
 515    fn buffer_id_from_proto(message: &proto::PrepareRename) -> Result<BufferId> {
 516        BufferId::new(message.buffer_id)
 517    }
 518}
 519
 520#[async_trait(?Send)]
 521impl LspCommand for PerformRename {
 522    type Response = ProjectTransaction;
 523    type LspRequest = lsp::request::Rename;
 524    type ProtoRequest = proto::PerformRename;
 525
 526    fn display_name(&self) -> &str {
 527        "Rename"
 528    }
 529
 530    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 531        capabilities
 532            .server_capabilities
 533            .rename_provider
 534            .is_some_and(|capability| match capability {
 535                OneOf::Left(enabled) => enabled,
 536                OneOf::Right(_) => true,
 537            })
 538    }
 539
 540    fn to_lsp(
 541        &self,
 542        path: &Path,
 543        _: &Buffer,
 544        _: &Arc<LanguageServer>,
 545        _: &App,
 546    ) -> Result<lsp::RenameParams> {
 547        Ok(lsp::RenameParams {
 548            text_document_position: make_lsp_text_document_position(path, self.position)?,
 549            new_name: self.new_name.clone(),
 550            work_done_progress_params: Default::default(),
 551        })
 552    }
 553
 554    async fn response_from_lsp(
 555        self,
 556        message: Option<lsp::WorkspaceEdit>,
 557        lsp_store: Entity<LspStore>,
 558        buffer: Entity<Buffer>,
 559        server_id: LanguageServerId,
 560        mut cx: AsyncApp,
 561    ) -> Result<ProjectTransaction> {
 562        if let Some(edit) = message {
 563            let (_, lsp_server) =
 564                language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
 565            LocalLspStore::deserialize_workspace_edit(
 566                lsp_store,
 567                edit,
 568                self.push_to_history,
 569                lsp_server,
 570                &mut cx,
 571            )
 572            .await
 573        } else {
 574            Ok(ProjectTransaction::default())
 575        }
 576    }
 577
 578    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::PerformRename {
 579        proto::PerformRename {
 580            project_id,
 581            buffer_id: buffer.remote_id().into(),
 582            position: Some(language::proto::serialize_anchor(
 583                &buffer.anchor_before(self.position),
 584            )),
 585            new_name: self.new_name.clone(),
 586            version: serialize_version(&buffer.version()),
 587        }
 588    }
 589
 590    async fn from_proto(
 591        message: proto::PerformRename,
 592        _: Entity<LspStore>,
 593        buffer: Entity<Buffer>,
 594        mut cx: AsyncApp,
 595    ) -> Result<Self> {
 596        let position = message
 597            .position
 598            .and_then(deserialize_anchor)
 599            .context("invalid position")?;
 600        buffer
 601            .update(&mut cx, |buffer, _| {
 602                buffer.wait_for_version(deserialize_version(&message.version))
 603            })
 604            .await?;
 605        Ok(Self {
 606            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 607            new_name: message.new_name,
 608            push_to_history: false,
 609        })
 610    }
 611
 612    fn response_to_proto(
 613        response: ProjectTransaction,
 614        lsp_store: &mut LspStore,
 615        peer_id: PeerId,
 616        _: &clock::Global,
 617        cx: &mut App,
 618    ) -> proto::PerformRenameResponse {
 619        let transaction = lsp_store.buffer_store().update(cx, |buffer_store, cx| {
 620            buffer_store.serialize_project_transaction_for_peer(response, peer_id, cx)
 621        });
 622        proto::PerformRenameResponse {
 623            transaction: Some(transaction),
 624        }
 625    }
 626
 627    async fn response_from_proto(
 628        self,
 629        message: proto::PerformRenameResponse,
 630        lsp_store: Entity<LspStore>,
 631        _: Entity<Buffer>,
 632        mut cx: AsyncApp,
 633    ) -> Result<ProjectTransaction> {
 634        let message = message.transaction.context("missing transaction")?;
 635        lsp_store
 636            .update(&mut cx, |lsp_store, cx| {
 637                lsp_store.buffer_store().update(cx, |buffer_store, cx| {
 638                    buffer_store.deserialize_project_transaction(message, self.push_to_history, cx)
 639                })
 640            })
 641            .await
 642    }
 643
 644    fn buffer_id_from_proto(message: &proto::PerformRename) -> Result<BufferId> {
 645        BufferId::new(message.buffer_id)
 646    }
 647}
 648
 649#[async_trait(?Send)]
 650impl LspCommand for GetDefinitions {
 651    type Response = Vec<LocationLink>;
 652    type LspRequest = lsp::request::GotoDefinition;
 653    type ProtoRequest = proto::GetDefinition;
 654
 655    fn display_name(&self) -> &str {
 656        "Get definition"
 657    }
 658
 659    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 660        capabilities
 661            .server_capabilities
 662            .definition_provider
 663            .is_some_and(|capability| match capability {
 664                OneOf::Left(supported) => supported,
 665                OneOf::Right(_options) => true,
 666            })
 667    }
 668
 669    fn to_lsp(
 670        &self,
 671        path: &Path,
 672        _: &Buffer,
 673        _: &Arc<LanguageServer>,
 674        _: &App,
 675    ) -> Result<lsp::GotoDefinitionParams> {
 676        Ok(lsp::GotoDefinitionParams {
 677            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 678            work_done_progress_params: Default::default(),
 679            partial_result_params: Default::default(),
 680        })
 681    }
 682
 683    async fn response_from_lsp(
 684        self,
 685        message: Option<lsp::GotoDefinitionResponse>,
 686        lsp_store: Entity<LspStore>,
 687        buffer: Entity<Buffer>,
 688        server_id: LanguageServerId,
 689        cx: AsyncApp,
 690    ) -> Result<Vec<LocationLink>> {
 691        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
 692    }
 693
 694    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDefinition {
 695        proto::GetDefinition {
 696            project_id,
 697            buffer_id: buffer.remote_id().into(),
 698            position: Some(language::proto::serialize_anchor(
 699                &buffer.anchor_before(self.position),
 700            )),
 701            version: serialize_version(&buffer.version()),
 702        }
 703    }
 704
 705    async fn from_proto(
 706        message: proto::GetDefinition,
 707        _: Entity<LspStore>,
 708        buffer: Entity<Buffer>,
 709        mut cx: AsyncApp,
 710    ) -> Result<Self> {
 711        let position = message
 712            .position
 713            .and_then(deserialize_anchor)
 714            .context("invalid position")?;
 715        buffer
 716            .update(&mut cx, |buffer, _| {
 717                buffer.wait_for_version(deserialize_version(&message.version))
 718            })
 719            .await?;
 720        Ok(Self {
 721            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 722        })
 723    }
 724
 725    fn response_to_proto(
 726        response: Vec<LocationLink>,
 727        lsp_store: &mut LspStore,
 728        peer_id: PeerId,
 729        _: &clock::Global,
 730        cx: &mut App,
 731    ) -> proto::GetDefinitionResponse {
 732        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
 733        proto::GetDefinitionResponse { links }
 734    }
 735
 736    async fn response_from_proto(
 737        self,
 738        message: proto::GetDefinitionResponse,
 739        lsp_store: Entity<LspStore>,
 740        _: Entity<Buffer>,
 741        cx: AsyncApp,
 742    ) -> Result<Vec<LocationLink>> {
 743        location_links_from_proto(message.links, lsp_store, cx).await
 744    }
 745
 746    fn buffer_id_from_proto(message: &proto::GetDefinition) -> Result<BufferId> {
 747        BufferId::new(message.buffer_id)
 748    }
 749}
 750
 751#[async_trait(?Send)]
 752impl LspCommand for GetDeclarations {
 753    type Response = Vec<LocationLink>;
 754    type LspRequest = lsp::request::GotoDeclaration;
 755    type ProtoRequest = proto::GetDeclaration;
 756
 757    fn display_name(&self) -> &str {
 758        "Get declaration"
 759    }
 760
 761    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 762        capabilities
 763            .server_capabilities
 764            .declaration_provider
 765            .is_some_and(|capability| match capability {
 766                lsp::DeclarationCapability::Simple(supported) => supported,
 767                lsp::DeclarationCapability::RegistrationOptions(..) => true,
 768                lsp::DeclarationCapability::Options(..) => true,
 769            })
 770    }
 771
 772    fn to_lsp(
 773        &self,
 774        path: &Path,
 775        _: &Buffer,
 776        _: &Arc<LanguageServer>,
 777        _: &App,
 778    ) -> Result<lsp::GotoDeclarationParams> {
 779        Ok(lsp::GotoDeclarationParams {
 780            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 781            work_done_progress_params: Default::default(),
 782            partial_result_params: Default::default(),
 783        })
 784    }
 785
 786    async fn response_from_lsp(
 787        self,
 788        message: Option<lsp::GotoDeclarationResponse>,
 789        lsp_store: Entity<LspStore>,
 790        buffer: Entity<Buffer>,
 791        server_id: LanguageServerId,
 792        cx: AsyncApp,
 793    ) -> Result<Vec<LocationLink>> {
 794        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
 795    }
 796
 797    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDeclaration {
 798        proto::GetDeclaration {
 799            project_id,
 800            buffer_id: buffer.remote_id().into(),
 801            position: Some(language::proto::serialize_anchor(
 802                &buffer.anchor_before(self.position),
 803            )),
 804            version: serialize_version(&buffer.version()),
 805        }
 806    }
 807
 808    async fn from_proto(
 809        message: proto::GetDeclaration,
 810        _: Entity<LspStore>,
 811        buffer: Entity<Buffer>,
 812        mut cx: AsyncApp,
 813    ) -> Result<Self> {
 814        let position = message
 815            .position
 816            .and_then(deserialize_anchor)
 817            .context("invalid position")?;
 818        buffer
 819            .update(&mut cx, |buffer, _| {
 820                buffer.wait_for_version(deserialize_version(&message.version))
 821            })
 822            .await?;
 823        Ok(Self {
 824            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 825        })
 826    }
 827
 828    fn response_to_proto(
 829        response: Vec<LocationLink>,
 830        lsp_store: &mut LspStore,
 831        peer_id: PeerId,
 832        _: &clock::Global,
 833        cx: &mut App,
 834    ) -> proto::GetDeclarationResponse {
 835        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
 836        proto::GetDeclarationResponse { links }
 837    }
 838
 839    async fn response_from_proto(
 840        self,
 841        message: proto::GetDeclarationResponse,
 842        lsp_store: Entity<LspStore>,
 843        _: Entity<Buffer>,
 844        cx: AsyncApp,
 845    ) -> Result<Vec<LocationLink>> {
 846        location_links_from_proto(message.links, lsp_store, cx).await
 847    }
 848
 849    fn buffer_id_from_proto(message: &proto::GetDeclaration) -> Result<BufferId> {
 850        BufferId::new(message.buffer_id)
 851    }
 852}
 853
 854#[async_trait(?Send)]
 855impl LspCommand for GetImplementations {
 856    type Response = Vec<LocationLink>;
 857    type LspRequest = lsp::request::GotoImplementation;
 858    type ProtoRequest = proto::GetImplementation;
 859
 860    fn display_name(&self) -> &str {
 861        "Get implementation"
 862    }
 863
 864    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 865        capabilities
 866            .server_capabilities
 867            .implementation_provider
 868            .is_some_and(|capability| match capability {
 869                lsp::ImplementationProviderCapability::Simple(enabled) => enabled,
 870                lsp::ImplementationProviderCapability::Options(_options) => true,
 871            })
 872    }
 873
 874    fn to_lsp(
 875        &self,
 876        path: &Path,
 877        _: &Buffer,
 878        _: &Arc<LanguageServer>,
 879        _: &App,
 880    ) -> Result<lsp::GotoImplementationParams> {
 881        Ok(lsp::GotoImplementationParams {
 882            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 883            work_done_progress_params: Default::default(),
 884            partial_result_params: Default::default(),
 885        })
 886    }
 887
 888    async fn response_from_lsp(
 889        self,
 890        message: Option<lsp::GotoImplementationResponse>,
 891        lsp_store: Entity<LspStore>,
 892        buffer: Entity<Buffer>,
 893        server_id: LanguageServerId,
 894        cx: AsyncApp,
 895    ) -> Result<Vec<LocationLink>> {
 896        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
 897    }
 898
 899    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetImplementation {
 900        proto::GetImplementation {
 901            project_id,
 902            buffer_id: buffer.remote_id().into(),
 903            position: Some(language::proto::serialize_anchor(
 904                &buffer.anchor_before(self.position),
 905            )),
 906            version: serialize_version(&buffer.version()),
 907        }
 908    }
 909
 910    async fn from_proto(
 911        message: proto::GetImplementation,
 912        _: Entity<LspStore>,
 913        buffer: Entity<Buffer>,
 914        mut cx: AsyncApp,
 915    ) -> Result<Self> {
 916        let position = message
 917            .position
 918            .and_then(deserialize_anchor)
 919            .context("invalid position")?;
 920        buffer
 921            .update(&mut cx, |buffer, _| {
 922                buffer.wait_for_version(deserialize_version(&message.version))
 923            })
 924            .await?;
 925        Ok(Self {
 926            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 927        })
 928    }
 929
 930    fn response_to_proto(
 931        response: Vec<LocationLink>,
 932        lsp_store: &mut LspStore,
 933        peer_id: PeerId,
 934        _: &clock::Global,
 935        cx: &mut App,
 936    ) -> proto::GetImplementationResponse {
 937        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
 938        proto::GetImplementationResponse { links }
 939    }
 940
 941    async fn response_from_proto(
 942        self,
 943        message: proto::GetImplementationResponse,
 944        project: Entity<LspStore>,
 945        _: Entity<Buffer>,
 946        cx: AsyncApp,
 947    ) -> Result<Vec<LocationLink>> {
 948        location_links_from_proto(message.links, project, cx).await
 949    }
 950
 951    fn buffer_id_from_proto(message: &proto::GetImplementation) -> Result<BufferId> {
 952        BufferId::new(message.buffer_id)
 953    }
 954}
 955
 956#[async_trait(?Send)]
 957impl LspCommand for GetTypeDefinitions {
 958    type Response = Vec<LocationLink>;
 959    type LspRequest = lsp::request::GotoTypeDefinition;
 960    type ProtoRequest = proto::GetTypeDefinition;
 961
 962    fn display_name(&self) -> &str {
 963        "Get type definition"
 964    }
 965
 966    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 967        !matches!(
 968            &capabilities.server_capabilities.type_definition_provider,
 969            None | Some(lsp::TypeDefinitionProviderCapability::Simple(false))
 970        )
 971    }
 972
 973    fn to_lsp(
 974        &self,
 975        path: &Path,
 976        _: &Buffer,
 977        _: &Arc<LanguageServer>,
 978        _: &App,
 979    ) -> Result<lsp::GotoTypeDefinitionParams> {
 980        Ok(lsp::GotoTypeDefinitionParams {
 981            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 982            work_done_progress_params: Default::default(),
 983            partial_result_params: Default::default(),
 984        })
 985    }
 986
 987    async fn response_from_lsp(
 988        self,
 989        message: Option<lsp::GotoTypeDefinitionResponse>,
 990        project: Entity<LspStore>,
 991        buffer: Entity<Buffer>,
 992        server_id: LanguageServerId,
 993        cx: AsyncApp,
 994    ) -> Result<Vec<LocationLink>> {
 995        location_links_from_lsp(message, project, buffer, server_id, cx).await
 996    }
 997
 998    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetTypeDefinition {
 999        proto::GetTypeDefinition {
1000            project_id,
1001            buffer_id: buffer.remote_id().into(),
1002            position: Some(language::proto::serialize_anchor(
1003                &buffer.anchor_before(self.position),
1004            )),
1005            version: serialize_version(&buffer.version()),
1006        }
1007    }
1008
1009    async fn from_proto(
1010        message: proto::GetTypeDefinition,
1011        _: Entity<LspStore>,
1012        buffer: Entity<Buffer>,
1013        mut cx: AsyncApp,
1014    ) -> Result<Self> {
1015        let position = message
1016            .position
1017            .and_then(deserialize_anchor)
1018            .context("invalid position")?;
1019        buffer
1020            .update(&mut cx, |buffer, _| {
1021                buffer.wait_for_version(deserialize_version(&message.version))
1022            })
1023            .await?;
1024        Ok(Self {
1025            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1026        })
1027    }
1028
1029    fn response_to_proto(
1030        response: Vec<LocationLink>,
1031        lsp_store: &mut LspStore,
1032        peer_id: PeerId,
1033        _: &clock::Global,
1034        cx: &mut App,
1035    ) -> proto::GetTypeDefinitionResponse {
1036        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
1037        proto::GetTypeDefinitionResponse { links }
1038    }
1039
1040    async fn response_from_proto(
1041        self,
1042        message: proto::GetTypeDefinitionResponse,
1043        project: Entity<LspStore>,
1044        _: Entity<Buffer>,
1045        cx: AsyncApp,
1046    ) -> Result<Vec<LocationLink>> {
1047        location_links_from_proto(message.links, project, cx).await
1048    }
1049
1050    fn buffer_id_from_proto(message: &proto::GetTypeDefinition) -> Result<BufferId> {
1051        BufferId::new(message.buffer_id)
1052    }
1053}
1054
1055fn language_server_for_buffer(
1056    lsp_store: &Entity<LspStore>,
1057    buffer: &Entity<Buffer>,
1058    server_id: LanguageServerId,
1059    cx: &mut AsyncApp,
1060) -> Result<(Arc<CachedLspAdapter>, Arc<LanguageServer>)> {
1061    lsp_store
1062        .update(cx, |lsp_store, cx| {
1063            buffer.update(cx, |buffer, cx| {
1064                lsp_store
1065                    .language_server_for_local_buffer(buffer, server_id, cx)
1066                    .map(|(adapter, server)| (adapter.clone(), server.clone()))
1067            })
1068        })
1069        .context("no language server found for buffer")
1070}
1071
1072pub async fn location_links_from_proto(
1073    proto_links: Vec<proto::LocationLink>,
1074    lsp_store: Entity<LspStore>,
1075    mut cx: AsyncApp,
1076) -> Result<Vec<LocationLink>> {
1077    let mut links = Vec::new();
1078
1079    for link in proto_links {
1080        links.push(location_link_from_proto(link, lsp_store.clone(), &mut cx).await?)
1081    }
1082
1083    Ok(links)
1084}
1085
1086pub fn location_link_from_proto(
1087    link: proto::LocationLink,
1088    lsp_store: Entity<LspStore>,
1089    cx: &mut AsyncApp,
1090) -> Task<Result<LocationLink>> {
1091    cx.spawn(async move |cx| {
1092        let origin = match link.origin {
1093            Some(origin) => {
1094                let buffer_id = BufferId::new(origin.buffer_id)?;
1095                let buffer = lsp_store
1096                    .update(cx, |lsp_store, cx| {
1097                        lsp_store.wait_for_remote_buffer(buffer_id, cx)
1098                    })
1099                    .await?;
1100                let start = origin
1101                    .start
1102                    .and_then(deserialize_anchor)
1103                    .context("missing origin start")?;
1104                let end = origin
1105                    .end
1106                    .and_then(deserialize_anchor)
1107                    .context("missing origin end")?;
1108                buffer
1109                    .update(cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1110                    .await?;
1111                Some(Location {
1112                    buffer,
1113                    range: start..end,
1114                })
1115            }
1116            None => None,
1117        };
1118
1119        let target = link.target.context("missing target")?;
1120        let buffer_id = BufferId::new(target.buffer_id)?;
1121        let buffer = lsp_store
1122            .update(cx, |lsp_store, cx| {
1123                lsp_store.wait_for_remote_buffer(buffer_id, cx)
1124            })
1125            .await?;
1126        let start = target
1127            .start
1128            .and_then(deserialize_anchor)
1129            .context("missing target start")?;
1130        let end = target
1131            .end
1132            .and_then(deserialize_anchor)
1133            .context("missing target end")?;
1134        buffer
1135            .update(cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1136            .await?;
1137        let target = Location {
1138            buffer,
1139            range: start..end,
1140        };
1141        Ok(LocationLink { origin, target })
1142    })
1143}
1144
1145pub async fn location_links_from_lsp(
1146    message: Option<lsp::GotoDefinitionResponse>,
1147    lsp_store: Entity<LspStore>,
1148    buffer: Entity<Buffer>,
1149    server_id: LanguageServerId,
1150    mut cx: AsyncApp,
1151) -> Result<Vec<LocationLink>> {
1152    let message = match message {
1153        Some(message) => message,
1154        None => return Ok(Vec::new()),
1155    };
1156
1157    let mut unresolved_links = Vec::new();
1158    match message {
1159        lsp::GotoDefinitionResponse::Scalar(loc) => {
1160            unresolved_links.push((None, loc.uri, loc.range));
1161        }
1162
1163        lsp::GotoDefinitionResponse::Array(locs) => {
1164            unresolved_links.extend(locs.into_iter().map(|l| (None, l.uri, l.range)));
1165        }
1166
1167        lsp::GotoDefinitionResponse::Link(links) => {
1168            unresolved_links.extend(links.into_iter().map(|l| {
1169                (
1170                    l.origin_selection_range,
1171                    l.target_uri,
1172                    l.target_selection_range,
1173                )
1174            }));
1175        }
1176    }
1177
1178    let (_, language_server) = language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1179    let mut definitions = Vec::new();
1180    for (origin_range, target_uri, target_range) in unresolved_links {
1181        let target_buffer_handle = lsp_store
1182            .update(&mut cx, |this, cx| {
1183                this.open_local_buffer_via_lsp(target_uri, language_server.server_id(), cx)
1184            })
1185            .await?;
1186
1187        cx.update(|cx| {
1188            let origin_location = origin_range.map(|origin_range| {
1189                let origin_buffer = buffer.read(cx);
1190                let origin_start =
1191                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
1192                let origin_end =
1193                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
1194                Location {
1195                    buffer: buffer.clone(),
1196                    range: origin_buffer.anchor_after(origin_start)
1197                        ..origin_buffer.anchor_before(origin_end),
1198                }
1199            });
1200
1201            let target_buffer = target_buffer_handle.read(cx);
1202            let target_start =
1203                target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
1204            let target_end =
1205                target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
1206            let target_location = Location {
1207                buffer: target_buffer_handle,
1208                range: target_buffer.anchor_after(target_start)
1209                    ..target_buffer.anchor_before(target_end),
1210            };
1211
1212            definitions.push(LocationLink {
1213                origin: origin_location,
1214                target: target_location,
1215            })
1216        });
1217    }
1218    Ok(definitions)
1219}
1220
1221pub async fn location_link_from_lsp(
1222    link: lsp::LocationLink,
1223    lsp_store: &Entity<LspStore>,
1224    buffer: &Entity<Buffer>,
1225    server_id: LanguageServerId,
1226    cx: &mut AsyncApp,
1227) -> Result<LocationLink> {
1228    let (_, language_server) = language_server_for_buffer(lsp_store, buffer, server_id, cx)?;
1229
1230    let (origin_range, target_uri, target_range) = (
1231        link.origin_selection_range,
1232        link.target_uri,
1233        link.target_selection_range,
1234    );
1235
1236    let target_buffer_handle = lsp_store
1237        .update(cx, |lsp_store, cx| {
1238            lsp_store.open_local_buffer_via_lsp(target_uri, language_server.server_id(), cx)
1239        })
1240        .await?;
1241
1242    Ok(cx.update(|cx| {
1243        let origin_location = origin_range.map(|origin_range| {
1244            let origin_buffer = buffer.read(cx);
1245            let origin_start =
1246                origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
1247            let origin_end =
1248                origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
1249            Location {
1250                buffer: buffer.clone(),
1251                range: origin_buffer.anchor_after(origin_start)
1252                    ..origin_buffer.anchor_before(origin_end),
1253            }
1254        });
1255
1256        let target_buffer = target_buffer_handle.read(cx);
1257        let target_start =
1258            target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
1259        let target_end =
1260            target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
1261        let target_location = Location {
1262            buffer: target_buffer_handle,
1263            range: target_buffer.anchor_after(target_start)
1264                ..target_buffer.anchor_before(target_end),
1265        };
1266
1267        LocationLink {
1268            origin: origin_location,
1269            target: target_location,
1270        }
1271    }))
1272}
1273
1274pub fn location_links_to_proto(
1275    links: Vec<LocationLink>,
1276    lsp_store: &mut LspStore,
1277    peer_id: PeerId,
1278    cx: &mut App,
1279) -> Vec<proto::LocationLink> {
1280    links
1281        .into_iter()
1282        .map(|definition| location_link_to_proto(definition, lsp_store, peer_id, cx))
1283        .collect()
1284}
1285
1286pub fn location_link_to_proto(
1287    location: LocationLink,
1288    lsp_store: &mut LspStore,
1289    peer_id: PeerId,
1290    cx: &mut App,
1291) -> proto::LocationLink {
1292    let origin = location.origin.map(|origin| {
1293        lsp_store
1294            .buffer_store()
1295            .update(cx, |buffer_store, cx| {
1296                buffer_store.create_buffer_for_peer(&origin.buffer, peer_id, cx)
1297            })
1298            .detach_and_log_err(cx);
1299
1300        let buffer_id = origin.buffer.read(cx).remote_id().into();
1301        proto::Location {
1302            start: Some(serialize_anchor(&origin.range.start)),
1303            end: Some(serialize_anchor(&origin.range.end)),
1304            buffer_id,
1305        }
1306    });
1307
1308    lsp_store
1309        .buffer_store()
1310        .update(cx, |buffer_store, cx| {
1311            buffer_store.create_buffer_for_peer(&location.target.buffer, peer_id, cx)
1312        })
1313        .detach_and_log_err(cx);
1314
1315    let buffer_id = location.target.buffer.read(cx).remote_id().into();
1316    let target = proto::Location {
1317        start: Some(serialize_anchor(&location.target.range.start)),
1318        end: Some(serialize_anchor(&location.target.range.end)),
1319        buffer_id,
1320    };
1321
1322    proto::LocationLink {
1323        origin,
1324        target: Some(target),
1325    }
1326}
1327
1328#[async_trait(?Send)]
1329impl LspCommand for GetReferences {
1330    type Response = Vec<Location>;
1331    type LspRequest = lsp::request::References;
1332    type ProtoRequest = proto::GetReferences;
1333
1334    fn display_name(&self) -> &str {
1335        "Find all references"
1336    }
1337
1338    fn status(&self) -> Option<String> {
1339        Some("Finding references...".to_owned())
1340    }
1341
1342    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1343        match &capabilities.server_capabilities.references_provider {
1344            Some(OneOf::Left(has_support)) => *has_support,
1345            Some(OneOf::Right(_)) => true,
1346            None => false,
1347        }
1348    }
1349
1350    fn to_lsp(
1351        &self,
1352        path: &Path,
1353        _: &Buffer,
1354        _: &Arc<LanguageServer>,
1355        _: &App,
1356    ) -> Result<lsp::ReferenceParams> {
1357        Ok(lsp::ReferenceParams {
1358            text_document_position: make_lsp_text_document_position(path, self.position)?,
1359            work_done_progress_params: Default::default(),
1360            partial_result_params: Default::default(),
1361            context: lsp::ReferenceContext {
1362                include_declaration: true,
1363            },
1364        })
1365    }
1366
1367    async fn response_from_lsp(
1368        self,
1369        locations: Option<Vec<lsp::Location>>,
1370        lsp_store: Entity<LspStore>,
1371        buffer: Entity<Buffer>,
1372        server_id: LanguageServerId,
1373        mut cx: AsyncApp,
1374    ) -> Result<Vec<Location>> {
1375        let mut references = Vec::new();
1376        let (_, language_server) =
1377            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1378
1379        if let Some(locations) = locations {
1380            for lsp_location in locations {
1381                let target_buffer_handle = lsp_store
1382                    .update(&mut cx, |lsp_store, cx| {
1383                        lsp_store.open_local_buffer_via_lsp(
1384                            lsp_location.uri,
1385                            language_server.server_id(),
1386                            cx,
1387                        )
1388                    })
1389                    .await?;
1390
1391                target_buffer_handle
1392                    .clone()
1393                    .read_with(&cx, |target_buffer, _| {
1394                        let target_start = target_buffer
1395                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
1396                        let target_end = target_buffer
1397                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
1398                        references.push(Location {
1399                            buffer: target_buffer_handle,
1400                            range: target_buffer.anchor_after(target_start)
1401                                ..target_buffer.anchor_before(target_end),
1402                        });
1403                    });
1404            }
1405        }
1406
1407        Ok(references)
1408    }
1409
1410    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetReferences {
1411        proto::GetReferences {
1412            project_id,
1413            buffer_id: buffer.remote_id().into(),
1414            position: Some(language::proto::serialize_anchor(
1415                &buffer.anchor_before(self.position),
1416            )),
1417            version: serialize_version(&buffer.version()),
1418        }
1419    }
1420
1421    async fn from_proto(
1422        message: proto::GetReferences,
1423        _: Entity<LspStore>,
1424        buffer: Entity<Buffer>,
1425        mut cx: AsyncApp,
1426    ) -> Result<Self> {
1427        let position = message
1428            .position
1429            .and_then(deserialize_anchor)
1430            .context("invalid position")?;
1431        buffer
1432            .update(&mut cx, |buffer, _| {
1433                buffer.wait_for_version(deserialize_version(&message.version))
1434            })
1435            .await?;
1436        Ok(Self {
1437            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1438        })
1439    }
1440
1441    fn response_to_proto(
1442        response: Vec<Location>,
1443        lsp_store: &mut LspStore,
1444        peer_id: PeerId,
1445        _: &clock::Global,
1446        cx: &mut App,
1447    ) -> proto::GetReferencesResponse {
1448        let locations = response
1449            .into_iter()
1450            .map(|definition| {
1451                lsp_store
1452                    .buffer_store()
1453                    .update(cx, |buffer_store, cx| {
1454                        buffer_store.create_buffer_for_peer(&definition.buffer, peer_id, cx)
1455                    })
1456                    .detach_and_log_err(cx);
1457                let buffer_id = definition.buffer.read(cx).remote_id();
1458                proto::Location {
1459                    start: Some(serialize_anchor(&definition.range.start)),
1460                    end: Some(serialize_anchor(&definition.range.end)),
1461                    buffer_id: buffer_id.into(),
1462                }
1463            })
1464            .collect();
1465        proto::GetReferencesResponse { locations }
1466    }
1467
1468    async fn response_from_proto(
1469        self,
1470        message: proto::GetReferencesResponse,
1471        project: Entity<LspStore>,
1472        _: Entity<Buffer>,
1473        mut cx: AsyncApp,
1474    ) -> Result<Vec<Location>> {
1475        let mut locations = Vec::new();
1476        for location in message.locations {
1477            let buffer_id = BufferId::new(location.buffer_id)?;
1478            let target_buffer = project
1479                .update(&mut cx, |this, cx| {
1480                    this.wait_for_remote_buffer(buffer_id, cx)
1481                })
1482                .await?;
1483            let start = location
1484                .start
1485                .and_then(deserialize_anchor)
1486                .context("missing target start")?;
1487            let end = location
1488                .end
1489                .and_then(deserialize_anchor)
1490                .context("missing target end")?;
1491            target_buffer
1492                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1493                .await?;
1494            locations.push(Location {
1495                buffer: target_buffer,
1496                range: start..end,
1497            })
1498        }
1499        Ok(locations)
1500    }
1501
1502    fn buffer_id_from_proto(message: &proto::GetReferences) -> Result<BufferId> {
1503        BufferId::new(message.buffer_id)
1504    }
1505}
1506
1507#[async_trait(?Send)]
1508impl LspCommand for GetDocumentHighlights {
1509    type Response = Vec<DocumentHighlight>;
1510    type LspRequest = lsp::request::DocumentHighlightRequest;
1511    type ProtoRequest = proto::GetDocumentHighlights;
1512
1513    fn display_name(&self) -> &str {
1514        "Get document highlights"
1515    }
1516
1517    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1518        capabilities
1519            .server_capabilities
1520            .document_highlight_provider
1521            .is_some_and(|capability| match capability {
1522                OneOf::Left(supported) => supported,
1523                OneOf::Right(_options) => true,
1524            })
1525    }
1526
1527    fn to_lsp(
1528        &self,
1529        path: &Path,
1530        _: &Buffer,
1531        _: &Arc<LanguageServer>,
1532        _: &App,
1533    ) -> Result<lsp::DocumentHighlightParams> {
1534        Ok(lsp::DocumentHighlightParams {
1535            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1536            work_done_progress_params: Default::default(),
1537            partial_result_params: Default::default(),
1538        })
1539    }
1540
1541    async fn response_from_lsp(
1542        self,
1543        lsp_highlights: Option<Vec<lsp::DocumentHighlight>>,
1544        _: Entity<LspStore>,
1545        buffer: Entity<Buffer>,
1546        _: LanguageServerId,
1547        cx: AsyncApp,
1548    ) -> Result<Vec<DocumentHighlight>> {
1549        Ok(buffer.read_with(&cx, |buffer, _| {
1550            let mut lsp_highlights = lsp_highlights.unwrap_or_default();
1551            lsp_highlights.sort_unstable_by_key(|h| (h.range.start, Reverse(h.range.end)));
1552            lsp_highlights
1553                .into_iter()
1554                .map(|lsp_highlight| {
1555                    let start = buffer
1556                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.start), Bias::Left);
1557                    let end = buffer
1558                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.end), Bias::Left);
1559                    DocumentHighlight {
1560                        range: buffer.anchor_after(start)..buffer.anchor_before(end),
1561                        kind: lsp_highlight
1562                            .kind
1563                            .unwrap_or(lsp::DocumentHighlightKind::READ),
1564                    }
1565                })
1566                .collect()
1567        }))
1568    }
1569
1570    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentHighlights {
1571        proto::GetDocumentHighlights {
1572            project_id,
1573            buffer_id: buffer.remote_id().into(),
1574            position: Some(language::proto::serialize_anchor(
1575                &buffer.anchor_before(self.position),
1576            )),
1577            version: serialize_version(&buffer.version()),
1578        }
1579    }
1580
1581    async fn from_proto(
1582        message: proto::GetDocumentHighlights,
1583        _: Entity<LspStore>,
1584        buffer: Entity<Buffer>,
1585        mut cx: AsyncApp,
1586    ) -> Result<Self> {
1587        let position = message
1588            .position
1589            .and_then(deserialize_anchor)
1590            .context("invalid position")?;
1591        buffer
1592            .update(&mut cx, |buffer, _| {
1593                buffer.wait_for_version(deserialize_version(&message.version))
1594            })
1595            .await?;
1596        Ok(Self {
1597            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1598        })
1599    }
1600
1601    fn response_to_proto(
1602        response: Vec<DocumentHighlight>,
1603        _: &mut LspStore,
1604        _: PeerId,
1605        _: &clock::Global,
1606        _: &mut App,
1607    ) -> proto::GetDocumentHighlightsResponse {
1608        let highlights = response
1609            .into_iter()
1610            .map(|highlight| proto::DocumentHighlight {
1611                start: Some(serialize_anchor(&highlight.range.start)),
1612                end: Some(serialize_anchor(&highlight.range.end)),
1613                kind: match highlight.kind {
1614                    DocumentHighlightKind::TEXT => proto::document_highlight::Kind::Text.into(),
1615                    DocumentHighlightKind::WRITE => proto::document_highlight::Kind::Write.into(),
1616                    DocumentHighlightKind::READ => proto::document_highlight::Kind::Read.into(),
1617                    _ => proto::document_highlight::Kind::Text.into(),
1618                },
1619            })
1620            .collect();
1621        proto::GetDocumentHighlightsResponse { highlights }
1622    }
1623
1624    async fn response_from_proto(
1625        self,
1626        message: proto::GetDocumentHighlightsResponse,
1627        _: Entity<LspStore>,
1628        buffer: Entity<Buffer>,
1629        mut cx: AsyncApp,
1630    ) -> Result<Vec<DocumentHighlight>> {
1631        let mut highlights = Vec::new();
1632        for highlight in message.highlights {
1633            let start = highlight
1634                .start
1635                .and_then(deserialize_anchor)
1636                .context("missing target start")?;
1637            let end = highlight
1638                .end
1639                .and_then(deserialize_anchor)
1640                .context("missing target end")?;
1641            buffer
1642                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1643                .await?;
1644            let kind = match proto::document_highlight::Kind::from_i32(highlight.kind) {
1645                Some(proto::document_highlight::Kind::Text) => DocumentHighlightKind::TEXT,
1646                Some(proto::document_highlight::Kind::Read) => DocumentHighlightKind::READ,
1647                Some(proto::document_highlight::Kind::Write) => DocumentHighlightKind::WRITE,
1648                None => DocumentHighlightKind::TEXT,
1649            };
1650            highlights.push(DocumentHighlight {
1651                range: start..end,
1652                kind,
1653            });
1654        }
1655        Ok(highlights)
1656    }
1657
1658    fn buffer_id_from_proto(message: &proto::GetDocumentHighlights) -> Result<BufferId> {
1659        BufferId::new(message.buffer_id)
1660    }
1661}
1662
1663#[async_trait(?Send)]
1664impl LspCommand for GetDocumentSymbols {
1665    type Response = Vec<DocumentSymbol>;
1666    type LspRequest = lsp::request::DocumentSymbolRequest;
1667    type ProtoRequest = proto::GetDocumentSymbols;
1668
1669    fn display_name(&self) -> &str {
1670        "Get document symbols"
1671    }
1672
1673    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1674        capabilities
1675            .server_capabilities
1676            .document_symbol_provider
1677            .is_some_and(|capability| match capability {
1678                OneOf::Left(supported) => supported,
1679                OneOf::Right(_options) => true,
1680            })
1681    }
1682
1683    fn to_lsp(
1684        &self,
1685        path: &Path,
1686        _: &Buffer,
1687        _: &Arc<LanguageServer>,
1688        _: &App,
1689    ) -> Result<lsp::DocumentSymbolParams> {
1690        Ok(lsp::DocumentSymbolParams {
1691            text_document: make_text_document_identifier(path)?,
1692            work_done_progress_params: Default::default(),
1693            partial_result_params: Default::default(),
1694        })
1695    }
1696
1697    async fn response_from_lsp(
1698        self,
1699        lsp_symbols: Option<lsp::DocumentSymbolResponse>,
1700        _: Entity<LspStore>,
1701        _: Entity<Buffer>,
1702        _: LanguageServerId,
1703        _: AsyncApp,
1704    ) -> Result<Vec<DocumentSymbol>> {
1705        let Some(lsp_symbols) = lsp_symbols else {
1706            return Ok(Vec::new());
1707        };
1708
1709        let symbols = match lsp_symbols {
1710            lsp::DocumentSymbolResponse::Flat(symbol_information) => symbol_information
1711                .into_iter()
1712                .map(|lsp_symbol| DocumentSymbol {
1713                    name: lsp_symbol.name,
1714                    kind: lsp_symbol.kind,
1715                    range: range_from_lsp(lsp_symbol.location.range),
1716                    selection_range: range_from_lsp(lsp_symbol.location.range),
1717                    children: Vec::new(),
1718                })
1719                .collect(),
1720            lsp::DocumentSymbolResponse::Nested(nested_responses) => {
1721                fn convert_symbol(lsp_symbol: lsp::DocumentSymbol) -> DocumentSymbol {
1722                    DocumentSymbol {
1723                        name: lsp_symbol.name,
1724                        kind: lsp_symbol.kind,
1725                        range: range_from_lsp(lsp_symbol.range),
1726                        selection_range: range_from_lsp(lsp_symbol.selection_range),
1727                        children: lsp_symbol
1728                            .children
1729                            .map(|children| {
1730                                children.into_iter().map(convert_symbol).collect::<Vec<_>>()
1731                            })
1732                            .unwrap_or_default(),
1733                    }
1734                }
1735                nested_responses.into_iter().map(convert_symbol).collect()
1736            }
1737        };
1738        Ok(symbols)
1739    }
1740
1741    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentSymbols {
1742        proto::GetDocumentSymbols {
1743            project_id,
1744            buffer_id: buffer.remote_id().into(),
1745            version: serialize_version(&buffer.version()),
1746        }
1747    }
1748
1749    async fn from_proto(
1750        message: proto::GetDocumentSymbols,
1751        _: Entity<LspStore>,
1752        buffer: Entity<Buffer>,
1753        mut cx: AsyncApp,
1754    ) -> Result<Self> {
1755        buffer
1756            .update(&mut cx, |buffer, _| {
1757                buffer.wait_for_version(deserialize_version(&message.version))
1758            })
1759            .await?;
1760        Ok(Self)
1761    }
1762
1763    fn response_to_proto(
1764        response: Vec<DocumentSymbol>,
1765        _: &mut LspStore,
1766        _: PeerId,
1767        _: &clock::Global,
1768        _: &mut App,
1769    ) -> proto::GetDocumentSymbolsResponse {
1770        let symbols = response
1771            .into_iter()
1772            .map(|symbol| {
1773                fn convert_symbol_to_proto(symbol: DocumentSymbol) -> proto::DocumentSymbol {
1774                    proto::DocumentSymbol {
1775                        name: symbol.name.clone(),
1776                        kind: unsafe { mem::transmute::<lsp::SymbolKind, i32>(symbol.kind) },
1777                        start: Some(proto::PointUtf16 {
1778                            row: symbol.range.start.0.row,
1779                            column: symbol.range.start.0.column,
1780                        }),
1781                        end: Some(proto::PointUtf16 {
1782                            row: symbol.range.end.0.row,
1783                            column: symbol.range.end.0.column,
1784                        }),
1785                        selection_start: Some(proto::PointUtf16 {
1786                            row: symbol.selection_range.start.0.row,
1787                            column: symbol.selection_range.start.0.column,
1788                        }),
1789                        selection_end: Some(proto::PointUtf16 {
1790                            row: symbol.selection_range.end.0.row,
1791                            column: symbol.selection_range.end.0.column,
1792                        }),
1793                        children: symbol
1794                            .children
1795                            .into_iter()
1796                            .map(convert_symbol_to_proto)
1797                            .collect(),
1798                    }
1799                }
1800                convert_symbol_to_proto(symbol)
1801            })
1802            .collect::<Vec<_>>();
1803
1804        proto::GetDocumentSymbolsResponse { symbols }
1805    }
1806
1807    async fn response_from_proto(
1808        self,
1809        message: proto::GetDocumentSymbolsResponse,
1810        _: Entity<LspStore>,
1811        _: Entity<Buffer>,
1812        _: AsyncApp,
1813    ) -> Result<Vec<DocumentSymbol>> {
1814        let mut symbols = Vec::with_capacity(message.symbols.len());
1815        for serialized_symbol in message.symbols {
1816            fn deserialize_symbol_with_children(
1817                serialized_symbol: proto::DocumentSymbol,
1818            ) -> Result<DocumentSymbol> {
1819                let kind =
1820                    unsafe { mem::transmute::<i32, lsp::SymbolKind>(serialized_symbol.kind) };
1821
1822                let start = serialized_symbol.start.context("invalid start")?;
1823                let end = serialized_symbol.end.context("invalid end")?;
1824
1825                let selection_start = serialized_symbol
1826                    .selection_start
1827                    .context("invalid selection start")?;
1828                let selection_end = serialized_symbol
1829                    .selection_end
1830                    .context("invalid selection end")?;
1831
1832                Ok(DocumentSymbol {
1833                    name: serialized_symbol.name,
1834                    kind,
1835                    range: Unclipped(PointUtf16::new(start.row, start.column))
1836                        ..Unclipped(PointUtf16::new(end.row, end.column)),
1837                    selection_range: Unclipped(PointUtf16::new(
1838                        selection_start.row,
1839                        selection_start.column,
1840                    ))
1841                        ..Unclipped(PointUtf16::new(selection_end.row, selection_end.column)),
1842                    children: serialized_symbol
1843                        .children
1844                        .into_iter()
1845                        .filter_map(|symbol| deserialize_symbol_with_children(symbol).ok())
1846                        .collect::<Vec<_>>(),
1847                })
1848            }
1849
1850            symbols.push(deserialize_symbol_with_children(serialized_symbol)?);
1851        }
1852
1853        Ok(symbols)
1854    }
1855
1856    fn buffer_id_from_proto(message: &proto::GetDocumentSymbols) -> Result<BufferId> {
1857        BufferId::new(message.buffer_id)
1858    }
1859}
1860
1861#[async_trait(?Send)]
1862impl LspCommand for GetSignatureHelp {
1863    type Response = Option<SignatureHelp>;
1864    type LspRequest = lsp::SignatureHelpRequest;
1865    type ProtoRequest = proto::GetSignatureHelp;
1866
1867    fn display_name(&self) -> &str {
1868        "Get signature help"
1869    }
1870
1871    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1872        capabilities
1873            .server_capabilities
1874            .signature_help_provider
1875            .is_some()
1876    }
1877
1878    fn to_lsp(
1879        &self,
1880        path: &Path,
1881        _: &Buffer,
1882        _: &Arc<LanguageServer>,
1883        _cx: &App,
1884    ) -> Result<lsp::SignatureHelpParams> {
1885        Ok(lsp::SignatureHelpParams {
1886            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1887            context: None,
1888            work_done_progress_params: Default::default(),
1889        })
1890    }
1891
1892    async fn response_from_lsp(
1893        self,
1894        message: Option<lsp::SignatureHelp>,
1895        lsp_store: Entity<LspStore>,
1896        _: Entity<Buffer>,
1897        id: LanguageServerId,
1898        cx: AsyncApp,
1899    ) -> Result<Self::Response> {
1900        let Some(message) = message else {
1901            return Ok(None);
1902        };
1903        Ok(cx.update(|cx| {
1904            SignatureHelp::new(
1905                message,
1906                Some(lsp_store.read(cx).languages.clone()),
1907                Some(id),
1908                cx,
1909            )
1910        }))
1911    }
1912
1913    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
1914        let offset = buffer.point_utf16_to_offset(self.position);
1915        proto::GetSignatureHelp {
1916            project_id,
1917            buffer_id: buffer.remote_id().to_proto(),
1918            position: Some(serialize_anchor(&buffer.anchor_after(offset))),
1919            version: serialize_version(&buffer.version()),
1920        }
1921    }
1922
1923    async fn from_proto(
1924        payload: Self::ProtoRequest,
1925        _: Entity<LspStore>,
1926        buffer: Entity<Buffer>,
1927        mut cx: AsyncApp,
1928    ) -> Result<Self> {
1929        buffer
1930            .update(&mut cx, |buffer, _| {
1931                buffer.wait_for_version(deserialize_version(&payload.version))
1932            })
1933            .await
1934            .with_context(|| format!("waiting for version for buffer {}", buffer.entity_id()))?;
1935        let buffer_snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
1936        Ok(Self {
1937            position: payload
1938                .position
1939                .and_then(deserialize_anchor)
1940                .context("invalid position")?
1941                .to_point_utf16(&buffer_snapshot),
1942        })
1943    }
1944
1945    fn response_to_proto(
1946        response: Self::Response,
1947        _: &mut LspStore,
1948        _: PeerId,
1949        _: &Global,
1950        _: &mut App,
1951    ) -> proto::GetSignatureHelpResponse {
1952        proto::GetSignatureHelpResponse {
1953            signature_help: response
1954                .map(|signature_help| lsp_to_proto_signature(signature_help.original_data)),
1955        }
1956    }
1957
1958    async fn response_from_proto(
1959        self,
1960        response: proto::GetSignatureHelpResponse,
1961        lsp_store: Entity<LspStore>,
1962        _: Entity<Buffer>,
1963        cx: AsyncApp,
1964    ) -> Result<Self::Response> {
1965        Ok(cx.update(|cx| {
1966            response
1967                .signature_help
1968                .map(proto_to_lsp_signature)
1969                .and_then(|signature| {
1970                    SignatureHelp::new(
1971                        signature,
1972                        Some(lsp_store.read(cx).languages.clone()),
1973                        None,
1974                        cx,
1975                    )
1976                })
1977        }))
1978    }
1979
1980    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
1981        BufferId::new(message.buffer_id)
1982    }
1983}
1984
1985#[async_trait(?Send)]
1986impl LspCommand for GetHover {
1987    type Response = Option<Hover>;
1988    type LspRequest = lsp::request::HoverRequest;
1989    type ProtoRequest = proto::GetHover;
1990
1991    fn display_name(&self) -> &str {
1992        "Get hover"
1993    }
1994
1995    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1996        match capabilities.server_capabilities.hover_provider {
1997            Some(lsp::HoverProviderCapability::Simple(enabled)) => enabled,
1998            Some(lsp::HoverProviderCapability::Options(_)) => true,
1999            None => false,
2000        }
2001    }
2002
2003    fn to_lsp(
2004        &self,
2005        path: &Path,
2006        _: &Buffer,
2007        _: &Arc<LanguageServer>,
2008        _: &App,
2009    ) -> Result<lsp::HoverParams> {
2010        Ok(lsp::HoverParams {
2011            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
2012            work_done_progress_params: Default::default(),
2013        })
2014    }
2015
2016    async fn response_from_lsp(
2017        self,
2018        message: Option<lsp::Hover>,
2019        _: Entity<LspStore>,
2020        buffer: Entity<Buffer>,
2021        _: LanguageServerId,
2022        cx: AsyncApp,
2023    ) -> Result<Self::Response> {
2024        let Some(hover) = message else {
2025            return Ok(None);
2026        };
2027
2028        let (language, range) = buffer.read_with(&cx, |buffer, _| {
2029            (
2030                buffer.language().cloned(),
2031                hover.range.map(|range| {
2032                    let token_start =
2033                        buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
2034                    let token_end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
2035                    buffer.anchor_after(token_start)..buffer.anchor_before(token_end)
2036                }),
2037            )
2038        });
2039
2040        fn hover_blocks_from_marked_string(marked_string: lsp::MarkedString) -> Option<HoverBlock> {
2041            let block = match marked_string {
2042                lsp::MarkedString::String(content) => HoverBlock {
2043                    text: content,
2044                    kind: HoverBlockKind::Markdown,
2045                },
2046                lsp::MarkedString::LanguageString(lsp::LanguageString { language, value }) => {
2047                    HoverBlock {
2048                        text: value,
2049                        kind: HoverBlockKind::Code { language },
2050                    }
2051                }
2052            };
2053            if block.text.is_empty() {
2054                None
2055            } else {
2056                Some(block)
2057            }
2058        }
2059
2060        let contents = match hover.contents {
2061            lsp::HoverContents::Scalar(marked_string) => {
2062                hover_blocks_from_marked_string(marked_string)
2063                    .into_iter()
2064                    .collect()
2065            }
2066            lsp::HoverContents::Array(marked_strings) => marked_strings
2067                .into_iter()
2068                .filter_map(hover_blocks_from_marked_string)
2069                .collect(),
2070            lsp::HoverContents::Markup(markup_content) => vec![HoverBlock {
2071                text: markup_content.value,
2072                kind: if markup_content.kind == lsp::MarkupKind::Markdown {
2073                    HoverBlockKind::Markdown
2074                } else {
2075                    HoverBlockKind::PlainText
2076                },
2077            }],
2078        };
2079
2080        Ok(Some(Hover {
2081            contents,
2082            range,
2083            language,
2084        }))
2085    }
2086
2087    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
2088        proto::GetHover {
2089            project_id,
2090            buffer_id: buffer.remote_id().into(),
2091            position: Some(language::proto::serialize_anchor(
2092                &buffer.anchor_before(self.position),
2093            )),
2094            version: serialize_version(&buffer.version),
2095        }
2096    }
2097
2098    async fn from_proto(
2099        message: Self::ProtoRequest,
2100        _: Entity<LspStore>,
2101        buffer: Entity<Buffer>,
2102        mut cx: AsyncApp,
2103    ) -> Result<Self> {
2104        let position = message
2105            .position
2106            .and_then(deserialize_anchor)
2107            .context("invalid position")?;
2108        buffer
2109            .update(&mut cx, |buffer, _| {
2110                buffer.wait_for_version(deserialize_version(&message.version))
2111            })
2112            .await?;
2113        Ok(Self {
2114            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
2115        })
2116    }
2117
2118    fn response_to_proto(
2119        response: Self::Response,
2120        _: &mut LspStore,
2121        _: PeerId,
2122        _: &clock::Global,
2123        _: &mut App,
2124    ) -> proto::GetHoverResponse {
2125        if let Some(response) = response {
2126            let (start, end) = if let Some(range) = response.range {
2127                (
2128                    Some(language::proto::serialize_anchor(&range.start)),
2129                    Some(language::proto::serialize_anchor(&range.end)),
2130                )
2131            } else {
2132                (None, None)
2133            };
2134
2135            let contents = response
2136                .contents
2137                .into_iter()
2138                .map(|block| proto::HoverBlock {
2139                    text: block.text,
2140                    is_markdown: block.kind == HoverBlockKind::Markdown,
2141                    language: if let HoverBlockKind::Code { language } = block.kind {
2142                        Some(language)
2143                    } else {
2144                        None
2145                    },
2146                })
2147                .collect();
2148
2149            proto::GetHoverResponse {
2150                start,
2151                end,
2152                contents,
2153            }
2154        } else {
2155            proto::GetHoverResponse {
2156                start: None,
2157                end: None,
2158                contents: Vec::new(),
2159            }
2160        }
2161    }
2162
2163    async fn response_from_proto(
2164        self,
2165        message: proto::GetHoverResponse,
2166        _: Entity<LspStore>,
2167        buffer: Entity<Buffer>,
2168        mut cx: AsyncApp,
2169    ) -> Result<Self::Response> {
2170        let contents: Vec<_> = message
2171            .contents
2172            .into_iter()
2173            .map(|block| HoverBlock {
2174                text: block.text,
2175                kind: if let Some(language) = block.language {
2176                    HoverBlockKind::Code { language }
2177                } else if block.is_markdown {
2178                    HoverBlockKind::Markdown
2179                } else {
2180                    HoverBlockKind::PlainText
2181                },
2182            })
2183            .collect();
2184        if contents.is_empty() {
2185            return Ok(None);
2186        }
2187
2188        let language = buffer.read_with(&cx, |buffer, _| buffer.language().cloned());
2189        let range = if let (Some(start), Some(end)) = (message.start, message.end) {
2190            language::proto::deserialize_anchor(start)
2191                .and_then(|start| language::proto::deserialize_anchor(end).map(|end| start..end))
2192        } else {
2193            None
2194        };
2195        if let Some(range) = range.as_ref() {
2196            buffer
2197                .update(&mut cx, |buffer, _| {
2198                    buffer.wait_for_anchors([range.start, range.end])
2199                })
2200                .await?;
2201        }
2202
2203        Ok(Some(Hover {
2204            contents,
2205            range,
2206            language,
2207        }))
2208    }
2209
2210    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
2211        BufferId::new(message.buffer_id)
2212    }
2213}
2214
2215impl GetCompletions {
2216    pub fn can_resolve_completions(capabilities: &lsp::ServerCapabilities) -> bool {
2217        capabilities
2218            .completion_provider
2219            .as_ref()
2220            .and_then(|options| options.resolve_provider)
2221            .unwrap_or(false)
2222    }
2223}
2224
2225#[async_trait(?Send)]
2226impl LspCommand for GetCompletions {
2227    type Response = CoreCompletionResponse;
2228    type LspRequest = lsp::request::Completion;
2229    type ProtoRequest = proto::GetCompletions;
2230
2231    fn display_name(&self) -> &str {
2232        "Get completion"
2233    }
2234
2235    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2236        capabilities
2237            .server_capabilities
2238            .completion_provider
2239            .is_some()
2240    }
2241
2242    fn to_lsp(
2243        &self,
2244        path: &Path,
2245        _: &Buffer,
2246        _: &Arc<LanguageServer>,
2247        _: &App,
2248    ) -> Result<lsp::CompletionParams> {
2249        Ok(lsp::CompletionParams {
2250            text_document_position: make_lsp_text_document_position(path, self.position)?,
2251            context: Some(self.context.clone()),
2252            work_done_progress_params: Default::default(),
2253            partial_result_params: Default::default(),
2254        })
2255    }
2256
2257    async fn response_from_lsp(
2258        self,
2259        completions: Option<lsp::CompletionResponse>,
2260        lsp_store: Entity<LspStore>,
2261        buffer: Entity<Buffer>,
2262        server_id: LanguageServerId,
2263        mut cx: AsyncApp,
2264    ) -> Result<Self::Response> {
2265        let mut response_list = None;
2266        let (mut completions, mut is_incomplete) = if let Some(completions) = completions {
2267            match completions {
2268                lsp::CompletionResponse::Array(completions) => (completions, false),
2269                lsp::CompletionResponse::List(mut list) => {
2270                    let is_incomplete = list.is_incomplete;
2271                    let items = std::mem::take(&mut list.items);
2272                    response_list = Some(list);
2273                    (items, is_incomplete)
2274                }
2275            }
2276        } else {
2277            (Vec::new(), false)
2278        };
2279
2280        let unfiltered_completions_count = completions.len();
2281
2282        let language_server_adapter = lsp_store
2283            .read_with(&cx, |lsp_store, _| {
2284                lsp_store.language_server_adapter_for_id(server_id)
2285            })
2286            .with_context(|| format!("no language server with id {server_id}"))?;
2287
2288        let lsp_defaults = response_list
2289            .as_ref()
2290            .and_then(|list| list.item_defaults.clone())
2291            .map(Arc::new);
2292
2293        let mut completion_edits = Vec::new();
2294        buffer.update(&mut cx, |buffer, _cx| {
2295            let snapshot = buffer.snapshot();
2296            let clipped_position = buffer.clip_point_utf16(Unclipped(self.position), Bias::Left);
2297
2298            let mut range_for_token = None;
2299            completions.retain(|lsp_completion| {
2300                let lsp_edit = lsp_completion.text_edit.clone().or_else(|| {
2301                    let default_text_edit = lsp_defaults.as_deref()?.edit_range.as_ref()?;
2302                    let new_text = lsp_completion
2303                        .text_edit_text
2304                        .as_ref()
2305                        .unwrap_or(&lsp_completion.label)
2306                        .clone();
2307                    match default_text_edit {
2308                        CompletionListItemDefaultsEditRange::Range(range) => {
2309                            Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
2310                                range: *range,
2311                                new_text,
2312                            }))
2313                        }
2314                        CompletionListItemDefaultsEditRange::InsertAndReplace {
2315                            insert,
2316                            replace,
2317                        } => Some(lsp::CompletionTextEdit::InsertAndReplace(
2318                            lsp::InsertReplaceEdit {
2319                                new_text,
2320                                insert: *insert,
2321                                replace: *replace,
2322                            },
2323                        )),
2324                    }
2325                });
2326
2327                let edit = match lsp_edit {
2328                    // If the language server provides a range to overwrite, then
2329                    // check that the range is valid.
2330                    Some(completion_text_edit) => {
2331                        match parse_completion_text_edit(&completion_text_edit, &snapshot) {
2332                            Some(edit) => edit,
2333                            None => return false,
2334                        }
2335                    }
2336                    // If the language server does not provide a range, then infer
2337                    // the range based on the syntax tree.
2338                    None => {
2339                        if self.position != clipped_position {
2340                            log::info!("completion out of expected range ");
2341                            return false;
2342                        }
2343
2344                        let default_edit_range = lsp_defaults.as_ref().and_then(|lsp_defaults| {
2345                            lsp_defaults
2346                                .edit_range
2347                                .as_ref()
2348                                .and_then(|range| match range {
2349                                    CompletionListItemDefaultsEditRange::Range(r) => Some(r),
2350                                    _ => None,
2351                                })
2352                        });
2353
2354                        let range = if let Some(range) = default_edit_range {
2355                            let range = range_from_lsp(*range);
2356                            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2357                            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2358                            if start != range.start.0 || end != range.end.0 {
2359                                log::info!("completion out of expected range");
2360                                return false;
2361                            }
2362
2363                            snapshot.anchor_before(start)..snapshot.anchor_after(end)
2364                        } else {
2365                            range_for_token
2366                                .get_or_insert_with(|| {
2367                                    let offset = self.position.to_offset(&snapshot);
2368                                    let (range, kind) = snapshot.surrounding_word(
2369                                        offset,
2370                                        Some(CharScopeContext::Completion),
2371                                    );
2372                                    let range = if kind == Some(CharKind::Word) {
2373                                        range
2374                                    } else {
2375                                        offset..offset
2376                                    };
2377
2378                                    snapshot.anchor_before(range.start)
2379                                        ..snapshot.anchor_after(range.end)
2380                                })
2381                                .clone()
2382                        };
2383
2384                        // We already know text_edit is None here
2385                        let text = lsp_completion
2386                            .insert_text
2387                            .as_ref()
2388                            .unwrap_or(&lsp_completion.label)
2389                            .clone();
2390
2391                        ParsedCompletionEdit {
2392                            replace_range: range,
2393                            insert_range: None,
2394                            new_text: text,
2395                        }
2396                    }
2397                };
2398
2399                completion_edits.push(edit);
2400                true
2401            });
2402        });
2403
2404        // If completions were filtered out due to errors that may be transient, mark the result
2405        // incomplete so that it is re-queried.
2406        if unfiltered_completions_count != completions.len() {
2407            is_incomplete = true;
2408        }
2409
2410        language_server_adapter
2411            .process_completions(&mut completions)
2412            .await;
2413
2414        let completions = completions
2415            .into_iter()
2416            .zip(completion_edits)
2417            .map(|(mut lsp_completion, mut edit)| {
2418                LineEnding::normalize(&mut edit.new_text);
2419                if lsp_completion.data.is_none()
2420                    && let Some(default_data) = lsp_defaults
2421                        .as_ref()
2422                        .and_then(|item_defaults| item_defaults.data.clone())
2423                {
2424                    // Servers (e.g. JDTLS) prefer unchanged completions, when resolving the items later,
2425                    // so we do not insert the defaults here, but `data` is needed for resolving, so this is an exception.
2426                    lsp_completion.data = Some(default_data);
2427                }
2428                CoreCompletion {
2429                    replace_range: edit.replace_range,
2430                    new_text: edit.new_text,
2431                    source: CompletionSource::Lsp {
2432                        insert_range: edit.insert_range,
2433                        server_id,
2434                        lsp_completion: Box::new(lsp_completion),
2435                        lsp_defaults: lsp_defaults.clone(),
2436                        resolved: false,
2437                    },
2438                }
2439            })
2440            .collect();
2441
2442        Ok(CoreCompletionResponse {
2443            completions,
2444            is_incomplete,
2445        })
2446    }
2447
2448    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCompletions {
2449        let anchor = buffer.anchor_after(self.position);
2450        proto::GetCompletions {
2451            project_id,
2452            buffer_id: buffer.remote_id().into(),
2453            position: Some(language::proto::serialize_anchor(&anchor)),
2454            version: serialize_version(&buffer.version()),
2455            server_id: self.server_id.map(|id| id.to_proto()),
2456        }
2457    }
2458
2459    async fn from_proto(
2460        message: proto::GetCompletions,
2461        _: Entity<LspStore>,
2462        buffer: Entity<Buffer>,
2463        mut cx: AsyncApp,
2464    ) -> Result<Self> {
2465        let version = deserialize_version(&message.version);
2466        buffer
2467            .update(&mut cx, |buffer, _| buffer.wait_for_version(version))
2468            .await?;
2469        let position = message
2470            .position
2471            .and_then(language::proto::deserialize_anchor)
2472            .map(|p| {
2473                buffer.read_with(&cx, |buffer, _| {
2474                    buffer.clip_point_utf16(Unclipped(p.to_point_utf16(buffer)), Bias::Left)
2475                })
2476            })
2477            .context("invalid position")?;
2478        Ok(Self {
2479            position,
2480            context: CompletionContext {
2481                trigger_kind: CompletionTriggerKind::INVOKED,
2482                trigger_character: None,
2483            },
2484            server_id: message
2485                .server_id
2486                .map(|id| lsp::LanguageServerId::from_proto(id)),
2487        })
2488    }
2489
2490    fn response_to_proto(
2491        response: CoreCompletionResponse,
2492        _: &mut LspStore,
2493        _: PeerId,
2494        buffer_version: &clock::Global,
2495        _: &mut App,
2496    ) -> proto::GetCompletionsResponse {
2497        proto::GetCompletionsResponse {
2498            completions: response
2499                .completions
2500                .iter()
2501                .map(LspStore::serialize_completion)
2502                .collect(),
2503            version: serialize_version(buffer_version),
2504            can_reuse: !response.is_incomplete,
2505        }
2506    }
2507
2508    async fn response_from_proto(
2509        self,
2510        message: proto::GetCompletionsResponse,
2511        _project: Entity<LspStore>,
2512        buffer: Entity<Buffer>,
2513        mut cx: AsyncApp,
2514    ) -> Result<Self::Response> {
2515        buffer
2516            .update(&mut cx, |buffer, _| {
2517                buffer.wait_for_version(deserialize_version(&message.version))
2518            })
2519            .await?;
2520
2521        let completions = message
2522            .completions
2523            .into_iter()
2524            .map(LspStore::deserialize_completion)
2525            .collect::<Result<Vec<_>>>()?;
2526
2527        Ok(CoreCompletionResponse {
2528            completions,
2529            is_incomplete: !message.can_reuse,
2530        })
2531    }
2532
2533    fn buffer_id_from_proto(message: &proto::GetCompletions) -> Result<BufferId> {
2534        BufferId::new(message.buffer_id)
2535    }
2536}
2537
2538pub struct ParsedCompletionEdit {
2539    pub replace_range: Range<Anchor>,
2540    pub insert_range: Option<Range<Anchor>>,
2541    pub new_text: String,
2542}
2543
2544pub(crate) fn parse_completion_text_edit(
2545    edit: &lsp::CompletionTextEdit,
2546    snapshot: &BufferSnapshot,
2547) -> Option<ParsedCompletionEdit> {
2548    let (replace_range, insert_range, new_text) = match edit {
2549        lsp::CompletionTextEdit::Edit(edit) => (edit.range, None, &edit.new_text),
2550        lsp::CompletionTextEdit::InsertAndReplace(edit) => {
2551            (edit.replace, Some(edit.insert), &edit.new_text)
2552        }
2553    };
2554
2555    let replace_range = {
2556        let range = range_from_lsp(replace_range);
2557        let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2558        let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2559        if start != range.start.0 || end != range.end.0 {
2560            log::info!(
2561                "completion out of expected range, start: {start:?}, end: {end:?}, range: {range:?}"
2562            );
2563            return None;
2564        }
2565        snapshot.anchor_before(start)..snapshot.anchor_after(end)
2566    };
2567
2568    let insert_range = match insert_range {
2569        None => None,
2570        Some(insert_range) => {
2571            let range = range_from_lsp(insert_range);
2572            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2573            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2574            if start != range.start.0 || end != range.end.0 {
2575                log::info!("completion (insert) out of expected range");
2576                return None;
2577            }
2578            Some(snapshot.anchor_before(start)..snapshot.anchor_after(end))
2579        }
2580    };
2581
2582    Some(ParsedCompletionEdit {
2583        insert_range,
2584        replace_range,
2585        new_text: new_text.clone(),
2586    })
2587}
2588
2589#[async_trait(?Send)]
2590impl LspCommand for GetCodeActions {
2591    type Response = Vec<CodeAction>;
2592    type LspRequest = lsp::request::CodeActionRequest;
2593    type ProtoRequest = proto::GetCodeActions;
2594
2595    fn display_name(&self) -> &str {
2596        "Get code actions"
2597    }
2598
2599    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2600        match &capabilities.server_capabilities.code_action_provider {
2601            None => false,
2602            Some(lsp::CodeActionProviderCapability::Simple(false)) => false,
2603            _ => {
2604                // If we do know that we want specific code actions AND we know that
2605                // the server only supports specific code actions, then we want to filter
2606                // down to the ones that are supported.
2607                if let Some((requested, supported)) = self
2608                    .kinds
2609                    .as_ref()
2610                    .zip(Self::supported_code_action_kinds(capabilities))
2611                {
2612                    requested.iter().any(|requested_kind| {
2613                        supported.iter().any(|supported_kind| {
2614                            code_action_kind_matches(requested_kind, supported_kind)
2615                        })
2616                    })
2617                } else {
2618                    true
2619                }
2620            }
2621        }
2622    }
2623
2624    fn to_lsp(
2625        &self,
2626        path: &Path,
2627        buffer: &Buffer,
2628        language_server: &Arc<LanguageServer>,
2629        _: &App,
2630    ) -> Result<lsp::CodeActionParams> {
2631        let mut relevant_diagnostics = Vec::new();
2632        for entry in buffer
2633            .snapshot()
2634            .diagnostics_in_range::<_, language::PointUtf16>(self.range.clone(), false)
2635        {
2636            relevant_diagnostics.push(entry.to_lsp_diagnostic_stub()?);
2637        }
2638
2639        let only = if let Some(requested) = &self.kinds {
2640            if let Some(supported_kinds) =
2641                Self::supported_code_action_kinds(language_server.adapter_server_capabilities())
2642            {
2643                let filtered = requested
2644                    .iter()
2645                    .filter(|requested_kind| {
2646                        supported_kinds.iter().any(|supported_kind| {
2647                            code_action_kind_matches(requested_kind, supported_kind)
2648                        })
2649                    })
2650                    .cloned()
2651                    .collect();
2652                Some(filtered)
2653            } else {
2654                Some(requested.clone())
2655            }
2656        } else {
2657            None
2658        };
2659
2660        Ok(lsp::CodeActionParams {
2661            text_document: make_text_document_identifier(path)?,
2662            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
2663            work_done_progress_params: Default::default(),
2664            partial_result_params: Default::default(),
2665            context: lsp::CodeActionContext {
2666                diagnostics: relevant_diagnostics,
2667                only,
2668                ..lsp::CodeActionContext::default()
2669            },
2670        })
2671    }
2672
2673    async fn response_from_lsp(
2674        self,
2675        actions: Option<lsp::CodeActionResponse>,
2676        lsp_store: Entity<LspStore>,
2677        _: Entity<Buffer>,
2678        server_id: LanguageServerId,
2679        cx: AsyncApp,
2680    ) -> Result<Vec<CodeAction>> {
2681        let requested_kinds = self.kinds.as_ref();
2682
2683        let language_server = cx.update(|cx| {
2684            lsp_store
2685                .read(cx)
2686                .language_server_for_id(server_id)
2687                .with_context(|| {
2688                    format!("Missing the language server that just returned a response {server_id}")
2689                })
2690        })?;
2691
2692        let server_capabilities = language_server.capabilities();
2693        let available_commands = server_capabilities
2694            .execute_command_provider
2695            .as_ref()
2696            .map(|options| options.commands.as_slice())
2697            .unwrap_or_default();
2698        Ok(actions
2699            .unwrap_or_default()
2700            .into_iter()
2701            .filter_map(|entry| {
2702                let (lsp_action, resolved) = match entry {
2703                    lsp::CodeActionOrCommand::CodeAction(lsp_action) => {
2704                        if let Some(command) = lsp_action.command.as_ref()
2705                            && !available_commands.contains(&command.command)
2706                        {
2707                            return None;
2708                        }
2709                        (LspAction::Action(Box::new(lsp_action)), false)
2710                    }
2711                    lsp::CodeActionOrCommand::Command(command) => {
2712                        if available_commands.contains(&command.command) {
2713                            (LspAction::Command(command), true)
2714                        } else {
2715                            return None;
2716                        }
2717                    }
2718                };
2719
2720                if let Some((kinds, kind)) = requested_kinds.zip(lsp_action.action_kind())
2721                    && !kinds
2722                        .iter()
2723                        .any(|requested_kind| code_action_kind_matches(requested_kind, &kind))
2724                {
2725                    return None;
2726                }
2727
2728                Some(CodeAction {
2729                    server_id,
2730                    range: self.range.clone(),
2731                    lsp_action,
2732                    resolved,
2733                })
2734            })
2735            .collect())
2736    }
2737
2738    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeActions {
2739        proto::GetCodeActions {
2740            project_id,
2741            buffer_id: buffer.remote_id().into(),
2742            start: Some(language::proto::serialize_anchor(&self.range.start)),
2743            end: Some(language::proto::serialize_anchor(&self.range.end)),
2744            version: serialize_version(&buffer.version()),
2745        }
2746    }
2747
2748    async fn from_proto(
2749        message: proto::GetCodeActions,
2750        _: Entity<LspStore>,
2751        buffer: Entity<Buffer>,
2752        mut cx: AsyncApp,
2753    ) -> Result<Self> {
2754        let start = message
2755            .start
2756            .and_then(language::proto::deserialize_anchor)
2757            .context("invalid start")?;
2758        let end = message
2759            .end
2760            .and_then(language::proto::deserialize_anchor)
2761            .context("invalid end")?;
2762        buffer
2763            .update(&mut cx, |buffer, _| {
2764                buffer.wait_for_version(deserialize_version(&message.version))
2765            })
2766            .await?;
2767
2768        Ok(Self {
2769            range: start..end,
2770            kinds: None,
2771        })
2772    }
2773
2774    fn response_to_proto(
2775        code_actions: Vec<CodeAction>,
2776        _: &mut LspStore,
2777        _: PeerId,
2778        buffer_version: &clock::Global,
2779        _: &mut App,
2780    ) -> proto::GetCodeActionsResponse {
2781        proto::GetCodeActionsResponse {
2782            actions: code_actions
2783                .iter()
2784                .map(LspStore::serialize_code_action)
2785                .collect(),
2786            version: serialize_version(buffer_version),
2787        }
2788    }
2789
2790    async fn response_from_proto(
2791        self,
2792        message: proto::GetCodeActionsResponse,
2793        _: Entity<LspStore>,
2794        buffer: Entity<Buffer>,
2795        mut cx: AsyncApp,
2796    ) -> Result<Vec<CodeAction>> {
2797        buffer
2798            .update(&mut cx, |buffer, _| {
2799                buffer.wait_for_version(deserialize_version(&message.version))
2800            })
2801            .await?;
2802        message
2803            .actions
2804            .into_iter()
2805            .map(LspStore::deserialize_code_action)
2806            .collect()
2807    }
2808
2809    fn buffer_id_from_proto(message: &proto::GetCodeActions) -> Result<BufferId> {
2810        BufferId::new(message.buffer_id)
2811    }
2812}
2813
2814impl GetCodeActions {
2815    fn supported_code_action_kinds(
2816        capabilities: AdapterServerCapabilities,
2817    ) -> Option<Vec<CodeActionKind>> {
2818        match capabilities.server_capabilities.code_action_provider {
2819            Some(lsp::CodeActionProviderCapability::Options(CodeActionOptions {
2820                code_action_kinds: Some(supported_action_kinds),
2821                ..
2822            })) => Some(supported_action_kinds),
2823            _ => capabilities.code_action_kinds,
2824        }
2825    }
2826
2827    pub fn can_resolve_actions(capabilities: &ServerCapabilities) -> bool {
2828        capabilities
2829            .code_action_provider
2830            .as_ref()
2831            .and_then(|options| match options {
2832                lsp::CodeActionProviderCapability::Simple(_is_supported) => None,
2833                lsp::CodeActionProviderCapability::Options(options) => options.resolve_provider,
2834            })
2835            .unwrap_or(false)
2836    }
2837}
2838
2839impl OnTypeFormatting {
2840    pub fn supports_on_type_formatting(trigger: &str, capabilities: &ServerCapabilities) -> bool {
2841        let Some(on_type_formatting_options) = &capabilities.document_on_type_formatting_provider
2842        else {
2843            return false;
2844        };
2845        on_type_formatting_options
2846            .first_trigger_character
2847            .contains(trigger)
2848            || on_type_formatting_options
2849                .more_trigger_character
2850                .iter()
2851                .flatten()
2852                .any(|chars| chars.contains(trigger))
2853    }
2854}
2855
2856#[async_trait(?Send)]
2857impl LspCommand for OnTypeFormatting {
2858    type Response = Option<Transaction>;
2859    type LspRequest = lsp::request::OnTypeFormatting;
2860    type ProtoRequest = proto::OnTypeFormatting;
2861
2862    fn display_name(&self) -> &str {
2863        "Formatting on typing"
2864    }
2865
2866    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2867        Self::supports_on_type_formatting(&self.trigger, &capabilities.server_capabilities)
2868    }
2869
2870    fn to_lsp(
2871        &self,
2872        path: &Path,
2873        _: &Buffer,
2874        _: &Arc<LanguageServer>,
2875        _: &App,
2876    ) -> Result<lsp::DocumentOnTypeFormattingParams> {
2877        Ok(lsp::DocumentOnTypeFormattingParams {
2878            text_document_position: make_lsp_text_document_position(path, self.position)?,
2879            ch: self.trigger.clone(),
2880            options: self.options.clone(),
2881        })
2882    }
2883
2884    async fn response_from_lsp(
2885        self,
2886        message: Option<Vec<lsp::TextEdit>>,
2887        lsp_store: Entity<LspStore>,
2888        buffer: Entity<Buffer>,
2889        server_id: LanguageServerId,
2890        mut cx: AsyncApp,
2891    ) -> Result<Option<Transaction>> {
2892        if let Some(edits) = message {
2893            let (lsp_adapter, lsp_server) =
2894                language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
2895            LocalLspStore::deserialize_text_edits(
2896                lsp_store,
2897                buffer,
2898                edits,
2899                self.push_to_history,
2900                lsp_adapter,
2901                lsp_server,
2902                &mut cx,
2903            )
2904            .await
2905        } else {
2906            Ok(None)
2907        }
2908    }
2909
2910    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::OnTypeFormatting {
2911        proto::OnTypeFormatting {
2912            project_id,
2913            buffer_id: buffer.remote_id().into(),
2914            position: Some(language::proto::serialize_anchor(
2915                &buffer.anchor_before(self.position),
2916            )),
2917            trigger: self.trigger.clone(),
2918            version: serialize_version(&buffer.version()),
2919        }
2920    }
2921
2922    async fn from_proto(
2923        message: proto::OnTypeFormatting,
2924        _: Entity<LspStore>,
2925        buffer: Entity<Buffer>,
2926        mut cx: AsyncApp,
2927    ) -> Result<Self> {
2928        let position = message
2929            .position
2930            .and_then(deserialize_anchor)
2931            .context("invalid position")?;
2932        buffer
2933            .update(&mut cx, |buffer, _| {
2934                buffer.wait_for_version(deserialize_version(&message.version))
2935            })
2936            .await?;
2937
2938        let options = buffer.update(&mut cx, |buffer, cx| {
2939            lsp_formatting_options(
2940                language_settings(buffer.language().map(|l| l.name()), buffer.file(), cx).as_ref(),
2941            )
2942        });
2943
2944        Ok(Self {
2945            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
2946            trigger: message.trigger.clone(),
2947            options,
2948            push_to_history: false,
2949        })
2950    }
2951
2952    fn response_to_proto(
2953        response: Option<Transaction>,
2954        _: &mut LspStore,
2955        _: PeerId,
2956        _: &clock::Global,
2957        _: &mut App,
2958    ) -> proto::OnTypeFormattingResponse {
2959        proto::OnTypeFormattingResponse {
2960            transaction: response
2961                .map(|transaction| language::proto::serialize_transaction(&transaction)),
2962        }
2963    }
2964
2965    async fn response_from_proto(
2966        self,
2967        message: proto::OnTypeFormattingResponse,
2968        _: Entity<LspStore>,
2969        _: Entity<Buffer>,
2970        _: AsyncApp,
2971    ) -> Result<Option<Transaction>> {
2972        let Some(transaction) = message.transaction else {
2973            return Ok(None);
2974        };
2975        Ok(Some(language::proto::deserialize_transaction(transaction)?))
2976    }
2977
2978    fn buffer_id_from_proto(message: &proto::OnTypeFormatting) -> Result<BufferId> {
2979        BufferId::new(message.buffer_id)
2980    }
2981}
2982
2983impl InlayHints {
2984    pub async fn lsp_to_project_hint(
2985        lsp_hint: lsp::InlayHint,
2986        buffer_handle: &Entity<Buffer>,
2987        server_id: LanguageServerId,
2988        resolve_state: ResolveState,
2989        force_no_type_left_padding: bool,
2990        cx: &mut AsyncApp,
2991    ) -> anyhow::Result<InlayHint> {
2992        let kind = lsp_hint.kind.and_then(|kind| match kind {
2993            lsp::InlayHintKind::TYPE => Some(InlayHintKind::Type),
2994            lsp::InlayHintKind::PARAMETER => Some(InlayHintKind::Parameter),
2995            _ => None,
2996        });
2997
2998        let position = buffer_handle.read_with(cx, |buffer, _| {
2999            let position = buffer.clip_point_utf16(point_from_lsp(lsp_hint.position), Bias::Left);
3000            if kind == Some(InlayHintKind::Parameter) {
3001                buffer.anchor_before(position)
3002            } else {
3003                buffer.anchor_after(position)
3004            }
3005        });
3006        let label = Self::lsp_inlay_label_to_project(lsp_hint.label, server_id)
3007            .await
3008            .context("lsp to project inlay hint conversion")?;
3009        let padding_left = if force_no_type_left_padding && kind == Some(InlayHintKind::Type) {
3010            false
3011        } else {
3012            lsp_hint.padding_left.unwrap_or(false)
3013        };
3014
3015        Ok(InlayHint {
3016            position,
3017            padding_left,
3018            padding_right: lsp_hint.padding_right.unwrap_or(false),
3019            label,
3020            kind,
3021            tooltip: lsp_hint.tooltip.map(|tooltip| match tooltip {
3022                lsp::InlayHintTooltip::String(s) => InlayHintTooltip::String(s),
3023                lsp::InlayHintTooltip::MarkupContent(markup_content) => {
3024                    InlayHintTooltip::MarkupContent(MarkupContent {
3025                        kind: match markup_content.kind {
3026                            lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
3027                            lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
3028                        },
3029                        value: markup_content.value,
3030                    })
3031                }
3032            }),
3033            resolve_state,
3034        })
3035    }
3036
3037    async fn lsp_inlay_label_to_project(
3038        lsp_label: lsp::InlayHintLabel,
3039        server_id: LanguageServerId,
3040    ) -> anyhow::Result<InlayHintLabel> {
3041        let label = match lsp_label {
3042            lsp::InlayHintLabel::String(s) => InlayHintLabel::String(s),
3043            lsp::InlayHintLabel::LabelParts(lsp_parts) => {
3044                let mut parts = Vec::with_capacity(lsp_parts.len());
3045                for lsp_part in lsp_parts {
3046                    parts.push(InlayHintLabelPart {
3047                        value: lsp_part.value,
3048                        tooltip: lsp_part.tooltip.map(|tooltip| match tooltip {
3049                            lsp::InlayHintLabelPartTooltip::String(s) => {
3050                                InlayHintLabelPartTooltip::String(s)
3051                            }
3052                            lsp::InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
3053                                InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
3054                                    kind: match markup_content.kind {
3055                                        lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
3056                                        lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
3057                                    },
3058                                    value: markup_content.value,
3059                                })
3060                            }
3061                        }),
3062                        location: Some(server_id).zip(lsp_part.location),
3063                    });
3064                }
3065                InlayHintLabel::LabelParts(parts)
3066            }
3067        };
3068
3069        Ok(label)
3070    }
3071
3072    pub fn project_to_proto_hint(response_hint: InlayHint) -> proto::InlayHint {
3073        let (state, lsp_resolve_state) = match response_hint.resolve_state {
3074            ResolveState::Resolved => (0, None),
3075            ResolveState::CanResolve(server_id, resolve_data) => (
3076                1,
3077                Some(proto::resolve_state::LspResolveState {
3078                    server_id: server_id.0 as u64,
3079                    value: resolve_data.map(|json_data| {
3080                        serde_json::to_string(&json_data)
3081                            .expect("failed to serialize resolve json data")
3082                    }),
3083                }),
3084            ),
3085            ResolveState::Resolving => (2, None),
3086        };
3087        let resolve_state = Some(proto::ResolveState {
3088            state,
3089            lsp_resolve_state,
3090        });
3091        proto::InlayHint {
3092            position: Some(language::proto::serialize_anchor(&response_hint.position)),
3093            padding_left: response_hint.padding_left,
3094            padding_right: response_hint.padding_right,
3095            label: Some(proto::InlayHintLabel {
3096                label: Some(match response_hint.label {
3097                    InlayHintLabel::String(s) => proto::inlay_hint_label::Label::Value(s),
3098                    InlayHintLabel::LabelParts(label_parts) => {
3099                        proto::inlay_hint_label::Label::LabelParts(proto::InlayHintLabelParts {
3100                            parts: label_parts.into_iter().map(|label_part| {
3101                                let location_url = label_part.location.as_ref().map(|(_, location)| location.uri.to_string());
3102                                let location_range_start = label_part.location.as_ref().map(|(_, location)| point_from_lsp(location.range.start).0).map(|point| proto::PointUtf16 { row: point.row, column: point.column });
3103                                let location_range_end = label_part.location.as_ref().map(|(_, location)| point_from_lsp(location.range.end).0).map(|point| proto::PointUtf16 { row: point.row, column: point.column });
3104                                proto::InlayHintLabelPart {
3105                                value: label_part.value,
3106                                tooltip: label_part.tooltip.map(|tooltip| {
3107                                    let proto_tooltip = match tooltip {
3108                                        InlayHintLabelPartTooltip::String(s) => proto::inlay_hint_label_part_tooltip::Content::Value(s),
3109                                        InlayHintLabelPartTooltip::MarkupContent(markup_content) => proto::inlay_hint_label_part_tooltip::Content::MarkupContent(proto::MarkupContent {
3110                                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
3111                                            value: markup_content.value,
3112                                        }),
3113                                    };
3114                                    proto::InlayHintLabelPartTooltip {content: Some(proto_tooltip)}
3115                                }),
3116                                location_url,
3117                                location_range_start,
3118                                location_range_end,
3119                                language_server_id: label_part.location.as_ref().map(|(server_id, _)| server_id.0 as u64),
3120                            }}).collect()
3121                        })
3122                    }
3123                }),
3124            }),
3125            kind: response_hint.kind.map(|kind| kind.name().to_string()),
3126            tooltip: response_hint.tooltip.map(|response_tooltip| {
3127                let proto_tooltip = match response_tooltip {
3128                    InlayHintTooltip::String(s) => proto::inlay_hint_tooltip::Content::Value(s),
3129                    InlayHintTooltip::MarkupContent(markup_content) => {
3130                        proto::inlay_hint_tooltip::Content::MarkupContent(proto::MarkupContent {
3131                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
3132                            value: markup_content.value,
3133                        })
3134                    }
3135                };
3136                proto::InlayHintTooltip {
3137                    content: Some(proto_tooltip),
3138                }
3139            }),
3140            resolve_state,
3141        }
3142    }
3143
3144    pub fn proto_to_project_hint(message_hint: proto::InlayHint) -> anyhow::Result<InlayHint> {
3145        let resolve_state = message_hint.resolve_state.as_ref().unwrap_or_else(|| {
3146            panic!("incorrect proto inlay hint message: no resolve state in hint {message_hint:?}",)
3147        });
3148        let resolve_state_data = resolve_state
3149            .lsp_resolve_state.as_ref()
3150            .map(|lsp_resolve_state| {
3151                let value = lsp_resolve_state.value.as_deref().map(|value| {
3152                    serde_json::from_str::<Option<lsp::LSPAny>>(value)
3153                        .with_context(|| format!("incorrect proto inlay hint message: non-json resolve state {lsp_resolve_state:?}"))
3154                }).transpose()?.flatten();
3155                anyhow::Ok((LanguageServerId(lsp_resolve_state.server_id as usize), value))
3156            })
3157            .transpose()?;
3158        let resolve_state = match resolve_state.state {
3159            0 => ResolveState::Resolved,
3160            1 => {
3161                let (server_id, lsp_resolve_state) = resolve_state_data.with_context(|| {
3162                    format!(
3163                        "No lsp resolve data for the hint that can be resolved: {message_hint:?}"
3164                    )
3165                })?;
3166                ResolveState::CanResolve(server_id, lsp_resolve_state)
3167            }
3168            2 => ResolveState::Resolving,
3169            invalid => {
3170                anyhow::bail!("Unexpected resolve state {invalid} for hint {message_hint:?}")
3171            }
3172        };
3173        Ok(InlayHint {
3174            position: message_hint
3175                .position
3176                .and_then(language::proto::deserialize_anchor)
3177                .context("invalid position")?,
3178            label: match message_hint
3179                .label
3180                .and_then(|label| label.label)
3181                .context("missing label")?
3182            {
3183                proto::inlay_hint_label::Label::Value(s) => InlayHintLabel::String(s),
3184                proto::inlay_hint_label::Label::LabelParts(parts) => {
3185                    let mut label_parts = Vec::new();
3186                    for part in parts.parts {
3187                        label_parts.push(InlayHintLabelPart {
3188                            value: part.value,
3189                            tooltip: part.tooltip.map(|tooltip| match tooltip.content {
3190                                Some(proto::inlay_hint_label_part_tooltip::Content::Value(s)) => {
3191                                    InlayHintLabelPartTooltip::String(s)
3192                                }
3193                                Some(
3194                                    proto::inlay_hint_label_part_tooltip::Content::MarkupContent(
3195                                        markup_content,
3196                                    ),
3197                                ) => InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
3198                                    kind: if markup_content.is_markdown {
3199                                        HoverBlockKind::Markdown
3200                                    } else {
3201                                        HoverBlockKind::PlainText
3202                                    },
3203                                    value: markup_content.value,
3204                                }),
3205                                None => InlayHintLabelPartTooltip::String(String::new()),
3206                            }),
3207                            location: {
3208                                match part
3209                                    .location_url
3210                                    .zip(
3211                                        part.location_range_start.and_then(|start| {
3212                                            Some(start..part.location_range_end?)
3213                                        }),
3214                                    )
3215                                    .zip(part.language_server_id)
3216                                {
3217                                    Some(((uri, range), server_id)) => Some((
3218                                        LanguageServerId(server_id as usize),
3219                                        lsp::Location {
3220                                            uri: lsp::Uri::from_str(&uri)
3221                                                .context("invalid uri in hint part {part:?}")?,
3222                                            range: lsp::Range::new(
3223                                                point_to_lsp(PointUtf16::new(
3224                                                    range.start.row,
3225                                                    range.start.column,
3226                                                )),
3227                                                point_to_lsp(PointUtf16::new(
3228                                                    range.end.row,
3229                                                    range.end.column,
3230                                                )),
3231                                            ),
3232                                        },
3233                                    )),
3234                                    None => None,
3235                                }
3236                            },
3237                        });
3238                    }
3239
3240                    InlayHintLabel::LabelParts(label_parts)
3241                }
3242            },
3243            padding_left: message_hint.padding_left,
3244            padding_right: message_hint.padding_right,
3245            kind: message_hint
3246                .kind
3247                .as_deref()
3248                .and_then(InlayHintKind::from_name),
3249            tooltip: message_hint.tooltip.and_then(|tooltip| {
3250                Some(match tooltip.content? {
3251                    proto::inlay_hint_tooltip::Content::Value(s) => InlayHintTooltip::String(s),
3252                    proto::inlay_hint_tooltip::Content::MarkupContent(markup_content) => {
3253                        InlayHintTooltip::MarkupContent(MarkupContent {
3254                            kind: if markup_content.is_markdown {
3255                                HoverBlockKind::Markdown
3256                            } else {
3257                                HoverBlockKind::PlainText
3258                            },
3259                            value: markup_content.value,
3260                        })
3261                    }
3262                })
3263            }),
3264            resolve_state,
3265        })
3266    }
3267
3268    pub fn project_to_lsp_hint(hint: InlayHint, snapshot: &BufferSnapshot) -> lsp::InlayHint {
3269        lsp::InlayHint {
3270            position: point_to_lsp(hint.position.to_point_utf16(snapshot)),
3271            kind: hint.kind.map(|kind| match kind {
3272                InlayHintKind::Type => lsp::InlayHintKind::TYPE,
3273                InlayHintKind::Parameter => lsp::InlayHintKind::PARAMETER,
3274            }),
3275            text_edits: None,
3276            tooltip: hint.tooltip.and_then(|tooltip| {
3277                Some(match tooltip {
3278                    InlayHintTooltip::String(s) => lsp::InlayHintTooltip::String(s),
3279                    InlayHintTooltip::MarkupContent(markup_content) => {
3280                        lsp::InlayHintTooltip::MarkupContent(lsp::MarkupContent {
3281                            kind: match markup_content.kind {
3282                                HoverBlockKind::PlainText => lsp::MarkupKind::PlainText,
3283                                HoverBlockKind::Markdown => lsp::MarkupKind::Markdown,
3284                                HoverBlockKind::Code { .. } => return None,
3285                            },
3286                            value: markup_content.value,
3287                        })
3288                    }
3289                })
3290            }),
3291            label: match hint.label {
3292                InlayHintLabel::String(s) => lsp::InlayHintLabel::String(s),
3293                InlayHintLabel::LabelParts(label_parts) => lsp::InlayHintLabel::LabelParts(
3294                    label_parts
3295                        .into_iter()
3296                        .map(|part| lsp::InlayHintLabelPart {
3297                            value: part.value,
3298                            tooltip: part.tooltip.and_then(|tooltip| {
3299                                Some(match tooltip {
3300                                    InlayHintLabelPartTooltip::String(s) => {
3301                                        lsp::InlayHintLabelPartTooltip::String(s)
3302                                    }
3303                                    InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
3304                                        lsp::InlayHintLabelPartTooltip::MarkupContent(
3305                                            lsp::MarkupContent {
3306                                                kind: match markup_content.kind {
3307                                                    HoverBlockKind::PlainText => {
3308                                                        lsp::MarkupKind::PlainText
3309                                                    }
3310                                                    HoverBlockKind::Markdown => {
3311                                                        lsp::MarkupKind::Markdown
3312                                                    }
3313                                                    HoverBlockKind::Code { .. } => return None,
3314                                                },
3315                                                value: markup_content.value,
3316                                            },
3317                                        )
3318                                    }
3319                                })
3320                            }),
3321                            location: part.location.map(|(_, location)| location),
3322                            command: None,
3323                        })
3324                        .collect(),
3325                ),
3326            },
3327            padding_left: Some(hint.padding_left),
3328            padding_right: Some(hint.padding_right),
3329            data: match hint.resolve_state {
3330                ResolveState::CanResolve(_, data) => data,
3331                ResolveState::Resolving | ResolveState::Resolved => None,
3332            },
3333        }
3334    }
3335
3336    pub fn can_resolve_inlays(capabilities: &ServerCapabilities) -> bool {
3337        capabilities
3338            .inlay_hint_provider
3339            .as_ref()
3340            .and_then(|options| match options {
3341                OneOf::Left(_is_supported) => None,
3342                OneOf::Right(capabilities) => match capabilities {
3343                    lsp::InlayHintServerCapabilities::Options(o) => o.resolve_provider,
3344                    lsp::InlayHintServerCapabilities::RegistrationOptions(o) => {
3345                        o.inlay_hint_options.resolve_provider
3346                    }
3347                },
3348            })
3349            .unwrap_or(false)
3350    }
3351
3352    pub fn check_capabilities(capabilities: &ServerCapabilities) -> bool {
3353        capabilities
3354            .inlay_hint_provider
3355            .as_ref()
3356            .is_some_and(|inlay_hint_provider| match inlay_hint_provider {
3357                lsp::OneOf::Left(enabled) => *enabled,
3358                lsp::OneOf::Right(_) => true,
3359            })
3360    }
3361}
3362
3363#[async_trait(?Send)]
3364impl LspCommand for InlayHints {
3365    type Response = Vec<InlayHint>;
3366    type LspRequest = lsp::InlayHintRequest;
3367    type ProtoRequest = proto::InlayHints;
3368
3369    fn display_name(&self) -> &str {
3370        "Inlay hints"
3371    }
3372
3373    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3374        Self::check_capabilities(&capabilities.server_capabilities)
3375    }
3376
3377    fn to_lsp(
3378        &self,
3379        path: &Path,
3380        buffer: &Buffer,
3381        _: &Arc<LanguageServer>,
3382        _: &App,
3383    ) -> Result<lsp::InlayHintParams> {
3384        Ok(lsp::InlayHintParams {
3385            text_document: lsp::TextDocumentIdentifier {
3386                uri: file_path_to_lsp_url(path)?,
3387            },
3388            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
3389            work_done_progress_params: Default::default(),
3390        })
3391    }
3392
3393    async fn response_from_lsp(
3394        self,
3395        message: Option<Vec<lsp::InlayHint>>,
3396        lsp_store: Entity<LspStore>,
3397        buffer: Entity<Buffer>,
3398        server_id: LanguageServerId,
3399        mut cx: AsyncApp,
3400    ) -> anyhow::Result<Vec<InlayHint>> {
3401        let (lsp_adapter, lsp_server) =
3402            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
3403        // `typescript-language-server` adds padding to the left for type hints, turning
3404        // `const foo: boolean` into `const foo : boolean` which looks odd.
3405        // `rust-analyzer` does not have the padding for this case, and we have to accommodate both.
3406        //
3407        // We could trim the whole string, but being pessimistic on par with the situation above,
3408        // there might be a hint with multiple whitespaces at the end(s) which we need to display properly.
3409        // Hence let's use a heuristic first to handle the most awkward case and look for more.
3410        let force_no_type_left_padding =
3411            lsp_adapter.name.0.as_ref() == "typescript-language-server";
3412
3413        let hints = message.unwrap_or_default().into_iter().map(|lsp_hint| {
3414            let resolve_state = if InlayHints::can_resolve_inlays(&lsp_server.capabilities()) {
3415                ResolveState::CanResolve(lsp_server.server_id(), lsp_hint.data.clone())
3416            } else {
3417                ResolveState::Resolved
3418            };
3419
3420            let buffer = buffer.clone();
3421            cx.spawn(async move |cx| {
3422                InlayHints::lsp_to_project_hint(
3423                    lsp_hint,
3424                    &buffer,
3425                    server_id,
3426                    resolve_state,
3427                    force_no_type_left_padding,
3428                    cx,
3429                )
3430                .await
3431            })
3432        });
3433        future::join_all(hints)
3434            .await
3435            .into_iter()
3436            .collect::<anyhow::Result<_>>()
3437            .context("lsp to project inlay hints conversion")
3438    }
3439
3440    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::InlayHints {
3441        proto::InlayHints {
3442            project_id,
3443            buffer_id: buffer.remote_id().into(),
3444            start: Some(language::proto::serialize_anchor(&self.range.start)),
3445            end: Some(language::proto::serialize_anchor(&self.range.end)),
3446            version: serialize_version(&buffer.version()),
3447        }
3448    }
3449
3450    async fn from_proto(
3451        message: proto::InlayHints,
3452        _: Entity<LspStore>,
3453        buffer: Entity<Buffer>,
3454        mut cx: AsyncApp,
3455    ) -> Result<Self> {
3456        let start = message
3457            .start
3458            .and_then(language::proto::deserialize_anchor)
3459            .context("invalid start")?;
3460        let end = message
3461            .end
3462            .and_then(language::proto::deserialize_anchor)
3463            .context("invalid end")?;
3464        buffer
3465            .update(&mut cx, |buffer, _| {
3466                buffer.wait_for_version(deserialize_version(&message.version))
3467            })
3468            .await?;
3469
3470        Ok(Self { range: start..end })
3471    }
3472
3473    fn response_to_proto(
3474        response: Vec<InlayHint>,
3475        _: &mut LspStore,
3476        _: PeerId,
3477        buffer_version: &clock::Global,
3478        _: &mut App,
3479    ) -> proto::InlayHintsResponse {
3480        proto::InlayHintsResponse {
3481            hints: response
3482                .into_iter()
3483                .map(InlayHints::project_to_proto_hint)
3484                .collect(),
3485            version: serialize_version(buffer_version),
3486        }
3487    }
3488
3489    async fn response_from_proto(
3490        self,
3491        message: proto::InlayHintsResponse,
3492        _: Entity<LspStore>,
3493        buffer: Entity<Buffer>,
3494        mut cx: AsyncApp,
3495    ) -> anyhow::Result<Vec<InlayHint>> {
3496        buffer
3497            .update(&mut cx, |buffer, _| {
3498                buffer.wait_for_version(deserialize_version(&message.version))
3499            })
3500            .await?;
3501
3502        let mut hints = Vec::new();
3503        for message_hint in message.hints {
3504            hints.push(InlayHints::proto_to_project_hint(message_hint)?);
3505        }
3506
3507        Ok(hints)
3508    }
3509
3510    fn buffer_id_from_proto(message: &proto::InlayHints) -> Result<BufferId> {
3511        BufferId::new(message.buffer_id)
3512    }
3513}
3514
3515#[async_trait(?Send)]
3516impl LspCommand for SemanticTokensFull {
3517    type Response = SemanticTokensResponse;
3518    type LspRequest = lsp::SemanticTokensFullRequest;
3519    type ProtoRequest = proto::SemanticTokens;
3520
3521    fn display_name(&self) -> &str {
3522        "Semantic tokens full"
3523    }
3524
3525    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3526        capabilities
3527            .server_capabilities
3528            .semantic_tokens_provider
3529            .as_ref()
3530            .is_some_and(|semantic_tokens_provider| {
3531                let options = match semantic_tokens_provider {
3532                    lsp::SemanticTokensServerCapabilities::SemanticTokensOptions(opts) => opts,
3533                    lsp::SemanticTokensServerCapabilities::SemanticTokensRegistrationOptions(
3534                        opts,
3535                    ) => &opts.semantic_tokens_options,
3536                };
3537
3538                match options.full {
3539                    Some(lsp::SemanticTokensFullOptions::Bool(is_supported)) => is_supported,
3540                    Some(lsp::SemanticTokensFullOptions::Delta { .. }) => true,
3541                    None => false,
3542                }
3543            })
3544    }
3545
3546    fn to_lsp(
3547        &self,
3548        path: &Path,
3549        _: &Buffer,
3550        _: &Arc<LanguageServer>,
3551        _: &App,
3552    ) -> Result<lsp::SemanticTokensParams> {
3553        Ok(lsp::SemanticTokensParams {
3554            text_document: lsp::TextDocumentIdentifier {
3555                uri: file_path_to_lsp_url(path)?,
3556            },
3557            partial_result_params: Default::default(),
3558            work_done_progress_params: Default::default(),
3559        })
3560    }
3561
3562    async fn response_from_lsp(
3563        self,
3564        message: Option<lsp::SemanticTokensResult>,
3565        _: Entity<LspStore>,
3566        _: Entity<Buffer>,
3567        _: LanguageServerId,
3568        _: AsyncApp,
3569    ) -> anyhow::Result<SemanticTokensResponse> {
3570        match message {
3571            Some(lsp::SemanticTokensResult::Tokens(tokens)) => Ok(SemanticTokensResponse::Full {
3572                data: tokens.data,
3573                result_id: tokens.result_id.map(SharedString::new),
3574            }),
3575            Some(lsp::SemanticTokensResult::Partial(_)) => {
3576                anyhow::bail!(
3577                    "Unexpected semantic tokens response with partial result for inlay hints"
3578                )
3579            }
3580            None => Ok(Default::default()),
3581        }
3582    }
3583
3584    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::SemanticTokens {
3585        proto::SemanticTokens {
3586            project_id,
3587            buffer_id: buffer.remote_id().into(),
3588            version: serialize_version(&buffer.version()),
3589            for_server: self.for_server.map(|id| id.to_proto()),
3590        }
3591    }
3592
3593    async fn from_proto(
3594        message: proto::SemanticTokens,
3595        _: Entity<LspStore>,
3596        buffer: Entity<Buffer>,
3597        mut cx: AsyncApp,
3598    ) -> Result<Self> {
3599        buffer
3600            .update(&mut cx, |buffer, _| {
3601                buffer.wait_for_version(deserialize_version(&message.version))
3602            })
3603            .await?;
3604
3605        Ok(Self {
3606            for_server: message
3607                .for_server
3608                .map(|id| LanguageServerId::from_proto(id)),
3609        })
3610    }
3611
3612    fn response_to_proto(
3613        response: SemanticTokensResponse,
3614        _: &mut LspStore,
3615        _: PeerId,
3616        buffer_version: &clock::Global,
3617        _: &mut App,
3618    ) -> proto::SemanticTokensResponse {
3619        match response {
3620            SemanticTokensResponse::Full { data, result_id } => proto::SemanticTokensResponse {
3621                data,
3622                edits: Vec::new(),
3623                result_id: result_id.map(|s| s.to_string()),
3624                version: serialize_version(buffer_version),
3625            },
3626            SemanticTokensResponse::Delta { edits, result_id } => proto::SemanticTokensResponse {
3627                data: Vec::new(),
3628                edits: edits
3629                    .into_iter()
3630                    .map(|edit| proto::SemanticTokensEdit {
3631                        start: edit.start,
3632                        delete_count: edit.delete_count,
3633                        data: edit.data,
3634                    })
3635                    .collect(),
3636                result_id: result_id.map(|s| s.to_string()),
3637                version: serialize_version(buffer_version),
3638            },
3639        }
3640    }
3641
3642    async fn response_from_proto(
3643        self,
3644        message: proto::SemanticTokensResponse,
3645        _: Entity<LspStore>,
3646        buffer: Entity<Buffer>,
3647        mut cx: AsyncApp,
3648    ) -> anyhow::Result<SemanticTokensResponse> {
3649        buffer
3650            .update(&mut cx, |buffer, _| {
3651                buffer.wait_for_version(deserialize_version(&message.version))
3652            })
3653            .await?;
3654
3655        Ok(SemanticTokensResponse::Full {
3656            data: message.data,
3657            result_id: message.result_id.map(SharedString::new),
3658        })
3659    }
3660
3661    fn buffer_id_from_proto(message: &proto::SemanticTokens) -> Result<BufferId> {
3662        BufferId::new(message.buffer_id)
3663    }
3664}
3665
3666#[async_trait(?Send)]
3667impl LspCommand for SemanticTokensDelta {
3668    type Response = SemanticTokensResponse;
3669    type LspRequest = lsp::SemanticTokensFullDeltaRequest;
3670    type ProtoRequest = proto::SemanticTokens;
3671
3672    fn display_name(&self) -> &str {
3673        "Semantic tokens delta"
3674    }
3675
3676    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3677        capabilities
3678            .server_capabilities
3679            .semantic_tokens_provider
3680            .as_ref()
3681            .is_some_and(|semantic_tokens_provider| {
3682                let options = match semantic_tokens_provider {
3683                    lsp::SemanticTokensServerCapabilities::SemanticTokensOptions(opts) => opts,
3684                    lsp::SemanticTokensServerCapabilities::SemanticTokensRegistrationOptions(
3685                        opts,
3686                    ) => &opts.semantic_tokens_options,
3687                };
3688
3689                match options.full {
3690                    Some(lsp::SemanticTokensFullOptions::Delta { delta }) => delta.unwrap_or(false),
3691                    // `full: true` (instead of `full: { delta: true }`) means no support for delta.
3692                    _ => false,
3693                }
3694            })
3695    }
3696
3697    fn to_lsp(
3698        &self,
3699        path: &Path,
3700        _: &Buffer,
3701        _: &Arc<LanguageServer>,
3702        _: &App,
3703    ) -> Result<lsp::SemanticTokensDeltaParams> {
3704        Ok(lsp::SemanticTokensDeltaParams {
3705            text_document: lsp::TextDocumentIdentifier {
3706                uri: file_path_to_lsp_url(path)?,
3707            },
3708            previous_result_id: self.previous_result_id.clone().map(|s| s.to_string()),
3709            partial_result_params: Default::default(),
3710            work_done_progress_params: Default::default(),
3711        })
3712    }
3713
3714    async fn response_from_lsp(
3715        self,
3716        message: Option<lsp::SemanticTokensFullDeltaResult>,
3717        _: Entity<LspStore>,
3718        _: Entity<Buffer>,
3719        _: LanguageServerId,
3720        _: AsyncApp,
3721    ) -> anyhow::Result<SemanticTokensResponse> {
3722        match message {
3723            Some(lsp::SemanticTokensFullDeltaResult::Tokens(tokens)) => {
3724                Ok(SemanticTokensResponse::Full {
3725                    data: tokens.data,
3726                    result_id: tokens.result_id.map(SharedString::new),
3727                })
3728            }
3729            Some(lsp::SemanticTokensFullDeltaResult::TokensDelta(delta)) => {
3730                Ok(SemanticTokensResponse::Delta {
3731                    edits: delta
3732                        .edits
3733                        .into_iter()
3734                        .map(|e| SemanticTokensEdit {
3735                            start: e.start,
3736                            delete_count: e.delete_count,
3737                            data: e.data.unwrap_or_default(),
3738                        })
3739                        .collect(),
3740                    result_id: delta.result_id.map(SharedString::new),
3741                })
3742            }
3743            Some(lsp::SemanticTokensFullDeltaResult::PartialTokensDelta { .. }) => {
3744                anyhow::bail!(
3745                    "Unexpected semantic tokens response with partial result for inlay hints"
3746                )
3747            }
3748            None => Ok(Default::default()),
3749        }
3750    }
3751
3752    fn to_proto(&self, _: u64, _: &Buffer) -> proto::SemanticTokens {
3753        unimplemented!("Delta requests are never initialted on the remote client side")
3754    }
3755
3756    async fn from_proto(
3757        _: proto::SemanticTokens,
3758        _: Entity<LspStore>,
3759        _: Entity<Buffer>,
3760        _: AsyncApp,
3761    ) -> Result<Self> {
3762        unimplemented!("Delta requests are never initialted on the remote client side")
3763    }
3764
3765    fn response_to_proto(
3766        response: SemanticTokensResponse,
3767        _: &mut LspStore,
3768        _: PeerId,
3769        buffer_version: &clock::Global,
3770        _: &mut App,
3771    ) -> proto::SemanticTokensResponse {
3772        match response {
3773            SemanticTokensResponse::Full { data, result_id } => proto::SemanticTokensResponse {
3774                data,
3775                edits: Vec::new(),
3776                result_id: result_id.map(|s| s.to_string()),
3777                version: serialize_version(buffer_version),
3778            },
3779            SemanticTokensResponse::Delta { edits, result_id } => proto::SemanticTokensResponse {
3780                data: Vec::new(),
3781                edits: edits
3782                    .into_iter()
3783                    .map(|edit| proto::SemanticTokensEdit {
3784                        start: edit.start,
3785                        delete_count: edit.delete_count,
3786                        data: edit.data,
3787                    })
3788                    .collect(),
3789                result_id: result_id.map(|s| s.to_string()),
3790                version: serialize_version(buffer_version),
3791            },
3792        }
3793    }
3794
3795    async fn response_from_proto(
3796        self,
3797        message: proto::SemanticTokensResponse,
3798        _: Entity<LspStore>,
3799        buffer: Entity<Buffer>,
3800        mut cx: AsyncApp,
3801    ) -> anyhow::Result<SemanticTokensResponse> {
3802        buffer
3803            .update(&mut cx, |buffer, _| {
3804                buffer.wait_for_version(deserialize_version(&message.version))
3805            })
3806            .await?;
3807
3808        Ok(SemanticTokensResponse::Full {
3809            data: message.data,
3810            result_id: message.result_id.map(SharedString::new),
3811        })
3812    }
3813
3814    fn buffer_id_from_proto(message: &proto::SemanticTokens) -> Result<BufferId> {
3815        BufferId::new(message.buffer_id)
3816    }
3817}
3818
3819#[async_trait(?Send)]
3820impl LspCommand for GetCodeLens {
3821    type Response = Vec<CodeAction>;
3822    type LspRequest = lsp::CodeLensRequest;
3823    type ProtoRequest = proto::GetCodeLens;
3824
3825    fn display_name(&self) -> &str {
3826        "Code Lens"
3827    }
3828
3829    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3830        capabilities
3831            .server_capabilities
3832            .code_lens_provider
3833            .is_some()
3834    }
3835
3836    fn to_lsp(
3837        &self,
3838        path: &Path,
3839        _: &Buffer,
3840        _: &Arc<LanguageServer>,
3841        _: &App,
3842    ) -> Result<lsp::CodeLensParams> {
3843        Ok(lsp::CodeLensParams {
3844            text_document: lsp::TextDocumentIdentifier {
3845                uri: file_path_to_lsp_url(path)?,
3846            },
3847            work_done_progress_params: lsp::WorkDoneProgressParams::default(),
3848            partial_result_params: lsp::PartialResultParams::default(),
3849        })
3850    }
3851
3852    async fn response_from_lsp(
3853        self,
3854        message: Option<Vec<lsp::CodeLens>>,
3855        lsp_store: Entity<LspStore>,
3856        buffer: Entity<Buffer>,
3857        server_id: LanguageServerId,
3858        cx: AsyncApp,
3859    ) -> anyhow::Result<Vec<CodeAction>> {
3860        let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
3861        let language_server = cx.update(|cx| {
3862            lsp_store
3863                .read(cx)
3864                .language_server_for_id(server_id)
3865                .with_context(|| {
3866                    format!("Missing the language server that just returned a response {server_id}")
3867                })
3868        })?;
3869        let server_capabilities = language_server.capabilities();
3870        let available_commands = server_capabilities
3871            .execute_command_provider
3872            .as_ref()
3873            .map(|options| options.commands.as_slice())
3874            .unwrap_or_default();
3875        Ok(message
3876            .unwrap_or_default()
3877            .into_iter()
3878            .filter(|code_lens| {
3879                code_lens
3880                    .command
3881                    .as_ref()
3882                    .is_none_or(|command| available_commands.contains(&command.command))
3883            })
3884            .map(|code_lens| {
3885                let code_lens_range = range_from_lsp(code_lens.range);
3886                let start = snapshot.clip_point_utf16(code_lens_range.start, Bias::Left);
3887                let end = snapshot.clip_point_utf16(code_lens_range.end, Bias::Right);
3888                let range = snapshot.anchor_before(start)..snapshot.anchor_after(end);
3889                CodeAction {
3890                    server_id,
3891                    range,
3892                    lsp_action: LspAction::CodeLens(code_lens),
3893                    resolved: false,
3894                }
3895            })
3896            .collect())
3897    }
3898
3899    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeLens {
3900        proto::GetCodeLens {
3901            project_id,
3902            buffer_id: buffer.remote_id().into(),
3903            version: serialize_version(&buffer.version()),
3904        }
3905    }
3906
3907    async fn from_proto(
3908        message: proto::GetCodeLens,
3909        _: Entity<LspStore>,
3910        buffer: Entity<Buffer>,
3911        mut cx: AsyncApp,
3912    ) -> Result<Self> {
3913        buffer
3914            .update(&mut cx, |buffer, _| {
3915                buffer.wait_for_version(deserialize_version(&message.version))
3916            })
3917            .await?;
3918        Ok(Self)
3919    }
3920
3921    fn response_to_proto(
3922        response: Vec<CodeAction>,
3923        _: &mut LspStore,
3924        _: PeerId,
3925        buffer_version: &clock::Global,
3926        _: &mut App,
3927    ) -> proto::GetCodeLensResponse {
3928        proto::GetCodeLensResponse {
3929            lens_actions: response
3930                .iter()
3931                .map(LspStore::serialize_code_action)
3932                .collect(),
3933            version: serialize_version(buffer_version),
3934        }
3935    }
3936
3937    async fn response_from_proto(
3938        self,
3939        message: proto::GetCodeLensResponse,
3940        _: Entity<LspStore>,
3941        buffer: Entity<Buffer>,
3942        mut cx: AsyncApp,
3943    ) -> anyhow::Result<Vec<CodeAction>> {
3944        buffer
3945            .update(&mut cx, |buffer, _| {
3946                buffer.wait_for_version(deserialize_version(&message.version))
3947            })
3948            .await?;
3949        message
3950            .lens_actions
3951            .into_iter()
3952            .map(LspStore::deserialize_code_action)
3953            .collect::<Result<Vec<_>>>()
3954            .context("deserializing proto code lens response")
3955    }
3956
3957    fn buffer_id_from_proto(message: &proto::GetCodeLens) -> Result<BufferId> {
3958        BufferId::new(message.buffer_id)
3959    }
3960}
3961
3962impl LinkedEditingRange {
3963    pub fn check_server_capabilities(capabilities: ServerCapabilities) -> bool {
3964        let Some(linked_editing_options) = capabilities.linked_editing_range_provider else {
3965            return false;
3966        };
3967        if let LinkedEditingRangeServerCapabilities::Simple(false) = linked_editing_options {
3968            return false;
3969        }
3970        true
3971    }
3972}
3973
3974#[async_trait(?Send)]
3975impl LspCommand for LinkedEditingRange {
3976    type Response = Vec<Range<Anchor>>;
3977    type LspRequest = lsp::request::LinkedEditingRange;
3978    type ProtoRequest = proto::LinkedEditingRange;
3979
3980    fn display_name(&self) -> &str {
3981        "Linked editing range"
3982    }
3983
3984    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3985        Self::check_server_capabilities(capabilities.server_capabilities)
3986    }
3987
3988    fn to_lsp(
3989        &self,
3990        path: &Path,
3991        buffer: &Buffer,
3992        _server: &Arc<LanguageServer>,
3993        _: &App,
3994    ) -> Result<lsp::LinkedEditingRangeParams> {
3995        let position = self.position.to_point_utf16(&buffer.snapshot());
3996        Ok(lsp::LinkedEditingRangeParams {
3997            text_document_position_params: make_lsp_text_document_position(path, position)?,
3998            work_done_progress_params: Default::default(),
3999        })
4000    }
4001
4002    async fn response_from_lsp(
4003        self,
4004        message: Option<lsp::LinkedEditingRanges>,
4005        _: Entity<LspStore>,
4006        buffer: Entity<Buffer>,
4007        _server_id: LanguageServerId,
4008        cx: AsyncApp,
4009    ) -> Result<Vec<Range<Anchor>>> {
4010        if let Some(lsp::LinkedEditingRanges { mut ranges, .. }) = message {
4011            ranges.sort_by_key(|range| range.start);
4012
4013            Ok(buffer.read_with(&cx, |buffer, _| {
4014                ranges
4015                    .into_iter()
4016                    .map(|range| {
4017                        let start =
4018                            buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
4019                        let end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
4020                        buffer.anchor_before(start)..buffer.anchor_after(end)
4021                    })
4022                    .collect()
4023            }))
4024        } else {
4025            Ok(vec![])
4026        }
4027    }
4028
4029    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::LinkedEditingRange {
4030        proto::LinkedEditingRange {
4031            project_id,
4032            buffer_id: buffer.remote_id().to_proto(),
4033            position: Some(serialize_anchor(&self.position)),
4034            version: serialize_version(&buffer.version()),
4035        }
4036    }
4037
4038    async fn from_proto(
4039        message: proto::LinkedEditingRange,
4040        _: Entity<LspStore>,
4041        buffer: Entity<Buffer>,
4042        mut cx: AsyncApp,
4043    ) -> Result<Self> {
4044        let position = message.position.context("invalid position")?;
4045        buffer
4046            .update(&mut cx, |buffer, _| {
4047                buffer.wait_for_version(deserialize_version(&message.version))
4048            })
4049            .await?;
4050        let position = deserialize_anchor(position).context("invalid position")?;
4051        buffer
4052            .update(&mut cx, |buffer, _| buffer.wait_for_anchors([position]))
4053            .await?;
4054        Ok(Self { position })
4055    }
4056
4057    fn response_to_proto(
4058        response: Vec<Range<Anchor>>,
4059        _: &mut LspStore,
4060        _: PeerId,
4061        buffer_version: &clock::Global,
4062        _: &mut App,
4063    ) -> proto::LinkedEditingRangeResponse {
4064        proto::LinkedEditingRangeResponse {
4065            items: response
4066                .into_iter()
4067                .map(|range| proto::AnchorRange {
4068                    start: Some(serialize_anchor(&range.start)),
4069                    end: Some(serialize_anchor(&range.end)),
4070                })
4071                .collect(),
4072            version: serialize_version(buffer_version),
4073        }
4074    }
4075
4076    async fn response_from_proto(
4077        self,
4078        message: proto::LinkedEditingRangeResponse,
4079        _: Entity<LspStore>,
4080        buffer: Entity<Buffer>,
4081        mut cx: AsyncApp,
4082    ) -> Result<Vec<Range<Anchor>>> {
4083        buffer
4084            .update(&mut cx, |buffer, _| {
4085                buffer.wait_for_version(deserialize_version(&message.version))
4086            })
4087            .await?;
4088        let items: Vec<Range<Anchor>> = message
4089            .items
4090            .into_iter()
4091            .filter_map(|range| {
4092                let start = deserialize_anchor(range.start?)?;
4093                let end = deserialize_anchor(range.end?)?;
4094                Some(start..end)
4095            })
4096            .collect();
4097        for range in &items {
4098            buffer
4099                .update(&mut cx, |buffer, _| {
4100                    buffer.wait_for_anchors([range.start, range.end])
4101                })
4102                .await?;
4103        }
4104        Ok(items)
4105    }
4106
4107    fn buffer_id_from_proto(message: &proto::LinkedEditingRange) -> Result<BufferId> {
4108        BufferId::new(message.buffer_id)
4109    }
4110}
4111
4112impl GetDocumentDiagnostics {
4113    pub fn diagnostics_from_proto(
4114        response: proto::GetDocumentDiagnosticsResponse,
4115    ) -> Vec<LspPullDiagnostics> {
4116        response
4117            .pulled_diagnostics
4118            .into_iter()
4119            .filter_map(|diagnostics| {
4120                Some(LspPullDiagnostics::Response {
4121                    registration_id: diagnostics.registration_id.map(SharedString::from),
4122                    server_id: LanguageServerId::from_proto(diagnostics.server_id),
4123                    uri: lsp::Uri::from_str(diagnostics.uri.as_str()).log_err()?,
4124                    diagnostics: if diagnostics.changed {
4125                        PulledDiagnostics::Unchanged {
4126                            result_id: SharedString::new(diagnostics.result_id?),
4127                        }
4128                    } else {
4129                        PulledDiagnostics::Changed {
4130                            result_id: diagnostics.result_id.map(SharedString::new),
4131                            diagnostics: diagnostics
4132                                .diagnostics
4133                                .into_iter()
4134                                .filter_map(|diagnostic| {
4135                                    GetDocumentDiagnostics::deserialize_lsp_diagnostic(diagnostic)
4136                                        .context("deserializing diagnostics")
4137                                        .log_err()
4138                                })
4139                                .collect(),
4140                        }
4141                    },
4142                })
4143            })
4144            .collect()
4145    }
4146
4147    pub fn deserialize_lsp_diagnostic(diagnostic: proto::LspDiagnostic) -> Result<lsp::Diagnostic> {
4148        let start = diagnostic.start.context("invalid start range")?;
4149        let end = diagnostic.end.context("invalid end range")?;
4150
4151        let range = Range::<PointUtf16> {
4152            start: PointUtf16 {
4153                row: start.row,
4154                column: start.column,
4155            },
4156            end: PointUtf16 {
4157                row: end.row,
4158                column: end.column,
4159            },
4160        };
4161
4162        let data = diagnostic.data.and_then(|data| Value::from_str(&data).ok());
4163        let code = diagnostic.code.map(lsp::NumberOrString::String);
4164
4165        let related_information = diagnostic
4166            .related_information
4167            .into_iter()
4168            .map(|info| {
4169                let start = info.location_range_start.unwrap();
4170                let end = info.location_range_end.unwrap();
4171
4172                lsp::DiagnosticRelatedInformation {
4173                    location: lsp::Location {
4174                        range: lsp::Range {
4175                            start: point_to_lsp(PointUtf16::new(start.row, start.column)),
4176                            end: point_to_lsp(PointUtf16::new(end.row, end.column)),
4177                        },
4178                        uri: lsp::Uri::from_str(&info.location_url.unwrap()).unwrap(),
4179                    },
4180                    message: info.message,
4181                }
4182            })
4183            .collect::<Vec<_>>();
4184
4185        let tags = diagnostic
4186            .tags
4187            .into_iter()
4188            .filter_map(|tag| match proto::LspDiagnosticTag::from_i32(tag) {
4189                Some(proto::LspDiagnosticTag::Unnecessary) => Some(lsp::DiagnosticTag::UNNECESSARY),
4190                Some(proto::LspDiagnosticTag::Deprecated) => Some(lsp::DiagnosticTag::DEPRECATED),
4191                _ => None,
4192            })
4193            .collect::<Vec<_>>();
4194
4195        Ok(lsp::Diagnostic {
4196            range: language::range_to_lsp(range)?,
4197            severity: match proto::lsp_diagnostic::Severity::from_i32(diagnostic.severity).unwrap()
4198            {
4199                proto::lsp_diagnostic::Severity::Error => Some(lsp::DiagnosticSeverity::ERROR),
4200                proto::lsp_diagnostic::Severity::Warning => Some(lsp::DiagnosticSeverity::WARNING),
4201                proto::lsp_diagnostic::Severity::Information => {
4202                    Some(lsp::DiagnosticSeverity::INFORMATION)
4203                }
4204                proto::lsp_diagnostic::Severity::Hint => Some(lsp::DiagnosticSeverity::HINT),
4205                _ => None,
4206            },
4207            code,
4208            code_description: diagnostic
4209                .code_description
4210                .map(|code_description| CodeDescription {
4211                    href: Some(lsp::Uri::from_str(&code_description).unwrap()),
4212                }),
4213            related_information: Some(related_information),
4214            tags: Some(tags),
4215            source: diagnostic.source.clone(),
4216            message: diagnostic.message,
4217            data,
4218        })
4219    }
4220
4221    pub fn serialize_lsp_diagnostic(diagnostic: lsp::Diagnostic) -> Result<proto::LspDiagnostic> {
4222        let range = language::range_from_lsp(diagnostic.range);
4223        let related_information = diagnostic
4224            .related_information
4225            .unwrap_or_default()
4226            .into_iter()
4227            .map(|related_information| {
4228                let location_range_start =
4229                    point_from_lsp(related_information.location.range.start).0;
4230                let location_range_end = point_from_lsp(related_information.location.range.end).0;
4231
4232                Ok(proto::LspDiagnosticRelatedInformation {
4233                    location_url: Some(related_information.location.uri.to_string()),
4234                    location_range_start: Some(proto::PointUtf16 {
4235                        row: location_range_start.row,
4236                        column: location_range_start.column,
4237                    }),
4238                    location_range_end: Some(proto::PointUtf16 {
4239                        row: location_range_end.row,
4240                        column: location_range_end.column,
4241                    }),
4242                    message: related_information.message,
4243                })
4244            })
4245            .collect::<Result<Vec<_>>>()?;
4246
4247        let tags = diagnostic
4248            .tags
4249            .unwrap_or_default()
4250            .into_iter()
4251            .map(|tag| match tag {
4252                lsp::DiagnosticTag::UNNECESSARY => proto::LspDiagnosticTag::Unnecessary,
4253                lsp::DiagnosticTag::DEPRECATED => proto::LspDiagnosticTag::Deprecated,
4254                _ => proto::LspDiagnosticTag::None,
4255            } as i32)
4256            .collect();
4257
4258        Ok(proto::LspDiagnostic {
4259            start: Some(proto::PointUtf16 {
4260                row: range.start.0.row,
4261                column: range.start.0.column,
4262            }),
4263            end: Some(proto::PointUtf16 {
4264                row: range.end.0.row,
4265                column: range.end.0.column,
4266            }),
4267            severity: match diagnostic.severity {
4268                Some(lsp::DiagnosticSeverity::ERROR) => proto::lsp_diagnostic::Severity::Error,
4269                Some(lsp::DiagnosticSeverity::WARNING) => proto::lsp_diagnostic::Severity::Warning,
4270                Some(lsp::DiagnosticSeverity::INFORMATION) => {
4271                    proto::lsp_diagnostic::Severity::Information
4272                }
4273                Some(lsp::DiagnosticSeverity::HINT) => proto::lsp_diagnostic::Severity::Hint,
4274                _ => proto::lsp_diagnostic::Severity::None,
4275            } as i32,
4276            code: diagnostic.code.as_ref().map(|code| match code {
4277                lsp::NumberOrString::Number(code) => code.to_string(),
4278                lsp::NumberOrString::String(code) => code.clone(),
4279            }),
4280            source: diagnostic.source.clone(),
4281            related_information,
4282            tags,
4283            code_description: diagnostic
4284                .code_description
4285                .and_then(|desc| desc.href.map(|url| url.to_string())),
4286            message: diagnostic.message,
4287            data: diagnostic.data.as_ref().map(|data| data.to_string()),
4288        })
4289    }
4290
4291    pub fn deserialize_workspace_diagnostics_report(
4292        report: lsp::WorkspaceDiagnosticReportResult,
4293        server_id: LanguageServerId,
4294        registration_id: Option<SharedString>,
4295    ) -> Vec<WorkspaceLspPullDiagnostics> {
4296        let mut pulled_diagnostics = HashMap::default();
4297        match report {
4298            lsp::WorkspaceDiagnosticReportResult::Report(workspace_diagnostic_report) => {
4299                for report in workspace_diagnostic_report.items {
4300                    match report {
4301                        lsp::WorkspaceDocumentDiagnosticReport::Full(report) => {
4302                            process_full_workspace_diagnostics_report(
4303                                &mut pulled_diagnostics,
4304                                server_id,
4305                                report,
4306                                registration_id.clone(),
4307                            )
4308                        }
4309                        lsp::WorkspaceDocumentDiagnosticReport::Unchanged(report) => {
4310                            process_unchanged_workspace_diagnostics_report(
4311                                &mut pulled_diagnostics,
4312                                server_id,
4313                                report,
4314                                registration_id.clone(),
4315                            )
4316                        }
4317                    }
4318                }
4319            }
4320            lsp::WorkspaceDiagnosticReportResult::Partial(
4321                workspace_diagnostic_report_partial_result,
4322            ) => {
4323                for report in workspace_diagnostic_report_partial_result.items {
4324                    match report {
4325                        lsp::WorkspaceDocumentDiagnosticReport::Full(report) => {
4326                            process_full_workspace_diagnostics_report(
4327                                &mut pulled_diagnostics,
4328                                server_id,
4329                                report,
4330                                registration_id.clone(),
4331                            )
4332                        }
4333                        lsp::WorkspaceDocumentDiagnosticReport::Unchanged(report) => {
4334                            process_unchanged_workspace_diagnostics_report(
4335                                &mut pulled_diagnostics,
4336                                server_id,
4337                                report,
4338                                registration_id.clone(),
4339                            )
4340                        }
4341                    }
4342                }
4343            }
4344        }
4345        pulled_diagnostics.into_values().collect()
4346    }
4347}
4348
4349#[derive(Debug)]
4350pub struct WorkspaceLspPullDiagnostics {
4351    pub version: Option<i32>,
4352    pub diagnostics: LspPullDiagnostics,
4353}
4354
4355fn process_full_workspace_diagnostics_report(
4356    diagnostics: &mut HashMap<lsp::Uri, WorkspaceLspPullDiagnostics>,
4357    server_id: LanguageServerId,
4358    report: lsp::WorkspaceFullDocumentDiagnosticReport,
4359    registration_id: Option<SharedString>,
4360) {
4361    let mut new_diagnostics = HashMap::default();
4362    process_full_diagnostics_report(
4363        &mut new_diagnostics,
4364        server_id,
4365        report.uri,
4366        report.full_document_diagnostic_report,
4367        registration_id,
4368    );
4369    diagnostics.extend(new_diagnostics.into_iter().map(|(uri, diagnostics)| {
4370        (
4371            uri,
4372            WorkspaceLspPullDiagnostics {
4373                version: report.version.map(|v| v as i32),
4374                diagnostics,
4375            },
4376        )
4377    }));
4378}
4379
4380fn process_unchanged_workspace_diagnostics_report(
4381    diagnostics: &mut HashMap<lsp::Uri, WorkspaceLspPullDiagnostics>,
4382    server_id: LanguageServerId,
4383    report: lsp::WorkspaceUnchangedDocumentDiagnosticReport,
4384    registration_id: Option<SharedString>,
4385) {
4386    let mut new_diagnostics = HashMap::default();
4387    process_unchanged_diagnostics_report(
4388        &mut new_diagnostics,
4389        server_id,
4390        report.uri,
4391        report.unchanged_document_diagnostic_report,
4392        registration_id,
4393    );
4394    diagnostics.extend(new_diagnostics.into_iter().map(|(uri, diagnostics)| {
4395        (
4396            uri,
4397            WorkspaceLspPullDiagnostics {
4398                version: report.version.map(|v| v as i32),
4399                diagnostics,
4400            },
4401        )
4402    }));
4403}
4404
4405#[async_trait(?Send)]
4406impl LspCommand for GetDocumentDiagnostics {
4407    type Response = Vec<LspPullDiagnostics>;
4408    type LspRequest = lsp::request::DocumentDiagnosticRequest;
4409    type ProtoRequest = proto::GetDocumentDiagnostics;
4410
4411    fn display_name(&self) -> &str {
4412        "Get diagnostics"
4413    }
4414
4415    fn check_capabilities(&self, _: AdapterServerCapabilities) -> bool {
4416        true
4417    }
4418
4419    fn to_lsp(
4420        &self,
4421        path: &Path,
4422        _: &Buffer,
4423        _: &Arc<LanguageServer>,
4424        _: &App,
4425    ) -> Result<lsp::DocumentDiagnosticParams> {
4426        Ok(lsp::DocumentDiagnosticParams {
4427            text_document: lsp::TextDocumentIdentifier {
4428                uri: file_path_to_lsp_url(path)?,
4429            },
4430            identifier: self.identifier.as_ref().map(ToString::to_string),
4431            previous_result_id: self.previous_result_id.as_ref().map(ToString::to_string),
4432            partial_result_params: Default::default(),
4433            work_done_progress_params: Default::default(),
4434        })
4435    }
4436
4437    async fn response_from_lsp(
4438        self,
4439        message: lsp::DocumentDiagnosticReportResult,
4440        _: Entity<LspStore>,
4441        buffer: Entity<Buffer>,
4442        server_id: LanguageServerId,
4443        cx: AsyncApp,
4444    ) -> Result<Self::Response> {
4445        let url = buffer.read_with(&cx, |buffer, cx| {
4446            buffer
4447                .file()
4448                .and_then(|file| file.as_local())
4449                .map(|file| {
4450                    let abs_path = file.abs_path(cx);
4451                    file_path_to_lsp_url(&abs_path)
4452                })
4453                .transpose()?
4454                .with_context(|| format!("missing url on buffer {}", buffer.remote_id()))
4455        })?;
4456
4457        let mut pulled_diagnostics = HashMap::default();
4458        match message {
4459            lsp::DocumentDiagnosticReportResult::Report(report) => match report {
4460                lsp::DocumentDiagnosticReport::Full(report) => {
4461                    if let Some(related_documents) = report.related_documents {
4462                        process_related_documents(
4463                            &mut pulled_diagnostics,
4464                            server_id,
4465                            related_documents,
4466                            self.registration_id.clone(),
4467                        );
4468                    }
4469                    process_full_diagnostics_report(
4470                        &mut pulled_diagnostics,
4471                        server_id,
4472                        url,
4473                        report.full_document_diagnostic_report,
4474                        self.registration_id,
4475                    );
4476                }
4477                lsp::DocumentDiagnosticReport::Unchanged(report) => {
4478                    if let Some(related_documents) = report.related_documents {
4479                        process_related_documents(
4480                            &mut pulled_diagnostics,
4481                            server_id,
4482                            related_documents,
4483                            self.registration_id.clone(),
4484                        );
4485                    }
4486                    process_unchanged_diagnostics_report(
4487                        &mut pulled_diagnostics,
4488                        server_id,
4489                        url,
4490                        report.unchanged_document_diagnostic_report,
4491                        self.registration_id,
4492                    );
4493                }
4494            },
4495            lsp::DocumentDiagnosticReportResult::Partial(report) => {
4496                if let Some(related_documents) = report.related_documents {
4497                    process_related_documents(
4498                        &mut pulled_diagnostics,
4499                        server_id,
4500                        related_documents,
4501                        self.registration_id,
4502                    );
4503                }
4504            }
4505        }
4506
4507        Ok(pulled_diagnostics.into_values().collect())
4508    }
4509
4510    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentDiagnostics {
4511        proto::GetDocumentDiagnostics {
4512            project_id,
4513            buffer_id: buffer.remote_id().into(),
4514            version: serialize_version(&buffer.version()),
4515        }
4516    }
4517
4518    async fn from_proto(
4519        _: proto::GetDocumentDiagnostics,
4520        _: Entity<LspStore>,
4521        _: Entity<Buffer>,
4522        _: AsyncApp,
4523    ) -> Result<Self> {
4524        anyhow::bail!(
4525            "proto::GetDocumentDiagnostics is not expected to be converted from proto directly, as it needs `previous_result_id` fetched first"
4526        )
4527    }
4528
4529    fn response_to_proto(
4530        response: Self::Response,
4531        _: &mut LspStore,
4532        _: PeerId,
4533        _: &clock::Global,
4534        _: &mut App,
4535    ) -> proto::GetDocumentDiagnosticsResponse {
4536        let pulled_diagnostics = response
4537            .into_iter()
4538            .filter_map(|diagnostics| match diagnostics {
4539                LspPullDiagnostics::Default => None,
4540                LspPullDiagnostics::Response {
4541                    server_id,
4542                    uri,
4543                    diagnostics,
4544                    registration_id,
4545                } => {
4546                    let mut changed = false;
4547                    let (diagnostics, result_id) = match diagnostics {
4548                        PulledDiagnostics::Unchanged { result_id } => (Vec::new(), Some(result_id)),
4549                        PulledDiagnostics::Changed {
4550                            result_id,
4551                            diagnostics,
4552                        } => {
4553                            changed = true;
4554                            (diagnostics, result_id)
4555                        }
4556                    };
4557                    Some(proto::PulledDiagnostics {
4558                        changed,
4559                        result_id: result_id.map(|id| id.to_string()),
4560                        uri: uri.to_string(),
4561                        server_id: server_id.to_proto(),
4562                        diagnostics: diagnostics
4563                            .into_iter()
4564                            .filter_map(|diagnostic| {
4565                                GetDocumentDiagnostics::serialize_lsp_diagnostic(diagnostic)
4566                                    .context("serializing diagnostics")
4567                                    .log_err()
4568                            })
4569                            .collect(),
4570                        registration_id: registration_id.as_ref().map(ToString::to_string),
4571                    })
4572                }
4573            })
4574            .collect();
4575
4576        proto::GetDocumentDiagnosticsResponse { pulled_diagnostics }
4577    }
4578
4579    async fn response_from_proto(
4580        self,
4581        response: proto::GetDocumentDiagnosticsResponse,
4582        _: Entity<LspStore>,
4583        _: Entity<Buffer>,
4584        _: AsyncApp,
4585    ) -> Result<Self::Response> {
4586        Ok(Self::diagnostics_from_proto(response))
4587    }
4588
4589    fn buffer_id_from_proto(message: &proto::GetDocumentDiagnostics) -> Result<BufferId> {
4590        BufferId::new(message.buffer_id)
4591    }
4592}
4593
4594#[async_trait(?Send)]
4595impl LspCommand for GetDocumentColor {
4596    type Response = Vec<DocumentColor>;
4597    type LspRequest = lsp::request::DocumentColor;
4598    type ProtoRequest = proto::GetDocumentColor;
4599
4600    fn display_name(&self) -> &str {
4601        "Document color"
4602    }
4603
4604    fn check_capabilities(&self, server_capabilities: AdapterServerCapabilities) -> bool {
4605        server_capabilities
4606            .server_capabilities
4607            .color_provider
4608            .as_ref()
4609            .is_some_and(|capability| match capability {
4610                lsp::ColorProviderCapability::Simple(supported) => *supported,
4611                lsp::ColorProviderCapability::ColorProvider(..) => true,
4612                lsp::ColorProviderCapability::Options(..) => true,
4613            })
4614    }
4615
4616    fn to_lsp(
4617        &self,
4618        path: &Path,
4619        _: &Buffer,
4620        _: &Arc<LanguageServer>,
4621        _: &App,
4622    ) -> Result<lsp::DocumentColorParams> {
4623        Ok(lsp::DocumentColorParams {
4624            text_document: make_text_document_identifier(path)?,
4625            work_done_progress_params: Default::default(),
4626            partial_result_params: Default::default(),
4627        })
4628    }
4629
4630    async fn response_from_lsp(
4631        self,
4632        message: Vec<lsp::ColorInformation>,
4633        _: Entity<LspStore>,
4634        _: Entity<Buffer>,
4635        _: LanguageServerId,
4636        _: AsyncApp,
4637    ) -> Result<Self::Response> {
4638        Ok(message
4639            .into_iter()
4640            .map(|color| DocumentColor {
4641                lsp_range: color.range,
4642                color: color.color,
4643                resolved: false,
4644                color_presentations: Vec::new(),
4645            })
4646            .collect())
4647    }
4648
4649    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
4650        proto::GetDocumentColor {
4651            project_id,
4652            buffer_id: buffer.remote_id().to_proto(),
4653            version: serialize_version(&buffer.version()),
4654        }
4655    }
4656
4657    async fn from_proto(
4658        _: Self::ProtoRequest,
4659        _: Entity<LspStore>,
4660        _: Entity<Buffer>,
4661        _: AsyncApp,
4662    ) -> Result<Self> {
4663        Ok(Self {})
4664    }
4665
4666    fn response_to_proto(
4667        response: Self::Response,
4668        _: &mut LspStore,
4669        _: PeerId,
4670        buffer_version: &clock::Global,
4671        _: &mut App,
4672    ) -> proto::GetDocumentColorResponse {
4673        proto::GetDocumentColorResponse {
4674            colors: response
4675                .into_iter()
4676                .map(|color| {
4677                    let start = point_from_lsp(color.lsp_range.start).0;
4678                    let end = point_from_lsp(color.lsp_range.end).0;
4679                    proto::ColorInformation {
4680                        red: color.color.red,
4681                        green: color.color.green,
4682                        blue: color.color.blue,
4683                        alpha: color.color.alpha,
4684                        lsp_range_start: Some(proto::PointUtf16 {
4685                            row: start.row,
4686                            column: start.column,
4687                        }),
4688                        lsp_range_end: Some(proto::PointUtf16 {
4689                            row: end.row,
4690                            column: end.column,
4691                        }),
4692                    }
4693                })
4694                .collect(),
4695            version: serialize_version(buffer_version),
4696        }
4697    }
4698
4699    async fn response_from_proto(
4700        self,
4701        message: proto::GetDocumentColorResponse,
4702        _: Entity<LspStore>,
4703        _: Entity<Buffer>,
4704        _: AsyncApp,
4705    ) -> Result<Self::Response> {
4706        Ok(message
4707            .colors
4708            .into_iter()
4709            .filter_map(|color| {
4710                let start = color.lsp_range_start?;
4711                let start = PointUtf16::new(start.row, start.column);
4712                let end = color.lsp_range_end?;
4713                let end = PointUtf16::new(end.row, end.column);
4714                Some(DocumentColor {
4715                    resolved: false,
4716                    color_presentations: Vec::new(),
4717                    lsp_range: lsp::Range {
4718                        start: point_to_lsp(start),
4719                        end: point_to_lsp(end),
4720                    },
4721                    color: lsp::Color {
4722                        red: color.red,
4723                        green: color.green,
4724                        blue: color.blue,
4725                        alpha: color.alpha,
4726                    },
4727                })
4728            })
4729            .collect())
4730    }
4731
4732    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
4733        BufferId::new(message.buffer_id)
4734    }
4735}
4736
4737#[async_trait(?Send)]
4738impl LspCommand for GetFoldingRanges {
4739    type Response = Vec<LspFoldingRange>;
4740    type LspRequest = lsp::request::FoldingRangeRequest;
4741    type ProtoRequest = proto::GetFoldingRanges;
4742
4743    fn display_name(&self) -> &str {
4744        "Folding ranges"
4745    }
4746
4747    fn check_capabilities(&self, server_capabilities: AdapterServerCapabilities) -> bool {
4748        server_capabilities
4749            .server_capabilities
4750            .folding_range_provider
4751            .as_ref()
4752            .is_some_and(|capability| match capability {
4753                lsp::FoldingRangeProviderCapability::Simple(supported) => *supported,
4754                lsp::FoldingRangeProviderCapability::FoldingProvider(..)
4755                | lsp::FoldingRangeProviderCapability::Options(..) => true,
4756            })
4757    }
4758
4759    fn to_lsp(
4760        &self,
4761        path: &Path,
4762        _: &Buffer,
4763        _: &Arc<LanguageServer>,
4764        _: &App,
4765    ) -> Result<lsp::FoldingRangeParams> {
4766        Ok(lsp::FoldingRangeParams {
4767            text_document: make_text_document_identifier(path)?,
4768            work_done_progress_params: Default::default(),
4769            partial_result_params: Default::default(),
4770        })
4771    }
4772
4773    async fn response_from_lsp(
4774        self,
4775        message: Option<Vec<lsp::FoldingRange>>,
4776        _: Entity<LspStore>,
4777        buffer: Entity<Buffer>,
4778        _: LanguageServerId,
4779        cx: AsyncApp,
4780    ) -> Result<Self::Response> {
4781        let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
4782        let max_point = snapshot.max_point_utf16();
4783        Ok(message
4784            .unwrap_or_default()
4785            .into_iter()
4786            .filter(|range| range.start_line < range.end_line)
4787            .filter(|range| range.start_line <= max_point.row && range.end_line <= max_point.row)
4788            .map(|folding_range| {
4789                let start_col = folding_range.start_character.unwrap_or(u32::MAX);
4790                let end_col = folding_range.end_character.unwrap_or(u32::MAX);
4791                let start = snapshot.clip_point_utf16(
4792                    Unclipped(PointUtf16::new(folding_range.start_line, start_col)),
4793                    Bias::Right,
4794                );
4795                let end = snapshot.clip_point_utf16(
4796                    Unclipped(PointUtf16::new(folding_range.end_line, end_col)),
4797                    Bias::Left,
4798                );
4799                let start = snapshot.anchor_after(start);
4800                let end = snapshot.anchor_before(end);
4801                let collapsed_text = folding_range
4802                    .collapsed_text
4803                    .filter(|t| !t.is_empty())
4804                    .map(|t| SharedString::from(crate::lsp_store::collapse_newlines(&t, " ")));
4805                LspFoldingRange {
4806                    range: start..end,
4807                    collapsed_text,
4808                }
4809            })
4810            .collect())
4811    }
4812
4813    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
4814        proto::GetFoldingRanges {
4815            project_id,
4816            buffer_id: buffer.remote_id().to_proto(),
4817            version: serialize_version(&buffer.version()),
4818        }
4819    }
4820
4821    async fn from_proto(
4822        _: Self::ProtoRequest,
4823        _: Entity<LspStore>,
4824        _: Entity<Buffer>,
4825        _: AsyncApp,
4826    ) -> Result<Self> {
4827        Ok(Self)
4828    }
4829
4830    fn response_to_proto(
4831        response: Self::Response,
4832        _: &mut LspStore,
4833        _: PeerId,
4834        buffer_version: &clock::Global,
4835        _: &mut App,
4836    ) -> proto::GetFoldingRangesResponse {
4837        let mut ranges = Vec::with_capacity(response.len());
4838        let mut collapsed_texts = Vec::with_capacity(response.len());
4839        for folding_range in response {
4840            ranges.push(serialize_anchor_range(folding_range.range));
4841            collapsed_texts.push(
4842                folding_range
4843                    .collapsed_text
4844                    .map(|t| t.to_string())
4845                    .unwrap_or_default(),
4846            );
4847        }
4848        proto::GetFoldingRangesResponse {
4849            ranges,
4850            collapsed_texts,
4851            version: serialize_version(buffer_version),
4852        }
4853    }
4854
4855    async fn response_from_proto(
4856        self,
4857        message: proto::GetFoldingRangesResponse,
4858        _: Entity<LspStore>,
4859        buffer: Entity<Buffer>,
4860        mut cx: AsyncApp,
4861    ) -> Result<Self::Response> {
4862        buffer
4863            .update(&mut cx, |buffer, _| {
4864                buffer.wait_for_version(deserialize_version(&message.version))
4865            })
4866            .await?;
4867        message
4868            .ranges
4869            .into_iter()
4870            .zip(
4871                message
4872                    .collapsed_texts
4873                    .into_iter()
4874                    .map(Some)
4875                    .chain(std::iter::repeat(None)),
4876            )
4877            .map(|(range, collapsed_text)| {
4878                Ok(LspFoldingRange {
4879                    range: deserialize_anchor_range(range)?,
4880                    collapsed_text: collapsed_text
4881                        .filter(|t| !t.is_empty())
4882                        .map(SharedString::from),
4883                })
4884            })
4885            .collect()
4886    }
4887
4888    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
4889        BufferId::new(message.buffer_id)
4890    }
4891}
4892
4893fn process_related_documents(
4894    diagnostics: &mut HashMap<lsp::Uri, LspPullDiagnostics>,
4895    server_id: LanguageServerId,
4896    documents: impl IntoIterator<Item = (lsp::Uri, lsp::DocumentDiagnosticReportKind)>,
4897    registration_id: Option<SharedString>,
4898) {
4899    for (url, report_kind) in documents {
4900        match report_kind {
4901            lsp::DocumentDiagnosticReportKind::Full(report) => process_full_diagnostics_report(
4902                diagnostics,
4903                server_id,
4904                url,
4905                report,
4906                registration_id.clone(),
4907            ),
4908            lsp::DocumentDiagnosticReportKind::Unchanged(report) => {
4909                process_unchanged_diagnostics_report(
4910                    diagnostics,
4911                    server_id,
4912                    url,
4913                    report,
4914                    registration_id.clone(),
4915                )
4916            }
4917        }
4918    }
4919}
4920
4921fn process_unchanged_diagnostics_report(
4922    diagnostics: &mut HashMap<lsp::Uri, LspPullDiagnostics>,
4923    server_id: LanguageServerId,
4924    uri: lsp::Uri,
4925    report: lsp::UnchangedDocumentDiagnosticReport,
4926    registration_id: Option<SharedString>,
4927) {
4928    let result_id = SharedString::new(report.result_id);
4929    match diagnostics.entry(uri.clone()) {
4930        hash_map::Entry::Occupied(mut o) => match o.get_mut() {
4931            LspPullDiagnostics::Default => {
4932                o.insert(LspPullDiagnostics::Response {
4933                    server_id,
4934                    uri,
4935                    diagnostics: PulledDiagnostics::Unchanged { result_id },
4936                    registration_id,
4937                });
4938            }
4939            LspPullDiagnostics::Response {
4940                server_id: existing_server_id,
4941                uri: existing_uri,
4942                diagnostics: existing_diagnostics,
4943                ..
4944            } => {
4945                if server_id != *existing_server_id || &uri != existing_uri {
4946                    debug_panic!(
4947                        "Unexpected state: file {uri} has two different sets of diagnostics reported"
4948                    );
4949                }
4950                match existing_diagnostics {
4951                    PulledDiagnostics::Unchanged { .. } => {
4952                        *existing_diagnostics = PulledDiagnostics::Unchanged { result_id };
4953                    }
4954                    PulledDiagnostics::Changed { .. } => {}
4955                }
4956            }
4957        },
4958        hash_map::Entry::Vacant(v) => {
4959            v.insert(LspPullDiagnostics::Response {
4960                server_id,
4961                uri,
4962                diagnostics: PulledDiagnostics::Unchanged { result_id },
4963                registration_id,
4964            });
4965        }
4966    }
4967}
4968
4969fn process_full_diagnostics_report(
4970    diagnostics: &mut HashMap<lsp::Uri, LspPullDiagnostics>,
4971    server_id: LanguageServerId,
4972    uri: lsp::Uri,
4973    report: lsp::FullDocumentDiagnosticReport,
4974    registration_id: Option<SharedString>,
4975) {
4976    let result_id = report.result_id.map(SharedString::new);
4977    match diagnostics.entry(uri.clone()) {
4978        hash_map::Entry::Occupied(mut o) => match o.get_mut() {
4979            LspPullDiagnostics::Default => {
4980                o.insert(LspPullDiagnostics::Response {
4981                    server_id,
4982                    uri,
4983                    diagnostics: PulledDiagnostics::Changed {
4984                        result_id,
4985                        diagnostics: report.items,
4986                    },
4987                    registration_id,
4988                });
4989            }
4990            LspPullDiagnostics::Response {
4991                server_id: existing_server_id,
4992                uri: existing_uri,
4993                diagnostics: existing_diagnostics,
4994                ..
4995            } => {
4996                if server_id != *existing_server_id || &uri != existing_uri {
4997                    debug_panic!(
4998                        "Unexpected state: file {uri} has two different sets of diagnostics reported"
4999                    );
5000                }
5001                match existing_diagnostics {
5002                    PulledDiagnostics::Unchanged { .. } => {
5003                        *existing_diagnostics = PulledDiagnostics::Changed {
5004                            result_id,
5005                            diagnostics: report.items,
5006                        };
5007                    }
5008                    PulledDiagnostics::Changed {
5009                        result_id: existing_result_id,
5010                        diagnostics: existing_diagnostics,
5011                    } => {
5012                        if result_id.is_some() {
5013                            *existing_result_id = result_id;
5014                        }
5015                        existing_diagnostics.extend(report.items);
5016                    }
5017                }
5018            }
5019        },
5020        hash_map::Entry::Vacant(v) => {
5021            v.insert(LspPullDiagnostics::Response {
5022                server_id,
5023                uri,
5024                diagnostics: PulledDiagnostics::Changed {
5025                    result_id,
5026                    diagnostics: report.items,
5027                },
5028                registration_id,
5029            });
5030        }
5031    }
5032}