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