lsp_command.rs

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