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