lsp_command.rs

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