lsp_command.rs

   1mod signature_help;
   2
   3use crate::{
   4    CodeAction, CompletionSource, CoreCompletion, DocumentHighlight, DocumentSymbol, Hover,
   5    HoverBlock, HoverBlockKind, InlayHint, InlayHintLabel, InlayHintLabelPart,
   6    InlayHintLabelPartTooltip, InlayHintTooltip, Location, LocationLink, LspAction, MarkupContent,
   7    PrepareRenameResponse, ProjectTransaction, ResolveState,
   8    lsp_store::{LocalLspStore, LspStore},
   9};
  10use anyhow::{Context as _, Result, anyhow};
  11use async_trait::async_trait;
  12use client::proto::{self, PeerId};
  13use clock::Global;
  14use collections::HashSet;
  15use futures::future;
  16use gpui::{App, AsyncApp, Entity, Task};
  17use language::{
  18    Anchor, Bias, Buffer, BufferSnapshot, CachedLspAdapter, CharKind, OffsetRangeExt, PointUtf16,
  19    ToOffset, ToPointUtf16, Transaction, Unclipped,
  20    language_settings::{InlayHintKind, LanguageSettings, language_settings},
  21    point_from_lsp, point_to_lsp,
  22    proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
  23    range_from_lsp, range_to_lsp,
  24};
  25use lsp::{
  26    AdapterServerCapabilities, CodeActionKind, CodeActionOptions, CompletionContext,
  27    CompletionListItemDefaultsEditRange, CompletionTriggerKind, DocumentHighlightKind,
  28    LanguageServer, LanguageServerId, LinkedEditingRangeServerCapabilities, OneOf, RenameOptions,
  29    ServerCapabilities,
  30};
  31use signature_help::{lsp_to_proto_signature, proto_to_lsp_signature};
  32use std::{cmp::Reverse, mem, ops::Range, path::Path, sync::Arc};
  33use text::{BufferId, LineEnding};
  34
  35pub use signature_help::SignatureHelp;
  36
  37pub fn lsp_formatting_options(settings: &LanguageSettings) -> lsp::FormattingOptions {
  38    lsp::FormattingOptions {
  39        tab_size: settings.tab_size.into(),
  40        insert_spaces: !settings.hard_tabs,
  41        trim_trailing_whitespace: Some(settings.remove_trailing_whitespace_on_save),
  42        trim_final_newlines: Some(settings.ensure_final_newline_on_save),
  43        insert_final_newline: Some(settings.ensure_final_newline_on_save),
  44        ..lsp::FormattingOptions::default()
  45    }
  46}
  47
  48pub(crate) fn file_path_to_lsp_url(path: &Path) -> Result<lsp::Url> {
  49    match lsp::Url::from_file_path(path) {
  50        Ok(url) => Ok(url),
  51        Err(()) => Err(anyhow!(
  52            "Invalid file path provided to LSP request: {path:?}"
  53        )),
  54    }
  55}
  56
  57pub(crate) fn make_text_document_identifier(path: &Path) -> Result<lsp::TextDocumentIdentifier> {
  58    Ok(lsp::TextDocumentIdentifier {
  59        uri: file_path_to_lsp_url(path)?,
  60    })
  61}
  62
  63pub(crate) fn make_lsp_text_document_position(
  64    path: &Path,
  65    position: PointUtf16,
  66) -> Result<lsp::TextDocumentPositionParams> {
  67    Ok(lsp::TextDocumentPositionParams {
  68        text_document: make_text_document_identifier(path)?,
  69        position: point_to_lsp(position),
  70    })
  71}
  72
  73#[async_trait(?Send)]
  74pub trait LspCommand: 'static + Sized + Send + std::fmt::Debug {
  75    type Response: 'static + Default + Send + std::fmt::Debug;
  76    type LspRequest: 'static + Send + lsp::request::Request;
  77    type ProtoRequest: 'static + Send + proto::RequestMessage;
  78
  79    fn display_name(&self) -> &str;
  80
  81    fn status(&self) -> Option<String> {
  82        None
  83    }
  84
  85    fn to_lsp_params_or_response(
  86        &self,
  87        path: &Path,
  88        buffer: &Buffer,
  89        language_server: &Arc<LanguageServer>,
  90        cx: &App,
  91    ) -> Result<
  92        LspParamsOrResponse<<Self::LspRequest as lsp::request::Request>::Params, Self::Response>,
  93    > {
  94        if self.check_capabilities(language_server.adapter_server_capabilities()) {
  95            Ok(LspParamsOrResponse::Params(self.to_lsp(
  96                path,
  97                buffer,
  98                language_server,
  99                cx,
 100            )?))
 101        } else {
 102            Ok(LspParamsOrResponse::Response(Default::default()))
 103        }
 104    }
 105
 106    /// When false, `to_lsp_params_or_response` default implementation will return the default response.
 107    fn check_capabilities(&self, _: AdapterServerCapabilities) -> bool {
 108        true
 109    }
 110
 111    fn to_lsp(
 112        &self,
 113        path: &Path,
 114        buffer: &Buffer,
 115        language_server: &Arc<LanguageServer>,
 116        cx: &App,
 117    ) -> Result<<Self::LspRequest as lsp::request::Request>::Params>;
 118
 119    async fn response_from_lsp(
 120        self,
 121        message: <Self::LspRequest as lsp::request::Request>::Result,
 122        lsp_store: Entity<LspStore>,
 123        buffer: Entity<Buffer>,
 124        server_id: LanguageServerId,
 125        cx: AsyncApp,
 126    ) -> Result<Self::Response>;
 127
 128    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest;
 129
 130    async fn from_proto(
 131        message: Self::ProtoRequest,
 132        lsp_store: Entity<LspStore>,
 133        buffer: Entity<Buffer>,
 134        cx: AsyncApp,
 135    ) -> Result<Self>;
 136
 137    fn response_to_proto(
 138        response: Self::Response,
 139        lsp_store: &mut LspStore,
 140        peer_id: PeerId,
 141        buffer_version: &clock::Global,
 142        cx: &mut App,
 143    ) -> <Self::ProtoRequest as proto::RequestMessage>::Response;
 144
 145    async fn response_from_proto(
 146        self,
 147        message: <Self::ProtoRequest as proto::RequestMessage>::Response,
 148        lsp_store: Entity<LspStore>,
 149        buffer: Entity<Buffer>,
 150        cx: AsyncApp,
 151    ) -> Result<Self::Response>;
 152
 153    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId>;
 154}
 155
 156pub enum LspParamsOrResponse<P, R> {
 157    Params(P),
 158    Response(R),
 159}
 160
 161#[derive(Debug)]
 162pub(crate) struct PrepareRename {
 163    pub position: PointUtf16,
 164}
 165
 166#[derive(Debug)]
 167pub(crate) struct PerformRename {
 168    pub position: PointUtf16,
 169    pub new_name: String,
 170    pub push_to_history: bool,
 171}
 172
 173#[derive(Debug)]
 174pub struct GetDefinition {
 175    pub position: PointUtf16,
 176}
 177
 178#[derive(Debug)]
 179pub(crate) struct GetDeclaration {
 180    pub position: PointUtf16,
 181}
 182
 183#[derive(Debug)]
 184pub(crate) struct GetTypeDefinition {
 185    pub position: PointUtf16,
 186}
 187
 188#[derive(Debug)]
 189pub(crate) struct GetImplementation {
 190    pub position: PointUtf16,
 191}
 192
 193#[derive(Debug)]
 194pub(crate) struct GetReferences {
 195    pub position: PointUtf16,
 196}
 197
 198#[derive(Debug)]
 199pub(crate) struct GetDocumentHighlights {
 200    pub position: PointUtf16,
 201}
 202
 203#[derive(Debug, Copy, Clone)]
 204pub(crate) struct GetDocumentSymbols;
 205
 206#[derive(Clone, Debug)]
 207pub(crate) struct GetSignatureHelp {
 208    pub position: PointUtf16,
 209}
 210
 211#[derive(Clone, Debug)]
 212pub(crate) struct GetHover {
 213    pub position: PointUtf16,
 214}
 215
 216#[derive(Debug)]
 217pub(crate) struct GetCompletions {
 218    pub position: PointUtf16,
 219    pub context: CompletionContext,
 220}
 221
 222#[derive(Clone, Debug)]
 223pub(crate) struct GetCodeActions {
 224    pub range: Range<Anchor>,
 225    pub kinds: Option<Vec<lsp::CodeActionKind>>,
 226}
 227
 228#[derive(Debug)]
 229pub(crate) struct OnTypeFormatting {
 230    pub position: PointUtf16,
 231    pub trigger: String,
 232    pub options: lsp::FormattingOptions,
 233    pub push_to_history: bool,
 234}
 235
 236#[derive(Debug)]
 237pub(crate) struct InlayHints {
 238    pub range: Range<Anchor>,
 239}
 240
 241#[derive(Debug, Copy, Clone)]
 242pub(crate) struct GetCodeLens;
 243
 244impl GetCodeLens {
 245    pub(crate) fn can_resolve_lens(capabilities: &ServerCapabilities) -> bool {
 246        capabilities
 247            .code_lens_provider
 248            .as_ref()
 249            .and_then(|code_lens_options| code_lens_options.resolve_provider)
 250            .unwrap_or(false)
 251    }
 252}
 253
 254#[derive(Debug)]
 255pub(crate) struct LinkedEditingRange {
 256    pub position: Anchor,
 257}
 258
 259#[async_trait(?Send)]
 260impl LspCommand for PrepareRename {
 261    type Response = PrepareRenameResponse;
 262    type LspRequest = lsp::request::PrepareRenameRequest;
 263    type ProtoRequest = proto::PrepareRename;
 264
 265    fn display_name(&self) -> &str {
 266        "Prepare rename"
 267    }
 268
 269    fn to_lsp_params_or_response(
 270        &self,
 271        path: &Path,
 272        buffer: &Buffer,
 273        language_server: &Arc<LanguageServer>,
 274        cx: &App,
 275    ) -> Result<LspParamsOrResponse<lsp::TextDocumentPositionParams, PrepareRenameResponse>> {
 276        let rename_provider = language_server
 277            .adapter_server_capabilities()
 278            .server_capabilities
 279            .rename_provider;
 280        match rename_provider {
 281            Some(lsp::OneOf::Right(RenameOptions {
 282                prepare_provider: Some(true),
 283                ..
 284            })) => Ok(LspParamsOrResponse::Params(self.to_lsp(
 285                path,
 286                buffer,
 287                language_server,
 288                cx,
 289            )?)),
 290            Some(lsp::OneOf::Right(_)) => Ok(LspParamsOrResponse::Response(
 291                PrepareRenameResponse::OnlyUnpreparedRenameSupported,
 292            )),
 293            Some(lsp::OneOf::Left(true)) => Ok(LspParamsOrResponse::Response(
 294                PrepareRenameResponse::OnlyUnpreparedRenameSupported,
 295            )),
 296            _ => Err(anyhow!("Rename not supported")),
 297        }
 298    }
 299
 300    fn to_lsp(
 301        &self,
 302        path: &Path,
 303        _: &Buffer,
 304        _: &Arc<LanguageServer>,
 305        _: &App,
 306    ) -> Result<lsp::TextDocumentPositionParams> {
 307        make_lsp_text_document_position(path, self.position)
 308    }
 309
 310    async fn response_from_lsp(
 311        self,
 312        message: Option<lsp::PrepareRenameResponse>,
 313        _: Entity<LspStore>,
 314        buffer: Entity<Buffer>,
 315        _: LanguageServerId,
 316        mut cx: AsyncApp,
 317    ) -> Result<PrepareRenameResponse> {
 318        buffer.update(&mut cx, |buffer, _| match message {
 319            Some(lsp::PrepareRenameResponse::Range(range))
 320            | Some(lsp::PrepareRenameResponse::RangeWithPlaceholder { range, .. }) => {
 321                let Range { start, end } = range_from_lsp(range);
 322                if buffer.clip_point_utf16(start, Bias::Left) == start.0
 323                    && buffer.clip_point_utf16(end, Bias::Left) == end.0
 324                {
 325                    Ok(PrepareRenameResponse::Success(
 326                        buffer.anchor_after(start)..buffer.anchor_before(end),
 327                    ))
 328                } else {
 329                    Ok(PrepareRenameResponse::InvalidPosition)
 330                }
 331            }
 332            Some(lsp::PrepareRenameResponse::DefaultBehavior { .. }) => {
 333                let snapshot = buffer.snapshot();
 334                let (range, _) = snapshot.surrounding_word(self.position);
 335                let range = snapshot.anchor_after(range.start)..snapshot.anchor_before(range.end);
 336                Ok(PrepareRenameResponse::Success(range))
 337            }
 338            None => Ok(PrepareRenameResponse::InvalidPosition),
 339        })?
 340    }
 341
 342    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::PrepareRename {
 343        proto::PrepareRename {
 344            project_id,
 345            buffer_id: buffer.remote_id().into(),
 346            position: Some(language::proto::serialize_anchor(
 347                &buffer.anchor_before(self.position),
 348            )),
 349            version: serialize_version(&buffer.version()),
 350        }
 351    }
 352
 353    async fn from_proto(
 354        message: proto::PrepareRename,
 355        _: Entity<LspStore>,
 356        buffer: Entity<Buffer>,
 357        mut cx: AsyncApp,
 358    ) -> Result<Self> {
 359        let position = message
 360            .position
 361            .and_then(deserialize_anchor)
 362            .ok_or_else(|| anyhow!("invalid position"))?;
 363        buffer
 364            .update(&mut cx, |buffer, _| {
 365                buffer.wait_for_version(deserialize_version(&message.version))
 366            })?
 367            .await?;
 368
 369        Ok(Self {
 370            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
 371        })
 372    }
 373
 374    fn response_to_proto(
 375        response: PrepareRenameResponse,
 376        _: &mut LspStore,
 377        _: PeerId,
 378        buffer_version: &clock::Global,
 379        _: &mut App,
 380    ) -> proto::PrepareRenameResponse {
 381        match response {
 382            PrepareRenameResponse::Success(range) => proto::PrepareRenameResponse {
 383                can_rename: true,
 384                only_unprepared_rename_supported: false,
 385                start: Some(language::proto::serialize_anchor(&range.start)),
 386                end: Some(language::proto::serialize_anchor(&range.end)),
 387                version: serialize_version(buffer_version),
 388            },
 389            PrepareRenameResponse::OnlyUnpreparedRenameSupported => proto::PrepareRenameResponse {
 390                can_rename: false,
 391                only_unprepared_rename_supported: true,
 392                start: None,
 393                end: None,
 394                version: vec![],
 395            },
 396            PrepareRenameResponse::InvalidPosition => proto::PrepareRenameResponse {
 397                can_rename: false,
 398                only_unprepared_rename_supported: false,
 399                start: None,
 400                end: None,
 401                version: vec![],
 402            },
 403        }
 404    }
 405
 406    async fn response_from_proto(
 407        self,
 408        message: proto::PrepareRenameResponse,
 409        _: Entity<LspStore>,
 410        buffer: Entity<Buffer>,
 411        mut cx: AsyncApp,
 412    ) -> Result<PrepareRenameResponse> {
 413        if message.can_rename {
 414            buffer
 415                .update(&mut cx, |buffer, _| {
 416                    buffer.wait_for_version(deserialize_version(&message.version))
 417                })?
 418                .await?;
 419            if let (Some(start), Some(end)) = (
 420                message.start.and_then(deserialize_anchor),
 421                message.end.and_then(deserialize_anchor),
 422            ) {
 423                Ok(PrepareRenameResponse::Success(start..end))
 424            } else {
 425                Err(anyhow!(
 426                    "Missing start or end position in remote project PrepareRenameResponse"
 427                ))
 428            }
 429        } else if message.only_unprepared_rename_supported {
 430            Ok(PrepareRenameResponse::OnlyUnpreparedRenameSupported)
 431        } else {
 432            Ok(PrepareRenameResponse::InvalidPosition)
 433        }
 434    }
 435
 436    fn buffer_id_from_proto(message: &proto::PrepareRename) -> Result<BufferId> {
 437        BufferId::new(message.buffer_id)
 438    }
 439}
 440
 441#[async_trait(?Send)]
 442impl LspCommand for PerformRename {
 443    type Response = ProjectTransaction;
 444    type LspRequest = lsp::request::Rename;
 445    type ProtoRequest = proto::PerformRename;
 446
 447    fn display_name(&self) -> &str {
 448        "Rename"
 449    }
 450
 451    fn to_lsp(
 452        &self,
 453        path: &Path,
 454        _: &Buffer,
 455        _: &Arc<LanguageServer>,
 456        _: &App,
 457    ) -> Result<lsp::RenameParams> {
 458        Ok(lsp::RenameParams {
 459            text_document_position: make_lsp_text_document_position(path, self.position)?,
 460            new_name: self.new_name.clone(),
 461            work_done_progress_params: Default::default(),
 462        })
 463    }
 464
 465    async fn response_from_lsp(
 466        self,
 467        message: Option<lsp::WorkspaceEdit>,
 468        lsp_store: Entity<LspStore>,
 469        buffer: Entity<Buffer>,
 470        server_id: LanguageServerId,
 471        mut cx: AsyncApp,
 472    ) -> Result<ProjectTransaction> {
 473        if let Some(edit) = message {
 474            let (lsp_adapter, lsp_server) =
 475                language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
 476            LocalLspStore::deserialize_workspace_edit(
 477                lsp_store,
 478                edit,
 479                self.push_to_history,
 480                lsp_adapter,
 481                lsp_server,
 482                &mut cx,
 483            )
 484            .await
 485        } else {
 486            Ok(ProjectTransaction::default())
 487        }
 488    }
 489
 490    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::PerformRename {
 491        proto::PerformRename {
 492            project_id,
 493            buffer_id: buffer.remote_id().into(),
 494            position: Some(language::proto::serialize_anchor(
 495                &buffer.anchor_before(self.position),
 496            )),
 497            new_name: self.new_name.clone(),
 498            version: serialize_version(&buffer.version()),
 499        }
 500    }
 501
 502    async fn from_proto(
 503        message: proto::PerformRename,
 504        _: Entity<LspStore>,
 505        buffer: Entity<Buffer>,
 506        mut cx: AsyncApp,
 507    ) -> Result<Self> {
 508        let position = message
 509            .position
 510            .and_then(deserialize_anchor)
 511            .ok_or_else(|| anyhow!("invalid position"))?;
 512        buffer
 513            .update(&mut cx, |buffer, _| {
 514                buffer.wait_for_version(deserialize_version(&message.version))
 515            })?
 516            .await?;
 517        Ok(Self {
 518            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
 519            new_name: message.new_name,
 520            push_to_history: false,
 521        })
 522    }
 523
 524    fn response_to_proto(
 525        response: ProjectTransaction,
 526        lsp_store: &mut LspStore,
 527        peer_id: PeerId,
 528        _: &clock::Global,
 529        cx: &mut App,
 530    ) -> proto::PerformRenameResponse {
 531        let transaction = lsp_store.buffer_store().update(cx, |buffer_store, cx| {
 532            buffer_store.serialize_project_transaction_for_peer(response, peer_id, cx)
 533        });
 534        proto::PerformRenameResponse {
 535            transaction: Some(transaction),
 536        }
 537    }
 538
 539    async fn response_from_proto(
 540        self,
 541        message: proto::PerformRenameResponse,
 542        lsp_store: Entity<LspStore>,
 543        _: Entity<Buffer>,
 544        mut cx: AsyncApp,
 545    ) -> Result<ProjectTransaction> {
 546        let message = message
 547            .transaction
 548            .ok_or_else(|| anyhow!("missing transaction"))?;
 549        lsp_store
 550            .update(&mut cx, |lsp_store, cx| {
 551                lsp_store.buffer_store().update(cx, |buffer_store, cx| {
 552                    buffer_store.deserialize_project_transaction(message, self.push_to_history, cx)
 553                })
 554            })?
 555            .await
 556    }
 557
 558    fn buffer_id_from_proto(message: &proto::PerformRename) -> Result<BufferId> {
 559        BufferId::new(message.buffer_id)
 560    }
 561}
 562
 563#[async_trait(?Send)]
 564impl LspCommand for GetDefinition {
 565    type Response = Vec<LocationLink>;
 566    type LspRequest = lsp::request::GotoDefinition;
 567    type ProtoRequest = proto::GetDefinition;
 568
 569    fn display_name(&self) -> &str {
 570        "Get definition"
 571    }
 572
 573    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 574        capabilities
 575            .server_capabilities
 576            .definition_provider
 577            .is_some()
 578    }
 579
 580    fn to_lsp(
 581        &self,
 582        path: &Path,
 583        _: &Buffer,
 584        _: &Arc<LanguageServer>,
 585        _: &App,
 586    ) -> Result<lsp::GotoDefinitionParams> {
 587        Ok(lsp::GotoDefinitionParams {
 588            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 589            work_done_progress_params: Default::default(),
 590            partial_result_params: Default::default(),
 591        })
 592    }
 593
 594    async fn response_from_lsp(
 595        self,
 596        message: Option<lsp::GotoDefinitionResponse>,
 597        lsp_store: Entity<LspStore>,
 598        buffer: Entity<Buffer>,
 599        server_id: LanguageServerId,
 600        cx: AsyncApp,
 601    ) -> Result<Vec<LocationLink>> {
 602        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
 603    }
 604
 605    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDefinition {
 606        proto::GetDefinition {
 607            project_id,
 608            buffer_id: buffer.remote_id().into(),
 609            position: Some(language::proto::serialize_anchor(
 610                &buffer.anchor_before(self.position),
 611            )),
 612            version: serialize_version(&buffer.version()),
 613        }
 614    }
 615
 616    async fn from_proto(
 617        message: proto::GetDefinition,
 618        _: Entity<LspStore>,
 619        buffer: Entity<Buffer>,
 620        mut cx: AsyncApp,
 621    ) -> Result<Self> {
 622        let position = message
 623            .position
 624            .and_then(deserialize_anchor)
 625            .ok_or_else(|| anyhow!("invalid position"))?;
 626        buffer
 627            .update(&mut cx, |buffer, _| {
 628                buffer.wait_for_version(deserialize_version(&message.version))
 629            })?
 630            .await?;
 631        Ok(Self {
 632            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
 633        })
 634    }
 635
 636    fn response_to_proto(
 637        response: Vec<LocationLink>,
 638        lsp_store: &mut LspStore,
 639        peer_id: PeerId,
 640        _: &clock::Global,
 641        cx: &mut App,
 642    ) -> proto::GetDefinitionResponse {
 643        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
 644        proto::GetDefinitionResponse { links }
 645    }
 646
 647    async fn response_from_proto(
 648        self,
 649        message: proto::GetDefinitionResponse,
 650        lsp_store: Entity<LspStore>,
 651        _: Entity<Buffer>,
 652        cx: AsyncApp,
 653    ) -> Result<Vec<LocationLink>> {
 654        location_links_from_proto(message.links, lsp_store, cx).await
 655    }
 656
 657    fn buffer_id_from_proto(message: &proto::GetDefinition) -> Result<BufferId> {
 658        BufferId::new(message.buffer_id)
 659    }
 660}
 661
 662#[async_trait(?Send)]
 663impl LspCommand for GetDeclaration {
 664    type Response = Vec<LocationLink>;
 665    type LspRequest = lsp::request::GotoDeclaration;
 666    type ProtoRequest = proto::GetDeclaration;
 667
 668    fn display_name(&self) -> &str {
 669        "Get declaration"
 670    }
 671
 672    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 673        capabilities
 674            .server_capabilities
 675            .declaration_provider
 676            .is_some()
 677    }
 678
 679    fn to_lsp(
 680        &self,
 681        path: &Path,
 682        _: &Buffer,
 683        _: &Arc<LanguageServer>,
 684        _: &App,
 685    ) -> Result<lsp::GotoDeclarationParams> {
 686        Ok(lsp::GotoDeclarationParams {
 687            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 688            work_done_progress_params: Default::default(),
 689            partial_result_params: Default::default(),
 690        })
 691    }
 692
 693    async fn response_from_lsp(
 694        self,
 695        message: Option<lsp::GotoDeclarationResponse>,
 696        lsp_store: Entity<LspStore>,
 697        buffer: Entity<Buffer>,
 698        server_id: LanguageServerId,
 699        cx: AsyncApp,
 700    ) -> Result<Vec<LocationLink>> {
 701        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
 702    }
 703
 704    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDeclaration {
 705        proto::GetDeclaration {
 706            project_id,
 707            buffer_id: buffer.remote_id().into(),
 708            position: Some(language::proto::serialize_anchor(
 709                &buffer.anchor_before(self.position),
 710            )),
 711            version: serialize_version(&buffer.version()),
 712        }
 713    }
 714
 715    async fn from_proto(
 716        message: proto::GetDeclaration,
 717        _: Entity<LspStore>,
 718        buffer: Entity<Buffer>,
 719        mut cx: AsyncApp,
 720    ) -> Result<Self> {
 721        let position = message
 722            .position
 723            .and_then(deserialize_anchor)
 724            .ok_or_else(|| anyhow!("invalid position"))?;
 725        buffer
 726            .update(&mut cx, |buffer, _| {
 727                buffer.wait_for_version(deserialize_version(&message.version))
 728            })?
 729            .await?;
 730        Ok(Self {
 731            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
 732        })
 733    }
 734
 735    fn response_to_proto(
 736        response: Vec<LocationLink>,
 737        lsp_store: &mut LspStore,
 738        peer_id: PeerId,
 739        _: &clock::Global,
 740        cx: &mut App,
 741    ) -> proto::GetDeclarationResponse {
 742        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
 743        proto::GetDeclarationResponse { links }
 744    }
 745
 746    async fn response_from_proto(
 747        self,
 748        message: proto::GetDeclarationResponse,
 749        lsp_store: Entity<LspStore>,
 750        _: Entity<Buffer>,
 751        cx: AsyncApp,
 752    ) -> Result<Vec<LocationLink>> {
 753        location_links_from_proto(message.links, lsp_store, cx).await
 754    }
 755
 756    fn buffer_id_from_proto(message: &proto::GetDeclaration) -> Result<BufferId> {
 757        BufferId::new(message.buffer_id)
 758    }
 759}
 760
 761#[async_trait(?Send)]
 762impl LspCommand for GetImplementation {
 763    type Response = Vec<LocationLink>;
 764    type LspRequest = lsp::request::GotoImplementation;
 765    type ProtoRequest = proto::GetImplementation;
 766
 767    fn display_name(&self) -> &str {
 768        "Get implementation"
 769    }
 770
 771    fn to_lsp(
 772        &self,
 773        path: &Path,
 774        _: &Buffer,
 775        _: &Arc<LanguageServer>,
 776        _: &App,
 777    ) -> Result<lsp::GotoImplementationParams> {
 778        Ok(lsp::GotoImplementationParams {
 779            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 780            work_done_progress_params: Default::default(),
 781            partial_result_params: Default::default(),
 782        })
 783    }
 784
 785    async fn response_from_lsp(
 786        self,
 787        message: Option<lsp::GotoImplementationResponse>,
 788        lsp_store: Entity<LspStore>,
 789        buffer: Entity<Buffer>,
 790        server_id: LanguageServerId,
 791        cx: AsyncApp,
 792    ) -> Result<Vec<LocationLink>> {
 793        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
 794    }
 795
 796    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetImplementation {
 797        proto::GetImplementation {
 798            project_id,
 799            buffer_id: buffer.remote_id().into(),
 800            position: Some(language::proto::serialize_anchor(
 801                &buffer.anchor_before(self.position),
 802            )),
 803            version: serialize_version(&buffer.version()),
 804        }
 805    }
 806
 807    async fn from_proto(
 808        message: proto::GetImplementation,
 809        _: Entity<LspStore>,
 810        buffer: Entity<Buffer>,
 811        mut cx: AsyncApp,
 812    ) -> Result<Self> {
 813        let position = message
 814            .position
 815            .and_then(deserialize_anchor)
 816            .ok_or_else(|| anyhow!("invalid position"))?;
 817        buffer
 818            .update(&mut cx, |buffer, _| {
 819                buffer.wait_for_version(deserialize_version(&message.version))
 820            })?
 821            .await?;
 822        Ok(Self {
 823            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
 824        })
 825    }
 826
 827    fn response_to_proto(
 828        response: Vec<LocationLink>,
 829        lsp_store: &mut LspStore,
 830        peer_id: PeerId,
 831        _: &clock::Global,
 832        cx: &mut App,
 833    ) -> proto::GetImplementationResponse {
 834        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
 835        proto::GetImplementationResponse { links }
 836    }
 837
 838    async fn response_from_proto(
 839        self,
 840        message: proto::GetImplementationResponse,
 841        project: Entity<LspStore>,
 842        _: Entity<Buffer>,
 843        cx: AsyncApp,
 844    ) -> Result<Vec<LocationLink>> {
 845        location_links_from_proto(message.links, project, cx).await
 846    }
 847
 848    fn buffer_id_from_proto(message: &proto::GetImplementation) -> Result<BufferId> {
 849        BufferId::new(message.buffer_id)
 850    }
 851}
 852
 853#[async_trait(?Send)]
 854impl LspCommand for GetTypeDefinition {
 855    type Response = Vec<LocationLink>;
 856    type LspRequest = lsp::request::GotoTypeDefinition;
 857    type ProtoRequest = proto::GetTypeDefinition;
 858
 859    fn display_name(&self) -> &str {
 860        "Get type definition"
 861    }
 862
 863    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 864        !matches!(
 865            &capabilities.server_capabilities.type_definition_provider,
 866            None | Some(lsp::TypeDefinitionProviderCapability::Simple(false))
 867        )
 868    }
 869
 870    fn to_lsp(
 871        &self,
 872        path: &Path,
 873        _: &Buffer,
 874        _: &Arc<LanguageServer>,
 875        _: &App,
 876    ) -> Result<lsp::GotoTypeDefinitionParams> {
 877        Ok(lsp::GotoTypeDefinitionParams {
 878            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 879            work_done_progress_params: Default::default(),
 880            partial_result_params: Default::default(),
 881        })
 882    }
 883
 884    async fn response_from_lsp(
 885        self,
 886        message: Option<lsp::GotoTypeDefinitionResponse>,
 887        project: Entity<LspStore>,
 888        buffer: Entity<Buffer>,
 889        server_id: LanguageServerId,
 890        cx: AsyncApp,
 891    ) -> Result<Vec<LocationLink>> {
 892        location_links_from_lsp(message, project, buffer, server_id, cx).await
 893    }
 894
 895    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetTypeDefinition {
 896        proto::GetTypeDefinition {
 897            project_id,
 898            buffer_id: buffer.remote_id().into(),
 899            position: Some(language::proto::serialize_anchor(
 900                &buffer.anchor_before(self.position),
 901            )),
 902            version: serialize_version(&buffer.version()),
 903        }
 904    }
 905
 906    async fn from_proto(
 907        message: proto::GetTypeDefinition,
 908        _: Entity<LspStore>,
 909        buffer: Entity<Buffer>,
 910        mut cx: AsyncApp,
 911    ) -> Result<Self> {
 912        let position = message
 913            .position
 914            .and_then(deserialize_anchor)
 915            .ok_or_else(|| anyhow!("invalid position"))?;
 916        buffer
 917            .update(&mut cx, |buffer, _| {
 918                buffer.wait_for_version(deserialize_version(&message.version))
 919            })?
 920            .await?;
 921        Ok(Self {
 922            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
 923        })
 924    }
 925
 926    fn response_to_proto(
 927        response: Vec<LocationLink>,
 928        lsp_store: &mut LspStore,
 929        peer_id: PeerId,
 930        _: &clock::Global,
 931        cx: &mut App,
 932    ) -> proto::GetTypeDefinitionResponse {
 933        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
 934        proto::GetTypeDefinitionResponse { links }
 935    }
 936
 937    async fn response_from_proto(
 938        self,
 939        message: proto::GetTypeDefinitionResponse,
 940        project: Entity<LspStore>,
 941        _: Entity<Buffer>,
 942        cx: AsyncApp,
 943    ) -> Result<Vec<LocationLink>> {
 944        location_links_from_proto(message.links, project, cx).await
 945    }
 946
 947    fn buffer_id_from_proto(message: &proto::GetTypeDefinition) -> Result<BufferId> {
 948        BufferId::new(message.buffer_id)
 949    }
 950}
 951
 952fn language_server_for_buffer(
 953    lsp_store: &Entity<LspStore>,
 954    buffer: &Entity<Buffer>,
 955    server_id: LanguageServerId,
 956    cx: &mut AsyncApp,
 957) -> Result<(Arc<CachedLspAdapter>, Arc<LanguageServer>)> {
 958    lsp_store
 959        .update(cx, |lsp_store, cx| {
 960            buffer.update(cx, |buffer, cx| {
 961                lsp_store
 962                    .language_server_for_local_buffer(buffer, server_id, cx)
 963                    .map(|(adapter, server)| (adapter.clone(), server.clone()))
 964            })
 965        })?
 966        .ok_or_else(|| anyhow!("no language server found for buffer"))
 967}
 968
 969pub async fn location_links_from_proto(
 970    proto_links: Vec<proto::LocationLink>,
 971    lsp_store: Entity<LspStore>,
 972    mut cx: AsyncApp,
 973) -> Result<Vec<LocationLink>> {
 974    let mut links = Vec::new();
 975
 976    for link in proto_links {
 977        links.push(location_link_from_proto(link, lsp_store.clone(), &mut cx).await?)
 978    }
 979
 980    Ok(links)
 981}
 982
 983pub fn location_link_from_proto(
 984    link: proto::LocationLink,
 985    lsp_store: Entity<LspStore>,
 986    cx: &mut AsyncApp,
 987) -> Task<Result<LocationLink>> {
 988    cx.spawn(async move |cx| {
 989        let origin = match link.origin {
 990            Some(origin) => {
 991                let buffer_id = BufferId::new(origin.buffer_id)?;
 992                let buffer = lsp_store
 993                    .update(cx, |lsp_store, cx| {
 994                        lsp_store.wait_for_remote_buffer(buffer_id, cx)
 995                    })?
 996                    .await?;
 997                let start = origin
 998                    .start
 999                    .and_then(deserialize_anchor)
1000                    .ok_or_else(|| anyhow!("missing origin start"))?;
1001                let end = origin
1002                    .end
1003                    .and_then(deserialize_anchor)
1004                    .ok_or_else(|| anyhow!("missing origin end"))?;
1005                buffer
1006                    .update(cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
1007                    .await?;
1008                Some(Location {
1009                    buffer,
1010                    range: start..end,
1011                })
1012            }
1013            None => None,
1014        };
1015
1016        let target = link.target.ok_or_else(|| anyhow!("missing target"))?;
1017        let buffer_id = BufferId::new(target.buffer_id)?;
1018        let buffer = lsp_store
1019            .update(cx, |lsp_store, cx| {
1020                lsp_store.wait_for_remote_buffer(buffer_id, cx)
1021            })?
1022            .await?;
1023        let start = target
1024            .start
1025            .and_then(deserialize_anchor)
1026            .ok_or_else(|| anyhow!("missing target start"))?;
1027        let end = target
1028            .end
1029            .and_then(deserialize_anchor)
1030            .ok_or_else(|| anyhow!("missing target end"))?;
1031        buffer
1032            .update(cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
1033            .await?;
1034        let target = Location {
1035            buffer,
1036            range: start..end,
1037        };
1038        Ok(LocationLink { origin, target })
1039    })
1040}
1041
1042pub async fn location_links_from_lsp(
1043    message: Option<lsp::GotoDefinitionResponse>,
1044    lsp_store: Entity<LspStore>,
1045    buffer: Entity<Buffer>,
1046    server_id: LanguageServerId,
1047    mut cx: AsyncApp,
1048) -> Result<Vec<LocationLink>> {
1049    let message = match message {
1050        Some(message) => message,
1051        None => return Ok(Vec::new()),
1052    };
1053
1054    let mut unresolved_links = Vec::new();
1055    match message {
1056        lsp::GotoDefinitionResponse::Scalar(loc) => {
1057            unresolved_links.push((None, loc.uri, loc.range));
1058        }
1059
1060        lsp::GotoDefinitionResponse::Array(locs) => {
1061            unresolved_links.extend(locs.into_iter().map(|l| (None, l.uri, l.range)));
1062        }
1063
1064        lsp::GotoDefinitionResponse::Link(links) => {
1065            unresolved_links.extend(links.into_iter().map(|l| {
1066                (
1067                    l.origin_selection_range,
1068                    l.target_uri,
1069                    l.target_selection_range,
1070                )
1071            }));
1072        }
1073    }
1074
1075    let (lsp_adapter, language_server) =
1076        language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1077    let mut definitions = Vec::new();
1078    for (origin_range, target_uri, target_range) in unresolved_links {
1079        let target_buffer_handle = lsp_store
1080            .update(&mut cx, |this, cx| {
1081                this.open_local_buffer_via_lsp(
1082                    target_uri,
1083                    language_server.server_id(),
1084                    lsp_adapter.name.clone(),
1085                    cx,
1086                )
1087            })?
1088            .await?;
1089
1090        cx.update(|cx| {
1091            let origin_location = origin_range.map(|origin_range| {
1092                let origin_buffer = buffer.read(cx);
1093                let origin_start =
1094                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
1095                let origin_end =
1096                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
1097                Location {
1098                    buffer: buffer.clone(),
1099                    range: origin_buffer.anchor_after(origin_start)
1100                        ..origin_buffer.anchor_before(origin_end),
1101                }
1102            });
1103
1104            let target_buffer = target_buffer_handle.read(cx);
1105            let target_start =
1106                target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
1107            let target_end =
1108                target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
1109            let target_location = Location {
1110                buffer: target_buffer_handle,
1111                range: target_buffer.anchor_after(target_start)
1112                    ..target_buffer.anchor_before(target_end),
1113            };
1114
1115            definitions.push(LocationLink {
1116                origin: origin_location,
1117                target: target_location,
1118            })
1119        })?;
1120    }
1121    Ok(definitions)
1122}
1123
1124pub async fn location_link_from_lsp(
1125    link: lsp::LocationLink,
1126    lsp_store: &Entity<LspStore>,
1127    buffer: &Entity<Buffer>,
1128    server_id: LanguageServerId,
1129    cx: &mut AsyncApp,
1130) -> Result<LocationLink> {
1131    let (lsp_adapter, language_server) =
1132        language_server_for_buffer(&lsp_store, &buffer, server_id, cx)?;
1133
1134    let (origin_range, target_uri, target_range) = (
1135        link.origin_selection_range,
1136        link.target_uri,
1137        link.target_selection_range,
1138    );
1139
1140    let target_buffer_handle = lsp_store
1141        .update(cx, |lsp_store, cx| {
1142            lsp_store.open_local_buffer_via_lsp(
1143                target_uri,
1144                language_server.server_id(),
1145                lsp_adapter.name.clone(),
1146                cx,
1147            )
1148        })?
1149        .await?;
1150
1151    cx.update(|cx| {
1152        let origin_location = origin_range.map(|origin_range| {
1153            let origin_buffer = buffer.read(cx);
1154            let origin_start =
1155                origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
1156            let origin_end =
1157                origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
1158            Location {
1159                buffer: buffer.clone(),
1160                range: origin_buffer.anchor_after(origin_start)
1161                    ..origin_buffer.anchor_before(origin_end),
1162            }
1163        });
1164
1165        let target_buffer = target_buffer_handle.read(cx);
1166        let target_start =
1167            target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
1168        let target_end =
1169            target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
1170        let target_location = Location {
1171            buffer: target_buffer_handle,
1172            range: target_buffer.anchor_after(target_start)
1173                ..target_buffer.anchor_before(target_end),
1174        };
1175
1176        LocationLink {
1177            origin: origin_location,
1178            target: target_location,
1179        }
1180    })
1181}
1182
1183pub fn location_links_to_proto(
1184    links: Vec<LocationLink>,
1185    lsp_store: &mut LspStore,
1186    peer_id: PeerId,
1187    cx: &mut App,
1188) -> Vec<proto::LocationLink> {
1189    links
1190        .into_iter()
1191        .map(|definition| location_link_to_proto(definition, lsp_store, peer_id, cx))
1192        .collect()
1193}
1194
1195pub fn location_link_to_proto(
1196    location: LocationLink,
1197    lsp_store: &mut LspStore,
1198    peer_id: PeerId,
1199    cx: &mut App,
1200) -> proto::LocationLink {
1201    let origin = location.origin.map(|origin| {
1202        lsp_store
1203            .buffer_store()
1204            .update(cx, |buffer_store, cx| {
1205                buffer_store.create_buffer_for_peer(&origin.buffer, peer_id, cx)
1206            })
1207            .detach_and_log_err(cx);
1208
1209        let buffer_id = origin.buffer.read(cx).remote_id().into();
1210        proto::Location {
1211            start: Some(serialize_anchor(&origin.range.start)),
1212            end: Some(serialize_anchor(&origin.range.end)),
1213            buffer_id,
1214        }
1215    });
1216
1217    lsp_store
1218        .buffer_store()
1219        .update(cx, |buffer_store, cx| {
1220            buffer_store.create_buffer_for_peer(&location.target.buffer, peer_id, cx)
1221        })
1222        .detach_and_log_err(cx);
1223
1224    let buffer_id = location.target.buffer.read(cx).remote_id().into();
1225    let target = proto::Location {
1226        start: Some(serialize_anchor(&location.target.range.start)),
1227        end: Some(serialize_anchor(&location.target.range.end)),
1228        buffer_id,
1229    };
1230
1231    proto::LocationLink {
1232        origin,
1233        target: Some(target),
1234    }
1235}
1236
1237#[async_trait(?Send)]
1238impl LspCommand for GetReferences {
1239    type Response = Vec<Location>;
1240    type LspRequest = lsp::request::References;
1241    type ProtoRequest = proto::GetReferences;
1242
1243    fn display_name(&self) -> &str {
1244        "Find all references"
1245    }
1246
1247    fn status(&self) -> Option<String> {
1248        Some("Finding references...".to_owned())
1249    }
1250
1251    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1252        match &capabilities.server_capabilities.references_provider {
1253            Some(OneOf::Left(has_support)) => *has_support,
1254            Some(OneOf::Right(_)) => true,
1255            None => false,
1256        }
1257    }
1258
1259    fn to_lsp(
1260        &self,
1261        path: &Path,
1262        _: &Buffer,
1263        _: &Arc<LanguageServer>,
1264        _: &App,
1265    ) -> Result<lsp::ReferenceParams> {
1266        Ok(lsp::ReferenceParams {
1267            text_document_position: make_lsp_text_document_position(path, self.position)?,
1268            work_done_progress_params: Default::default(),
1269            partial_result_params: Default::default(),
1270            context: lsp::ReferenceContext {
1271                include_declaration: true,
1272            },
1273        })
1274    }
1275
1276    async fn response_from_lsp(
1277        self,
1278        locations: Option<Vec<lsp::Location>>,
1279        lsp_store: Entity<LspStore>,
1280        buffer: Entity<Buffer>,
1281        server_id: LanguageServerId,
1282        mut cx: AsyncApp,
1283    ) -> Result<Vec<Location>> {
1284        let mut references = Vec::new();
1285        let (lsp_adapter, language_server) =
1286            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1287
1288        if let Some(locations) = locations {
1289            for lsp_location in locations {
1290                let target_buffer_handle = lsp_store
1291                    .update(&mut cx, |lsp_store, cx| {
1292                        lsp_store.open_local_buffer_via_lsp(
1293                            lsp_location.uri,
1294                            language_server.server_id(),
1295                            lsp_adapter.name.clone(),
1296                            cx,
1297                        )
1298                    })?
1299                    .await?;
1300
1301                target_buffer_handle
1302                    .clone()
1303                    .update(&mut cx, |target_buffer, _| {
1304                        let target_start = target_buffer
1305                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
1306                        let target_end = target_buffer
1307                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
1308                        references.push(Location {
1309                            buffer: target_buffer_handle,
1310                            range: target_buffer.anchor_after(target_start)
1311                                ..target_buffer.anchor_before(target_end),
1312                        });
1313                    })?;
1314            }
1315        }
1316
1317        Ok(references)
1318    }
1319
1320    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetReferences {
1321        proto::GetReferences {
1322            project_id,
1323            buffer_id: buffer.remote_id().into(),
1324            position: Some(language::proto::serialize_anchor(
1325                &buffer.anchor_before(self.position),
1326            )),
1327            version: serialize_version(&buffer.version()),
1328        }
1329    }
1330
1331    async fn from_proto(
1332        message: proto::GetReferences,
1333        _: Entity<LspStore>,
1334        buffer: Entity<Buffer>,
1335        mut cx: AsyncApp,
1336    ) -> Result<Self> {
1337        let position = message
1338            .position
1339            .and_then(deserialize_anchor)
1340            .ok_or_else(|| anyhow!("invalid position"))?;
1341        buffer
1342            .update(&mut cx, |buffer, _| {
1343                buffer.wait_for_version(deserialize_version(&message.version))
1344            })?
1345            .await?;
1346        Ok(Self {
1347            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
1348        })
1349    }
1350
1351    fn response_to_proto(
1352        response: Vec<Location>,
1353        lsp_store: &mut LspStore,
1354        peer_id: PeerId,
1355        _: &clock::Global,
1356        cx: &mut App,
1357    ) -> proto::GetReferencesResponse {
1358        let locations = response
1359            .into_iter()
1360            .map(|definition| {
1361                lsp_store
1362                    .buffer_store()
1363                    .update(cx, |buffer_store, cx| {
1364                        buffer_store.create_buffer_for_peer(&definition.buffer, peer_id, cx)
1365                    })
1366                    .detach_and_log_err(cx);
1367                let buffer_id = definition.buffer.read(cx).remote_id();
1368                proto::Location {
1369                    start: Some(serialize_anchor(&definition.range.start)),
1370                    end: Some(serialize_anchor(&definition.range.end)),
1371                    buffer_id: buffer_id.into(),
1372                }
1373            })
1374            .collect();
1375        proto::GetReferencesResponse { locations }
1376    }
1377
1378    async fn response_from_proto(
1379        self,
1380        message: proto::GetReferencesResponse,
1381        project: Entity<LspStore>,
1382        _: Entity<Buffer>,
1383        mut cx: AsyncApp,
1384    ) -> Result<Vec<Location>> {
1385        let mut locations = Vec::new();
1386        for location in message.locations {
1387            let buffer_id = BufferId::new(location.buffer_id)?;
1388            let target_buffer = project
1389                .update(&mut cx, |this, cx| {
1390                    this.wait_for_remote_buffer(buffer_id, cx)
1391                })?
1392                .await?;
1393            let start = location
1394                .start
1395                .and_then(deserialize_anchor)
1396                .ok_or_else(|| anyhow!("missing target start"))?;
1397            let end = location
1398                .end
1399                .and_then(deserialize_anchor)
1400                .ok_or_else(|| anyhow!("missing target end"))?;
1401            target_buffer
1402                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
1403                .await?;
1404            locations.push(Location {
1405                buffer: target_buffer,
1406                range: start..end,
1407            })
1408        }
1409        Ok(locations)
1410    }
1411
1412    fn buffer_id_from_proto(message: &proto::GetReferences) -> Result<BufferId> {
1413        BufferId::new(message.buffer_id)
1414    }
1415}
1416
1417#[async_trait(?Send)]
1418impl LspCommand for GetDocumentHighlights {
1419    type Response = Vec<DocumentHighlight>;
1420    type LspRequest = lsp::request::DocumentHighlightRequest;
1421    type ProtoRequest = proto::GetDocumentHighlights;
1422
1423    fn display_name(&self) -> &str {
1424        "Get document highlights"
1425    }
1426
1427    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1428        capabilities
1429            .server_capabilities
1430            .document_highlight_provider
1431            .is_some()
1432    }
1433
1434    fn to_lsp(
1435        &self,
1436        path: &Path,
1437        _: &Buffer,
1438        _: &Arc<LanguageServer>,
1439        _: &App,
1440    ) -> Result<lsp::DocumentHighlightParams> {
1441        Ok(lsp::DocumentHighlightParams {
1442            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1443            work_done_progress_params: Default::default(),
1444            partial_result_params: Default::default(),
1445        })
1446    }
1447
1448    async fn response_from_lsp(
1449        self,
1450        lsp_highlights: Option<Vec<lsp::DocumentHighlight>>,
1451        _: Entity<LspStore>,
1452        buffer: Entity<Buffer>,
1453        _: LanguageServerId,
1454        mut cx: AsyncApp,
1455    ) -> Result<Vec<DocumentHighlight>> {
1456        buffer.update(&mut cx, |buffer, _| {
1457            let mut lsp_highlights = lsp_highlights.unwrap_or_default();
1458            lsp_highlights.sort_unstable_by_key(|h| (h.range.start, Reverse(h.range.end)));
1459            lsp_highlights
1460                .into_iter()
1461                .map(|lsp_highlight| {
1462                    let start = buffer
1463                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.start), Bias::Left);
1464                    let end = buffer
1465                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.end), Bias::Left);
1466                    DocumentHighlight {
1467                        range: buffer.anchor_after(start)..buffer.anchor_before(end),
1468                        kind: lsp_highlight
1469                            .kind
1470                            .unwrap_or(lsp::DocumentHighlightKind::READ),
1471                    }
1472                })
1473                .collect()
1474        })
1475    }
1476
1477    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentHighlights {
1478        proto::GetDocumentHighlights {
1479            project_id,
1480            buffer_id: buffer.remote_id().into(),
1481            position: Some(language::proto::serialize_anchor(
1482                &buffer.anchor_before(self.position),
1483            )),
1484            version: serialize_version(&buffer.version()),
1485        }
1486    }
1487
1488    async fn from_proto(
1489        message: proto::GetDocumentHighlights,
1490        _: Entity<LspStore>,
1491        buffer: Entity<Buffer>,
1492        mut cx: AsyncApp,
1493    ) -> Result<Self> {
1494        let position = message
1495            .position
1496            .and_then(deserialize_anchor)
1497            .ok_or_else(|| anyhow!("invalid position"))?;
1498        buffer
1499            .update(&mut cx, |buffer, _| {
1500                buffer.wait_for_version(deserialize_version(&message.version))
1501            })?
1502            .await?;
1503        Ok(Self {
1504            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
1505        })
1506    }
1507
1508    fn response_to_proto(
1509        response: Vec<DocumentHighlight>,
1510        _: &mut LspStore,
1511        _: PeerId,
1512        _: &clock::Global,
1513        _: &mut App,
1514    ) -> proto::GetDocumentHighlightsResponse {
1515        let highlights = response
1516            .into_iter()
1517            .map(|highlight| proto::DocumentHighlight {
1518                start: Some(serialize_anchor(&highlight.range.start)),
1519                end: Some(serialize_anchor(&highlight.range.end)),
1520                kind: match highlight.kind {
1521                    DocumentHighlightKind::TEXT => proto::document_highlight::Kind::Text.into(),
1522                    DocumentHighlightKind::WRITE => proto::document_highlight::Kind::Write.into(),
1523                    DocumentHighlightKind::READ => proto::document_highlight::Kind::Read.into(),
1524                    _ => proto::document_highlight::Kind::Text.into(),
1525                },
1526            })
1527            .collect();
1528        proto::GetDocumentHighlightsResponse { highlights }
1529    }
1530
1531    async fn response_from_proto(
1532        self,
1533        message: proto::GetDocumentHighlightsResponse,
1534        _: Entity<LspStore>,
1535        buffer: Entity<Buffer>,
1536        mut cx: AsyncApp,
1537    ) -> Result<Vec<DocumentHighlight>> {
1538        let mut highlights = Vec::new();
1539        for highlight in message.highlights {
1540            let start = highlight
1541                .start
1542                .and_then(deserialize_anchor)
1543                .ok_or_else(|| anyhow!("missing target start"))?;
1544            let end = highlight
1545                .end
1546                .and_then(deserialize_anchor)
1547                .ok_or_else(|| anyhow!("missing target end"))?;
1548            buffer
1549                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
1550                .await?;
1551            let kind = match proto::document_highlight::Kind::from_i32(highlight.kind) {
1552                Some(proto::document_highlight::Kind::Text) => DocumentHighlightKind::TEXT,
1553                Some(proto::document_highlight::Kind::Read) => DocumentHighlightKind::READ,
1554                Some(proto::document_highlight::Kind::Write) => DocumentHighlightKind::WRITE,
1555                None => DocumentHighlightKind::TEXT,
1556            };
1557            highlights.push(DocumentHighlight {
1558                range: start..end,
1559                kind,
1560            });
1561        }
1562        Ok(highlights)
1563    }
1564
1565    fn buffer_id_from_proto(message: &proto::GetDocumentHighlights) -> Result<BufferId> {
1566        BufferId::new(message.buffer_id)
1567    }
1568}
1569
1570#[async_trait(?Send)]
1571impl LspCommand for GetDocumentSymbols {
1572    type Response = Vec<DocumentSymbol>;
1573    type LspRequest = lsp::request::DocumentSymbolRequest;
1574    type ProtoRequest = proto::GetDocumentSymbols;
1575
1576    fn display_name(&self) -> &str {
1577        "Get document symbols"
1578    }
1579
1580    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1581        capabilities
1582            .server_capabilities
1583            .document_symbol_provider
1584            .is_some()
1585    }
1586
1587    fn to_lsp(
1588        &self,
1589        path: &Path,
1590        _: &Buffer,
1591        _: &Arc<LanguageServer>,
1592        _: &App,
1593    ) -> Result<lsp::DocumentSymbolParams> {
1594        Ok(lsp::DocumentSymbolParams {
1595            text_document: make_text_document_identifier(path)?,
1596            work_done_progress_params: Default::default(),
1597            partial_result_params: Default::default(),
1598        })
1599    }
1600
1601    async fn response_from_lsp(
1602        self,
1603        lsp_symbols: Option<lsp::DocumentSymbolResponse>,
1604        _: Entity<LspStore>,
1605        _: Entity<Buffer>,
1606        _: LanguageServerId,
1607        _: AsyncApp,
1608    ) -> Result<Vec<DocumentSymbol>> {
1609        let Some(lsp_symbols) = lsp_symbols else {
1610            return Ok(Vec::new());
1611        };
1612
1613        let symbols: Vec<_> = match lsp_symbols {
1614            lsp::DocumentSymbolResponse::Flat(symbol_information) => symbol_information
1615                .into_iter()
1616                .map(|lsp_symbol| DocumentSymbol {
1617                    name: lsp_symbol.name,
1618                    kind: lsp_symbol.kind,
1619                    range: range_from_lsp(lsp_symbol.location.range),
1620                    selection_range: range_from_lsp(lsp_symbol.location.range),
1621                    children: Vec::new(),
1622                })
1623                .collect(),
1624            lsp::DocumentSymbolResponse::Nested(nested_responses) => {
1625                fn convert_symbol(lsp_symbol: lsp::DocumentSymbol) -> DocumentSymbol {
1626                    DocumentSymbol {
1627                        name: lsp_symbol.name,
1628                        kind: lsp_symbol.kind,
1629                        range: range_from_lsp(lsp_symbol.range),
1630                        selection_range: range_from_lsp(lsp_symbol.selection_range),
1631                        children: lsp_symbol
1632                            .children
1633                            .map(|children| {
1634                                children.into_iter().map(convert_symbol).collect::<Vec<_>>()
1635                            })
1636                            .unwrap_or_default(),
1637                    }
1638                }
1639                nested_responses.into_iter().map(convert_symbol).collect()
1640            }
1641        };
1642        Ok(symbols)
1643    }
1644
1645    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentSymbols {
1646        proto::GetDocumentSymbols {
1647            project_id,
1648            buffer_id: buffer.remote_id().into(),
1649            version: serialize_version(&buffer.version()),
1650        }
1651    }
1652
1653    async fn from_proto(
1654        message: proto::GetDocumentSymbols,
1655        _: Entity<LspStore>,
1656        buffer: Entity<Buffer>,
1657        mut cx: AsyncApp,
1658    ) -> Result<Self> {
1659        buffer
1660            .update(&mut cx, |buffer, _| {
1661                buffer.wait_for_version(deserialize_version(&message.version))
1662            })?
1663            .await?;
1664        Ok(Self)
1665    }
1666
1667    fn response_to_proto(
1668        response: Vec<DocumentSymbol>,
1669        _: &mut LspStore,
1670        _: PeerId,
1671        _: &clock::Global,
1672        _: &mut App,
1673    ) -> proto::GetDocumentSymbolsResponse {
1674        let symbols = response
1675            .into_iter()
1676            .map(|symbol| {
1677                fn convert_symbol_to_proto(symbol: DocumentSymbol) -> proto::DocumentSymbol {
1678                    proto::DocumentSymbol {
1679                        name: symbol.name.clone(),
1680                        kind: unsafe { mem::transmute::<lsp::SymbolKind, i32>(symbol.kind) },
1681                        start: Some(proto::PointUtf16 {
1682                            row: symbol.range.start.0.row,
1683                            column: symbol.range.start.0.column,
1684                        }),
1685                        end: Some(proto::PointUtf16 {
1686                            row: symbol.range.end.0.row,
1687                            column: symbol.range.end.0.column,
1688                        }),
1689                        selection_start: Some(proto::PointUtf16 {
1690                            row: symbol.selection_range.start.0.row,
1691                            column: symbol.selection_range.start.0.column,
1692                        }),
1693                        selection_end: Some(proto::PointUtf16 {
1694                            row: symbol.selection_range.end.0.row,
1695                            column: symbol.selection_range.end.0.column,
1696                        }),
1697                        children: symbol
1698                            .children
1699                            .into_iter()
1700                            .map(convert_symbol_to_proto)
1701                            .collect(),
1702                    }
1703                }
1704                convert_symbol_to_proto(symbol)
1705            })
1706            .collect::<Vec<_>>();
1707
1708        proto::GetDocumentSymbolsResponse { symbols }
1709    }
1710
1711    async fn response_from_proto(
1712        self,
1713        message: proto::GetDocumentSymbolsResponse,
1714        _: Entity<LspStore>,
1715        _: Entity<Buffer>,
1716        _: AsyncApp,
1717    ) -> Result<Vec<DocumentSymbol>> {
1718        let mut symbols = Vec::with_capacity(message.symbols.len());
1719        for serialized_symbol in message.symbols {
1720            fn deserialize_symbol_with_children(
1721                serialized_symbol: proto::DocumentSymbol,
1722            ) -> Result<DocumentSymbol> {
1723                let kind =
1724                    unsafe { mem::transmute::<i32, lsp::SymbolKind>(serialized_symbol.kind) };
1725
1726                let start = serialized_symbol
1727                    .start
1728                    .ok_or_else(|| anyhow!("invalid start"))?;
1729                let end = serialized_symbol
1730                    .end
1731                    .ok_or_else(|| anyhow!("invalid end"))?;
1732
1733                let selection_start = serialized_symbol
1734                    .selection_start
1735                    .ok_or_else(|| anyhow!("invalid selection start"))?;
1736                let selection_end = serialized_symbol
1737                    .selection_end
1738                    .ok_or_else(|| anyhow!("invalid selection end"))?;
1739
1740                Ok(DocumentSymbol {
1741                    name: serialized_symbol.name,
1742                    kind,
1743                    range: Unclipped(PointUtf16::new(start.row, start.column))
1744                        ..Unclipped(PointUtf16::new(end.row, end.column)),
1745                    selection_range: Unclipped(PointUtf16::new(
1746                        selection_start.row,
1747                        selection_start.column,
1748                    ))
1749                        ..Unclipped(PointUtf16::new(selection_end.row, selection_end.column)),
1750                    children: serialized_symbol
1751                        .children
1752                        .into_iter()
1753                        .filter_map(|symbol| deserialize_symbol_with_children(symbol).ok())
1754                        .collect::<Vec<_>>(),
1755                })
1756            }
1757
1758            symbols.push(deserialize_symbol_with_children(serialized_symbol)?);
1759        }
1760
1761        Ok(symbols)
1762    }
1763
1764    fn buffer_id_from_proto(message: &proto::GetDocumentSymbols) -> Result<BufferId> {
1765        BufferId::new(message.buffer_id)
1766    }
1767}
1768
1769#[async_trait(?Send)]
1770impl LspCommand for GetSignatureHelp {
1771    type Response = Option<SignatureHelp>;
1772    type LspRequest = lsp::SignatureHelpRequest;
1773    type ProtoRequest = proto::GetSignatureHelp;
1774
1775    fn display_name(&self) -> &str {
1776        "Get signature help"
1777    }
1778
1779    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1780        capabilities
1781            .server_capabilities
1782            .signature_help_provider
1783            .is_some()
1784    }
1785
1786    fn to_lsp(
1787        &self,
1788        path: &Path,
1789        _: &Buffer,
1790        _: &Arc<LanguageServer>,
1791        _cx: &App,
1792    ) -> Result<lsp::SignatureHelpParams> {
1793        Ok(lsp::SignatureHelpParams {
1794            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1795            context: None,
1796            work_done_progress_params: Default::default(),
1797        })
1798    }
1799
1800    async fn response_from_lsp(
1801        self,
1802        message: Option<lsp::SignatureHelp>,
1803        _: Entity<LspStore>,
1804        _: Entity<Buffer>,
1805        _: LanguageServerId,
1806        _: AsyncApp,
1807    ) -> Result<Self::Response> {
1808        Ok(message.and_then(SignatureHelp::new))
1809    }
1810
1811    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
1812        let offset = buffer.point_utf16_to_offset(self.position);
1813        proto::GetSignatureHelp {
1814            project_id,
1815            buffer_id: buffer.remote_id().to_proto(),
1816            position: Some(serialize_anchor(&buffer.anchor_after(offset))),
1817            version: serialize_version(&buffer.version()),
1818        }
1819    }
1820
1821    async fn from_proto(
1822        payload: Self::ProtoRequest,
1823        _: Entity<LspStore>,
1824        buffer: Entity<Buffer>,
1825        mut cx: AsyncApp,
1826    ) -> Result<Self> {
1827        buffer
1828            .update(&mut cx, |buffer, _| {
1829                buffer.wait_for_version(deserialize_version(&payload.version))
1830            })?
1831            .await
1832            .with_context(|| format!("waiting for version for buffer {}", buffer.entity_id()))?;
1833        let buffer_snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot())?;
1834        Ok(Self {
1835            position: payload
1836                .position
1837                .and_then(deserialize_anchor)
1838                .context("invalid position")?
1839                .to_point_utf16(&buffer_snapshot),
1840        })
1841    }
1842
1843    fn response_to_proto(
1844        response: Self::Response,
1845        _: &mut LspStore,
1846        _: PeerId,
1847        _: &Global,
1848        _: &mut App,
1849    ) -> proto::GetSignatureHelpResponse {
1850        proto::GetSignatureHelpResponse {
1851            signature_help: response
1852                .map(|signature_help| lsp_to_proto_signature(signature_help.original_data)),
1853        }
1854    }
1855
1856    async fn response_from_proto(
1857        self,
1858        response: proto::GetSignatureHelpResponse,
1859        _: Entity<LspStore>,
1860        _: Entity<Buffer>,
1861        _: AsyncApp,
1862    ) -> Result<Self::Response> {
1863        Ok(response
1864            .signature_help
1865            .map(proto_to_lsp_signature)
1866            .and_then(SignatureHelp::new))
1867    }
1868
1869    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
1870        BufferId::new(message.buffer_id)
1871    }
1872}
1873
1874#[async_trait(?Send)]
1875impl LspCommand for GetHover {
1876    type Response = Option<Hover>;
1877    type LspRequest = lsp::request::HoverRequest;
1878    type ProtoRequest = proto::GetHover;
1879
1880    fn display_name(&self) -> &str {
1881        "Get hover"
1882    }
1883
1884    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1885        match capabilities.server_capabilities.hover_provider {
1886            Some(lsp::HoverProviderCapability::Simple(enabled)) => enabled,
1887            Some(lsp::HoverProviderCapability::Options(_)) => true,
1888            None => false,
1889        }
1890    }
1891
1892    fn to_lsp(
1893        &self,
1894        path: &Path,
1895        _: &Buffer,
1896        _: &Arc<LanguageServer>,
1897        _: &App,
1898    ) -> Result<lsp::HoverParams> {
1899        Ok(lsp::HoverParams {
1900            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1901            work_done_progress_params: Default::default(),
1902        })
1903    }
1904
1905    async fn response_from_lsp(
1906        self,
1907        message: Option<lsp::Hover>,
1908        _: Entity<LspStore>,
1909        buffer: Entity<Buffer>,
1910        _: LanguageServerId,
1911        mut cx: AsyncApp,
1912    ) -> Result<Self::Response> {
1913        let Some(hover) = message else {
1914            return Ok(None);
1915        };
1916
1917        let (language, range) = buffer.update(&mut cx, |buffer, _| {
1918            (
1919                buffer.language().cloned(),
1920                hover.range.map(|range| {
1921                    let token_start =
1922                        buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
1923                    let token_end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
1924                    buffer.anchor_after(token_start)..buffer.anchor_before(token_end)
1925                }),
1926            )
1927        })?;
1928
1929        fn hover_blocks_from_marked_string(marked_string: lsp::MarkedString) -> Option<HoverBlock> {
1930            let block = match marked_string {
1931                lsp::MarkedString::String(content) => HoverBlock {
1932                    text: content,
1933                    kind: HoverBlockKind::Markdown,
1934                },
1935                lsp::MarkedString::LanguageString(lsp::LanguageString { language, value }) => {
1936                    HoverBlock {
1937                        text: value,
1938                        kind: HoverBlockKind::Code { language },
1939                    }
1940                }
1941            };
1942            if block.text.is_empty() {
1943                None
1944            } else {
1945                Some(block)
1946            }
1947        }
1948
1949        let contents = match hover.contents {
1950            lsp::HoverContents::Scalar(marked_string) => {
1951                hover_blocks_from_marked_string(marked_string)
1952                    .into_iter()
1953                    .collect()
1954            }
1955            lsp::HoverContents::Array(marked_strings) => marked_strings
1956                .into_iter()
1957                .filter_map(hover_blocks_from_marked_string)
1958                .collect(),
1959            lsp::HoverContents::Markup(markup_content) => vec![HoverBlock {
1960                text: markup_content.value,
1961                kind: if markup_content.kind == lsp::MarkupKind::Markdown {
1962                    HoverBlockKind::Markdown
1963                } else {
1964                    HoverBlockKind::PlainText
1965                },
1966            }],
1967        };
1968
1969        Ok(Some(Hover {
1970            contents,
1971            range,
1972            language,
1973        }))
1974    }
1975
1976    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
1977        proto::GetHover {
1978            project_id,
1979            buffer_id: buffer.remote_id().into(),
1980            position: Some(language::proto::serialize_anchor(
1981                &buffer.anchor_before(self.position),
1982            )),
1983            version: serialize_version(&buffer.version),
1984        }
1985    }
1986
1987    async fn from_proto(
1988        message: Self::ProtoRequest,
1989        _: Entity<LspStore>,
1990        buffer: Entity<Buffer>,
1991        mut cx: AsyncApp,
1992    ) -> Result<Self> {
1993        let position = message
1994            .position
1995            .and_then(deserialize_anchor)
1996            .ok_or_else(|| anyhow!("invalid position"))?;
1997        buffer
1998            .update(&mut cx, |buffer, _| {
1999                buffer.wait_for_version(deserialize_version(&message.version))
2000            })?
2001            .await?;
2002        Ok(Self {
2003            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
2004        })
2005    }
2006
2007    fn response_to_proto(
2008        response: Self::Response,
2009        _: &mut LspStore,
2010        _: PeerId,
2011        _: &clock::Global,
2012        _: &mut App,
2013    ) -> proto::GetHoverResponse {
2014        if let Some(response) = response {
2015            let (start, end) = if let Some(range) = response.range {
2016                (
2017                    Some(language::proto::serialize_anchor(&range.start)),
2018                    Some(language::proto::serialize_anchor(&range.end)),
2019                )
2020            } else {
2021                (None, None)
2022            };
2023
2024            let contents = response
2025                .contents
2026                .into_iter()
2027                .map(|block| proto::HoverBlock {
2028                    text: block.text,
2029                    is_markdown: block.kind == HoverBlockKind::Markdown,
2030                    language: if let HoverBlockKind::Code { language } = block.kind {
2031                        Some(language)
2032                    } else {
2033                        None
2034                    },
2035                })
2036                .collect();
2037
2038            proto::GetHoverResponse {
2039                start,
2040                end,
2041                contents,
2042            }
2043        } else {
2044            proto::GetHoverResponse {
2045                start: None,
2046                end: None,
2047                contents: Vec::new(),
2048            }
2049        }
2050    }
2051
2052    async fn response_from_proto(
2053        self,
2054        message: proto::GetHoverResponse,
2055        _: Entity<LspStore>,
2056        buffer: Entity<Buffer>,
2057        mut cx: AsyncApp,
2058    ) -> Result<Self::Response> {
2059        let contents: Vec<_> = message
2060            .contents
2061            .into_iter()
2062            .map(|block| HoverBlock {
2063                text: block.text,
2064                kind: if let Some(language) = block.language {
2065                    HoverBlockKind::Code { language }
2066                } else if block.is_markdown {
2067                    HoverBlockKind::Markdown
2068                } else {
2069                    HoverBlockKind::PlainText
2070                },
2071            })
2072            .collect();
2073        if contents.is_empty() {
2074            return Ok(None);
2075        }
2076
2077        let language = buffer.update(&mut cx, |buffer, _| buffer.language().cloned())?;
2078        let range = if let (Some(start), Some(end)) = (message.start, message.end) {
2079            language::proto::deserialize_anchor(start)
2080                .and_then(|start| language::proto::deserialize_anchor(end).map(|end| start..end))
2081        } else {
2082            None
2083        };
2084        if let Some(range) = range.as_ref() {
2085            buffer
2086                .update(&mut cx, |buffer, _| {
2087                    buffer.wait_for_anchors([range.start, range.end])
2088                })?
2089                .await?;
2090        }
2091
2092        Ok(Some(Hover {
2093            contents,
2094            range,
2095            language,
2096        }))
2097    }
2098
2099    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
2100        BufferId::new(message.buffer_id)
2101    }
2102}
2103
2104#[async_trait(?Send)]
2105impl LspCommand for GetCompletions {
2106    type Response = Vec<CoreCompletion>;
2107    type LspRequest = lsp::request::Completion;
2108    type ProtoRequest = proto::GetCompletions;
2109
2110    fn display_name(&self) -> &str {
2111        "Get completion"
2112    }
2113
2114    fn to_lsp(
2115        &self,
2116        path: &Path,
2117        _: &Buffer,
2118        _: &Arc<LanguageServer>,
2119        _: &App,
2120    ) -> Result<lsp::CompletionParams> {
2121        Ok(lsp::CompletionParams {
2122            text_document_position: make_lsp_text_document_position(path, self.position)?,
2123            context: Some(self.context.clone()),
2124            work_done_progress_params: Default::default(),
2125            partial_result_params: Default::default(),
2126        })
2127    }
2128
2129    async fn response_from_lsp(
2130        self,
2131        completions: Option<lsp::CompletionResponse>,
2132        lsp_store: Entity<LspStore>,
2133        buffer: Entity<Buffer>,
2134        server_id: LanguageServerId,
2135        mut cx: AsyncApp,
2136    ) -> Result<Self::Response> {
2137        let mut response_list = None;
2138        let mut completions = if let Some(completions) = completions {
2139            match completions {
2140                lsp::CompletionResponse::Array(completions) => completions,
2141                lsp::CompletionResponse::List(mut list) => {
2142                    let items = std::mem::take(&mut list.items);
2143                    response_list = Some(list);
2144                    items
2145                }
2146            }
2147        } else {
2148            Vec::new()
2149        };
2150
2151        let language_server_adapter = lsp_store
2152            .update(&mut cx, |lsp_store, _| {
2153                lsp_store.language_server_adapter_for_id(server_id)
2154            })?
2155            .with_context(|| format!("no language server with id {server_id}"))?;
2156
2157        let lsp_defaults = response_list
2158            .as_ref()
2159            .and_then(|list| list.item_defaults.clone())
2160            .map(Arc::new);
2161
2162        let mut completion_edits = Vec::new();
2163        buffer.update(&mut cx, |buffer, _cx| {
2164            let snapshot = buffer.snapshot();
2165            let clipped_position = buffer.clip_point_utf16(Unclipped(self.position), Bias::Left);
2166
2167            let mut range_for_token = None;
2168            completions.retain(|lsp_completion| {
2169                let lsp_edit = lsp_completion.text_edit.clone().or_else(|| {
2170                    let default_text_edit = lsp_defaults.as_deref()?.edit_range.as_ref()?;
2171                    let new_text = lsp_completion
2172                        .insert_text
2173                        .as_ref()
2174                        .unwrap_or(&lsp_completion.label)
2175                        .clone();
2176                    match default_text_edit {
2177                        CompletionListItemDefaultsEditRange::Range(range) => {
2178                            Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
2179                                range: *range,
2180                                new_text,
2181                            }))
2182                        }
2183                        CompletionListItemDefaultsEditRange::InsertAndReplace {
2184                            insert,
2185                            replace,
2186                        } => Some(lsp::CompletionTextEdit::InsertAndReplace(
2187                            lsp::InsertReplaceEdit {
2188                                new_text,
2189                                insert: *insert,
2190                                replace: *replace,
2191                            },
2192                        )),
2193                    }
2194                });
2195
2196                let edit = match lsp_edit {
2197                    // If the language server provides a range to overwrite, then
2198                    // check that the range is valid.
2199                    Some(completion_text_edit) => {
2200                        match parse_completion_text_edit(&completion_text_edit, &snapshot) {
2201                            Some(edit) => edit,
2202                            None => return false,
2203                        }
2204                    }
2205                    // If the language server does not provide a range, then infer
2206                    // the range based on the syntax tree.
2207                    None => {
2208                        if self.position != clipped_position {
2209                            log::info!("completion out of expected range");
2210                            return false;
2211                        }
2212
2213                        let default_edit_range = lsp_defaults.as_ref().and_then(|lsp_defaults| {
2214                            lsp_defaults
2215                                .edit_range
2216                                .as_ref()
2217                                .and_then(|range| match range {
2218                                    CompletionListItemDefaultsEditRange::Range(r) => Some(r),
2219                                    _ => None,
2220                                })
2221                        });
2222
2223                        let range = if let Some(range) = default_edit_range {
2224                            let range = range_from_lsp(*range);
2225                            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2226                            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2227                            if start != range.start.0 || end != range.end.0 {
2228                                log::info!("completion out of expected range");
2229                                return false;
2230                            }
2231
2232                            snapshot.anchor_before(start)..snapshot.anchor_after(end)
2233                        } else {
2234                            range_for_token
2235                                .get_or_insert_with(|| {
2236                                    let offset = self.position.to_offset(&snapshot);
2237                                    let (range, kind) = snapshot.surrounding_word(offset);
2238                                    let range = if kind == Some(CharKind::Word) {
2239                                        range
2240                                    } else {
2241                                        offset..offset
2242                                    };
2243
2244                                    snapshot.anchor_before(range.start)
2245                                        ..snapshot.anchor_after(range.end)
2246                                })
2247                                .clone()
2248                        };
2249
2250                        // We already know text_edit is None here
2251                        let text = lsp_completion
2252                            .insert_text
2253                            .as_ref()
2254                            .unwrap_or(&lsp_completion.label)
2255                            .clone();
2256
2257                        ParsedCompletionEdit {
2258                            replace_range: range,
2259                            insert_range: None,
2260                            new_text: text,
2261                        }
2262                    }
2263                };
2264
2265                completion_edits.push(edit);
2266                true
2267            });
2268        })?;
2269
2270        language_server_adapter
2271            .process_completions(&mut completions)
2272            .await;
2273
2274        Ok(completions
2275            .into_iter()
2276            .zip(completion_edits)
2277            .map(|(mut lsp_completion, mut edit)| {
2278                LineEnding::normalize(&mut edit.new_text);
2279                if lsp_completion.data.is_none() {
2280                    if let Some(default_data) = lsp_defaults
2281                        .as_ref()
2282                        .and_then(|item_defaults| item_defaults.data.clone())
2283                    {
2284                        // Servers (e.g. JDTLS) prefer unchanged completions, when resolving the items later,
2285                        // so we do not insert the defaults here, but `data` is needed for resolving, so this is an exception.
2286                        lsp_completion.data = Some(default_data);
2287                    }
2288                }
2289                CoreCompletion {
2290                    replace_range: edit.replace_range,
2291                    new_text: edit.new_text,
2292                    source: CompletionSource::Lsp {
2293                        insert_range: edit.insert_range,
2294                        server_id,
2295                        lsp_completion: Box::new(lsp_completion),
2296                        lsp_defaults: lsp_defaults.clone(),
2297                        resolved: false,
2298                    },
2299                }
2300            })
2301            .collect())
2302    }
2303
2304    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCompletions {
2305        let anchor = buffer.anchor_after(self.position);
2306        proto::GetCompletions {
2307            project_id,
2308            buffer_id: buffer.remote_id().into(),
2309            position: Some(language::proto::serialize_anchor(&anchor)),
2310            version: serialize_version(&buffer.version()),
2311        }
2312    }
2313
2314    async fn from_proto(
2315        message: proto::GetCompletions,
2316        _: Entity<LspStore>,
2317        buffer: Entity<Buffer>,
2318        mut cx: AsyncApp,
2319    ) -> Result<Self> {
2320        let version = deserialize_version(&message.version);
2321        buffer
2322            .update(&mut cx, |buffer, _| buffer.wait_for_version(version))?
2323            .await?;
2324        let position = message
2325            .position
2326            .and_then(language::proto::deserialize_anchor)
2327            .map(|p| {
2328                buffer.update(&mut cx, |buffer, _| {
2329                    buffer.clip_point_utf16(Unclipped(p.to_point_utf16(buffer)), Bias::Left)
2330                })
2331            })
2332            .ok_or_else(|| anyhow!("invalid position"))??;
2333        Ok(Self {
2334            position,
2335            context: CompletionContext {
2336                trigger_kind: CompletionTriggerKind::INVOKED,
2337                trigger_character: None,
2338            },
2339        })
2340    }
2341
2342    fn response_to_proto(
2343        completions: Vec<CoreCompletion>,
2344        _: &mut LspStore,
2345        _: PeerId,
2346        buffer_version: &clock::Global,
2347        _: &mut App,
2348    ) -> proto::GetCompletionsResponse {
2349        proto::GetCompletionsResponse {
2350            completions: completions
2351                .iter()
2352                .map(LspStore::serialize_completion)
2353                .collect(),
2354            version: serialize_version(buffer_version),
2355        }
2356    }
2357
2358    async fn response_from_proto(
2359        self,
2360        message: proto::GetCompletionsResponse,
2361        _project: Entity<LspStore>,
2362        buffer: Entity<Buffer>,
2363        mut cx: AsyncApp,
2364    ) -> Result<Self::Response> {
2365        buffer
2366            .update(&mut cx, |buffer, _| {
2367                buffer.wait_for_version(deserialize_version(&message.version))
2368            })?
2369            .await?;
2370
2371        message
2372            .completions
2373            .into_iter()
2374            .map(LspStore::deserialize_completion)
2375            .collect()
2376    }
2377
2378    fn buffer_id_from_proto(message: &proto::GetCompletions) -> Result<BufferId> {
2379        BufferId::new(message.buffer_id)
2380    }
2381}
2382
2383pub struct ParsedCompletionEdit {
2384    pub replace_range: Range<Anchor>,
2385    pub insert_range: Option<Range<Anchor>>,
2386    pub new_text: String,
2387}
2388
2389pub(crate) fn parse_completion_text_edit(
2390    edit: &lsp::CompletionTextEdit,
2391    snapshot: &BufferSnapshot,
2392) -> Option<ParsedCompletionEdit> {
2393    let (replace_range, insert_range, new_text) = match edit {
2394        lsp::CompletionTextEdit::Edit(edit) => (edit.range, None, &edit.new_text),
2395        lsp::CompletionTextEdit::InsertAndReplace(edit) => {
2396            (edit.replace, Some(edit.insert), &edit.new_text)
2397        }
2398    };
2399
2400    let replace_range = {
2401        let range = range_from_lsp(replace_range);
2402        let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2403        let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2404        if start != range.start.0 || end != range.end.0 {
2405            log::info!("completion out of expected range");
2406            return None;
2407        }
2408        snapshot.anchor_before(start)..snapshot.anchor_after(end)
2409    };
2410
2411    let insert_range = match insert_range {
2412        None => None,
2413        Some(insert_range) => {
2414            let range = range_from_lsp(insert_range);
2415            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2416            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2417            if start != range.start.0 || end != range.end.0 {
2418                log::info!("completion (insert) out of expected range");
2419                return None;
2420            }
2421            Some(snapshot.anchor_before(start)..snapshot.anchor_after(end))
2422        }
2423    };
2424
2425    Some(ParsedCompletionEdit {
2426        insert_range: insert_range,
2427        replace_range: replace_range,
2428        new_text: new_text.clone(),
2429    })
2430}
2431
2432#[async_trait(?Send)]
2433impl LspCommand for GetCodeActions {
2434    type Response = Vec<CodeAction>;
2435    type LspRequest = lsp::request::CodeActionRequest;
2436    type ProtoRequest = proto::GetCodeActions;
2437
2438    fn display_name(&self) -> &str {
2439        "Get code actions"
2440    }
2441
2442    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2443        match &capabilities.server_capabilities.code_action_provider {
2444            None => false,
2445            Some(lsp::CodeActionProviderCapability::Simple(false)) => false,
2446            _ => {
2447                // If we do know that we want specific code actions AND we know that
2448                // the server only supports specific code actions, then we want to filter
2449                // down to the ones that are supported.
2450                if let Some((requested, supported)) = self
2451                    .kinds
2452                    .as_ref()
2453                    .zip(Self::supported_code_action_kinds(capabilities))
2454                {
2455                    let server_supported = supported.into_iter().collect::<HashSet<_>>();
2456                    requested.iter().any(|kind| server_supported.contains(kind))
2457                } else {
2458                    true
2459                }
2460            }
2461        }
2462    }
2463
2464    fn to_lsp(
2465        &self,
2466        path: &Path,
2467        buffer: &Buffer,
2468        language_server: &Arc<LanguageServer>,
2469        _: &App,
2470    ) -> Result<lsp::CodeActionParams> {
2471        let mut relevant_diagnostics = Vec::new();
2472        for entry in buffer
2473            .snapshot()
2474            .diagnostics_in_range::<_, language::PointUtf16>(self.range.clone(), false)
2475        {
2476            relevant_diagnostics.push(entry.to_lsp_diagnostic_stub()?);
2477        }
2478
2479        let supported =
2480            Self::supported_code_action_kinds(language_server.adapter_server_capabilities());
2481
2482        let only = if let Some(requested) = &self.kinds {
2483            if let Some(supported_kinds) = supported {
2484                let server_supported = supported_kinds.into_iter().collect::<HashSet<_>>();
2485
2486                let filtered = requested
2487                    .iter()
2488                    .filter(|kind| server_supported.contains(kind))
2489                    .cloned()
2490                    .collect();
2491                Some(filtered)
2492            } else {
2493                Some(requested.clone())
2494            }
2495        } else {
2496            supported
2497        };
2498
2499        Ok(lsp::CodeActionParams {
2500            text_document: make_text_document_identifier(path)?,
2501            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
2502            work_done_progress_params: Default::default(),
2503            partial_result_params: Default::default(),
2504            context: lsp::CodeActionContext {
2505                diagnostics: relevant_diagnostics,
2506                only,
2507                ..lsp::CodeActionContext::default()
2508            },
2509        })
2510    }
2511
2512    async fn response_from_lsp(
2513        self,
2514        actions: Option<lsp::CodeActionResponse>,
2515        lsp_store: Entity<LspStore>,
2516        _: Entity<Buffer>,
2517        server_id: LanguageServerId,
2518        cx: AsyncApp,
2519    ) -> Result<Vec<CodeAction>> {
2520        let requested_kinds_set = if let Some(kinds) = self.kinds {
2521            Some(kinds.into_iter().collect::<HashSet<_>>())
2522        } else {
2523            None
2524        };
2525
2526        let language_server = cx.update(|cx| {
2527            lsp_store
2528                .read(cx)
2529                .language_server_for_id(server_id)
2530                .with_context(|| {
2531                    format!("Missing the language server that just returned a response {server_id}")
2532                })
2533        })??;
2534
2535        let server_capabilities = language_server.capabilities();
2536        let available_commands = server_capabilities
2537            .execute_command_provider
2538            .as_ref()
2539            .map(|options| options.commands.as_slice())
2540            .unwrap_or_default();
2541        Ok(actions
2542            .unwrap_or_default()
2543            .into_iter()
2544            .filter_map(|entry| {
2545                let (lsp_action, resolved) = match entry {
2546                    lsp::CodeActionOrCommand::CodeAction(lsp_action) => {
2547                        if let Some(command) = lsp_action.command.as_ref() {
2548                            if !available_commands.contains(&command.command) {
2549                                return None;
2550                            }
2551                        }
2552                        (LspAction::Action(Box::new(lsp_action)), false)
2553                    }
2554                    lsp::CodeActionOrCommand::Command(command) => {
2555                        if available_commands.contains(&command.command) {
2556                            (LspAction::Command(command), true)
2557                        } else {
2558                            return None;
2559                        }
2560                    }
2561                };
2562
2563                if let Some((requested_kinds, kind)) =
2564                    requested_kinds_set.as_ref().zip(lsp_action.action_kind())
2565                {
2566                    if !requested_kinds.contains(&kind) {
2567                        return None;
2568                    }
2569                }
2570
2571                Some(CodeAction {
2572                    server_id,
2573                    range: self.range.clone(),
2574                    lsp_action,
2575                    resolved,
2576                })
2577            })
2578            .collect())
2579    }
2580
2581    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeActions {
2582        proto::GetCodeActions {
2583            project_id,
2584            buffer_id: buffer.remote_id().into(),
2585            start: Some(language::proto::serialize_anchor(&self.range.start)),
2586            end: Some(language::proto::serialize_anchor(&self.range.end)),
2587            version: serialize_version(&buffer.version()),
2588        }
2589    }
2590
2591    async fn from_proto(
2592        message: proto::GetCodeActions,
2593        _: Entity<LspStore>,
2594        buffer: Entity<Buffer>,
2595        mut cx: AsyncApp,
2596    ) -> Result<Self> {
2597        let start = message
2598            .start
2599            .and_then(language::proto::deserialize_anchor)
2600            .ok_or_else(|| anyhow!("invalid start"))?;
2601        let end = message
2602            .end
2603            .and_then(language::proto::deserialize_anchor)
2604            .ok_or_else(|| anyhow!("invalid end"))?;
2605        buffer
2606            .update(&mut cx, |buffer, _| {
2607                buffer.wait_for_version(deserialize_version(&message.version))
2608            })?
2609            .await?;
2610
2611        Ok(Self {
2612            range: start..end,
2613            kinds: None,
2614        })
2615    }
2616
2617    fn response_to_proto(
2618        code_actions: Vec<CodeAction>,
2619        _: &mut LspStore,
2620        _: PeerId,
2621        buffer_version: &clock::Global,
2622        _: &mut App,
2623    ) -> proto::GetCodeActionsResponse {
2624        proto::GetCodeActionsResponse {
2625            actions: code_actions
2626                .iter()
2627                .map(LspStore::serialize_code_action)
2628                .collect(),
2629            version: serialize_version(buffer_version),
2630        }
2631    }
2632
2633    async fn response_from_proto(
2634        self,
2635        message: proto::GetCodeActionsResponse,
2636        _: Entity<LspStore>,
2637        buffer: Entity<Buffer>,
2638        mut cx: AsyncApp,
2639    ) -> Result<Vec<CodeAction>> {
2640        buffer
2641            .update(&mut cx, |buffer, _| {
2642                buffer.wait_for_version(deserialize_version(&message.version))
2643            })?
2644            .await?;
2645        message
2646            .actions
2647            .into_iter()
2648            .map(LspStore::deserialize_code_action)
2649            .collect()
2650    }
2651
2652    fn buffer_id_from_proto(message: &proto::GetCodeActions) -> Result<BufferId> {
2653        BufferId::new(message.buffer_id)
2654    }
2655}
2656
2657impl GetCodeActions {
2658    fn supported_code_action_kinds(
2659        capabilities: AdapterServerCapabilities,
2660    ) -> Option<Vec<CodeActionKind>> {
2661        match capabilities.server_capabilities.code_action_provider {
2662            Some(lsp::CodeActionProviderCapability::Options(CodeActionOptions {
2663                code_action_kinds: Some(supported_action_kinds),
2664                ..
2665            })) => Some(supported_action_kinds.clone()),
2666            _ => capabilities.code_action_kinds,
2667        }
2668    }
2669
2670    pub fn can_resolve_actions(capabilities: &ServerCapabilities) -> bool {
2671        capabilities
2672            .code_action_provider
2673            .as_ref()
2674            .and_then(|options| match options {
2675                lsp::CodeActionProviderCapability::Simple(_is_supported) => None,
2676                lsp::CodeActionProviderCapability::Options(options) => options.resolve_provider,
2677            })
2678            .unwrap_or(false)
2679    }
2680}
2681
2682#[async_trait(?Send)]
2683impl LspCommand for OnTypeFormatting {
2684    type Response = Option<Transaction>;
2685    type LspRequest = lsp::request::OnTypeFormatting;
2686    type ProtoRequest = proto::OnTypeFormatting;
2687
2688    fn display_name(&self) -> &str {
2689        "Formatting on typing"
2690    }
2691
2692    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2693        let Some(on_type_formatting_options) = &capabilities
2694            .server_capabilities
2695            .document_on_type_formatting_provider
2696        else {
2697            return false;
2698        };
2699        on_type_formatting_options
2700            .first_trigger_character
2701            .contains(&self.trigger)
2702            || on_type_formatting_options
2703                .more_trigger_character
2704                .iter()
2705                .flatten()
2706                .any(|chars| chars.contains(&self.trigger))
2707    }
2708
2709    fn to_lsp(
2710        &self,
2711        path: &Path,
2712        _: &Buffer,
2713        _: &Arc<LanguageServer>,
2714        _: &App,
2715    ) -> Result<lsp::DocumentOnTypeFormattingParams> {
2716        Ok(lsp::DocumentOnTypeFormattingParams {
2717            text_document_position: make_lsp_text_document_position(path, self.position)?,
2718            ch: self.trigger.clone(),
2719            options: self.options.clone(),
2720        })
2721    }
2722
2723    async fn response_from_lsp(
2724        self,
2725        message: Option<Vec<lsp::TextEdit>>,
2726        lsp_store: Entity<LspStore>,
2727        buffer: Entity<Buffer>,
2728        server_id: LanguageServerId,
2729        mut cx: AsyncApp,
2730    ) -> Result<Option<Transaction>> {
2731        if let Some(edits) = message {
2732            let (lsp_adapter, lsp_server) =
2733                language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
2734            LocalLspStore::deserialize_text_edits(
2735                lsp_store,
2736                buffer,
2737                edits,
2738                self.push_to_history,
2739                lsp_adapter,
2740                lsp_server,
2741                &mut cx,
2742            )
2743            .await
2744        } else {
2745            Ok(None)
2746        }
2747    }
2748
2749    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::OnTypeFormatting {
2750        proto::OnTypeFormatting {
2751            project_id,
2752            buffer_id: buffer.remote_id().into(),
2753            position: Some(language::proto::serialize_anchor(
2754                &buffer.anchor_before(self.position),
2755            )),
2756            trigger: self.trigger.clone(),
2757            version: serialize_version(&buffer.version()),
2758        }
2759    }
2760
2761    async fn from_proto(
2762        message: proto::OnTypeFormatting,
2763        _: Entity<LspStore>,
2764        buffer: Entity<Buffer>,
2765        mut cx: AsyncApp,
2766    ) -> Result<Self> {
2767        let position = message
2768            .position
2769            .and_then(deserialize_anchor)
2770            .ok_or_else(|| anyhow!("invalid position"))?;
2771        buffer
2772            .update(&mut cx, |buffer, _| {
2773                buffer.wait_for_version(deserialize_version(&message.version))
2774            })?
2775            .await?;
2776
2777        let options = buffer.update(&mut cx, |buffer, cx| {
2778            lsp_formatting_options(
2779                language_settings(buffer.language().map(|l| l.name()), buffer.file(), cx).as_ref(),
2780            )
2781        })?;
2782
2783        Ok(Self {
2784            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
2785            trigger: message.trigger.clone(),
2786            options,
2787            push_to_history: false,
2788        })
2789    }
2790
2791    fn response_to_proto(
2792        response: Option<Transaction>,
2793        _: &mut LspStore,
2794        _: PeerId,
2795        _: &clock::Global,
2796        _: &mut App,
2797    ) -> proto::OnTypeFormattingResponse {
2798        proto::OnTypeFormattingResponse {
2799            transaction: response
2800                .map(|transaction| language::proto::serialize_transaction(&transaction)),
2801        }
2802    }
2803
2804    async fn response_from_proto(
2805        self,
2806        message: proto::OnTypeFormattingResponse,
2807        _: Entity<LspStore>,
2808        _: Entity<Buffer>,
2809        _: AsyncApp,
2810    ) -> Result<Option<Transaction>> {
2811        let Some(transaction) = message.transaction else {
2812            return Ok(None);
2813        };
2814        Ok(Some(language::proto::deserialize_transaction(transaction)?))
2815    }
2816
2817    fn buffer_id_from_proto(message: &proto::OnTypeFormatting) -> Result<BufferId> {
2818        BufferId::new(message.buffer_id)
2819    }
2820}
2821
2822impl InlayHints {
2823    pub async fn lsp_to_project_hint(
2824        lsp_hint: lsp::InlayHint,
2825        buffer_handle: &Entity<Buffer>,
2826        server_id: LanguageServerId,
2827        resolve_state: ResolveState,
2828        force_no_type_left_padding: bool,
2829        cx: &mut AsyncApp,
2830    ) -> anyhow::Result<InlayHint> {
2831        let kind = lsp_hint.kind.and_then(|kind| match kind {
2832            lsp::InlayHintKind::TYPE => Some(InlayHintKind::Type),
2833            lsp::InlayHintKind::PARAMETER => Some(InlayHintKind::Parameter),
2834            _ => None,
2835        });
2836
2837        let position = buffer_handle.update(cx, |buffer, _| {
2838            let position = buffer.clip_point_utf16(point_from_lsp(lsp_hint.position), Bias::Left);
2839            if kind == Some(InlayHintKind::Parameter) {
2840                buffer.anchor_before(position)
2841            } else {
2842                buffer.anchor_after(position)
2843            }
2844        })?;
2845        let label = Self::lsp_inlay_label_to_project(lsp_hint.label, server_id)
2846            .await
2847            .context("lsp to project inlay hint conversion")?;
2848        let padding_left = if force_no_type_left_padding && kind == Some(InlayHintKind::Type) {
2849            false
2850        } else {
2851            lsp_hint.padding_left.unwrap_or(false)
2852        };
2853
2854        Ok(InlayHint {
2855            position,
2856            padding_left,
2857            padding_right: lsp_hint.padding_right.unwrap_or(false),
2858            label,
2859            kind,
2860            tooltip: lsp_hint.tooltip.map(|tooltip| match tooltip {
2861                lsp::InlayHintTooltip::String(s) => InlayHintTooltip::String(s),
2862                lsp::InlayHintTooltip::MarkupContent(markup_content) => {
2863                    InlayHintTooltip::MarkupContent(MarkupContent {
2864                        kind: match markup_content.kind {
2865                            lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
2866                            lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
2867                        },
2868                        value: markup_content.value,
2869                    })
2870                }
2871            }),
2872            resolve_state,
2873        })
2874    }
2875
2876    async fn lsp_inlay_label_to_project(
2877        lsp_label: lsp::InlayHintLabel,
2878        server_id: LanguageServerId,
2879    ) -> anyhow::Result<InlayHintLabel> {
2880        let label = match lsp_label {
2881            lsp::InlayHintLabel::String(s) => InlayHintLabel::String(s),
2882            lsp::InlayHintLabel::LabelParts(lsp_parts) => {
2883                let mut parts = Vec::with_capacity(lsp_parts.len());
2884                for lsp_part in lsp_parts {
2885                    parts.push(InlayHintLabelPart {
2886                        value: lsp_part.value,
2887                        tooltip: lsp_part.tooltip.map(|tooltip| match tooltip {
2888                            lsp::InlayHintLabelPartTooltip::String(s) => {
2889                                InlayHintLabelPartTooltip::String(s)
2890                            }
2891                            lsp::InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
2892                                InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
2893                                    kind: match markup_content.kind {
2894                                        lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
2895                                        lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
2896                                    },
2897                                    value: markup_content.value,
2898                                })
2899                            }
2900                        }),
2901                        location: Some(server_id).zip(lsp_part.location),
2902                    });
2903                }
2904                InlayHintLabel::LabelParts(parts)
2905            }
2906        };
2907
2908        Ok(label)
2909    }
2910
2911    pub fn project_to_proto_hint(response_hint: InlayHint) -> proto::InlayHint {
2912        let (state, lsp_resolve_state) = match response_hint.resolve_state {
2913            ResolveState::Resolved => (0, None),
2914            ResolveState::CanResolve(server_id, resolve_data) => (
2915                1,
2916                Some(proto::resolve_state::LspResolveState {
2917                    server_id: server_id.0 as u64,
2918                    value: resolve_data.map(|json_data| {
2919                        serde_json::to_string(&json_data)
2920                            .expect("failed to serialize resolve json data")
2921                    }),
2922                }),
2923            ),
2924            ResolveState::Resolving => (2, None),
2925        };
2926        let resolve_state = Some(proto::ResolveState {
2927            state,
2928            lsp_resolve_state,
2929        });
2930        proto::InlayHint {
2931            position: Some(language::proto::serialize_anchor(&response_hint.position)),
2932            padding_left: response_hint.padding_left,
2933            padding_right: response_hint.padding_right,
2934            label: Some(proto::InlayHintLabel {
2935                label: Some(match response_hint.label {
2936                    InlayHintLabel::String(s) => proto::inlay_hint_label::Label::Value(s),
2937                    InlayHintLabel::LabelParts(label_parts) => {
2938                        proto::inlay_hint_label::Label::LabelParts(proto::InlayHintLabelParts {
2939                            parts: label_parts.into_iter().map(|label_part| {
2940                                let location_url = label_part.location.as_ref().map(|(_, location)| location.uri.to_string());
2941                                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 });
2942                                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 });
2943                                proto::InlayHintLabelPart {
2944                                value: label_part.value,
2945                                tooltip: label_part.tooltip.map(|tooltip| {
2946                                    let proto_tooltip = match tooltip {
2947                                        InlayHintLabelPartTooltip::String(s) => proto::inlay_hint_label_part_tooltip::Content::Value(s),
2948                                        InlayHintLabelPartTooltip::MarkupContent(markup_content) => proto::inlay_hint_label_part_tooltip::Content::MarkupContent(proto::MarkupContent {
2949                                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
2950                                            value: markup_content.value,
2951                                        }),
2952                                    };
2953                                    proto::InlayHintLabelPartTooltip {content: Some(proto_tooltip)}
2954                                }),
2955                                location_url,
2956                                location_range_start,
2957                                location_range_end,
2958                                language_server_id: label_part.location.as_ref().map(|(server_id, _)| server_id.0 as u64),
2959                            }}).collect()
2960                        })
2961                    }
2962                }),
2963            }),
2964            kind: response_hint.kind.map(|kind| kind.name().to_string()),
2965            tooltip: response_hint.tooltip.map(|response_tooltip| {
2966                let proto_tooltip = match response_tooltip {
2967                    InlayHintTooltip::String(s) => proto::inlay_hint_tooltip::Content::Value(s),
2968                    InlayHintTooltip::MarkupContent(markup_content) => {
2969                        proto::inlay_hint_tooltip::Content::MarkupContent(proto::MarkupContent {
2970                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
2971                            value: markup_content.value,
2972                        })
2973                    }
2974                };
2975                proto::InlayHintTooltip {
2976                    content: Some(proto_tooltip),
2977                }
2978            }),
2979            resolve_state,
2980        }
2981    }
2982
2983    pub fn proto_to_project_hint(message_hint: proto::InlayHint) -> anyhow::Result<InlayHint> {
2984        let resolve_state = message_hint.resolve_state.as_ref().unwrap_or_else(|| {
2985            panic!("incorrect proto inlay hint message: no resolve state in hint {message_hint:?}",)
2986        });
2987        let resolve_state_data = resolve_state
2988            .lsp_resolve_state.as_ref()
2989            .map(|lsp_resolve_state| {
2990                let value = lsp_resolve_state.value.as_deref().map(|value| {
2991                    serde_json::from_str::<Option<lsp::LSPAny>>(value)
2992                        .with_context(|| format!("incorrect proto inlay hint message: non-json resolve state {lsp_resolve_state:?}"))
2993                }).transpose()?.flatten();
2994                anyhow::Ok((LanguageServerId(lsp_resolve_state.server_id as usize), value))
2995            })
2996            .transpose()?;
2997        let resolve_state = match resolve_state.state {
2998            0 => ResolveState::Resolved,
2999            1 => {
3000                let (server_id, lsp_resolve_state) = resolve_state_data.with_context(|| {
3001                    format!(
3002                        "No lsp resolve data for the hint that can be resolved: {message_hint:?}"
3003                    )
3004                })?;
3005                ResolveState::CanResolve(server_id, lsp_resolve_state)
3006            }
3007            2 => ResolveState::Resolving,
3008            invalid => {
3009                anyhow::bail!("Unexpected resolve state {invalid} for hint {message_hint:?}")
3010            }
3011        };
3012        Ok(InlayHint {
3013            position: message_hint
3014                .position
3015                .and_then(language::proto::deserialize_anchor)
3016                .context("invalid position")?,
3017            label: match message_hint
3018                .label
3019                .and_then(|label| label.label)
3020                .context("missing label")?
3021            {
3022                proto::inlay_hint_label::Label::Value(s) => InlayHintLabel::String(s),
3023                proto::inlay_hint_label::Label::LabelParts(parts) => {
3024                    let mut label_parts = Vec::new();
3025                    for part in parts.parts {
3026                        label_parts.push(InlayHintLabelPart {
3027                            value: part.value,
3028                            tooltip: part.tooltip.map(|tooltip| match tooltip.content {
3029                                Some(proto::inlay_hint_label_part_tooltip::Content::Value(s)) => {
3030                                    InlayHintLabelPartTooltip::String(s)
3031                                }
3032                                Some(
3033                                    proto::inlay_hint_label_part_tooltip::Content::MarkupContent(
3034                                        markup_content,
3035                                    ),
3036                                ) => InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
3037                                    kind: if markup_content.is_markdown {
3038                                        HoverBlockKind::Markdown
3039                                    } else {
3040                                        HoverBlockKind::PlainText
3041                                    },
3042                                    value: markup_content.value,
3043                                }),
3044                                None => InlayHintLabelPartTooltip::String(String::new()),
3045                            }),
3046                            location: {
3047                                match part
3048                                    .location_url
3049                                    .zip(
3050                                        part.location_range_start.and_then(|start| {
3051                                            Some(start..part.location_range_end?)
3052                                        }),
3053                                    )
3054                                    .zip(part.language_server_id)
3055                                {
3056                                    Some(((uri, range), server_id)) => Some((
3057                                        LanguageServerId(server_id as usize),
3058                                        lsp::Location {
3059                                            uri: lsp::Url::parse(&uri)
3060                                                .context("invalid uri in hint part {part:?}")?,
3061                                            range: lsp::Range::new(
3062                                                point_to_lsp(PointUtf16::new(
3063                                                    range.start.row,
3064                                                    range.start.column,
3065                                                )),
3066                                                point_to_lsp(PointUtf16::new(
3067                                                    range.end.row,
3068                                                    range.end.column,
3069                                                )),
3070                                            ),
3071                                        },
3072                                    )),
3073                                    None => None,
3074                                }
3075                            },
3076                        });
3077                    }
3078
3079                    InlayHintLabel::LabelParts(label_parts)
3080                }
3081            },
3082            padding_left: message_hint.padding_left,
3083            padding_right: message_hint.padding_right,
3084            kind: message_hint
3085                .kind
3086                .as_deref()
3087                .and_then(InlayHintKind::from_name),
3088            tooltip: message_hint.tooltip.and_then(|tooltip| {
3089                Some(match tooltip.content? {
3090                    proto::inlay_hint_tooltip::Content::Value(s) => InlayHintTooltip::String(s),
3091                    proto::inlay_hint_tooltip::Content::MarkupContent(markup_content) => {
3092                        InlayHintTooltip::MarkupContent(MarkupContent {
3093                            kind: if markup_content.is_markdown {
3094                                HoverBlockKind::Markdown
3095                            } else {
3096                                HoverBlockKind::PlainText
3097                            },
3098                            value: markup_content.value,
3099                        })
3100                    }
3101                })
3102            }),
3103            resolve_state,
3104        })
3105    }
3106
3107    pub fn project_to_lsp_hint(hint: InlayHint, snapshot: &BufferSnapshot) -> lsp::InlayHint {
3108        lsp::InlayHint {
3109            position: point_to_lsp(hint.position.to_point_utf16(snapshot)),
3110            kind: hint.kind.map(|kind| match kind {
3111                InlayHintKind::Type => lsp::InlayHintKind::TYPE,
3112                InlayHintKind::Parameter => lsp::InlayHintKind::PARAMETER,
3113            }),
3114            text_edits: None,
3115            tooltip: hint.tooltip.and_then(|tooltip| {
3116                Some(match tooltip {
3117                    InlayHintTooltip::String(s) => lsp::InlayHintTooltip::String(s),
3118                    InlayHintTooltip::MarkupContent(markup_content) => {
3119                        lsp::InlayHintTooltip::MarkupContent(lsp::MarkupContent {
3120                            kind: match markup_content.kind {
3121                                HoverBlockKind::PlainText => lsp::MarkupKind::PlainText,
3122                                HoverBlockKind::Markdown => lsp::MarkupKind::Markdown,
3123                                HoverBlockKind::Code { .. } => return None,
3124                            },
3125                            value: markup_content.value,
3126                        })
3127                    }
3128                })
3129            }),
3130            label: match hint.label {
3131                InlayHintLabel::String(s) => lsp::InlayHintLabel::String(s),
3132                InlayHintLabel::LabelParts(label_parts) => lsp::InlayHintLabel::LabelParts(
3133                    label_parts
3134                        .into_iter()
3135                        .map(|part| lsp::InlayHintLabelPart {
3136                            value: part.value,
3137                            tooltip: part.tooltip.and_then(|tooltip| {
3138                                Some(match tooltip {
3139                                    InlayHintLabelPartTooltip::String(s) => {
3140                                        lsp::InlayHintLabelPartTooltip::String(s)
3141                                    }
3142                                    InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
3143                                        lsp::InlayHintLabelPartTooltip::MarkupContent(
3144                                            lsp::MarkupContent {
3145                                                kind: match markup_content.kind {
3146                                                    HoverBlockKind::PlainText => {
3147                                                        lsp::MarkupKind::PlainText
3148                                                    }
3149                                                    HoverBlockKind::Markdown => {
3150                                                        lsp::MarkupKind::Markdown
3151                                                    }
3152                                                    HoverBlockKind::Code { .. } => return None,
3153                                                },
3154                                                value: markup_content.value,
3155                                            },
3156                                        )
3157                                    }
3158                                })
3159                            }),
3160                            location: part.location.map(|(_, location)| location),
3161                            command: None,
3162                        })
3163                        .collect(),
3164                ),
3165            },
3166            padding_left: Some(hint.padding_left),
3167            padding_right: Some(hint.padding_right),
3168            data: match hint.resolve_state {
3169                ResolveState::CanResolve(_, data) => data,
3170                ResolveState::Resolving | ResolveState::Resolved => None,
3171            },
3172        }
3173    }
3174
3175    pub fn can_resolve_inlays(capabilities: &ServerCapabilities) -> bool {
3176        capabilities
3177            .inlay_hint_provider
3178            .as_ref()
3179            .and_then(|options| match options {
3180                OneOf::Left(_is_supported) => None,
3181                OneOf::Right(capabilities) => match capabilities {
3182                    lsp::InlayHintServerCapabilities::Options(o) => o.resolve_provider,
3183                    lsp::InlayHintServerCapabilities::RegistrationOptions(o) => {
3184                        o.inlay_hint_options.resolve_provider
3185                    }
3186                },
3187            })
3188            .unwrap_or(false)
3189    }
3190}
3191
3192#[async_trait(?Send)]
3193impl LspCommand for InlayHints {
3194    type Response = Vec<InlayHint>;
3195    type LspRequest = lsp::InlayHintRequest;
3196    type ProtoRequest = proto::InlayHints;
3197
3198    fn display_name(&self) -> &str {
3199        "Inlay hints"
3200    }
3201
3202    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3203        let Some(inlay_hint_provider) = &capabilities.server_capabilities.inlay_hint_provider
3204        else {
3205            return false;
3206        };
3207        match inlay_hint_provider {
3208            lsp::OneOf::Left(enabled) => *enabled,
3209            lsp::OneOf::Right(inlay_hint_capabilities) => match inlay_hint_capabilities {
3210                lsp::InlayHintServerCapabilities::Options(_) => true,
3211                lsp::InlayHintServerCapabilities::RegistrationOptions(_) => false,
3212            },
3213        }
3214    }
3215
3216    fn to_lsp(
3217        &self,
3218        path: &Path,
3219        buffer: &Buffer,
3220        _: &Arc<LanguageServer>,
3221        _: &App,
3222    ) -> Result<lsp::InlayHintParams> {
3223        Ok(lsp::InlayHintParams {
3224            text_document: lsp::TextDocumentIdentifier {
3225                uri: file_path_to_lsp_url(path)?,
3226            },
3227            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
3228            work_done_progress_params: Default::default(),
3229        })
3230    }
3231
3232    async fn response_from_lsp(
3233        self,
3234        message: Option<Vec<lsp::InlayHint>>,
3235        lsp_store: Entity<LspStore>,
3236        buffer: Entity<Buffer>,
3237        server_id: LanguageServerId,
3238        mut cx: AsyncApp,
3239    ) -> anyhow::Result<Vec<InlayHint>> {
3240        let (lsp_adapter, lsp_server) =
3241            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
3242        // `typescript-language-server` adds padding to the left for type hints, turning
3243        // `const foo: boolean` into `const foo : boolean` which looks odd.
3244        // `rust-analyzer` does not have the padding for this case, and we have to accommodate both.
3245        //
3246        // We could trim the whole string, but being pessimistic on par with the situation above,
3247        // there might be a hint with multiple whitespaces at the end(s) which we need to display properly.
3248        // Hence let's use a heuristic first to handle the most awkward case and look for more.
3249        let force_no_type_left_padding =
3250            lsp_adapter.name.0.as_ref() == "typescript-language-server";
3251
3252        let hints = message.unwrap_or_default().into_iter().map(|lsp_hint| {
3253            let resolve_state = if InlayHints::can_resolve_inlays(&lsp_server.capabilities()) {
3254                ResolveState::CanResolve(lsp_server.server_id(), lsp_hint.data.clone())
3255            } else {
3256                ResolveState::Resolved
3257            };
3258
3259            let buffer = buffer.clone();
3260            cx.spawn(async move |cx| {
3261                InlayHints::lsp_to_project_hint(
3262                    lsp_hint,
3263                    &buffer,
3264                    server_id,
3265                    resolve_state,
3266                    force_no_type_left_padding,
3267                    cx,
3268                )
3269                .await
3270            })
3271        });
3272        future::join_all(hints)
3273            .await
3274            .into_iter()
3275            .collect::<anyhow::Result<_>>()
3276            .context("lsp to project inlay hints conversion")
3277    }
3278
3279    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::InlayHints {
3280        proto::InlayHints {
3281            project_id,
3282            buffer_id: buffer.remote_id().into(),
3283            start: Some(language::proto::serialize_anchor(&self.range.start)),
3284            end: Some(language::proto::serialize_anchor(&self.range.end)),
3285            version: serialize_version(&buffer.version()),
3286        }
3287    }
3288
3289    async fn from_proto(
3290        message: proto::InlayHints,
3291        _: Entity<LspStore>,
3292        buffer: Entity<Buffer>,
3293        mut cx: AsyncApp,
3294    ) -> Result<Self> {
3295        let start = message
3296            .start
3297            .and_then(language::proto::deserialize_anchor)
3298            .context("invalid start")?;
3299        let end = message
3300            .end
3301            .and_then(language::proto::deserialize_anchor)
3302            .context("invalid end")?;
3303        buffer
3304            .update(&mut cx, |buffer, _| {
3305                buffer.wait_for_version(deserialize_version(&message.version))
3306            })?
3307            .await?;
3308
3309        Ok(Self { range: start..end })
3310    }
3311
3312    fn response_to_proto(
3313        response: Vec<InlayHint>,
3314        _: &mut LspStore,
3315        _: PeerId,
3316        buffer_version: &clock::Global,
3317        _: &mut App,
3318    ) -> proto::InlayHintsResponse {
3319        proto::InlayHintsResponse {
3320            hints: response
3321                .into_iter()
3322                .map(InlayHints::project_to_proto_hint)
3323                .collect(),
3324            version: serialize_version(buffer_version),
3325        }
3326    }
3327
3328    async fn response_from_proto(
3329        self,
3330        message: proto::InlayHintsResponse,
3331        _: Entity<LspStore>,
3332        buffer: Entity<Buffer>,
3333        mut cx: AsyncApp,
3334    ) -> anyhow::Result<Vec<InlayHint>> {
3335        buffer
3336            .update(&mut cx, |buffer, _| {
3337                buffer.wait_for_version(deserialize_version(&message.version))
3338            })?
3339            .await?;
3340
3341        let mut hints = Vec::new();
3342        for message_hint in message.hints {
3343            hints.push(InlayHints::proto_to_project_hint(message_hint)?);
3344        }
3345
3346        Ok(hints)
3347    }
3348
3349    fn buffer_id_from_proto(message: &proto::InlayHints) -> Result<BufferId> {
3350        BufferId::new(message.buffer_id)
3351    }
3352}
3353
3354#[async_trait(?Send)]
3355impl LspCommand for GetCodeLens {
3356    type Response = Vec<CodeAction>;
3357    type LspRequest = lsp::CodeLensRequest;
3358    type ProtoRequest = proto::GetCodeLens;
3359
3360    fn display_name(&self) -> &str {
3361        "Code Lens"
3362    }
3363
3364    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3365        capabilities
3366            .server_capabilities
3367            .code_lens_provider
3368            .as_ref()
3369            .map_or(false, |code_lens_options| {
3370                code_lens_options.resolve_provider.unwrap_or(false)
3371            })
3372    }
3373
3374    fn to_lsp(
3375        &self,
3376        path: &Path,
3377        _: &Buffer,
3378        _: &Arc<LanguageServer>,
3379        _: &App,
3380    ) -> Result<lsp::CodeLensParams> {
3381        Ok(lsp::CodeLensParams {
3382            text_document: lsp::TextDocumentIdentifier {
3383                uri: file_path_to_lsp_url(path)?,
3384            },
3385            work_done_progress_params: lsp::WorkDoneProgressParams::default(),
3386            partial_result_params: lsp::PartialResultParams::default(),
3387        })
3388    }
3389
3390    async fn response_from_lsp(
3391        self,
3392        message: Option<Vec<lsp::CodeLens>>,
3393        lsp_store: Entity<LspStore>,
3394        buffer: Entity<Buffer>,
3395        server_id: LanguageServerId,
3396        mut cx: AsyncApp,
3397    ) -> anyhow::Result<Vec<CodeAction>> {
3398        let snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot())?;
3399        let language_server = cx.update(|cx| {
3400            lsp_store
3401                .read(cx)
3402                .language_server_for_id(server_id)
3403                .with_context(|| {
3404                    format!("Missing the language server that just returned a response {server_id}")
3405                })
3406        })??;
3407        let server_capabilities = language_server.capabilities();
3408        let available_commands = server_capabilities
3409            .execute_command_provider
3410            .as_ref()
3411            .map(|options| options.commands.as_slice())
3412            .unwrap_or_default();
3413        Ok(message
3414            .unwrap_or_default()
3415            .into_iter()
3416            .filter(|code_lens| {
3417                code_lens
3418                    .command
3419                    .as_ref()
3420                    .is_none_or(|command| available_commands.contains(&command.command))
3421            })
3422            .map(|code_lens| {
3423                let code_lens_range = range_from_lsp(code_lens.range);
3424                let start = snapshot.clip_point_utf16(code_lens_range.start, Bias::Left);
3425                let end = snapshot.clip_point_utf16(code_lens_range.end, Bias::Right);
3426                let range = snapshot.anchor_before(start)..snapshot.anchor_after(end);
3427                CodeAction {
3428                    server_id,
3429                    range,
3430                    lsp_action: LspAction::CodeLens(code_lens),
3431                    resolved: false,
3432                }
3433            })
3434            .collect())
3435    }
3436
3437    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeLens {
3438        proto::GetCodeLens {
3439            project_id,
3440            buffer_id: buffer.remote_id().into(),
3441            version: serialize_version(&buffer.version()),
3442        }
3443    }
3444
3445    async fn from_proto(
3446        message: proto::GetCodeLens,
3447        _: Entity<LspStore>,
3448        buffer: Entity<Buffer>,
3449        mut cx: AsyncApp,
3450    ) -> Result<Self> {
3451        buffer
3452            .update(&mut cx, |buffer, _| {
3453                buffer.wait_for_version(deserialize_version(&message.version))
3454            })?
3455            .await?;
3456        Ok(Self)
3457    }
3458
3459    fn response_to_proto(
3460        response: Vec<CodeAction>,
3461        _: &mut LspStore,
3462        _: PeerId,
3463        buffer_version: &clock::Global,
3464        _: &mut App,
3465    ) -> proto::GetCodeLensResponse {
3466        proto::GetCodeLensResponse {
3467            lens_actions: response
3468                .iter()
3469                .map(LspStore::serialize_code_action)
3470                .collect(),
3471            version: serialize_version(buffer_version),
3472        }
3473    }
3474
3475    async fn response_from_proto(
3476        self,
3477        message: proto::GetCodeLensResponse,
3478        _: Entity<LspStore>,
3479        buffer: Entity<Buffer>,
3480        mut cx: AsyncApp,
3481    ) -> anyhow::Result<Vec<CodeAction>> {
3482        buffer
3483            .update(&mut cx, |buffer, _| {
3484                buffer.wait_for_version(deserialize_version(&message.version))
3485            })?
3486            .await?;
3487        message
3488            .lens_actions
3489            .into_iter()
3490            .map(LspStore::deserialize_code_action)
3491            .collect::<Result<Vec<_>>>()
3492            .context("deserializing proto code lens response")
3493    }
3494
3495    fn buffer_id_from_proto(message: &proto::GetCodeLens) -> Result<BufferId> {
3496        BufferId::new(message.buffer_id)
3497    }
3498}
3499
3500#[async_trait(?Send)]
3501impl LspCommand for LinkedEditingRange {
3502    type Response = Vec<Range<Anchor>>;
3503    type LspRequest = lsp::request::LinkedEditingRange;
3504    type ProtoRequest = proto::LinkedEditingRange;
3505
3506    fn display_name(&self) -> &str {
3507        "Linked editing range"
3508    }
3509
3510    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3511        let Some(linked_editing_options) = &capabilities
3512            .server_capabilities
3513            .linked_editing_range_provider
3514        else {
3515            return false;
3516        };
3517        if let LinkedEditingRangeServerCapabilities::Simple(false) = linked_editing_options {
3518            return false;
3519        }
3520        true
3521    }
3522
3523    fn to_lsp(
3524        &self,
3525        path: &Path,
3526        buffer: &Buffer,
3527        _server: &Arc<LanguageServer>,
3528        _: &App,
3529    ) -> Result<lsp::LinkedEditingRangeParams> {
3530        let position = self.position.to_point_utf16(&buffer.snapshot());
3531        Ok(lsp::LinkedEditingRangeParams {
3532            text_document_position_params: make_lsp_text_document_position(path, position)?,
3533            work_done_progress_params: Default::default(),
3534        })
3535    }
3536
3537    async fn response_from_lsp(
3538        self,
3539        message: Option<lsp::LinkedEditingRanges>,
3540        _: Entity<LspStore>,
3541        buffer: Entity<Buffer>,
3542        _server_id: LanguageServerId,
3543        cx: AsyncApp,
3544    ) -> Result<Vec<Range<Anchor>>> {
3545        if let Some(lsp::LinkedEditingRanges { mut ranges, .. }) = message {
3546            ranges.sort_by_key(|range| range.start);
3547
3548            buffer.read_with(&cx, |buffer, _| {
3549                ranges
3550                    .into_iter()
3551                    .map(|range| {
3552                        let start =
3553                            buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
3554                        let end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
3555                        buffer.anchor_before(start)..buffer.anchor_after(end)
3556                    })
3557                    .collect()
3558            })
3559        } else {
3560            Ok(vec![])
3561        }
3562    }
3563
3564    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::LinkedEditingRange {
3565        proto::LinkedEditingRange {
3566            project_id,
3567            buffer_id: buffer.remote_id().to_proto(),
3568            position: Some(serialize_anchor(&self.position)),
3569            version: serialize_version(&buffer.version()),
3570        }
3571    }
3572
3573    async fn from_proto(
3574        message: proto::LinkedEditingRange,
3575        _: Entity<LspStore>,
3576        buffer: Entity<Buffer>,
3577        mut cx: AsyncApp,
3578    ) -> Result<Self> {
3579        let position = message
3580            .position
3581            .ok_or_else(|| anyhow!("invalid position"))?;
3582        buffer
3583            .update(&mut cx, |buffer, _| {
3584                buffer.wait_for_version(deserialize_version(&message.version))
3585            })?
3586            .await?;
3587        let position = deserialize_anchor(position).ok_or_else(|| anyhow!("invalid position"))?;
3588        buffer
3589            .update(&mut cx, |buffer, _| buffer.wait_for_anchors([position]))?
3590            .await?;
3591        Ok(Self { position })
3592    }
3593
3594    fn response_to_proto(
3595        response: Vec<Range<Anchor>>,
3596        _: &mut LspStore,
3597        _: PeerId,
3598        buffer_version: &clock::Global,
3599        _: &mut App,
3600    ) -> proto::LinkedEditingRangeResponse {
3601        proto::LinkedEditingRangeResponse {
3602            items: response
3603                .into_iter()
3604                .map(|range| proto::AnchorRange {
3605                    start: Some(serialize_anchor(&range.start)),
3606                    end: Some(serialize_anchor(&range.end)),
3607                })
3608                .collect(),
3609            version: serialize_version(buffer_version),
3610        }
3611    }
3612
3613    async fn response_from_proto(
3614        self,
3615        message: proto::LinkedEditingRangeResponse,
3616        _: Entity<LspStore>,
3617        buffer: Entity<Buffer>,
3618        mut cx: AsyncApp,
3619    ) -> Result<Vec<Range<Anchor>>> {
3620        buffer
3621            .update(&mut cx, |buffer, _| {
3622                buffer.wait_for_version(deserialize_version(&message.version))
3623            })?
3624            .await?;
3625        let items: Vec<Range<Anchor>> = message
3626            .items
3627            .into_iter()
3628            .filter_map(|range| {
3629                let start = deserialize_anchor(range.start?)?;
3630                let end = deserialize_anchor(range.end?)?;
3631                Some(start..end)
3632            })
3633            .collect();
3634        for range in &items {
3635            buffer
3636                .update(&mut cx, |buffer, _| {
3637                    buffer.wait_for_anchors([range.start, range.end])
3638                })?
3639                .await?;
3640        }
3641        Ok(items)
3642    }
3643
3644    fn buffer_id_from_proto(message: &proto::LinkedEditingRange) -> Result<BufferId> {
3645        BufferId::new(message.buffer_id)
3646    }
3647}