lsp_command.rs

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