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