lsp_command.rs

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