lsp_command.rs

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