lsp_command.rs

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