lsp_command.rs

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