lsp_command.rs

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