lsp_command.rs

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