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            buffer.update(cx, |buffer, cx| {
 945                lsp_store
 946                    .language_server_for_local_buffer(buffer, server_id, cx)
 947                    .map(|(adapter, server)| (adapter.clone(), server.clone()))
 948            })
 949        })?
 950        .ok_or_else(|| anyhow!("no language server found for buffer"))
 951}
 952
 953async fn location_links_from_proto(
 954    proto_links: Vec<proto::LocationLink>,
 955    lsp_store: Entity<LspStore>,
 956    mut cx: AsyncApp,
 957) -> Result<Vec<LocationLink>> {
 958    let mut links = Vec::new();
 959
 960    for link in proto_links {
 961        let origin = match link.origin {
 962            Some(origin) => {
 963                let buffer_id = BufferId::new(origin.buffer_id)?;
 964                let buffer = lsp_store
 965                    .update(&mut cx, |lsp_store, cx| {
 966                        lsp_store.wait_for_remote_buffer(buffer_id, cx)
 967                    })?
 968                    .await?;
 969                let start = origin
 970                    .start
 971                    .and_then(deserialize_anchor)
 972                    .ok_or_else(|| anyhow!("missing origin start"))?;
 973                let end = origin
 974                    .end
 975                    .and_then(deserialize_anchor)
 976                    .ok_or_else(|| anyhow!("missing origin end"))?;
 977                buffer
 978                    .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
 979                    .await?;
 980                Some(Location {
 981                    buffer,
 982                    range: start..end,
 983                })
 984            }
 985            None => None,
 986        };
 987
 988        let target = link.target.ok_or_else(|| anyhow!("missing target"))?;
 989        let buffer_id = BufferId::new(target.buffer_id)?;
 990        let buffer = lsp_store
 991            .update(&mut cx, |lsp_store, cx| {
 992                lsp_store.wait_for_remote_buffer(buffer_id, cx)
 993            })?
 994            .await?;
 995        let start = target
 996            .start
 997            .and_then(deserialize_anchor)
 998            .ok_or_else(|| anyhow!("missing target start"))?;
 999        let end = target
1000            .end
1001            .and_then(deserialize_anchor)
1002            .ok_or_else(|| anyhow!("missing target end"))?;
1003        buffer
1004            .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
1005            .await?;
1006        let target = Location {
1007            buffer,
1008            range: start..end,
1009        };
1010
1011        links.push(LocationLink { origin, target })
1012    }
1013
1014    Ok(links)
1015}
1016
1017async fn location_links_from_lsp(
1018    message: Option<lsp::GotoDefinitionResponse>,
1019    lsp_store: Entity<LspStore>,
1020    buffer: Entity<Buffer>,
1021    server_id: LanguageServerId,
1022    mut cx: AsyncApp,
1023) -> Result<Vec<LocationLink>> {
1024    let message = match message {
1025        Some(message) => message,
1026        None => return Ok(Vec::new()),
1027    };
1028
1029    let mut unresolved_links = Vec::new();
1030    match message {
1031        lsp::GotoDefinitionResponse::Scalar(loc) => {
1032            unresolved_links.push((None, loc.uri, loc.range));
1033        }
1034
1035        lsp::GotoDefinitionResponse::Array(locs) => {
1036            unresolved_links.extend(locs.into_iter().map(|l| (None, l.uri, l.range)));
1037        }
1038
1039        lsp::GotoDefinitionResponse::Link(links) => {
1040            unresolved_links.extend(links.into_iter().map(|l| {
1041                (
1042                    l.origin_selection_range,
1043                    l.target_uri,
1044                    l.target_selection_range,
1045                )
1046            }));
1047        }
1048    }
1049
1050    let (lsp_adapter, language_server) =
1051        language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1052    let mut definitions = Vec::new();
1053    for (origin_range, target_uri, target_range) in unresolved_links {
1054        let target_buffer_handle = lsp_store
1055            .update(&mut cx, |this, cx| {
1056                this.open_local_buffer_via_lsp(
1057                    target_uri,
1058                    language_server.server_id(),
1059                    lsp_adapter.name.clone(),
1060                    cx,
1061                )
1062            })?
1063            .await?;
1064
1065        cx.update(|cx| {
1066            let origin_location = origin_range.map(|origin_range| {
1067                let origin_buffer = buffer.read(cx);
1068                let origin_start =
1069                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
1070                let origin_end =
1071                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
1072                Location {
1073                    buffer: buffer.clone(),
1074                    range: origin_buffer.anchor_after(origin_start)
1075                        ..origin_buffer.anchor_before(origin_end),
1076                }
1077            });
1078
1079            let target_buffer = target_buffer_handle.read(cx);
1080            let target_start =
1081                target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
1082            let target_end =
1083                target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
1084            let target_location = Location {
1085                buffer: target_buffer_handle,
1086                range: target_buffer.anchor_after(target_start)
1087                    ..target_buffer.anchor_before(target_end),
1088            };
1089
1090            definitions.push(LocationLink {
1091                origin: origin_location,
1092                target: target_location,
1093            })
1094        })?;
1095    }
1096    Ok(definitions)
1097}
1098
1099fn location_links_to_proto(
1100    links: Vec<LocationLink>,
1101    lsp_store: &mut LspStore,
1102    peer_id: PeerId,
1103    cx: &mut App,
1104) -> Vec<proto::LocationLink> {
1105    links
1106        .into_iter()
1107        .map(|definition| {
1108            let origin = definition.origin.map(|origin| {
1109                lsp_store
1110                    .buffer_store()
1111                    .update(cx, |buffer_store, cx| {
1112                        buffer_store.create_buffer_for_peer(&origin.buffer, peer_id, cx)
1113                    })
1114                    .detach_and_log_err(cx);
1115
1116                let buffer_id = origin.buffer.read(cx).remote_id().into();
1117                proto::Location {
1118                    start: Some(serialize_anchor(&origin.range.start)),
1119                    end: Some(serialize_anchor(&origin.range.end)),
1120                    buffer_id,
1121                }
1122            });
1123
1124            lsp_store
1125                .buffer_store()
1126                .update(cx, |buffer_store, cx| {
1127                    buffer_store.create_buffer_for_peer(&definition.target.buffer, peer_id, cx)
1128                })
1129                .detach_and_log_err(cx);
1130
1131            let buffer_id = definition.target.buffer.read(cx).remote_id().into();
1132            let target = proto::Location {
1133                start: Some(serialize_anchor(&definition.target.range.start)),
1134                end: Some(serialize_anchor(&definition.target.range.end)),
1135                buffer_id,
1136            };
1137
1138            proto::LocationLink {
1139                origin,
1140                target: Some(target),
1141            }
1142        })
1143        .collect()
1144}
1145
1146#[async_trait(?Send)]
1147impl LspCommand for GetReferences {
1148    type Response = Vec<Location>;
1149    type LspRequest = lsp::request::References;
1150    type ProtoRequest = proto::GetReferences;
1151
1152    fn display_name(&self) -> &str {
1153        "Find all references"
1154    }
1155
1156    fn status(&self) -> Option<String> {
1157        Some("Finding references...".to_owned())
1158    }
1159
1160    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1161        match &capabilities.server_capabilities.references_provider {
1162            Some(OneOf::Left(has_support)) => *has_support,
1163            Some(OneOf::Right(_)) => true,
1164            None => false,
1165        }
1166    }
1167
1168    fn to_lsp(
1169        &self,
1170        path: &Path,
1171        _: &Buffer,
1172        _: &Arc<LanguageServer>,
1173        _: &App,
1174    ) -> Result<lsp::ReferenceParams> {
1175        Ok(lsp::ReferenceParams {
1176            text_document_position: make_lsp_text_document_position(path, self.position)?,
1177            work_done_progress_params: Default::default(),
1178            partial_result_params: Default::default(),
1179            context: lsp::ReferenceContext {
1180                include_declaration: true,
1181            },
1182        })
1183    }
1184
1185    async fn response_from_lsp(
1186        self,
1187        locations: Option<Vec<lsp::Location>>,
1188        lsp_store: Entity<LspStore>,
1189        buffer: Entity<Buffer>,
1190        server_id: LanguageServerId,
1191        mut cx: AsyncApp,
1192    ) -> Result<Vec<Location>> {
1193        let mut references = Vec::new();
1194        let (lsp_adapter, language_server) =
1195            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1196
1197        if let Some(locations) = locations {
1198            for lsp_location in locations {
1199                let target_buffer_handle = lsp_store
1200                    .update(&mut cx, |lsp_store, cx| {
1201                        lsp_store.open_local_buffer_via_lsp(
1202                            lsp_location.uri,
1203                            language_server.server_id(),
1204                            lsp_adapter.name.clone(),
1205                            cx,
1206                        )
1207                    })?
1208                    .await?;
1209
1210                target_buffer_handle
1211                    .clone()
1212                    .update(&mut cx, |target_buffer, _| {
1213                        let target_start = target_buffer
1214                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
1215                        let target_end = target_buffer
1216                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
1217                        references.push(Location {
1218                            buffer: target_buffer_handle,
1219                            range: target_buffer.anchor_after(target_start)
1220                                ..target_buffer.anchor_before(target_end),
1221                        });
1222                    })?;
1223            }
1224        }
1225
1226        Ok(references)
1227    }
1228
1229    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetReferences {
1230        proto::GetReferences {
1231            project_id,
1232            buffer_id: buffer.remote_id().into(),
1233            position: Some(language::proto::serialize_anchor(
1234                &buffer.anchor_before(self.position),
1235            )),
1236            version: serialize_version(&buffer.version()),
1237        }
1238    }
1239
1240    async fn from_proto(
1241        message: proto::GetReferences,
1242        _: Entity<LspStore>,
1243        buffer: Entity<Buffer>,
1244        mut cx: AsyncApp,
1245    ) -> Result<Self> {
1246        let position = message
1247            .position
1248            .and_then(deserialize_anchor)
1249            .ok_or_else(|| anyhow!("invalid position"))?;
1250        buffer
1251            .update(&mut cx, |buffer, _| {
1252                buffer.wait_for_version(deserialize_version(&message.version))
1253            })?
1254            .await?;
1255        Ok(Self {
1256            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
1257        })
1258    }
1259
1260    fn response_to_proto(
1261        response: Vec<Location>,
1262        lsp_store: &mut LspStore,
1263        peer_id: PeerId,
1264        _: &clock::Global,
1265        cx: &mut App,
1266    ) -> proto::GetReferencesResponse {
1267        let locations = response
1268            .into_iter()
1269            .map(|definition| {
1270                lsp_store
1271                    .buffer_store()
1272                    .update(cx, |buffer_store, cx| {
1273                        buffer_store.create_buffer_for_peer(&definition.buffer, peer_id, cx)
1274                    })
1275                    .detach_and_log_err(cx);
1276                let buffer_id = definition.buffer.read(cx).remote_id();
1277                proto::Location {
1278                    start: Some(serialize_anchor(&definition.range.start)),
1279                    end: Some(serialize_anchor(&definition.range.end)),
1280                    buffer_id: buffer_id.into(),
1281                }
1282            })
1283            .collect();
1284        proto::GetReferencesResponse { locations }
1285    }
1286
1287    async fn response_from_proto(
1288        self,
1289        message: proto::GetReferencesResponse,
1290        project: Entity<LspStore>,
1291        _: Entity<Buffer>,
1292        mut cx: AsyncApp,
1293    ) -> Result<Vec<Location>> {
1294        let mut locations = Vec::new();
1295        for location in message.locations {
1296            let buffer_id = BufferId::new(location.buffer_id)?;
1297            let target_buffer = project
1298                .update(&mut cx, |this, cx| {
1299                    this.wait_for_remote_buffer(buffer_id, cx)
1300                })?
1301                .await?;
1302            let start = location
1303                .start
1304                .and_then(deserialize_anchor)
1305                .ok_or_else(|| anyhow!("missing target start"))?;
1306            let end = location
1307                .end
1308                .and_then(deserialize_anchor)
1309                .ok_or_else(|| anyhow!("missing target end"))?;
1310            target_buffer
1311                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
1312                .await?;
1313            locations.push(Location {
1314                buffer: target_buffer,
1315                range: start..end,
1316            })
1317        }
1318        Ok(locations)
1319    }
1320
1321    fn buffer_id_from_proto(message: &proto::GetReferences) -> Result<BufferId> {
1322        BufferId::new(message.buffer_id)
1323    }
1324}
1325
1326#[async_trait(?Send)]
1327impl LspCommand for GetDocumentHighlights {
1328    type Response = Vec<DocumentHighlight>;
1329    type LspRequest = lsp::request::DocumentHighlightRequest;
1330    type ProtoRequest = proto::GetDocumentHighlights;
1331
1332    fn display_name(&self) -> &str {
1333        "Get document highlights"
1334    }
1335
1336    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1337        capabilities
1338            .server_capabilities
1339            .document_highlight_provider
1340            .is_some()
1341    }
1342
1343    fn to_lsp(
1344        &self,
1345        path: &Path,
1346        _: &Buffer,
1347        _: &Arc<LanguageServer>,
1348        _: &App,
1349    ) -> Result<lsp::DocumentHighlightParams> {
1350        Ok(lsp::DocumentHighlightParams {
1351            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1352            work_done_progress_params: Default::default(),
1353            partial_result_params: Default::default(),
1354        })
1355    }
1356
1357    async fn response_from_lsp(
1358        self,
1359        lsp_highlights: Option<Vec<lsp::DocumentHighlight>>,
1360        _: Entity<LspStore>,
1361        buffer: Entity<Buffer>,
1362        _: LanguageServerId,
1363        mut cx: AsyncApp,
1364    ) -> Result<Vec<DocumentHighlight>> {
1365        buffer.update(&mut cx, |buffer, _| {
1366            let mut lsp_highlights = lsp_highlights.unwrap_or_default();
1367            lsp_highlights.sort_unstable_by_key(|h| (h.range.start, Reverse(h.range.end)));
1368            lsp_highlights
1369                .into_iter()
1370                .map(|lsp_highlight| {
1371                    let start = buffer
1372                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.start), Bias::Left);
1373                    let end = buffer
1374                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.end), Bias::Left);
1375                    DocumentHighlight {
1376                        range: buffer.anchor_after(start)..buffer.anchor_before(end),
1377                        kind: lsp_highlight
1378                            .kind
1379                            .unwrap_or(lsp::DocumentHighlightKind::READ),
1380                    }
1381                })
1382                .collect()
1383        })
1384    }
1385
1386    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentHighlights {
1387        proto::GetDocumentHighlights {
1388            project_id,
1389            buffer_id: buffer.remote_id().into(),
1390            position: Some(language::proto::serialize_anchor(
1391                &buffer.anchor_before(self.position),
1392            )),
1393            version: serialize_version(&buffer.version()),
1394        }
1395    }
1396
1397    async fn from_proto(
1398        message: proto::GetDocumentHighlights,
1399        _: Entity<LspStore>,
1400        buffer: Entity<Buffer>,
1401        mut cx: AsyncApp,
1402    ) -> Result<Self> {
1403        let position = message
1404            .position
1405            .and_then(deserialize_anchor)
1406            .ok_or_else(|| anyhow!("invalid position"))?;
1407        buffer
1408            .update(&mut cx, |buffer, _| {
1409                buffer.wait_for_version(deserialize_version(&message.version))
1410            })?
1411            .await?;
1412        Ok(Self {
1413            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
1414        })
1415    }
1416
1417    fn response_to_proto(
1418        response: Vec<DocumentHighlight>,
1419        _: &mut LspStore,
1420        _: PeerId,
1421        _: &clock::Global,
1422        _: &mut App,
1423    ) -> proto::GetDocumentHighlightsResponse {
1424        let highlights = response
1425            .into_iter()
1426            .map(|highlight| proto::DocumentHighlight {
1427                start: Some(serialize_anchor(&highlight.range.start)),
1428                end: Some(serialize_anchor(&highlight.range.end)),
1429                kind: match highlight.kind {
1430                    DocumentHighlightKind::TEXT => proto::document_highlight::Kind::Text.into(),
1431                    DocumentHighlightKind::WRITE => proto::document_highlight::Kind::Write.into(),
1432                    DocumentHighlightKind::READ => proto::document_highlight::Kind::Read.into(),
1433                    _ => proto::document_highlight::Kind::Text.into(),
1434                },
1435            })
1436            .collect();
1437        proto::GetDocumentHighlightsResponse { highlights }
1438    }
1439
1440    async fn response_from_proto(
1441        self,
1442        message: proto::GetDocumentHighlightsResponse,
1443        _: Entity<LspStore>,
1444        buffer: Entity<Buffer>,
1445        mut cx: AsyncApp,
1446    ) -> Result<Vec<DocumentHighlight>> {
1447        let mut highlights = Vec::new();
1448        for highlight in message.highlights {
1449            let start = highlight
1450                .start
1451                .and_then(deserialize_anchor)
1452                .ok_or_else(|| anyhow!("missing target start"))?;
1453            let end = highlight
1454                .end
1455                .and_then(deserialize_anchor)
1456                .ok_or_else(|| anyhow!("missing target end"))?;
1457            buffer
1458                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
1459                .await?;
1460            let kind = match proto::document_highlight::Kind::from_i32(highlight.kind) {
1461                Some(proto::document_highlight::Kind::Text) => DocumentHighlightKind::TEXT,
1462                Some(proto::document_highlight::Kind::Read) => DocumentHighlightKind::READ,
1463                Some(proto::document_highlight::Kind::Write) => DocumentHighlightKind::WRITE,
1464                None => DocumentHighlightKind::TEXT,
1465            };
1466            highlights.push(DocumentHighlight {
1467                range: start..end,
1468                kind,
1469            });
1470        }
1471        Ok(highlights)
1472    }
1473
1474    fn buffer_id_from_proto(message: &proto::GetDocumentHighlights) -> Result<BufferId> {
1475        BufferId::new(message.buffer_id)
1476    }
1477}
1478
1479#[async_trait(?Send)]
1480impl LspCommand for GetSignatureHelp {
1481    type Response = Option<SignatureHelp>;
1482    type LspRequest = lsp::SignatureHelpRequest;
1483    type ProtoRequest = proto::GetSignatureHelp;
1484
1485    fn display_name(&self) -> &str {
1486        "Get signature help"
1487    }
1488
1489    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1490        capabilities
1491            .server_capabilities
1492            .signature_help_provider
1493            .is_some()
1494    }
1495
1496    fn to_lsp(
1497        &self,
1498        path: &Path,
1499        _: &Buffer,
1500        _: &Arc<LanguageServer>,
1501        _cx: &App,
1502    ) -> Result<lsp::SignatureHelpParams> {
1503        Ok(lsp::SignatureHelpParams {
1504            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1505            context: None,
1506            work_done_progress_params: Default::default(),
1507        })
1508    }
1509
1510    async fn response_from_lsp(
1511        self,
1512        message: Option<lsp::SignatureHelp>,
1513        _: Entity<LspStore>,
1514        buffer: Entity<Buffer>,
1515        _: LanguageServerId,
1516        mut cx: AsyncApp,
1517    ) -> Result<Self::Response> {
1518        let language = buffer.update(&mut cx, |buffer, _| buffer.language().cloned())?;
1519        Ok(message.and_then(|message| SignatureHelp::new(message, language)))
1520    }
1521
1522    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
1523        let offset = buffer.point_utf16_to_offset(self.position);
1524        proto::GetSignatureHelp {
1525            project_id,
1526            buffer_id: buffer.remote_id().to_proto(),
1527            position: Some(serialize_anchor(&buffer.anchor_after(offset))),
1528            version: serialize_version(&buffer.version()),
1529        }
1530    }
1531
1532    async fn from_proto(
1533        payload: Self::ProtoRequest,
1534        _: Entity<LspStore>,
1535        buffer: Entity<Buffer>,
1536        mut cx: AsyncApp,
1537    ) -> Result<Self> {
1538        buffer
1539            .update(&mut cx, |buffer, _| {
1540                buffer.wait_for_version(deserialize_version(&payload.version))
1541            })?
1542            .await
1543            .with_context(|| format!("waiting for version for buffer {}", buffer.entity_id()))?;
1544        let buffer_snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot())?;
1545        Ok(Self {
1546            position: payload
1547                .position
1548                .and_then(deserialize_anchor)
1549                .context("invalid position")?
1550                .to_point_utf16(&buffer_snapshot),
1551        })
1552    }
1553
1554    fn response_to_proto(
1555        response: Self::Response,
1556        _: &mut LspStore,
1557        _: PeerId,
1558        _: &Global,
1559        _: &mut App,
1560    ) -> proto::GetSignatureHelpResponse {
1561        proto::GetSignatureHelpResponse {
1562            signature_help: response
1563                .map(|signature_help| lsp_to_proto_signature(signature_help.original_data)),
1564        }
1565    }
1566
1567    async fn response_from_proto(
1568        self,
1569        response: proto::GetSignatureHelpResponse,
1570        _: Entity<LspStore>,
1571        buffer: Entity<Buffer>,
1572        mut cx: AsyncApp,
1573    ) -> Result<Self::Response> {
1574        let language = buffer.update(&mut cx, |buffer, _| buffer.language().cloned())?;
1575        Ok(response
1576            .signature_help
1577            .map(proto_to_lsp_signature)
1578            .and_then(|lsp_help| SignatureHelp::new(lsp_help, language)))
1579    }
1580
1581    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
1582        BufferId::new(message.buffer_id)
1583    }
1584}
1585
1586#[async_trait(?Send)]
1587impl LspCommand for GetHover {
1588    type Response = Option<Hover>;
1589    type LspRequest = lsp::request::HoverRequest;
1590    type ProtoRequest = proto::GetHover;
1591
1592    fn display_name(&self) -> &str {
1593        "Get hover"
1594    }
1595
1596    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1597        match capabilities.server_capabilities.hover_provider {
1598            Some(lsp::HoverProviderCapability::Simple(enabled)) => enabled,
1599            Some(lsp::HoverProviderCapability::Options(_)) => true,
1600            None => false,
1601        }
1602    }
1603
1604    fn to_lsp(
1605        &self,
1606        path: &Path,
1607        _: &Buffer,
1608        _: &Arc<LanguageServer>,
1609        _: &App,
1610    ) -> Result<lsp::HoverParams> {
1611        Ok(lsp::HoverParams {
1612            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1613            work_done_progress_params: Default::default(),
1614        })
1615    }
1616
1617    async fn response_from_lsp(
1618        self,
1619        message: Option<lsp::Hover>,
1620        _: Entity<LspStore>,
1621        buffer: Entity<Buffer>,
1622        _: LanguageServerId,
1623        mut cx: AsyncApp,
1624    ) -> Result<Self::Response> {
1625        let Some(hover) = message else {
1626            return Ok(None);
1627        };
1628
1629        let (language, range) = buffer.update(&mut cx, |buffer, _| {
1630            (
1631                buffer.language().cloned(),
1632                hover.range.map(|range| {
1633                    let token_start =
1634                        buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
1635                    let token_end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
1636                    buffer.anchor_after(token_start)..buffer.anchor_before(token_end)
1637                }),
1638            )
1639        })?;
1640
1641        fn hover_blocks_from_marked_string(marked_string: lsp::MarkedString) -> Option<HoverBlock> {
1642            let block = match marked_string {
1643                lsp::MarkedString::String(content) => HoverBlock {
1644                    text: content,
1645                    kind: HoverBlockKind::Markdown,
1646                },
1647                lsp::MarkedString::LanguageString(lsp::LanguageString { language, value }) => {
1648                    HoverBlock {
1649                        text: value,
1650                        kind: HoverBlockKind::Code { language },
1651                    }
1652                }
1653            };
1654            if block.text.is_empty() {
1655                None
1656            } else {
1657                Some(block)
1658            }
1659        }
1660
1661        let contents = match hover.contents {
1662            lsp::HoverContents::Scalar(marked_string) => {
1663                hover_blocks_from_marked_string(marked_string)
1664                    .into_iter()
1665                    .collect()
1666            }
1667            lsp::HoverContents::Array(marked_strings) => marked_strings
1668                .into_iter()
1669                .filter_map(hover_blocks_from_marked_string)
1670                .collect(),
1671            lsp::HoverContents::Markup(markup_content) => vec![HoverBlock {
1672                text: markup_content.value,
1673                kind: if markup_content.kind == lsp::MarkupKind::Markdown {
1674                    HoverBlockKind::Markdown
1675                } else {
1676                    HoverBlockKind::PlainText
1677                },
1678            }],
1679        };
1680
1681        Ok(Some(Hover {
1682            contents,
1683            range,
1684            language,
1685        }))
1686    }
1687
1688    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
1689        proto::GetHover {
1690            project_id,
1691            buffer_id: buffer.remote_id().into(),
1692            position: Some(language::proto::serialize_anchor(
1693                &buffer.anchor_before(self.position),
1694            )),
1695            version: serialize_version(&buffer.version),
1696        }
1697    }
1698
1699    async fn from_proto(
1700        message: Self::ProtoRequest,
1701        _: Entity<LspStore>,
1702        buffer: Entity<Buffer>,
1703        mut cx: AsyncApp,
1704    ) -> Result<Self> {
1705        let position = message
1706            .position
1707            .and_then(deserialize_anchor)
1708            .ok_or_else(|| anyhow!("invalid position"))?;
1709        buffer
1710            .update(&mut cx, |buffer, _| {
1711                buffer.wait_for_version(deserialize_version(&message.version))
1712            })?
1713            .await?;
1714        Ok(Self {
1715            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
1716        })
1717    }
1718
1719    fn response_to_proto(
1720        response: Self::Response,
1721        _: &mut LspStore,
1722        _: PeerId,
1723        _: &clock::Global,
1724        _: &mut App,
1725    ) -> proto::GetHoverResponse {
1726        if let Some(response) = response {
1727            let (start, end) = if let Some(range) = response.range {
1728                (
1729                    Some(language::proto::serialize_anchor(&range.start)),
1730                    Some(language::proto::serialize_anchor(&range.end)),
1731                )
1732            } else {
1733                (None, None)
1734            };
1735
1736            let contents = response
1737                .contents
1738                .into_iter()
1739                .map(|block| proto::HoverBlock {
1740                    text: block.text,
1741                    is_markdown: block.kind == HoverBlockKind::Markdown,
1742                    language: if let HoverBlockKind::Code { language } = block.kind {
1743                        Some(language)
1744                    } else {
1745                        None
1746                    },
1747                })
1748                .collect();
1749
1750            proto::GetHoverResponse {
1751                start,
1752                end,
1753                contents,
1754            }
1755        } else {
1756            proto::GetHoverResponse {
1757                start: None,
1758                end: None,
1759                contents: Vec::new(),
1760            }
1761        }
1762    }
1763
1764    async fn response_from_proto(
1765        self,
1766        message: proto::GetHoverResponse,
1767        _: Entity<LspStore>,
1768        buffer: Entity<Buffer>,
1769        mut cx: AsyncApp,
1770    ) -> Result<Self::Response> {
1771        let contents: Vec<_> = message
1772            .contents
1773            .into_iter()
1774            .map(|block| HoverBlock {
1775                text: block.text,
1776                kind: if let Some(language) = block.language {
1777                    HoverBlockKind::Code { language }
1778                } else if block.is_markdown {
1779                    HoverBlockKind::Markdown
1780                } else {
1781                    HoverBlockKind::PlainText
1782                },
1783            })
1784            .collect();
1785        if contents.is_empty() {
1786            return Ok(None);
1787        }
1788
1789        let language = buffer.update(&mut cx, |buffer, _| buffer.language().cloned())?;
1790        let range = if let (Some(start), Some(end)) = (message.start, message.end) {
1791            language::proto::deserialize_anchor(start)
1792                .and_then(|start| language::proto::deserialize_anchor(end).map(|end| start..end))
1793        } else {
1794            None
1795        };
1796        if let Some(range) = range.as_ref() {
1797            buffer
1798                .update(&mut cx, |buffer, _| {
1799                    buffer.wait_for_anchors([range.start, range.end])
1800                })?
1801                .await?;
1802        }
1803
1804        Ok(Some(Hover {
1805            contents,
1806            range,
1807            language,
1808        }))
1809    }
1810
1811    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
1812        BufferId::new(message.buffer_id)
1813    }
1814}
1815
1816#[async_trait(?Send)]
1817impl LspCommand for GetCompletions {
1818    type Response = Vec<CoreCompletion>;
1819    type LspRequest = lsp::request::Completion;
1820    type ProtoRequest = proto::GetCompletions;
1821
1822    fn display_name(&self) -> &str {
1823        "Get completion"
1824    }
1825
1826    fn to_lsp(
1827        &self,
1828        path: &Path,
1829        _: &Buffer,
1830        _: &Arc<LanguageServer>,
1831        _: &App,
1832    ) -> Result<lsp::CompletionParams> {
1833        Ok(lsp::CompletionParams {
1834            text_document_position: make_lsp_text_document_position(path, self.position)?,
1835            context: Some(self.context.clone()),
1836            work_done_progress_params: Default::default(),
1837            partial_result_params: Default::default(),
1838        })
1839    }
1840
1841    async fn response_from_lsp(
1842        self,
1843        completions: Option<lsp::CompletionResponse>,
1844        lsp_store: Entity<LspStore>,
1845        buffer: Entity<Buffer>,
1846        server_id: LanguageServerId,
1847        mut cx: AsyncApp,
1848    ) -> Result<Self::Response> {
1849        let mut response_list = None;
1850        let mut completions = if let Some(completions) = completions {
1851            match completions {
1852                lsp::CompletionResponse::Array(completions) => completions,
1853
1854                lsp::CompletionResponse::List(mut list) => {
1855                    let items = std::mem::take(&mut list.items);
1856                    response_list = Some(list);
1857                    items
1858                }
1859            }
1860        } else {
1861            Default::default()
1862        };
1863
1864        let language_server_adapter = lsp_store
1865            .update(&mut cx, |lsp_store, _| {
1866                lsp_store.language_server_adapter_for_id(server_id)
1867            })?
1868            .ok_or_else(|| anyhow!("no such language server"))?;
1869
1870        let item_defaults = response_list
1871            .as_ref()
1872            .and_then(|list| list.item_defaults.as_ref());
1873
1874        if let Some(item_defaults) = item_defaults {
1875            let default_data = item_defaults.data.as_ref();
1876            let default_commit_characters = item_defaults.commit_characters.as_ref();
1877            let default_edit_range = item_defaults.edit_range.as_ref();
1878            let default_insert_text_format = item_defaults.insert_text_format.as_ref();
1879            let default_insert_text_mode = item_defaults.insert_text_mode.as_ref();
1880
1881            if default_data.is_some()
1882                || default_commit_characters.is_some()
1883                || default_edit_range.is_some()
1884                || default_insert_text_format.is_some()
1885                || default_insert_text_mode.is_some()
1886            {
1887                for item in completions.iter_mut() {
1888                    if item.data.is_none() && default_data.is_some() {
1889                        item.data = default_data.cloned()
1890                    }
1891                    if item.commit_characters.is_none() && default_commit_characters.is_some() {
1892                        item.commit_characters = default_commit_characters.cloned()
1893                    }
1894                    if item.text_edit.is_none() {
1895                        if let Some(default_edit_range) = default_edit_range {
1896                            match default_edit_range {
1897                                CompletionListItemDefaultsEditRange::Range(range) => {
1898                                    item.text_edit =
1899                                        Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
1900                                            range: *range,
1901                                            new_text: item.label.clone(),
1902                                        }))
1903                                }
1904                                CompletionListItemDefaultsEditRange::InsertAndReplace {
1905                                    insert,
1906                                    replace,
1907                                } => {
1908                                    item.text_edit =
1909                                        Some(lsp::CompletionTextEdit::InsertAndReplace(
1910                                            lsp::InsertReplaceEdit {
1911                                                new_text: item.label.clone(),
1912                                                insert: *insert,
1913                                                replace: *replace,
1914                                            },
1915                                        ))
1916                                }
1917                            }
1918                        }
1919                    }
1920                    if item.insert_text_format.is_none() && default_insert_text_format.is_some() {
1921                        item.insert_text_format = default_insert_text_format.cloned()
1922                    }
1923                    if item.insert_text_mode.is_none() && default_insert_text_mode.is_some() {
1924                        item.insert_text_mode = default_insert_text_mode.cloned()
1925                    }
1926                }
1927            }
1928        }
1929
1930        let mut completion_edits = Vec::new();
1931        buffer.update(&mut cx, |buffer, _cx| {
1932            let snapshot = buffer.snapshot();
1933            let clipped_position = buffer.clip_point_utf16(Unclipped(self.position), Bias::Left);
1934
1935            let mut range_for_token = None;
1936            completions.retain_mut(|lsp_completion| {
1937                let edit = match lsp_completion.text_edit.as_ref() {
1938                    // If the language server provides a range to overwrite, then
1939                    // check that the range is valid.
1940                    Some(completion_text_edit) => {
1941                        match parse_completion_text_edit(completion_text_edit, &snapshot) {
1942                            Some(edit) => edit,
1943                            None => return false,
1944                        }
1945                    }
1946
1947                    // If the language server does not provide a range, then infer
1948                    // the range based on the syntax tree.
1949                    None => {
1950                        if self.position != clipped_position {
1951                            log::info!("completion out of expected range");
1952                            return false;
1953                        }
1954
1955                        let default_edit_range = response_list
1956                            .as_ref()
1957                            .and_then(|list| list.item_defaults.as_ref())
1958                            .and_then(|defaults| defaults.edit_range.as_ref())
1959                            .and_then(|range| match range {
1960                                CompletionListItemDefaultsEditRange::Range(r) => Some(r),
1961                                _ => None,
1962                            });
1963
1964                        let range = if let Some(range) = default_edit_range {
1965                            let range = range_from_lsp(*range);
1966                            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
1967                            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
1968                            if start != range.start.0 || end != range.end.0 {
1969                                log::info!("completion out of expected range");
1970                                return false;
1971                            }
1972
1973                            snapshot.anchor_before(start)..snapshot.anchor_after(end)
1974                        } else {
1975                            range_for_token
1976                                .get_or_insert_with(|| {
1977                                    let offset = self.position.to_offset(&snapshot);
1978                                    let (range, kind) = snapshot.surrounding_word(offset);
1979                                    let range = if kind == Some(CharKind::Word) {
1980                                        range
1981                                    } else {
1982                                        offset..offset
1983                                    };
1984
1985                                    snapshot.anchor_before(range.start)
1986                                        ..snapshot.anchor_after(range.end)
1987                                })
1988                                .clone()
1989                        };
1990
1991                        let text = lsp_completion
1992                            .insert_text
1993                            .as_ref()
1994                            .unwrap_or(&lsp_completion.label)
1995                            .clone();
1996                        (range, text)
1997                    }
1998                };
1999
2000                completion_edits.push(edit);
2001                true
2002            });
2003        })?;
2004
2005        language_server_adapter
2006            .process_completions(&mut completions)
2007            .await;
2008
2009        Ok(completions
2010            .into_iter()
2011            .zip(completion_edits)
2012            .map(|(lsp_completion, (old_range, mut new_text))| {
2013                LineEnding::normalize(&mut new_text);
2014                CoreCompletion {
2015                    old_range,
2016                    new_text,
2017                    server_id,
2018                    lsp_completion,
2019                    resolved: false,
2020                }
2021            })
2022            .collect())
2023    }
2024
2025    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCompletions {
2026        let anchor = buffer.anchor_after(self.position);
2027        proto::GetCompletions {
2028            project_id,
2029            buffer_id: buffer.remote_id().into(),
2030            position: Some(language::proto::serialize_anchor(&anchor)),
2031            version: serialize_version(&buffer.version()),
2032        }
2033    }
2034
2035    async fn from_proto(
2036        message: proto::GetCompletions,
2037        _: Entity<LspStore>,
2038        buffer: Entity<Buffer>,
2039        mut cx: AsyncApp,
2040    ) -> Result<Self> {
2041        let version = deserialize_version(&message.version);
2042        buffer
2043            .update(&mut cx, |buffer, _| buffer.wait_for_version(version))?
2044            .await?;
2045        let position = message
2046            .position
2047            .and_then(language::proto::deserialize_anchor)
2048            .map(|p| {
2049                buffer.update(&mut cx, |buffer, _| {
2050                    buffer.clip_point_utf16(Unclipped(p.to_point_utf16(buffer)), Bias::Left)
2051                })
2052            })
2053            .ok_or_else(|| anyhow!("invalid position"))??;
2054        Ok(Self {
2055            position,
2056            context: CompletionContext {
2057                trigger_kind: CompletionTriggerKind::INVOKED,
2058                trigger_character: None,
2059            },
2060        })
2061    }
2062
2063    fn response_to_proto(
2064        completions: Vec<CoreCompletion>,
2065        _: &mut LspStore,
2066        _: PeerId,
2067        buffer_version: &clock::Global,
2068        _: &mut App,
2069    ) -> proto::GetCompletionsResponse {
2070        proto::GetCompletionsResponse {
2071            completions: completions
2072                .iter()
2073                .map(LspStore::serialize_completion)
2074                .collect(),
2075            version: serialize_version(buffer_version),
2076        }
2077    }
2078
2079    async fn response_from_proto(
2080        self,
2081        message: proto::GetCompletionsResponse,
2082        _project: Entity<LspStore>,
2083        buffer: Entity<Buffer>,
2084        mut cx: AsyncApp,
2085    ) -> Result<Self::Response> {
2086        buffer
2087            .update(&mut cx, |buffer, _| {
2088                buffer.wait_for_version(deserialize_version(&message.version))
2089            })?
2090            .await?;
2091
2092        message
2093            .completions
2094            .into_iter()
2095            .map(LspStore::deserialize_completion)
2096            .collect()
2097    }
2098
2099    fn buffer_id_from_proto(message: &proto::GetCompletions) -> Result<BufferId> {
2100        BufferId::new(message.buffer_id)
2101    }
2102}
2103
2104pub(crate) fn parse_completion_text_edit(
2105    edit: &lsp::CompletionTextEdit,
2106    snapshot: &BufferSnapshot,
2107) -> Option<(Range<Anchor>, String)> {
2108    match edit {
2109        lsp::CompletionTextEdit::Edit(edit) => {
2110            let range = range_from_lsp(edit.range);
2111            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2112            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2113            if start != range.start.0 || end != range.end.0 {
2114                log::info!("completion out of expected range");
2115                None
2116            } else {
2117                Some((
2118                    snapshot.anchor_before(start)..snapshot.anchor_after(end),
2119                    edit.new_text.clone(),
2120                ))
2121            }
2122        }
2123
2124        lsp::CompletionTextEdit::InsertAndReplace(edit) => {
2125            let range = range_from_lsp(edit.replace);
2126
2127            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2128            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2129            if start != range.start.0 || end != range.end.0 {
2130                log::info!("completion out of expected range");
2131                None
2132            } else {
2133                Some((
2134                    snapshot.anchor_before(start)..snapshot.anchor_after(end),
2135                    edit.new_text.clone(),
2136                ))
2137            }
2138        }
2139    }
2140}
2141
2142#[async_trait(?Send)]
2143impl LspCommand for GetCodeActions {
2144    type Response = Vec<CodeAction>;
2145    type LspRequest = lsp::request::CodeActionRequest;
2146    type ProtoRequest = proto::GetCodeActions;
2147
2148    fn display_name(&self) -> &str {
2149        "Get code actions"
2150    }
2151
2152    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2153        match &capabilities.server_capabilities.code_action_provider {
2154            None => false,
2155            Some(lsp::CodeActionProviderCapability::Simple(false)) => false,
2156            _ => {
2157                // If we do know that we want specific code actions AND we know that
2158                // the server only supports specific code actions, then we want to filter
2159                // down to the ones that are supported.
2160                if let Some((requested, supported)) = self
2161                    .kinds
2162                    .as_ref()
2163                    .zip(Self::supported_code_action_kinds(capabilities))
2164                {
2165                    let server_supported = supported.into_iter().collect::<HashSet<_>>();
2166                    requested.iter().any(|kind| server_supported.contains(kind))
2167                } else {
2168                    true
2169                }
2170            }
2171        }
2172    }
2173
2174    fn to_lsp(
2175        &self,
2176        path: &Path,
2177        buffer: &Buffer,
2178        language_server: &Arc<LanguageServer>,
2179        _: &App,
2180    ) -> Result<lsp::CodeActionParams> {
2181        let mut relevant_diagnostics = Vec::new();
2182        for entry in buffer
2183            .snapshot()
2184            .diagnostics_in_range::<_, language::PointUtf16>(self.range.clone(), false)
2185        {
2186            relevant_diagnostics.push(entry.to_lsp_diagnostic_stub()?);
2187        }
2188
2189        let supported =
2190            Self::supported_code_action_kinds(language_server.adapter_server_capabilities());
2191
2192        let only = if let Some(requested) = &self.kinds {
2193            if let Some(supported_kinds) = supported {
2194                let server_supported = supported_kinds.into_iter().collect::<HashSet<_>>();
2195
2196                let filtered = requested
2197                    .iter()
2198                    .filter(|kind| server_supported.contains(kind))
2199                    .cloned()
2200                    .collect();
2201                Some(filtered)
2202            } else {
2203                Some(requested.clone())
2204            }
2205        } else {
2206            supported
2207        };
2208
2209        Ok(lsp::CodeActionParams {
2210            text_document: make_text_document_identifier(path)?,
2211            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
2212            work_done_progress_params: Default::default(),
2213            partial_result_params: Default::default(),
2214            context: lsp::CodeActionContext {
2215                diagnostics: relevant_diagnostics,
2216                only,
2217                ..lsp::CodeActionContext::default()
2218            },
2219        })
2220    }
2221
2222    async fn response_from_lsp(
2223        self,
2224        actions: Option<lsp::CodeActionResponse>,
2225        _: Entity<LspStore>,
2226        _: Entity<Buffer>,
2227        server_id: LanguageServerId,
2228        _: AsyncApp,
2229    ) -> Result<Vec<CodeAction>> {
2230        let requested_kinds_set = if let Some(kinds) = self.kinds {
2231            Some(kinds.into_iter().collect::<HashSet<_>>())
2232        } else {
2233            None
2234        };
2235
2236        Ok(actions
2237            .unwrap_or_default()
2238            .into_iter()
2239            .filter_map(|entry| {
2240                let lsp::CodeActionOrCommand::CodeAction(lsp_action) = entry else {
2241                    return None;
2242                };
2243
2244                if let Some((requested_kinds, kind)) =
2245                    requested_kinds_set.as_ref().zip(lsp_action.kind.as_ref())
2246                {
2247                    if !requested_kinds.contains(kind) {
2248                        return None;
2249                    }
2250                }
2251
2252                Some(CodeAction {
2253                    server_id,
2254                    range: self.range.clone(),
2255                    lsp_action,
2256                })
2257            })
2258            .collect())
2259    }
2260
2261    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeActions {
2262        proto::GetCodeActions {
2263            project_id,
2264            buffer_id: buffer.remote_id().into(),
2265            start: Some(language::proto::serialize_anchor(&self.range.start)),
2266            end: Some(language::proto::serialize_anchor(&self.range.end)),
2267            version: serialize_version(&buffer.version()),
2268        }
2269    }
2270
2271    async fn from_proto(
2272        message: proto::GetCodeActions,
2273        _: Entity<LspStore>,
2274        buffer: Entity<Buffer>,
2275        mut cx: AsyncApp,
2276    ) -> Result<Self> {
2277        let start = message
2278            .start
2279            .and_then(language::proto::deserialize_anchor)
2280            .ok_or_else(|| anyhow!("invalid start"))?;
2281        let end = message
2282            .end
2283            .and_then(language::proto::deserialize_anchor)
2284            .ok_or_else(|| anyhow!("invalid end"))?;
2285        buffer
2286            .update(&mut cx, |buffer, _| {
2287                buffer.wait_for_version(deserialize_version(&message.version))
2288            })?
2289            .await?;
2290
2291        Ok(Self {
2292            range: start..end,
2293            kinds: None,
2294        })
2295    }
2296
2297    fn response_to_proto(
2298        code_actions: Vec<CodeAction>,
2299        _: &mut LspStore,
2300        _: PeerId,
2301        buffer_version: &clock::Global,
2302        _: &mut App,
2303    ) -> proto::GetCodeActionsResponse {
2304        proto::GetCodeActionsResponse {
2305            actions: code_actions
2306                .iter()
2307                .map(LspStore::serialize_code_action)
2308                .collect(),
2309            version: serialize_version(buffer_version),
2310        }
2311    }
2312
2313    async fn response_from_proto(
2314        self,
2315        message: proto::GetCodeActionsResponse,
2316        _: Entity<LspStore>,
2317        buffer: Entity<Buffer>,
2318        mut cx: AsyncApp,
2319    ) -> Result<Vec<CodeAction>> {
2320        buffer
2321            .update(&mut cx, |buffer, _| {
2322                buffer.wait_for_version(deserialize_version(&message.version))
2323            })?
2324            .await?;
2325        message
2326            .actions
2327            .into_iter()
2328            .map(LspStore::deserialize_code_action)
2329            .collect()
2330    }
2331
2332    fn buffer_id_from_proto(message: &proto::GetCodeActions) -> Result<BufferId> {
2333        BufferId::new(message.buffer_id)
2334    }
2335}
2336
2337impl GetCodeActions {
2338    fn supported_code_action_kinds(
2339        capabilities: AdapterServerCapabilities,
2340    ) -> Option<Vec<CodeActionKind>> {
2341        match capabilities.server_capabilities.code_action_provider {
2342            Some(lsp::CodeActionProviderCapability::Options(CodeActionOptions {
2343                code_action_kinds: Some(supported_action_kinds),
2344                ..
2345            })) => Some(supported_action_kinds.clone()),
2346            _ => capabilities.code_action_kinds,
2347        }
2348    }
2349
2350    pub fn can_resolve_actions(capabilities: &ServerCapabilities) -> bool {
2351        capabilities
2352            .code_action_provider
2353            .as_ref()
2354            .and_then(|options| match options {
2355                lsp::CodeActionProviderCapability::Simple(_is_supported) => None,
2356                lsp::CodeActionProviderCapability::Options(options) => options.resolve_provider,
2357            })
2358            .unwrap_or(false)
2359    }
2360}
2361
2362#[async_trait(?Send)]
2363impl LspCommand for OnTypeFormatting {
2364    type Response = Option<Transaction>;
2365    type LspRequest = lsp::request::OnTypeFormatting;
2366    type ProtoRequest = proto::OnTypeFormatting;
2367
2368    fn display_name(&self) -> &str {
2369        "Formatting on typing"
2370    }
2371
2372    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2373        let Some(on_type_formatting_options) = &capabilities
2374            .server_capabilities
2375            .document_on_type_formatting_provider
2376        else {
2377            return false;
2378        };
2379        on_type_formatting_options
2380            .first_trigger_character
2381            .contains(&self.trigger)
2382            || on_type_formatting_options
2383                .more_trigger_character
2384                .iter()
2385                .flatten()
2386                .any(|chars| chars.contains(&self.trigger))
2387    }
2388
2389    fn to_lsp(
2390        &self,
2391        path: &Path,
2392        _: &Buffer,
2393        _: &Arc<LanguageServer>,
2394        _: &App,
2395    ) -> Result<lsp::DocumentOnTypeFormattingParams> {
2396        Ok(lsp::DocumentOnTypeFormattingParams {
2397            text_document_position: make_lsp_text_document_position(path, self.position)?,
2398            ch: self.trigger.clone(),
2399            options: self.options.clone(),
2400        })
2401    }
2402
2403    async fn response_from_lsp(
2404        self,
2405        message: Option<Vec<lsp::TextEdit>>,
2406        lsp_store: Entity<LspStore>,
2407        buffer: Entity<Buffer>,
2408        server_id: LanguageServerId,
2409        mut cx: AsyncApp,
2410    ) -> Result<Option<Transaction>> {
2411        if let Some(edits) = message {
2412            let (lsp_adapter, lsp_server) =
2413                language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
2414            LocalLspStore::deserialize_text_edits(
2415                lsp_store,
2416                buffer,
2417                edits,
2418                self.push_to_history,
2419                lsp_adapter,
2420                lsp_server,
2421                &mut cx,
2422            )
2423            .await
2424        } else {
2425            Ok(None)
2426        }
2427    }
2428
2429    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::OnTypeFormatting {
2430        proto::OnTypeFormatting {
2431            project_id,
2432            buffer_id: buffer.remote_id().into(),
2433            position: Some(language::proto::serialize_anchor(
2434                &buffer.anchor_before(self.position),
2435            )),
2436            trigger: self.trigger.clone(),
2437            version: serialize_version(&buffer.version()),
2438        }
2439    }
2440
2441    async fn from_proto(
2442        message: proto::OnTypeFormatting,
2443        _: Entity<LspStore>,
2444        buffer: Entity<Buffer>,
2445        mut cx: AsyncApp,
2446    ) -> Result<Self> {
2447        let position = message
2448            .position
2449            .and_then(deserialize_anchor)
2450            .ok_or_else(|| anyhow!("invalid position"))?;
2451        buffer
2452            .update(&mut cx, |buffer, _| {
2453                buffer.wait_for_version(deserialize_version(&message.version))
2454            })?
2455            .await?;
2456
2457        let options = buffer.update(&mut cx, |buffer, cx| {
2458            lsp_formatting_options(
2459                language_settings(buffer.language().map(|l| l.name()), buffer.file(), cx).as_ref(),
2460            )
2461        })?;
2462
2463        Ok(Self {
2464            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
2465            trigger: message.trigger.clone(),
2466            options,
2467            push_to_history: false,
2468        })
2469    }
2470
2471    fn response_to_proto(
2472        response: Option<Transaction>,
2473        _: &mut LspStore,
2474        _: PeerId,
2475        _: &clock::Global,
2476        _: &mut App,
2477    ) -> proto::OnTypeFormattingResponse {
2478        proto::OnTypeFormattingResponse {
2479            transaction: response
2480                .map(|transaction| language::proto::serialize_transaction(&transaction)),
2481        }
2482    }
2483
2484    async fn response_from_proto(
2485        self,
2486        message: proto::OnTypeFormattingResponse,
2487        _: Entity<LspStore>,
2488        _: Entity<Buffer>,
2489        _: AsyncApp,
2490    ) -> Result<Option<Transaction>> {
2491        let Some(transaction) = message.transaction else {
2492            return Ok(None);
2493        };
2494        Ok(Some(language::proto::deserialize_transaction(transaction)?))
2495    }
2496
2497    fn buffer_id_from_proto(message: &proto::OnTypeFormatting) -> Result<BufferId> {
2498        BufferId::new(message.buffer_id)
2499    }
2500}
2501
2502impl InlayHints {
2503    pub async fn lsp_to_project_hint(
2504        lsp_hint: lsp::InlayHint,
2505        buffer_handle: &Entity<Buffer>,
2506        server_id: LanguageServerId,
2507        resolve_state: ResolveState,
2508        force_no_type_left_padding: bool,
2509        cx: &mut AsyncApp,
2510    ) -> anyhow::Result<InlayHint> {
2511        let kind = lsp_hint.kind.and_then(|kind| match kind {
2512            lsp::InlayHintKind::TYPE => Some(InlayHintKind::Type),
2513            lsp::InlayHintKind::PARAMETER => Some(InlayHintKind::Parameter),
2514            _ => None,
2515        });
2516
2517        let position = buffer_handle.update(cx, |buffer, _| {
2518            let position = buffer.clip_point_utf16(point_from_lsp(lsp_hint.position), Bias::Left);
2519            if kind == Some(InlayHintKind::Parameter) {
2520                buffer.anchor_before(position)
2521            } else {
2522                buffer.anchor_after(position)
2523            }
2524        })?;
2525        let label = Self::lsp_inlay_label_to_project(lsp_hint.label, server_id)
2526            .await
2527            .context("lsp to project inlay hint conversion")?;
2528        let padding_left = if force_no_type_left_padding && kind == Some(InlayHintKind::Type) {
2529            false
2530        } else {
2531            lsp_hint.padding_left.unwrap_or(false)
2532        };
2533
2534        Ok(InlayHint {
2535            position,
2536            padding_left,
2537            padding_right: lsp_hint.padding_right.unwrap_or(false),
2538            label,
2539            kind,
2540            tooltip: lsp_hint.tooltip.map(|tooltip| match tooltip {
2541                lsp::InlayHintTooltip::String(s) => InlayHintTooltip::String(s),
2542                lsp::InlayHintTooltip::MarkupContent(markup_content) => {
2543                    InlayHintTooltip::MarkupContent(MarkupContent {
2544                        kind: match markup_content.kind {
2545                            lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
2546                            lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
2547                        },
2548                        value: markup_content.value,
2549                    })
2550                }
2551            }),
2552            resolve_state,
2553        })
2554    }
2555
2556    async fn lsp_inlay_label_to_project(
2557        lsp_label: lsp::InlayHintLabel,
2558        server_id: LanguageServerId,
2559    ) -> anyhow::Result<InlayHintLabel> {
2560        let label = match lsp_label {
2561            lsp::InlayHintLabel::String(s) => InlayHintLabel::String(s),
2562            lsp::InlayHintLabel::LabelParts(lsp_parts) => {
2563                let mut parts = Vec::with_capacity(lsp_parts.len());
2564                for lsp_part in lsp_parts {
2565                    parts.push(InlayHintLabelPart {
2566                        value: lsp_part.value,
2567                        tooltip: lsp_part.tooltip.map(|tooltip| match tooltip {
2568                            lsp::InlayHintLabelPartTooltip::String(s) => {
2569                                InlayHintLabelPartTooltip::String(s)
2570                            }
2571                            lsp::InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
2572                                InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
2573                                    kind: match markup_content.kind {
2574                                        lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
2575                                        lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
2576                                    },
2577                                    value: markup_content.value,
2578                                })
2579                            }
2580                        }),
2581                        location: Some(server_id).zip(lsp_part.location),
2582                    });
2583                }
2584                InlayHintLabel::LabelParts(parts)
2585            }
2586        };
2587
2588        Ok(label)
2589    }
2590
2591    pub fn project_to_proto_hint(response_hint: InlayHint) -> proto::InlayHint {
2592        let (state, lsp_resolve_state) = match response_hint.resolve_state {
2593            ResolveState::Resolved => (0, None),
2594            ResolveState::CanResolve(server_id, resolve_data) => (
2595                1,
2596                Some(proto::resolve_state::LspResolveState {
2597                    server_id: server_id.0 as u64,
2598                    value: resolve_data.map(|json_data| {
2599                        serde_json::to_string(&json_data)
2600                            .expect("failed to serialize resolve json data")
2601                    }),
2602                }),
2603            ),
2604            ResolveState::Resolving => (2, None),
2605        };
2606        let resolve_state = Some(proto::ResolveState {
2607            state,
2608            lsp_resolve_state,
2609        });
2610        proto::InlayHint {
2611            position: Some(language::proto::serialize_anchor(&response_hint.position)),
2612            padding_left: response_hint.padding_left,
2613            padding_right: response_hint.padding_right,
2614            label: Some(proto::InlayHintLabel {
2615                label: Some(match response_hint.label {
2616                    InlayHintLabel::String(s) => proto::inlay_hint_label::Label::Value(s),
2617                    InlayHintLabel::LabelParts(label_parts) => {
2618                        proto::inlay_hint_label::Label::LabelParts(proto::InlayHintLabelParts {
2619                            parts: label_parts.into_iter().map(|label_part| {
2620                                let location_url = label_part.location.as_ref().map(|(_, location)| location.uri.to_string());
2621                                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 });
2622                                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 });
2623                                proto::InlayHintLabelPart {
2624                                value: label_part.value,
2625                                tooltip: label_part.tooltip.map(|tooltip| {
2626                                    let proto_tooltip = match tooltip {
2627                                        InlayHintLabelPartTooltip::String(s) => proto::inlay_hint_label_part_tooltip::Content::Value(s),
2628                                        InlayHintLabelPartTooltip::MarkupContent(markup_content) => proto::inlay_hint_label_part_tooltip::Content::MarkupContent(proto::MarkupContent {
2629                                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
2630                                            value: markup_content.value,
2631                                        }),
2632                                    };
2633                                    proto::InlayHintLabelPartTooltip {content: Some(proto_tooltip)}
2634                                }),
2635                                location_url,
2636                                location_range_start,
2637                                location_range_end,
2638                                language_server_id: label_part.location.as_ref().map(|(server_id, _)| server_id.0 as u64),
2639                            }}).collect()
2640                        })
2641                    }
2642                }),
2643            }),
2644            kind: response_hint.kind.map(|kind| kind.name().to_string()),
2645            tooltip: response_hint.tooltip.map(|response_tooltip| {
2646                let proto_tooltip = match response_tooltip {
2647                    InlayHintTooltip::String(s) => proto::inlay_hint_tooltip::Content::Value(s),
2648                    InlayHintTooltip::MarkupContent(markup_content) => {
2649                        proto::inlay_hint_tooltip::Content::MarkupContent(proto::MarkupContent {
2650                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
2651                            value: markup_content.value,
2652                        })
2653                    }
2654                };
2655                proto::InlayHintTooltip {
2656                    content: Some(proto_tooltip),
2657                }
2658            }),
2659            resolve_state,
2660        }
2661    }
2662
2663    pub fn proto_to_project_hint(message_hint: proto::InlayHint) -> anyhow::Result<InlayHint> {
2664        let resolve_state = message_hint.resolve_state.as_ref().unwrap_or_else(|| {
2665            panic!("incorrect proto inlay hint message: no resolve state in hint {message_hint:?}",)
2666        });
2667        let resolve_state_data = resolve_state
2668            .lsp_resolve_state.as_ref()
2669            .map(|lsp_resolve_state| {
2670                let value = lsp_resolve_state.value.as_deref().map(|value| {
2671                    serde_json::from_str::<Option<lsp::LSPAny>>(value)
2672                        .with_context(|| format!("incorrect proto inlay hint message: non-json resolve state {lsp_resolve_state:?}"))
2673                }).transpose()?.flatten();
2674                anyhow::Ok((LanguageServerId(lsp_resolve_state.server_id as usize), value))
2675            })
2676            .transpose()?;
2677        let resolve_state = match resolve_state.state {
2678            0 => ResolveState::Resolved,
2679            1 => {
2680                let (server_id, lsp_resolve_state) = resolve_state_data.with_context(|| {
2681                    format!(
2682                        "No lsp resolve data for the hint that can be resolved: {message_hint:?}"
2683                    )
2684                })?;
2685                ResolveState::CanResolve(server_id, lsp_resolve_state)
2686            }
2687            2 => ResolveState::Resolving,
2688            invalid => {
2689                anyhow::bail!("Unexpected resolve state {invalid} for hint {message_hint:?}")
2690            }
2691        };
2692        Ok(InlayHint {
2693            position: message_hint
2694                .position
2695                .and_then(language::proto::deserialize_anchor)
2696                .context("invalid position")?,
2697            label: match message_hint
2698                .label
2699                .and_then(|label| label.label)
2700                .context("missing label")?
2701            {
2702                proto::inlay_hint_label::Label::Value(s) => InlayHintLabel::String(s),
2703                proto::inlay_hint_label::Label::LabelParts(parts) => {
2704                    let mut label_parts = Vec::new();
2705                    for part in parts.parts {
2706                        label_parts.push(InlayHintLabelPart {
2707                            value: part.value,
2708                            tooltip: part.tooltip.map(|tooltip| match tooltip.content {
2709                                Some(proto::inlay_hint_label_part_tooltip::Content::Value(s)) => {
2710                                    InlayHintLabelPartTooltip::String(s)
2711                                }
2712                                Some(
2713                                    proto::inlay_hint_label_part_tooltip::Content::MarkupContent(
2714                                        markup_content,
2715                                    ),
2716                                ) => InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
2717                                    kind: if markup_content.is_markdown {
2718                                        HoverBlockKind::Markdown
2719                                    } else {
2720                                        HoverBlockKind::PlainText
2721                                    },
2722                                    value: markup_content.value,
2723                                }),
2724                                None => InlayHintLabelPartTooltip::String(String::new()),
2725                            }),
2726                            location: {
2727                                match part
2728                                    .location_url
2729                                    .zip(
2730                                        part.location_range_start.and_then(|start| {
2731                                            Some(start..part.location_range_end?)
2732                                        }),
2733                                    )
2734                                    .zip(part.language_server_id)
2735                                {
2736                                    Some(((uri, range), server_id)) => Some((
2737                                        LanguageServerId(server_id as usize),
2738                                        lsp::Location {
2739                                            uri: lsp::Url::parse(&uri)
2740                                                .context("invalid uri in hint part {part:?}")?,
2741                                            range: lsp::Range::new(
2742                                                point_to_lsp(PointUtf16::new(
2743                                                    range.start.row,
2744                                                    range.start.column,
2745                                                )),
2746                                                point_to_lsp(PointUtf16::new(
2747                                                    range.end.row,
2748                                                    range.end.column,
2749                                                )),
2750                                            ),
2751                                        },
2752                                    )),
2753                                    None => None,
2754                                }
2755                            },
2756                        });
2757                    }
2758
2759                    InlayHintLabel::LabelParts(label_parts)
2760                }
2761            },
2762            padding_left: message_hint.padding_left,
2763            padding_right: message_hint.padding_right,
2764            kind: message_hint
2765                .kind
2766                .as_deref()
2767                .and_then(InlayHintKind::from_name),
2768            tooltip: message_hint.tooltip.and_then(|tooltip| {
2769                Some(match tooltip.content? {
2770                    proto::inlay_hint_tooltip::Content::Value(s) => InlayHintTooltip::String(s),
2771                    proto::inlay_hint_tooltip::Content::MarkupContent(markup_content) => {
2772                        InlayHintTooltip::MarkupContent(MarkupContent {
2773                            kind: if markup_content.is_markdown {
2774                                HoverBlockKind::Markdown
2775                            } else {
2776                                HoverBlockKind::PlainText
2777                            },
2778                            value: markup_content.value,
2779                        })
2780                    }
2781                })
2782            }),
2783            resolve_state,
2784        })
2785    }
2786
2787    pub fn project_to_lsp_hint(hint: InlayHint, snapshot: &BufferSnapshot) -> lsp::InlayHint {
2788        lsp::InlayHint {
2789            position: point_to_lsp(hint.position.to_point_utf16(snapshot)),
2790            kind: hint.kind.map(|kind| match kind {
2791                InlayHintKind::Type => lsp::InlayHintKind::TYPE,
2792                InlayHintKind::Parameter => lsp::InlayHintKind::PARAMETER,
2793            }),
2794            text_edits: None,
2795            tooltip: hint.tooltip.and_then(|tooltip| {
2796                Some(match tooltip {
2797                    InlayHintTooltip::String(s) => lsp::InlayHintTooltip::String(s),
2798                    InlayHintTooltip::MarkupContent(markup_content) => {
2799                        lsp::InlayHintTooltip::MarkupContent(lsp::MarkupContent {
2800                            kind: match markup_content.kind {
2801                                HoverBlockKind::PlainText => lsp::MarkupKind::PlainText,
2802                                HoverBlockKind::Markdown => lsp::MarkupKind::Markdown,
2803                                HoverBlockKind::Code { .. } => return None,
2804                            },
2805                            value: markup_content.value,
2806                        })
2807                    }
2808                })
2809            }),
2810            label: match hint.label {
2811                InlayHintLabel::String(s) => lsp::InlayHintLabel::String(s),
2812                InlayHintLabel::LabelParts(label_parts) => lsp::InlayHintLabel::LabelParts(
2813                    label_parts
2814                        .into_iter()
2815                        .map(|part| lsp::InlayHintLabelPart {
2816                            value: part.value,
2817                            tooltip: part.tooltip.and_then(|tooltip| {
2818                                Some(match tooltip {
2819                                    InlayHintLabelPartTooltip::String(s) => {
2820                                        lsp::InlayHintLabelPartTooltip::String(s)
2821                                    }
2822                                    InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
2823                                        lsp::InlayHintLabelPartTooltip::MarkupContent(
2824                                            lsp::MarkupContent {
2825                                                kind: match markup_content.kind {
2826                                                    HoverBlockKind::PlainText => {
2827                                                        lsp::MarkupKind::PlainText
2828                                                    }
2829                                                    HoverBlockKind::Markdown => {
2830                                                        lsp::MarkupKind::Markdown
2831                                                    }
2832                                                    HoverBlockKind::Code { .. } => return None,
2833                                                },
2834                                                value: markup_content.value,
2835                                            },
2836                                        )
2837                                    }
2838                                })
2839                            }),
2840                            location: part.location.map(|(_, location)| location),
2841                            command: None,
2842                        })
2843                        .collect(),
2844                ),
2845            },
2846            padding_left: Some(hint.padding_left),
2847            padding_right: Some(hint.padding_right),
2848            data: match hint.resolve_state {
2849                ResolveState::CanResolve(_, data) => data,
2850                ResolveState::Resolving | ResolveState::Resolved => None,
2851            },
2852        }
2853    }
2854
2855    pub fn can_resolve_inlays(capabilities: &ServerCapabilities) -> bool {
2856        capabilities
2857            .inlay_hint_provider
2858            .as_ref()
2859            .and_then(|options| match options {
2860                OneOf::Left(_is_supported) => None,
2861                OneOf::Right(capabilities) => match capabilities {
2862                    lsp::InlayHintServerCapabilities::Options(o) => o.resolve_provider,
2863                    lsp::InlayHintServerCapabilities::RegistrationOptions(o) => {
2864                        o.inlay_hint_options.resolve_provider
2865                    }
2866                },
2867            })
2868            .unwrap_or(false)
2869    }
2870}
2871
2872#[async_trait(?Send)]
2873impl LspCommand for InlayHints {
2874    type Response = Vec<InlayHint>;
2875    type LspRequest = lsp::InlayHintRequest;
2876    type ProtoRequest = proto::InlayHints;
2877
2878    fn display_name(&self) -> &str {
2879        "Inlay hints"
2880    }
2881
2882    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2883        let Some(inlay_hint_provider) = &capabilities.server_capabilities.inlay_hint_provider
2884        else {
2885            return false;
2886        };
2887        match inlay_hint_provider {
2888            lsp::OneOf::Left(enabled) => *enabled,
2889            lsp::OneOf::Right(inlay_hint_capabilities) => match inlay_hint_capabilities {
2890                lsp::InlayHintServerCapabilities::Options(_) => true,
2891                lsp::InlayHintServerCapabilities::RegistrationOptions(_) => false,
2892            },
2893        }
2894    }
2895
2896    fn to_lsp(
2897        &self,
2898        path: &Path,
2899        buffer: &Buffer,
2900        _: &Arc<LanguageServer>,
2901        _: &App,
2902    ) -> Result<lsp::InlayHintParams> {
2903        Ok(lsp::InlayHintParams {
2904            text_document: lsp::TextDocumentIdentifier {
2905                uri: file_path_to_lsp_url(path)?,
2906            },
2907            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
2908            work_done_progress_params: Default::default(),
2909        })
2910    }
2911
2912    async fn response_from_lsp(
2913        self,
2914        message: Option<Vec<lsp::InlayHint>>,
2915        lsp_store: Entity<LspStore>,
2916        buffer: Entity<Buffer>,
2917        server_id: LanguageServerId,
2918        mut cx: AsyncApp,
2919    ) -> anyhow::Result<Vec<InlayHint>> {
2920        let (lsp_adapter, lsp_server) =
2921            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
2922        // `typescript-language-server` adds padding to the left for type hints, turning
2923        // `const foo: boolean` into `const foo : boolean` which looks odd.
2924        // `rust-analyzer` does not have the padding for this case, and we have to accommodate both.
2925        //
2926        // We could trim the whole string, but being pessimistic on par with the situation above,
2927        // there might be a hint with multiple whitespaces at the end(s) which we need to display properly.
2928        // Hence let's use a heuristic first to handle the most awkward case and look for more.
2929        let force_no_type_left_padding =
2930            lsp_adapter.name.0.as_ref() == "typescript-language-server";
2931
2932        let hints = message.unwrap_or_default().into_iter().map(|lsp_hint| {
2933            let resolve_state = if InlayHints::can_resolve_inlays(&lsp_server.capabilities()) {
2934                ResolveState::CanResolve(lsp_server.server_id(), lsp_hint.data.clone())
2935            } else {
2936                ResolveState::Resolved
2937            };
2938
2939            let buffer = buffer.clone();
2940            cx.spawn(move |mut cx| async move {
2941                InlayHints::lsp_to_project_hint(
2942                    lsp_hint,
2943                    &buffer,
2944                    server_id,
2945                    resolve_state,
2946                    force_no_type_left_padding,
2947                    &mut cx,
2948                )
2949                .await
2950            })
2951        });
2952        future::join_all(hints)
2953            .await
2954            .into_iter()
2955            .collect::<anyhow::Result<_>>()
2956            .context("lsp to project inlay hints conversion")
2957    }
2958
2959    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::InlayHints {
2960        proto::InlayHints {
2961            project_id,
2962            buffer_id: buffer.remote_id().into(),
2963            start: Some(language::proto::serialize_anchor(&self.range.start)),
2964            end: Some(language::proto::serialize_anchor(&self.range.end)),
2965            version: serialize_version(&buffer.version()),
2966        }
2967    }
2968
2969    async fn from_proto(
2970        message: proto::InlayHints,
2971        _: Entity<LspStore>,
2972        buffer: Entity<Buffer>,
2973        mut cx: AsyncApp,
2974    ) -> Result<Self> {
2975        let start = message
2976            .start
2977            .and_then(language::proto::deserialize_anchor)
2978            .context("invalid start")?;
2979        let end = message
2980            .end
2981            .and_then(language::proto::deserialize_anchor)
2982            .context("invalid end")?;
2983        buffer
2984            .update(&mut cx, |buffer, _| {
2985                buffer.wait_for_version(deserialize_version(&message.version))
2986            })?
2987            .await?;
2988
2989        Ok(Self { range: start..end })
2990    }
2991
2992    fn response_to_proto(
2993        response: Vec<InlayHint>,
2994        _: &mut LspStore,
2995        _: PeerId,
2996        buffer_version: &clock::Global,
2997        _: &mut App,
2998    ) -> proto::InlayHintsResponse {
2999        proto::InlayHintsResponse {
3000            hints: response
3001                .into_iter()
3002                .map(InlayHints::project_to_proto_hint)
3003                .collect(),
3004            version: serialize_version(buffer_version),
3005        }
3006    }
3007
3008    async fn response_from_proto(
3009        self,
3010        message: proto::InlayHintsResponse,
3011        _: Entity<LspStore>,
3012        buffer: Entity<Buffer>,
3013        mut cx: AsyncApp,
3014    ) -> anyhow::Result<Vec<InlayHint>> {
3015        buffer
3016            .update(&mut cx, |buffer, _| {
3017                buffer.wait_for_version(deserialize_version(&message.version))
3018            })?
3019            .await?;
3020
3021        let mut hints = Vec::new();
3022        for message_hint in message.hints {
3023            hints.push(InlayHints::proto_to_project_hint(message_hint)?);
3024        }
3025
3026        Ok(hints)
3027    }
3028
3029    fn buffer_id_from_proto(message: &proto::InlayHints) -> Result<BufferId> {
3030        BufferId::new(message.buffer_id)
3031    }
3032}
3033
3034#[async_trait(?Send)]
3035impl LspCommand for LinkedEditingRange {
3036    type Response = Vec<Range<Anchor>>;
3037    type LspRequest = lsp::request::LinkedEditingRange;
3038    type ProtoRequest = proto::LinkedEditingRange;
3039
3040    fn display_name(&self) -> &str {
3041        "Linked editing range"
3042    }
3043
3044    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3045        let Some(linked_editing_options) = &capabilities
3046            .server_capabilities
3047            .linked_editing_range_provider
3048        else {
3049            return false;
3050        };
3051        if let LinkedEditingRangeServerCapabilities::Simple(false) = linked_editing_options {
3052            return false;
3053        }
3054        true
3055    }
3056
3057    fn to_lsp(
3058        &self,
3059        path: &Path,
3060        buffer: &Buffer,
3061        _server: &Arc<LanguageServer>,
3062        _: &App,
3063    ) -> Result<lsp::LinkedEditingRangeParams> {
3064        let position = self.position.to_point_utf16(&buffer.snapshot());
3065        Ok(lsp::LinkedEditingRangeParams {
3066            text_document_position_params: make_lsp_text_document_position(path, position)?,
3067            work_done_progress_params: Default::default(),
3068        })
3069    }
3070
3071    async fn response_from_lsp(
3072        self,
3073        message: Option<lsp::LinkedEditingRanges>,
3074        _: Entity<LspStore>,
3075        buffer: Entity<Buffer>,
3076        _server_id: LanguageServerId,
3077        cx: AsyncApp,
3078    ) -> Result<Vec<Range<Anchor>>> {
3079        if let Some(lsp::LinkedEditingRanges { mut ranges, .. }) = message {
3080            ranges.sort_by_key(|range| range.start);
3081
3082            buffer.read_with(&cx, |buffer, _| {
3083                ranges
3084                    .into_iter()
3085                    .map(|range| {
3086                        let start =
3087                            buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
3088                        let end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
3089                        buffer.anchor_before(start)..buffer.anchor_after(end)
3090                    })
3091                    .collect()
3092            })
3093        } else {
3094            Ok(vec![])
3095        }
3096    }
3097
3098    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::LinkedEditingRange {
3099        proto::LinkedEditingRange {
3100            project_id,
3101            buffer_id: buffer.remote_id().to_proto(),
3102            position: Some(serialize_anchor(&self.position)),
3103            version: serialize_version(&buffer.version()),
3104        }
3105    }
3106
3107    async fn from_proto(
3108        message: proto::LinkedEditingRange,
3109        _: Entity<LspStore>,
3110        buffer: Entity<Buffer>,
3111        mut cx: AsyncApp,
3112    ) -> Result<Self> {
3113        let position = message
3114            .position
3115            .ok_or_else(|| anyhow!("invalid position"))?;
3116        buffer
3117            .update(&mut cx, |buffer, _| {
3118                buffer.wait_for_version(deserialize_version(&message.version))
3119            })?
3120            .await?;
3121        let position = deserialize_anchor(position).ok_or_else(|| anyhow!("invalid position"))?;
3122        buffer
3123            .update(&mut cx, |buffer, _| buffer.wait_for_anchors([position]))?
3124            .await?;
3125        Ok(Self { position })
3126    }
3127
3128    fn response_to_proto(
3129        response: Vec<Range<Anchor>>,
3130        _: &mut LspStore,
3131        _: PeerId,
3132        buffer_version: &clock::Global,
3133        _: &mut App,
3134    ) -> proto::LinkedEditingRangeResponse {
3135        proto::LinkedEditingRangeResponse {
3136            items: response
3137                .into_iter()
3138                .map(|range| proto::AnchorRange {
3139                    start: Some(serialize_anchor(&range.start)),
3140                    end: Some(serialize_anchor(&range.end)),
3141                })
3142                .collect(),
3143            version: serialize_version(buffer_version),
3144        }
3145    }
3146
3147    async fn response_from_proto(
3148        self,
3149        message: proto::LinkedEditingRangeResponse,
3150        _: Entity<LspStore>,
3151        buffer: Entity<Buffer>,
3152        mut cx: AsyncApp,
3153    ) -> Result<Vec<Range<Anchor>>> {
3154        buffer
3155            .update(&mut cx, |buffer, _| {
3156                buffer.wait_for_version(deserialize_version(&message.version))
3157            })?
3158            .await?;
3159        let items: Vec<Range<Anchor>> = message
3160            .items
3161            .into_iter()
3162            .filter_map(|range| {
3163                let start = deserialize_anchor(range.start?)?;
3164                let end = deserialize_anchor(range.end?)?;
3165                Some(start..end)
3166            })
3167            .collect();
3168        for range in &items {
3169            buffer
3170                .update(&mut cx, |buffer, _| {
3171                    buffer.wait_for_anchors([range.start, range.end])
3172                })?
3173                .await?;
3174        }
3175        Ok(items)
3176    }
3177
3178    fn buffer_id_from_proto(message: &proto::LinkedEditingRange) -> Result<BufferId> {
3179        BufferId::new(message.buffer_id)
3180    }
3181}