lsp_command.rs

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