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        let origin = match link.origin {
 981            Some(origin) => {
 982                let buffer_id = BufferId::new(origin.buffer_id)?;
 983                let buffer = lsp_store
 984                    .update(&mut cx, |lsp_store, cx| {
 985                        lsp_store.wait_for_remote_buffer(buffer_id, cx)
 986                    })?
 987                    .await?;
 988                let start = origin
 989                    .start
 990                    .and_then(deserialize_anchor)
 991                    .ok_or_else(|| anyhow!("missing origin start"))?;
 992                let end = origin
 993                    .end
 994                    .and_then(deserialize_anchor)
 995                    .ok_or_else(|| anyhow!("missing origin end"))?;
 996                buffer
 997                    .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
 998                    .await?;
 999                Some(Location {
1000                    buffer,
1001                    range: start..end,
1002                })
1003            }
1004            None => None,
1005        };
1006
1007        let target = link.target.ok_or_else(|| anyhow!("missing target"))?;
1008        let buffer_id = BufferId::new(target.buffer_id)?;
1009        let buffer = lsp_store
1010            .update(&mut cx, |lsp_store, cx| {
1011                lsp_store.wait_for_remote_buffer(buffer_id, cx)
1012            })?
1013            .await?;
1014        let start = target
1015            .start
1016            .and_then(deserialize_anchor)
1017            .ok_or_else(|| anyhow!("missing target start"))?;
1018        let end = target
1019            .end
1020            .and_then(deserialize_anchor)
1021            .ok_or_else(|| anyhow!("missing target end"))?;
1022        buffer
1023            .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
1024            .await?;
1025        let target = Location {
1026            buffer,
1027            range: start..end,
1028        };
1029
1030        links.push(LocationLink { origin, target })
1031    }
1032
1033    Ok(links)
1034}
1035
1036async fn location_links_from_lsp(
1037    message: Option<lsp::GotoDefinitionResponse>,
1038    lsp_store: Entity<LspStore>,
1039    buffer: Entity<Buffer>,
1040    server_id: LanguageServerId,
1041    mut cx: AsyncApp,
1042) -> Result<Vec<LocationLink>> {
1043    let message = match message {
1044        Some(message) => message,
1045        None => return Ok(Vec::new()),
1046    };
1047
1048    let mut unresolved_links = Vec::new();
1049    match message {
1050        lsp::GotoDefinitionResponse::Scalar(loc) => {
1051            unresolved_links.push((None, loc.uri, loc.range));
1052        }
1053
1054        lsp::GotoDefinitionResponse::Array(locs) => {
1055            unresolved_links.extend(locs.into_iter().map(|l| (None, l.uri, l.range)));
1056        }
1057
1058        lsp::GotoDefinitionResponse::Link(links) => {
1059            unresolved_links.extend(links.into_iter().map(|l| {
1060                (
1061                    l.origin_selection_range,
1062                    l.target_uri,
1063                    l.target_selection_range,
1064                )
1065            }));
1066        }
1067    }
1068
1069    let (lsp_adapter, language_server) =
1070        language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1071    let mut definitions = Vec::new();
1072    for (origin_range, target_uri, target_range) in unresolved_links {
1073        let target_buffer_handle = lsp_store
1074            .update(&mut cx, |this, cx| {
1075                this.open_local_buffer_via_lsp(
1076                    target_uri,
1077                    language_server.server_id(),
1078                    lsp_adapter.name.clone(),
1079                    cx,
1080                )
1081            })?
1082            .await?;
1083
1084        cx.update(|cx| {
1085            let origin_location = origin_range.map(|origin_range| {
1086                let origin_buffer = buffer.read(cx);
1087                let origin_start =
1088                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
1089                let origin_end =
1090                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
1091                Location {
1092                    buffer: buffer.clone(),
1093                    range: origin_buffer.anchor_after(origin_start)
1094                        ..origin_buffer.anchor_before(origin_end),
1095                }
1096            });
1097
1098            let target_buffer = target_buffer_handle.read(cx);
1099            let target_start =
1100                target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
1101            let target_end =
1102                target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
1103            let target_location = Location {
1104                buffer: target_buffer_handle,
1105                range: target_buffer.anchor_after(target_start)
1106                    ..target_buffer.anchor_before(target_end),
1107            };
1108
1109            definitions.push(LocationLink {
1110                origin: origin_location,
1111                target: target_location,
1112            })
1113        })?;
1114    }
1115    Ok(definitions)
1116}
1117
1118fn location_links_to_proto(
1119    links: Vec<LocationLink>,
1120    lsp_store: &mut LspStore,
1121    peer_id: PeerId,
1122    cx: &mut App,
1123) -> Vec<proto::LocationLink> {
1124    links
1125        .into_iter()
1126        .map(|definition| {
1127            let origin = definition.origin.map(|origin| {
1128                lsp_store
1129                    .buffer_store()
1130                    .update(cx, |buffer_store, cx| {
1131                        buffer_store.create_buffer_for_peer(&origin.buffer, peer_id, cx)
1132                    })
1133                    .detach_and_log_err(cx);
1134
1135                let buffer_id = origin.buffer.read(cx).remote_id().into();
1136                proto::Location {
1137                    start: Some(serialize_anchor(&origin.range.start)),
1138                    end: Some(serialize_anchor(&origin.range.end)),
1139                    buffer_id,
1140                }
1141            });
1142
1143            lsp_store
1144                .buffer_store()
1145                .update(cx, |buffer_store, cx| {
1146                    buffer_store.create_buffer_for_peer(&definition.target.buffer, peer_id, cx)
1147                })
1148                .detach_and_log_err(cx);
1149
1150            let buffer_id = definition.target.buffer.read(cx).remote_id().into();
1151            let target = proto::Location {
1152                start: Some(serialize_anchor(&definition.target.range.start)),
1153                end: Some(serialize_anchor(&definition.target.range.end)),
1154                buffer_id,
1155            };
1156
1157            proto::LocationLink {
1158                origin,
1159                target: Some(target),
1160            }
1161        })
1162        .collect()
1163}
1164
1165#[async_trait(?Send)]
1166impl LspCommand for GetReferences {
1167    type Response = Vec<Location>;
1168    type LspRequest = lsp::request::References;
1169    type ProtoRequest = proto::GetReferences;
1170
1171    fn display_name(&self) -> &str {
1172        "Find all references"
1173    }
1174
1175    fn status(&self) -> Option<String> {
1176        Some("Finding references...".to_owned())
1177    }
1178
1179    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1180        match &capabilities.server_capabilities.references_provider {
1181            Some(OneOf::Left(has_support)) => *has_support,
1182            Some(OneOf::Right(_)) => true,
1183            None => false,
1184        }
1185    }
1186
1187    fn to_lsp(
1188        &self,
1189        path: &Path,
1190        _: &Buffer,
1191        _: &Arc<LanguageServer>,
1192        _: &App,
1193    ) -> Result<lsp::ReferenceParams> {
1194        Ok(lsp::ReferenceParams {
1195            text_document_position: make_lsp_text_document_position(path, self.position)?,
1196            work_done_progress_params: Default::default(),
1197            partial_result_params: Default::default(),
1198            context: lsp::ReferenceContext {
1199                include_declaration: true,
1200            },
1201        })
1202    }
1203
1204    async fn response_from_lsp(
1205        self,
1206        locations: Option<Vec<lsp::Location>>,
1207        lsp_store: Entity<LspStore>,
1208        buffer: Entity<Buffer>,
1209        server_id: LanguageServerId,
1210        mut cx: AsyncApp,
1211    ) -> Result<Vec<Location>> {
1212        let mut references = Vec::new();
1213        let (lsp_adapter, language_server) =
1214            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1215
1216        if let Some(locations) = locations {
1217            for lsp_location in locations {
1218                let target_buffer_handle = lsp_store
1219                    .update(&mut cx, |lsp_store, cx| {
1220                        lsp_store.open_local_buffer_via_lsp(
1221                            lsp_location.uri,
1222                            language_server.server_id(),
1223                            lsp_adapter.name.clone(),
1224                            cx,
1225                        )
1226                    })?
1227                    .await?;
1228
1229                target_buffer_handle
1230                    .clone()
1231                    .update(&mut cx, |target_buffer, _| {
1232                        let target_start = target_buffer
1233                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
1234                        let target_end = target_buffer
1235                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
1236                        references.push(Location {
1237                            buffer: target_buffer_handle,
1238                            range: target_buffer.anchor_after(target_start)
1239                                ..target_buffer.anchor_before(target_end),
1240                        });
1241                    })?;
1242            }
1243        }
1244
1245        Ok(references)
1246    }
1247
1248    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetReferences {
1249        proto::GetReferences {
1250            project_id,
1251            buffer_id: buffer.remote_id().into(),
1252            position: Some(language::proto::serialize_anchor(
1253                &buffer.anchor_before(self.position),
1254            )),
1255            version: serialize_version(&buffer.version()),
1256        }
1257    }
1258
1259    async fn from_proto(
1260        message: proto::GetReferences,
1261        _: Entity<LspStore>,
1262        buffer: Entity<Buffer>,
1263        mut cx: AsyncApp,
1264    ) -> Result<Self> {
1265        let position = message
1266            .position
1267            .and_then(deserialize_anchor)
1268            .ok_or_else(|| anyhow!("invalid position"))?;
1269        buffer
1270            .update(&mut cx, |buffer, _| {
1271                buffer.wait_for_version(deserialize_version(&message.version))
1272            })?
1273            .await?;
1274        Ok(Self {
1275            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
1276        })
1277    }
1278
1279    fn response_to_proto(
1280        response: Vec<Location>,
1281        lsp_store: &mut LspStore,
1282        peer_id: PeerId,
1283        _: &clock::Global,
1284        cx: &mut App,
1285    ) -> proto::GetReferencesResponse {
1286        let locations = response
1287            .into_iter()
1288            .map(|definition| {
1289                lsp_store
1290                    .buffer_store()
1291                    .update(cx, |buffer_store, cx| {
1292                        buffer_store.create_buffer_for_peer(&definition.buffer, peer_id, cx)
1293                    })
1294                    .detach_and_log_err(cx);
1295                let buffer_id = definition.buffer.read(cx).remote_id();
1296                proto::Location {
1297                    start: Some(serialize_anchor(&definition.range.start)),
1298                    end: Some(serialize_anchor(&definition.range.end)),
1299                    buffer_id: buffer_id.into(),
1300                }
1301            })
1302            .collect();
1303        proto::GetReferencesResponse { locations }
1304    }
1305
1306    async fn response_from_proto(
1307        self,
1308        message: proto::GetReferencesResponse,
1309        project: Entity<LspStore>,
1310        _: Entity<Buffer>,
1311        mut cx: AsyncApp,
1312    ) -> Result<Vec<Location>> {
1313        let mut locations = Vec::new();
1314        for location in message.locations {
1315            let buffer_id = BufferId::new(location.buffer_id)?;
1316            let target_buffer = project
1317                .update(&mut cx, |this, cx| {
1318                    this.wait_for_remote_buffer(buffer_id, cx)
1319                })?
1320                .await?;
1321            let start = location
1322                .start
1323                .and_then(deserialize_anchor)
1324                .ok_or_else(|| anyhow!("missing target start"))?;
1325            let end = location
1326                .end
1327                .and_then(deserialize_anchor)
1328                .ok_or_else(|| anyhow!("missing target end"))?;
1329            target_buffer
1330                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
1331                .await?;
1332            locations.push(Location {
1333                buffer: target_buffer,
1334                range: start..end,
1335            })
1336        }
1337        Ok(locations)
1338    }
1339
1340    fn buffer_id_from_proto(message: &proto::GetReferences) -> Result<BufferId> {
1341        BufferId::new(message.buffer_id)
1342    }
1343}
1344
1345#[async_trait(?Send)]
1346impl LspCommand for GetDocumentHighlights {
1347    type Response = Vec<DocumentHighlight>;
1348    type LspRequest = lsp::request::DocumentHighlightRequest;
1349    type ProtoRequest = proto::GetDocumentHighlights;
1350
1351    fn display_name(&self) -> &str {
1352        "Get document highlights"
1353    }
1354
1355    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1356        capabilities
1357            .server_capabilities
1358            .document_highlight_provider
1359            .is_some()
1360    }
1361
1362    fn to_lsp(
1363        &self,
1364        path: &Path,
1365        _: &Buffer,
1366        _: &Arc<LanguageServer>,
1367        _: &App,
1368    ) -> Result<lsp::DocumentHighlightParams> {
1369        Ok(lsp::DocumentHighlightParams {
1370            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1371            work_done_progress_params: Default::default(),
1372            partial_result_params: Default::default(),
1373        })
1374    }
1375
1376    async fn response_from_lsp(
1377        self,
1378        lsp_highlights: Option<Vec<lsp::DocumentHighlight>>,
1379        _: Entity<LspStore>,
1380        buffer: Entity<Buffer>,
1381        _: LanguageServerId,
1382        mut cx: AsyncApp,
1383    ) -> Result<Vec<DocumentHighlight>> {
1384        buffer.update(&mut cx, |buffer, _| {
1385            let mut lsp_highlights = lsp_highlights.unwrap_or_default();
1386            lsp_highlights.sort_unstable_by_key(|h| (h.range.start, Reverse(h.range.end)));
1387            lsp_highlights
1388                .into_iter()
1389                .map(|lsp_highlight| {
1390                    let start = buffer
1391                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.start), Bias::Left);
1392                    let end = buffer
1393                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.end), Bias::Left);
1394                    DocumentHighlight {
1395                        range: buffer.anchor_after(start)..buffer.anchor_before(end),
1396                        kind: lsp_highlight
1397                            .kind
1398                            .unwrap_or(lsp::DocumentHighlightKind::READ),
1399                    }
1400                })
1401                .collect()
1402        })
1403    }
1404
1405    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentHighlights {
1406        proto::GetDocumentHighlights {
1407            project_id,
1408            buffer_id: buffer.remote_id().into(),
1409            position: Some(language::proto::serialize_anchor(
1410                &buffer.anchor_before(self.position),
1411            )),
1412            version: serialize_version(&buffer.version()),
1413        }
1414    }
1415
1416    async fn from_proto(
1417        message: proto::GetDocumentHighlights,
1418        _: Entity<LspStore>,
1419        buffer: Entity<Buffer>,
1420        mut cx: AsyncApp,
1421    ) -> Result<Self> {
1422        let position = message
1423            .position
1424            .and_then(deserialize_anchor)
1425            .ok_or_else(|| anyhow!("invalid position"))?;
1426        buffer
1427            .update(&mut cx, |buffer, _| {
1428                buffer.wait_for_version(deserialize_version(&message.version))
1429            })?
1430            .await?;
1431        Ok(Self {
1432            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
1433        })
1434    }
1435
1436    fn response_to_proto(
1437        response: Vec<DocumentHighlight>,
1438        _: &mut LspStore,
1439        _: PeerId,
1440        _: &clock::Global,
1441        _: &mut App,
1442    ) -> proto::GetDocumentHighlightsResponse {
1443        let highlights = response
1444            .into_iter()
1445            .map(|highlight| proto::DocumentHighlight {
1446                start: Some(serialize_anchor(&highlight.range.start)),
1447                end: Some(serialize_anchor(&highlight.range.end)),
1448                kind: match highlight.kind {
1449                    DocumentHighlightKind::TEXT => proto::document_highlight::Kind::Text.into(),
1450                    DocumentHighlightKind::WRITE => proto::document_highlight::Kind::Write.into(),
1451                    DocumentHighlightKind::READ => proto::document_highlight::Kind::Read.into(),
1452                    _ => proto::document_highlight::Kind::Text.into(),
1453                },
1454            })
1455            .collect();
1456        proto::GetDocumentHighlightsResponse { highlights }
1457    }
1458
1459    async fn response_from_proto(
1460        self,
1461        message: proto::GetDocumentHighlightsResponse,
1462        _: Entity<LspStore>,
1463        buffer: Entity<Buffer>,
1464        mut cx: AsyncApp,
1465    ) -> Result<Vec<DocumentHighlight>> {
1466        let mut highlights = Vec::new();
1467        for highlight in message.highlights {
1468            let start = highlight
1469                .start
1470                .and_then(deserialize_anchor)
1471                .ok_or_else(|| anyhow!("missing target start"))?;
1472            let end = highlight
1473                .end
1474                .and_then(deserialize_anchor)
1475                .ok_or_else(|| anyhow!("missing target end"))?;
1476            buffer
1477                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))?
1478                .await?;
1479            let kind = match proto::document_highlight::Kind::from_i32(highlight.kind) {
1480                Some(proto::document_highlight::Kind::Text) => DocumentHighlightKind::TEXT,
1481                Some(proto::document_highlight::Kind::Read) => DocumentHighlightKind::READ,
1482                Some(proto::document_highlight::Kind::Write) => DocumentHighlightKind::WRITE,
1483                None => DocumentHighlightKind::TEXT,
1484            };
1485            highlights.push(DocumentHighlight {
1486                range: start..end,
1487                kind,
1488            });
1489        }
1490        Ok(highlights)
1491    }
1492
1493    fn buffer_id_from_proto(message: &proto::GetDocumentHighlights) -> Result<BufferId> {
1494        BufferId::new(message.buffer_id)
1495    }
1496}
1497
1498#[async_trait(?Send)]
1499impl LspCommand for GetDocumentSymbols {
1500    type Response = Vec<DocumentSymbol>;
1501    type LspRequest = lsp::request::DocumentSymbolRequest;
1502    type ProtoRequest = proto::GetDocumentSymbols;
1503
1504    fn display_name(&self) -> &str {
1505        "Get document symbols"
1506    }
1507
1508    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1509        capabilities
1510            .server_capabilities
1511            .document_symbol_provider
1512            .is_some()
1513    }
1514
1515    fn to_lsp(
1516        &self,
1517        path: &Path,
1518        _: &Buffer,
1519        _: &Arc<LanguageServer>,
1520        _: &App,
1521    ) -> Result<lsp::DocumentSymbolParams> {
1522        Ok(lsp::DocumentSymbolParams {
1523            text_document: make_text_document_identifier(path)?,
1524            work_done_progress_params: Default::default(),
1525            partial_result_params: Default::default(),
1526        })
1527    }
1528
1529    async fn response_from_lsp(
1530        self,
1531        lsp_symbols: Option<lsp::DocumentSymbolResponse>,
1532        _: Entity<LspStore>,
1533        _: Entity<Buffer>,
1534        _: LanguageServerId,
1535        _: AsyncApp,
1536    ) -> Result<Vec<DocumentSymbol>> {
1537        let Some(lsp_symbols) = lsp_symbols else {
1538            return Ok(Vec::new());
1539        };
1540
1541        let symbols: Vec<_> = match lsp_symbols {
1542            lsp::DocumentSymbolResponse::Flat(symbol_information) => symbol_information
1543                .into_iter()
1544                .map(|lsp_symbol| DocumentSymbol {
1545                    name: lsp_symbol.name,
1546                    kind: lsp_symbol.kind,
1547                    range: range_from_lsp(lsp_symbol.location.range),
1548                    selection_range: range_from_lsp(lsp_symbol.location.range),
1549                    children: Vec::new(),
1550                })
1551                .collect(),
1552            lsp::DocumentSymbolResponse::Nested(nested_responses) => {
1553                fn convert_symbol(lsp_symbol: lsp::DocumentSymbol) -> DocumentSymbol {
1554                    DocumentSymbol {
1555                        name: lsp_symbol.name,
1556                        kind: lsp_symbol.kind,
1557                        range: range_from_lsp(lsp_symbol.range),
1558                        selection_range: range_from_lsp(lsp_symbol.selection_range),
1559                        children: lsp_symbol
1560                            .children
1561                            .map(|children| {
1562                                children.into_iter().map(convert_symbol).collect::<Vec<_>>()
1563                            })
1564                            .unwrap_or_default(),
1565                    }
1566                }
1567                nested_responses.into_iter().map(convert_symbol).collect()
1568            }
1569        };
1570        Ok(symbols)
1571    }
1572
1573    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentSymbols {
1574        proto::GetDocumentSymbols {
1575            project_id,
1576            buffer_id: buffer.remote_id().into(),
1577            version: serialize_version(&buffer.version()),
1578        }
1579    }
1580
1581    async fn from_proto(
1582        message: proto::GetDocumentSymbols,
1583        _: Entity<LspStore>,
1584        buffer: Entity<Buffer>,
1585        mut cx: AsyncApp,
1586    ) -> Result<Self> {
1587        buffer
1588            .update(&mut cx, |buffer, _| {
1589                buffer.wait_for_version(deserialize_version(&message.version))
1590            })?
1591            .await?;
1592        Ok(Self)
1593    }
1594
1595    fn response_to_proto(
1596        response: Vec<DocumentSymbol>,
1597        _: &mut LspStore,
1598        _: PeerId,
1599        _: &clock::Global,
1600        _: &mut App,
1601    ) -> proto::GetDocumentSymbolsResponse {
1602        let symbols = response
1603            .into_iter()
1604            .map(|symbol| {
1605                fn convert_symbol_to_proto(symbol: DocumentSymbol) -> proto::DocumentSymbol {
1606                    proto::DocumentSymbol {
1607                        name: symbol.name.clone(),
1608                        kind: unsafe { mem::transmute::<lsp::SymbolKind, i32>(symbol.kind) },
1609                        start: Some(proto::PointUtf16 {
1610                            row: symbol.range.start.0.row,
1611                            column: symbol.range.start.0.column,
1612                        }),
1613                        end: Some(proto::PointUtf16 {
1614                            row: symbol.range.end.0.row,
1615                            column: symbol.range.end.0.column,
1616                        }),
1617                        selection_start: Some(proto::PointUtf16 {
1618                            row: symbol.selection_range.start.0.row,
1619                            column: symbol.selection_range.start.0.column,
1620                        }),
1621                        selection_end: Some(proto::PointUtf16 {
1622                            row: symbol.selection_range.end.0.row,
1623                            column: symbol.selection_range.end.0.column,
1624                        }),
1625                        children: symbol
1626                            .children
1627                            .into_iter()
1628                            .map(convert_symbol_to_proto)
1629                            .collect(),
1630                    }
1631                }
1632                convert_symbol_to_proto(symbol)
1633            })
1634            .collect::<Vec<_>>();
1635
1636        proto::GetDocumentSymbolsResponse { symbols }
1637    }
1638
1639    async fn response_from_proto(
1640        self,
1641        message: proto::GetDocumentSymbolsResponse,
1642        _: Entity<LspStore>,
1643        _: Entity<Buffer>,
1644        _: AsyncApp,
1645    ) -> Result<Vec<DocumentSymbol>> {
1646        let mut symbols = Vec::with_capacity(message.symbols.len());
1647        for serialized_symbol in message.symbols {
1648            fn deserialize_symbol_with_children(
1649                serialized_symbol: proto::DocumentSymbol,
1650            ) -> Result<DocumentSymbol> {
1651                let kind =
1652                    unsafe { mem::transmute::<i32, lsp::SymbolKind>(serialized_symbol.kind) };
1653
1654                let start = serialized_symbol
1655                    .start
1656                    .ok_or_else(|| anyhow!("invalid start"))?;
1657                let end = serialized_symbol
1658                    .end
1659                    .ok_or_else(|| anyhow!("invalid end"))?;
1660
1661                let selection_start = serialized_symbol
1662                    .selection_start
1663                    .ok_or_else(|| anyhow!("invalid selection start"))?;
1664                let selection_end = serialized_symbol
1665                    .selection_end
1666                    .ok_or_else(|| anyhow!("invalid selection end"))?;
1667
1668                Ok(DocumentSymbol {
1669                    name: serialized_symbol.name,
1670                    kind,
1671                    range: Unclipped(PointUtf16::new(start.row, start.column))
1672                        ..Unclipped(PointUtf16::new(end.row, end.column)),
1673                    selection_range: Unclipped(PointUtf16::new(
1674                        selection_start.row,
1675                        selection_start.column,
1676                    ))
1677                        ..Unclipped(PointUtf16::new(selection_end.row, selection_end.column)),
1678                    children: serialized_symbol
1679                        .children
1680                        .into_iter()
1681                        .filter_map(|symbol| deserialize_symbol_with_children(symbol).ok())
1682                        .collect::<Vec<_>>(),
1683                })
1684            }
1685
1686            symbols.push(deserialize_symbol_with_children(serialized_symbol)?);
1687        }
1688
1689        Ok(symbols)
1690    }
1691
1692    fn buffer_id_from_proto(message: &proto::GetDocumentSymbols) -> Result<BufferId> {
1693        BufferId::new(message.buffer_id)
1694    }
1695}
1696
1697#[async_trait(?Send)]
1698impl LspCommand for GetSignatureHelp {
1699    type Response = Option<SignatureHelp>;
1700    type LspRequest = lsp::SignatureHelpRequest;
1701    type ProtoRequest = proto::GetSignatureHelp;
1702
1703    fn display_name(&self) -> &str {
1704        "Get signature help"
1705    }
1706
1707    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1708        capabilities
1709            .server_capabilities
1710            .signature_help_provider
1711            .is_some()
1712    }
1713
1714    fn to_lsp(
1715        &self,
1716        path: &Path,
1717        _: &Buffer,
1718        _: &Arc<LanguageServer>,
1719        _cx: &App,
1720    ) -> Result<lsp::SignatureHelpParams> {
1721        Ok(lsp::SignatureHelpParams {
1722            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1723            context: None,
1724            work_done_progress_params: Default::default(),
1725        })
1726    }
1727
1728    async fn response_from_lsp(
1729        self,
1730        message: Option<lsp::SignatureHelp>,
1731        _: Entity<LspStore>,
1732        _: Entity<Buffer>,
1733        _: LanguageServerId,
1734        _: AsyncApp,
1735    ) -> Result<Self::Response> {
1736        Ok(message.and_then(SignatureHelp::new))
1737    }
1738
1739    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
1740        let offset = buffer.point_utf16_to_offset(self.position);
1741        proto::GetSignatureHelp {
1742            project_id,
1743            buffer_id: buffer.remote_id().to_proto(),
1744            position: Some(serialize_anchor(&buffer.anchor_after(offset))),
1745            version: serialize_version(&buffer.version()),
1746        }
1747    }
1748
1749    async fn from_proto(
1750        payload: Self::ProtoRequest,
1751        _: Entity<LspStore>,
1752        buffer: Entity<Buffer>,
1753        mut cx: AsyncApp,
1754    ) -> Result<Self> {
1755        buffer
1756            .update(&mut cx, |buffer, _| {
1757                buffer.wait_for_version(deserialize_version(&payload.version))
1758            })?
1759            .await
1760            .with_context(|| format!("waiting for version for buffer {}", buffer.entity_id()))?;
1761        let buffer_snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot())?;
1762        Ok(Self {
1763            position: payload
1764                .position
1765                .and_then(deserialize_anchor)
1766                .context("invalid position")?
1767                .to_point_utf16(&buffer_snapshot),
1768        })
1769    }
1770
1771    fn response_to_proto(
1772        response: Self::Response,
1773        _: &mut LspStore,
1774        _: PeerId,
1775        _: &Global,
1776        _: &mut App,
1777    ) -> proto::GetSignatureHelpResponse {
1778        proto::GetSignatureHelpResponse {
1779            signature_help: response
1780                .map(|signature_help| lsp_to_proto_signature(signature_help.original_data)),
1781        }
1782    }
1783
1784    async fn response_from_proto(
1785        self,
1786        response: proto::GetSignatureHelpResponse,
1787        _: Entity<LspStore>,
1788        _: Entity<Buffer>,
1789        _: AsyncApp,
1790    ) -> Result<Self::Response> {
1791        Ok(response
1792            .signature_help
1793            .map(proto_to_lsp_signature)
1794            .and_then(SignatureHelp::new))
1795    }
1796
1797    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
1798        BufferId::new(message.buffer_id)
1799    }
1800}
1801
1802#[async_trait(?Send)]
1803impl LspCommand for GetHover {
1804    type Response = Option<Hover>;
1805    type LspRequest = lsp::request::HoverRequest;
1806    type ProtoRequest = proto::GetHover;
1807
1808    fn display_name(&self) -> &str {
1809        "Get hover"
1810    }
1811
1812    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1813        match capabilities.server_capabilities.hover_provider {
1814            Some(lsp::HoverProviderCapability::Simple(enabled)) => enabled,
1815            Some(lsp::HoverProviderCapability::Options(_)) => true,
1816            None => false,
1817        }
1818    }
1819
1820    fn to_lsp(
1821        &self,
1822        path: &Path,
1823        _: &Buffer,
1824        _: &Arc<LanguageServer>,
1825        _: &App,
1826    ) -> Result<lsp::HoverParams> {
1827        Ok(lsp::HoverParams {
1828            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1829            work_done_progress_params: Default::default(),
1830        })
1831    }
1832
1833    async fn response_from_lsp(
1834        self,
1835        message: Option<lsp::Hover>,
1836        _: Entity<LspStore>,
1837        buffer: Entity<Buffer>,
1838        _: LanguageServerId,
1839        mut cx: AsyncApp,
1840    ) -> Result<Self::Response> {
1841        let Some(hover) = message else {
1842            return Ok(None);
1843        };
1844
1845        let (language, range) = buffer.update(&mut cx, |buffer, _| {
1846            (
1847                buffer.language().cloned(),
1848                hover.range.map(|range| {
1849                    let token_start =
1850                        buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
1851                    let token_end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
1852                    buffer.anchor_after(token_start)..buffer.anchor_before(token_end)
1853                }),
1854            )
1855        })?;
1856
1857        fn hover_blocks_from_marked_string(marked_string: lsp::MarkedString) -> Option<HoverBlock> {
1858            let block = match marked_string {
1859                lsp::MarkedString::String(content) => HoverBlock {
1860                    text: content,
1861                    kind: HoverBlockKind::Markdown,
1862                },
1863                lsp::MarkedString::LanguageString(lsp::LanguageString { language, value }) => {
1864                    HoverBlock {
1865                        text: value,
1866                        kind: HoverBlockKind::Code { language },
1867                    }
1868                }
1869            };
1870            if block.text.is_empty() {
1871                None
1872            } else {
1873                Some(block)
1874            }
1875        }
1876
1877        let contents = match hover.contents {
1878            lsp::HoverContents::Scalar(marked_string) => {
1879                hover_blocks_from_marked_string(marked_string)
1880                    .into_iter()
1881                    .collect()
1882            }
1883            lsp::HoverContents::Array(marked_strings) => marked_strings
1884                .into_iter()
1885                .filter_map(hover_blocks_from_marked_string)
1886                .collect(),
1887            lsp::HoverContents::Markup(markup_content) => vec![HoverBlock {
1888                text: markup_content.value,
1889                kind: if markup_content.kind == lsp::MarkupKind::Markdown {
1890                    HoverBlockKind::Markdown
1891                } else {
1892                    HoverBlockKind::PlainText
1893                },
1894            }],
1895        };
1896
1897        Ok(Some(Hover {
1898            contents,
1899            range,
1900            language,
1901        }))
1902    }
1903
1904    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
1905        proto::GetHover {
1906            project_id,
1907            buffer_id: buffer.remote_id().into(),
1908            position: Some(language::proto::serialize_anchor(
1909                &buffer.anchor_before(self.position),
1910            )),
1911            version: serialize_version(&buffer.version),
1912        }
1913    }
1914
1915    async fn from_proto(
1916        message: Self::ProtoRequest,
1917        _: Entity<LspStore>,
1918        buffer: Entity<Buffer>,
1919        mut cx: AsyncApp,
1920    ) -> Result<Self> {
1921        let position = message
1922            .position
1923            .and_then(deserialize_anchor)
1924            .ok_or_else(|| anyhow!("invalid position"))?;
1925        buffer
1926            .update(&mut cx, |buffer, _| {
1927                buffer.wait_for_version(deserialize_version(&message.version))
1928            })?
1929            .await?;
1930        Ok(Self {
1931            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
1932        })
1933    }
1934
1935    fn response_to_proto(
1936        response: Self::Response,
1937        _: &mut LspStore,
1938        _: PeerId,
1939        _: &clock::Global,
1940        _: &mut App,
1941    ) -> proto::GetHoverResponse {
1942        if let Some(response) = response {
1943            let (start, end) = if let Some(range) = response.range {
1944                (
1945                    Some(language::proto::serialize_anchor(&range.start)),
1946                    Some(language::proto::serialize_anchor(&range.end)),
1947                )
1948            } else {
1949                (None, None)
1950            };
1951
1952            let contents = response
1953                .contents
1954                .into_iter()
1955                .map(|block| proto::HoverBlock {
1956                    text: block.text,
1957                    is_markdown: block.kind == HoverBlockKind::Markdown,
1958                    language: if let HoverBlockKind::Code { language } = block.kind {
1959                        Some(language)
1960                    } else {
1961                        None
1962                    },
1963                })
1964                .collect();
1965
1966            proto::GetHoverResponse {
1967                start,
1968                end,
1969                contents,
1970            }
1971        } else {
1972            proto::GetHoverResponse {
1973                start: None,
1974                end: None,
1975                contents: Vec::new(),
1976            }
1977        }
1978    }
1979
1980    async fn response_from_proto(
1981        self,
1982        message: proto::GetHoverResponse,
1983        _: Entity<LspStore>,
1984        buffer: Entity<Buffer>,
1985        mut cx: AsyncApp,
1986    ) -> Result<Self::Response> {
1987        let contents: Vec<_> = message
1988            .contents
1989            .into_iter()
1990            .map(|block| HoverBlock {
1991                text: block.text,
1992                kind: if let Some(language) = block.language {
1993                    HoverBlockKind::Code { language }
1994                } else if block.is_markdown {
1995                    HoverBlockKind::Markdown
1996                } else {
1997                    HoverBlockKind::PlainText
1998                },
1999            })
2000            .collect();
2001        if contents.is_empty() {
2002            return Ok(None);
2003        }
2004
2005        let language = buffer.update(&mut cx, |buffer, _| buffer.language().cloned())?;
2006        let range = if let (Some(start), Some(end)) = (message.start, message.end) {
2007            language::proto::deserialize_anchor(start)
2008                .and_then(|start| language::proto::deserialize_anchor(end).map(|end| start..end))
2009        } else {
2010            None
2011        };
2012        if let Some(range) = range.as_ref() {
2013            buffer
2014                .update(&mut cx, |buffer, _| {
2015                    buffer.wait_for_anchors([range.start, range.end])
2016                })?
2017                .await?;
2018        }
2019
2020        Ok(Some(Hover {
2021            contents,
2022            range,
2023            language,
2024        }))
2025    }
2026
2027    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
2028        BufferId::new(message.buffer_id)
2029    }
2030}
2031
2032#[async_trait(?Send)]
2033impl LspCommand for GetCompletions {
2034    type Response = Vec<CoreCompletion>;
2035    type LspRequest = lsp::request::Completion;
2036    type ProtoRequest = proto::GetCompletions;
2037
2038    fn display_name(&self) -> &str {
2039        "Get completion"
2040    }
2041
2042    fn to_lsp(
2043        &self,
2044        path: &Path,
2045        _: &Buffer,
2046        _: &Arc<LanguageServer>,
2047        _: &App,
2048    ) -> Result<lsp::CompletionParams> {
2049        Ok(lsp::CompletionParams {
2050            text_document_position: make_lsp_text_document_position(path, self.position)?,
2051            context: Some(self.context.clone()),
2052            work_done_progress_params: Default::default(),
2053            partial_result_params: Default::default(),
2054        })
2055    }
2056
2057    async fn response_from_lsp(
2058        self,
2059        completions: Option<lsp::CompletionResponse>,
2060        lsp_store: Entity<LspStore>,
2061        buffer: Entity<Buffer>,
2062        server_id: LanguageServerId,
2063        mut cx: AsyncApp,
2064    ) -> Result<Self::Response> {
2065        let mut response_list = None;
2066        let mut completions = if let Some(completions) = completions {
2067            match completions {
2068                lsp::CompletionResponse::Array(completions) => completions,
2069                lsp::CompletionResponse::List(mut list) => {
2070                    let items = std::mem::take(&mut list.items);
2071                    response_list = Some(list);
2072                    items
2073                }
2074            }
2075        } else {
2076            Vec::new()
2077        };
2078
2079        let language_server_adapter = lsp_store
2080            .update(&mut cx, |lsp_store, _| {
2081                lsp_store.language_server_adapter_for_id(server_id)
2082            })?
2083            .with_context(|| format!("no language server with id {server_id}"))?;
2084
2085        let lsp_defaults = response_list
2086            .as_ref()
2087            .and_then(|list| list.item_defaults.clone())
2088            .map(Arc::new);
2089
2090        let mut completion_edits = Vec::new();
2091        buffer.update(&mut cx, |buffer, cx| {
2092            let snapshot = buffer.snapshot();
2093            let clipped_position = buffer.clip_point_utf16(Unclipped(self.position), Bias::Left);
2094
2095            let mut range_for_token = None;
2096            completions.retain(|lsp_completion| {
2097                let lsp_edit = lsp_completion.text_edit.clone().or_else(|| {
2098                    let default_text_edit = lsp_defaults.as_deref()?.edit_range.as_ref()?;
2099                    let new_text = lsp_completion
2100                        .insert_text
2101                        .as_ref()
2102                        .unwrap_or(&lsp_completion.label)
2103                        .clone();
2104                    match default_text_edit {
2105                        CompletionListItemDefaultsEditRange::Range(range) => {
2106                            Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
2107                                range: *range,
2108                                new_text,
2109                            }))
2110                        }
2111                        CompletionListItemDefaultsEditRange::InsertAndReplace {
2112                            insert,
2113                            replace,
2114                        } => Some(lsp::CompletionTextEdit::InsertAndReplace(
2115                            lsp::InsertReplaceEdit {
2116                                new_text,
2117                                insert: *insert,
2118                                replace: *replace,
2119                            },
2120                        )),
2121                    }
2122                });
2123
2124                let edit = match lsp_edit {
2125                    // If the language server provides a range to overwrite, then
2126                    // check that the range is valid.
2127                    Some(completion_text_edit) => {
2128                        let completion_mode = AllLanguageSettings::get_global(cx)
2129                            .defaults
2130                            .completions
2131                            .lsp_insert_mode;
2132
2133                        match parse_completion_text_edit(
2134                            &completion_text_edit,
2135                            &snapshot,
2136                            completion_mode,
2137                        ) {
2138                            Some(edit) => edit,
2139                            None => return false,
2140                        }
2141                    }
2142
2143                    // If the language server does not provide a range, then infer
2144                    // the range based on the syntax tree.
2145                    None => {
2146                        if self.position != clipped_position {
2147                            log::info!("completion out of expected range");
2148                            return false;
2149                        }
2150
2151                        let default_edit_range = lsp_defaults.as_ref().and_then(|lsp_defaults| {
2152                            lsp_defaults
2153                                .edit_range
2154                                .as_ref()
2155                                .and_then(|range| match range {
2156                                    CompletionListItemDefaultsEditRange::Range(r) => Some(r),
2157                                    _ => None,
2158                                })
2159                        });
2160
2161                        let range = if let Some(range) = default_edit_range {
2162                            let range = range_from_lsp(*range);
2163                            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2164                            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2165                            if start != range.start.0 || end != range.end.0 {
2166                                log::info!("completion out of expected range");
2167                                return false;
2168                            }
2169
2170                            snapshot.anchor_before(start)..snapshot.anchor_after(end)
2171                        } else {
2172                            range_for_token
2173                                .get_or_insert_with(|| {
2174                                    let offset = self.position.to_offset(&snapshot);
2175                                    let (range, kind) = snapshot.surrounding_word(offset);
2176                                    let range = if kind == Some(CharKind::Word) {
2177                                        range
2178                                    } else {
2179                                        offset..offset
2180                                    };
2181
2182                                    snapshot.anchor_before(range.start)
2183                                        ..snapshot.anchor_after(range.end)
2184                                })
2185                                .clone()
2186                        };
2187
2188                        // We already know text_edit is None here
2189                        let text = lsp_completion
2190                            .insert_text
2191                            .as_ref()
2192                            .unwrap_or(&lsp_completion.label)
2193                            .clone();
2194                        (range, text)
2195                    }
2196                };
2197
2198                completion_edits.push(edit);
2199                true
2200            });
2201        })?;
2202
2203        language_server_adapter
2204            .process_completions(&mut completions)
2205            .await;
2206
2207        Ok(completions
2208            .into_iter()
2209            .zip(completion_edits)
2210            .map(|(mut lsp_completion, (old_range, mut new_text))| {
2211                LineEnding::normalize(&mut new_text);
2212                if lsp_completion.data.is_none() {
2213                    if let Some(default_data) = lsp_defaults
2214                        .as_ref()
2215                        .and_then(|item_defaults| item_defaults.data.clone())
2216                    {
2217                        // Servers (e.g. JDTLS) prefer unchanged completions, when resolving the items later,
2218                        // so we do not insert the defaults here, but `data` is needed for resolving, so this is an exception.
2219                        lsp_completion.data = Some(default_data);
2220                    }
2221                }
2222                CoreCompletion {
2223                    old_range,
2224                    new_text,
2225                    source: CompletionSource::Lsp {
2226                        server_id,
2227                        lsp_completion: Box::new(lsp_completion),
2228                        lsp_defaults: lsp_defaults.clone(),
2229                        resolved: false,
2230                    },
2231                }
2232            })
2233            .collect())
2234    }
2235
2236    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCompletions {
2237        let anchor = buffer.anchor_after(self.position);
2238        proto::GetCompletions {
2239            project_id,
2240            buffer_id: buffer.remote_id().into(),
2241            position: Some(language::proto::serialize_anchor(&anchor)),
2242            version: serialize_version(&buffer.version()),
2243        }
2244    }
2245
2246    async fn from_proto(
2247        message: proto::GetCompletions,
2248        _: Entity<LspStore>,
2249        buffer: Entity<Buffer>,
2250        mut cx: AsyncApp,
2251    ) -> Result<Self> {
2252        let version = deserialize_version(&message.version);
2253        buffer
2254            .update(&mut cx, |buffer, _| buffer.wait_for_version(version))?
2255            .await?;
2256        let position = message
2257            .position
2258            .and_then(language::proto::deserialize_anchor)
2259            .map(|p| {
2260                buffer.update(&mut cx, |buffer, _| {
2261                    buffer.clip_point_utf16(Unclipped(p.to_point_utf16(buffer)), Bias::Left)
2262                })
2263            })
2264            .ok_or_else(|| anyhow!("invalid position"))??;
2265        Ok(Self {
2266            position,
2267            context: CompletionContext {
2268                trigger_kind: CompletionTriggerKind::INVOKED,
2269                trigger_character: None,
2270            },
2271        })
2272    }
2273
2274    fn response_to_proto(
2275        completions: Vec<CoreCompletion>,
2276        _: &mut LspStore,
2277        _: PeerId,
2278        buffer_version: &clock::Global,
2279        _: &mut App,
2280    ) -> proto::GetCompletionsResponse {
2281        proto::GetCompletionsResponse {
2282            completions: completions
2283                .iter()
2284                .map(LspStore::serialize_completion)
2285                .collect(),
2286            version: serialize_version(buffer_version),
2287        }
2288    }
2289
2290    async fn response_from_proto(
2291        self,
2292        message: proto::GetCompletionsResponse,
2293        _project: Entity<LspStore>,
2294        buffer: Entity<Buffer>,
2295        mut cx: AsyncApp,
2296    ) -> Result<Self::Response> {
2297        buffer
2298            .update(&mut cx, |buffer, _| {
2299                buffer.wait_for_version(deserialize_version(&message.version))
2300            })?
2301            .await?;
2302
2303        message
2304            .completions
2305            .into_iter()
2306            .map(LspStore::deserialize_completion)
2307            .collect()
2308    }
2309
2310    fn buffer_id_from_proto(message: &proto::GetCompletions) -> Result<BufferId> {
2311        BufferId::new(message.buffer_id)
2312    }
2313}
2314
2315pub(crate) fn parse_completion_text_edit(
2316    edit: &lsp::CompletionTextEdit,
2317    snapshot: &BufferSnapshot,
2318    completion_mode: LspInsertMode,
2319) -> Option<(Range<Anchor>, String)> {
2320    match edit {
2321        lsp::CompletionTextEdit::Edit(edit) => {
2322            let range = range_from_lsp(edit.range);
2323            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2324            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2325            if start != range.start.0 || end != range.end.0 {
2326                log::info!("completion out of expected range");
2327                None
2328            } else {
2329                Some((
2330                    snapshot.anchor_before(start)..snapshot.anchor_after(end),
2331                    edit.new_text.clone(),
2332                ))
2333            }
2334        }
2335
2336        lsp::CompletionTextEdit::InsertAndReplace(edit) => {
2337            let replace = match completion_mode {
2338                LspInsertMode::Insert => false,
2339                LspInsertMode::Replace => true,
2340                LspInsertMode::ReplaceSubsequence => {
2341                    let range_to_replace = range_from_lsp(edit.replace);
2342
2343                    let start = snapshot.clip_point_utf16(range_to_replace.start, Bias::Left);
2344                    let end = snapshot.clip_point_utf16(range_to_replace.end, Bias::Left);
2345                    if start != range_to_replace.start.0 || end != range_to_replace.end.0 {
2346                        false
2347                    } else {
2348                        let mut completion_text = edit.new_text.chars();
2349
2350                        let mut text_to_replace = snapshot.chars_for_range(
2351                            snapshot.anchor_before(start)..snapshot.anchor_after(end),
2352                        );
2353
2354                        // is `text_to_replace` a subsequence of `completion_text`
2355                        text_to_replace.all(|needle_ch| {
2356                            completion_text.any(|haystack_ch| haystack_ch == needle_ch)
2357                        })
2358                    }
2359                }
2360                LspInsertMode::ReplaceSuffix => {
2361                    let range_after_cursor = lsp::Range {
2362                        start: edit.insert.end,
2363                        end: edit.replace.end,
2364                    };
2365                    let range_after_cursor = range_from_lsp(range_after_cursor);
2366
2367                    let start = snapshot.clip_point_utf16(range_after_cursor.start, Bias::Left);
2368                    let end = snapshot.clip_point_utf16(range_after_cursor.end, Bias::Left);
2369                    if start != range_after_cursor.start.0 || end != range_after_cursor.end.0 {
2370                        false
2371                    } else {
2372                        let text_after_cursor = snapshot
2373                            .text_for_range(
2374                                snapshot.anchor_before(start)..snapshot.anchor_after(end),
2375                            )
2376                            .collect::<String>();
2377                        edit.new_text.ends_with(&text_after_cursor)
2378                    }
2379                }
2380            };
2381
2382            let range = range_from_lsp(match replace {
2383                true => edit.replace,
2384                false => edit.insert,
2385            });
2386
2387            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2388            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2389            if start != range.start.0 || end != range.end.0 {
2390                log::info!("completion out of expected range");
2391                None
2392            } else {
2393                Some((
2394                    snapshot.anchor_before(start)..snapshot.anchor_after(end),
2395                    edit.new_text.clone(),
2396                ))
2397            }
2398        }
2399    }
2400}
2401
2402#[async_trait(?Send)]
2403impl LspCommand for GetCodeActions {
2404    type Response = Vec<CodeAction>;
2405    type LspRequest = lsp::request::CodeActionRequest;
2406    type ProtoRequest = proto::GetCodeActions;
2407
2408    fn display_name(&self) -> &str {
2409        "Get code actions"
2410    }
2411
2412    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2413        match &capabilities.server_capabilities.code_action_provider {
2414            None => false,
2415            Some(lsp::CodeActionProviderCapability::Simple(false)) => false,
2416            _ => {
2417                // If we do know that we want specific code actions AND we know that
2418                // the server only supports specific code actions, then we want to filter
2419                // down to the ones that are supported.
2420                if let Some((requested, supported)) = self
2421                    .kinds
2422                    .as_ref()
2423                    .zip(Self::supported_code_action_kinds(capabilities))
2424                {
2425                    let server_supported = supported.into_iter().collect::<HashSet<_>>();
2426                    requested.iter().any(|kind| server_supported.contains(kind))
2427                } else {
2428                    true
2429                }
2430            }
2431        }
2432    }
2433
2434    fn to_lsp(
2435        &self,
2436        path: &Path,
2437        buffer: &Buffer,
2438        language_server: &Arc<LanguageServer>,
2439        _: &App,
2440    ) -> Result<lsp::CodeActionParams> {
2441        let mut relevant_diagnostics = Vec::new();
2442        for entry in buffer
2443            .snapshot()
2444            .diagnostics_in_range::<_, language::PointUtf16>(self.range.clone(), false)
2445        {
2446            relevant_diagnostics.push(entry.to_lsp_diagnostic_stub()?);
2447        }
2448
2449        let supported =
2450            Self::supported_code_action_kinds(language_server.adapter_server_capabilities());
2451
2452        let only = if let Some(requested) = &self.kinds {
2453            if let Some(supported_kinds) = supported {
2454                let server_supported = supported_kinds.into_iter().collect::<HashSet<_>>();
2455
2456                let filtered = requested
2457                    .iter()
2458                    .filter(|kind| server_supported.contains(kind))
2459                    .cloned()
2460                    .collect();
2461                Some(filtered)
2462            } else {
2463                Some(requested.clone())
2464            }
2465        } else {
2466            supported
2467        };
2468
2469        Ok(lsp::CodeActionParams {
2470            text_document: make_text_document_identifier(path)?,
2471            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
2472            work_done_progress_params: Default::default(),
2473            partial_result_params: Default::default(),
2474            context: lsp::CodeActionContext {
2475                diagnostics: relevant_diagnostics,
2476                only,
2477                ..lsp::CodeActionContext::default()
2478            },
2479        })
2480    }
2481
2482    async fn response_from_lsp(
2483        self,
2484        actions: Option<lsp::CodeActionResponse>,
2485        lsp_store: Entity<LspStore>,
2486        _: Entity<Buffer>,
2487        server_id: LanguageServerId,
2488        cx: AsyncApp,
2489    ) -> Result<Vec<CodeAction>> {
2490        let requested_kinds_set = if let Some(kinds) = self.kinds {
2491            Some(kinds.into_iter().collect::<HashSet<_>>())
2492        } else {
2493            None
2494        };
2495
2496        let language_server = cx.update(|cx| {
2497            lsp_store
2498                .read(cx)
2499                .language_server_for_id(server_id)
2500                .with_context(|| {
2501                    format!("Missing the language server that just returned a response {server_id}")
2502                })
2503        })??;
2504
2505        let server_capabilities = language_server.capabilities();
2506        let available_commands = server_capabilities
2507            .execute_command_provider
2508            .as_ref()
2509            .map(|options| options.commands.as_slice())
2510            .unwrap_or_default();
2511        Ok(actions
2512            .unwrap_or_default()
2513            .into_iter()
2514            .filter_map(|entry| {
2515                let (lsp_action, resolved) = match entry {
2516                    lsp::CodeActionOrCommand::CodeAction(lsp_action) => {
2517                        if let Some(command) = lsp_action.command.as_ref() {
2518                            if !available_commands.contains(&command.command) {
2519                                return None;
2520                            }
2521                        }
2522                        (LspAction::Action(Box::new(lsp_action)), false)
2523                    }
2524                    lsp::CodeActionOrCommand::Command(command) => {
2525                        if available_commands.contains(&command.command) {
2526                            (LspAction::Command(command), true)
2527                        } else {
2528                            return None;
2529                        }
2530                    }
2531                };
2532
2533                if let Some((requested_kinds, kind)) =
2534                    requested_kinds_set.as_ref().zip(lsp_action.action_kind())
2535                {
2536                    if !requested_kinds.contains(&kind) {
2537                        return None;
2538                    }
2539                }
2540
2541                Some(CodeAction {
2542                    server_id,
2543                    range: self.range.clone(),
2544                    lsp_action,
2545                    resolved,
2546                })
2547            })
2548            .collect())
2549    }
2550
2551    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeActions {
2552        proto::GetCodeActions {
2553            project_id,
2554            buffer_id: buffer.remote_id().into(),
2555            start: Some(language::proto::serialize_anchor(&self.range.start)),
2556            end: Some(language::proto::serialize_anchor(&self.range.end)),
2557            version: serialize_version(&buffer.version()),
2558        }
2559    }
2560
2561    async fn from_proto(
2562        message: proto::GetCodeActions,
2563        _: Entity<LspStore>,
2564        buffer: Entity<Buffer>,
2565        mut cx: AsyncApp,
2566    ) -> Result<Self> {
2567        let start = message
2568            .start
2569            .and_then(language::proto::deserialize_anchor)
2570            .ok_or_else(|| anyhow!("invalid start"))?;
2571        let end = message
2572            .end
2573            .and_then(language::proto::deserialize_anchor)
2574            .ok_or_else(|| anyhow!("invalid end"))?;
2575        buffer
2576            .update(&mut cx, |buffer, _| {
2577                buffer.wait_for_version(deserialize_version(&message.version))
2578            })?
2579            .await?;
2580
2581        Ok(Self {
2582            range: start..end,
2583            kinds: None,
2584        })
2585    }
2586
2587    fn response_to_proto(
2588        code_actions: Vec<CodeAction>,
2589        _: &mut LspStore,
2590        _: PeerId,
2591        buffer_version: &clock::Global,
2592        _: &mut App,
2593    ) -> proto::GetCodeActionsResponse {
2594        proto::GetCodeActionsResponse {
2595            actions: code_actions
2596                .iter()
2597                .map(LspStore::serialize_code_action)
2598                .collect(),
2599            version: serialize_version(buffer_version),
2600        }
2601    }
2602
2603    async fn response_from_proto(
2604        self,
2605        message: proto::GetCodeActionsResponse,
2606        _: Entity<LspStore>,
2607        buffer: Entity<Buffer>,
2608        mut cx: AsyncApp,
2609    ) -> Result<Vec<CodeAction>> {
2610        buffer
2611            .update(&mut cx, |buffer, _| {
2612                buffer.wait_for_version(deserialize_version(&message.version))
2613            })?
2614            .await?;
2615        message
2616            .actions
2617            .into_iter()
2618            .map(LspStore::deserialize_code_action)
2619            .collect()
2620    }
2621
2622    fn buffer_id_from_proto(message: &proto::GetCodeActions) -> Result<BufferId> {
2623        BufferId::new(message.buffer_id)
2624    }
2625}
2626
2627impl GetCodeActions {
2628    fn supported_code_action_kinds(
2629        capabilities: AdapterServerCapabilities,
2630    ) -> Option<Vec<CodeActionKind>> {
2631        match capabilities.server_capabilities.code_action_provider {
2632            Some(lsp::CodeActionProviderCapability::Options(CodeActionOptions {
2633                code_action_kinds: Some(supported_action_kinds),
2634                ..
2635            })) => Some(supported_action_kinds.clone()),
2636            _ => capabilities.code_action_kinds,
2637        }
2638    }
2639
2640    pub fn can_resolve_actions(capabilities: &ServerCapabilities) -> bool {
2641        capabilities
2642            .code_action_provider
2643            .as_ref()
2644            .and_then(|options| match options {
2645                lsp::CodeActionProviderCapability::Simple(_is_supported) => None,
2646                lsp::CodeActionProviderCapability::Options(options) => options.resolve_provider,
2647            })
2648            .unwrap_or(false)
2649    }
2650}
2651
2652#[async_trait(?Send)]
2653impl LspCommand for OnTypeFormatting {
2654    type Response = Option<Transaction>;
2655    type LspRequest = lsp::request::OnTypeFormatting;
2656    type ProtoRequest = proto::OnTypeFormatting;
2657
2658    fn display_name(&self) -> &str {
2659        "Formatting on typing"
2660    }
2661
2662    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2663        let Some(on_type_formatting_options) = &capabilities
2664            .server_capabilities
2665            .document_on_type_formatting_provider
2666        else {
2667            return false;
2668        };
2669        on_type_formatting_options
2670            .first_trigger_character
2671            .contains(&self.trigger)
2672            || on_type_formatting_options
2673                .more_trigger_character
2674                .iter()
2675                .flatten()
2676                .any(|chars| chars.contains(&self.trigger))
2677    }
2678
2679    fn to_lsp(
2680        &self,
2681        path: &Path,
2682        _: &Buffer,
2683        _: &Arc<LanguageServer>,
2684        _: &App,
2685    ) -> Result<lsp::DocumentOnTypeFormattingParams> {
2686        Ok(lsp::DocumentOnTypeFormattingParams {
2687            text_document_position: make_lsp_text_document_position(path, self.position)?,
2688            ch: self.trigger.clone(),
2689            options: self.options.clone(),
2690        })
2691    }
2692
2693    async fn response_from_lsp(
2694        self,
2695        message: Option<Vec<lsp::TextEdit>>,
2696        lsp_store: Entity<LspStore>,
2697        buffer: Entity<Buffer>,
2698        server_id: LanguageServerId,
2699        mut cx: AsyncApp,
2700    ) -> Result<Option<Transaction>> {
2701        if let Some(edits) = message {
2702            let (lsp_adapter, lsp_server) =
2703                language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
2704            LocalLspStore::deserialize_text_edits(
2705                lsp_store,
2706                buffer,
2707                edits,
2708                self.push_to_history,
2709                lsp_adapter,
2710                lsp_server,
2711                &mut cx,
2712            )
2713            .await
2714        } else {
2715            Ok(None)
2716        }
2717    }
2718
2719    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::OnTypeFormatting {
2720        proto::OnTypeFormatting {
2721            project_id,
2722            buffer_id: buffer.remote_id().into(),
2723            position: Some(language::proto::serialize_anchor(
2724                &buffer.anchor_before(self.position),
2725            )),
2726            trigger: self.trigger.clone(),
2727            version: serialize_version(&buffer.version()),
2728        }
2729    }
2730
2731    async fn from_proto(
2732        message: proto::OnTypeFormatting,
2733        _: Entity<LspStore>,
2734        buffer: Entity<Buffer>,
2735        mut cx: AsyncApp,
2736    ) -> Result<Self> {
2737        let position = message
2738            .position
2739            .and_then(deserialize_anchor)
2740            .ok_or_else(|| anyhow!("invalid position"))?;
2741        buffer
2742            .update(&mut cx, |buffer, _| {
2743                buffer.wait_for_version(deserialize_version(&message.version))
2744            })?
2745            .await?;
2746
2747        let options = buffer.update(&mut cx, |buffer, cx| {
2748            lsp_formatting_options(
2749                language_settings(buffer.language().map(|l| l.name()), buffer.file(), cx).as_ref(),
2750            )
2751        })?;
2752
2753        Ok(Self {
2754            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
2755            trigger: message.trigger.clone(),
2756            options,
2757            push_to_history: false,
2758        })
2759    }
2760
2761    fn response_to_proto(
2762        response: Option<Transaction>,
2763        _: &mut LspStore,
2764        _: PeerId,
2765        _: &clock::Global,
2766        _: &mut App,
2767    ) -> proto::OnTypeFormattingResponse {
2768        proto::OnTypeFormattingResponse {
2769            transaction: response
2770                .map(|transaction| language::proto::serialize_transaction(&transaction)),
2771        }
2772    }
2773
2774    async fn response_from_proto(
2775        self,
2776        message: proto::OnTypeFormattingResponse,
2777        _: Entity<LspStore>,
2778        _: Entity<Buffer>,
2779        _: AsyncApp,
2780    ) -> Result<Option<Transaction>> {
2781        let Some(transaction) = message.transaction else {
2782            return Ok(None);
2783        };
2784        Ok(Some(language::proto::deserialize_transaction(transaction)?))
2785    }
2786
2787    fn buffer_id_from_proto(message: &proto::OnTypeFormatting) -> Result<BufferId> {
2788        BufferId::new(message.buffer_id)
2789    }
2790}
2791
2792impl InlayHints {
2793    pub async fn lsp_to_project_hint(
2794        lsp_hint: lsp::InlayHint,
2795        buffer_handle: &Entity<Buffer>,
2796        server_id: LanguageServerId,
2797        resolve_state: ResolveState,
2798        force_no_type_left_padding: bool,
2799        cx: &mut AsyncApp,
2800    ) -> anyhow::Result<InlayHint> {
2801        let kind = lsp_hint.kind.and_then(|kind| match kind {
2802            lsp::InlayHintKind::TYPE => Some(InlayHintKind::Type),
2803            lsp::InlayHintKind::PARAMETER => Some(InlayHintKind::Parameter),
2804            _ => None,
2805        });
2806
2807        let position = buffer_handle.update(cx, |buffer, _| {
2808            let position = buffer.clip_point_utf16(point_from_lsp(lsp_hint.position), Bias::Left);
2809            if kind == Some(InlayHintKind::Parameter) {
2810                buffer.anchor_before(position)
2811            } else {
2812                buffer.anchor_after(position)
2813            }
2814        })?;
2815        let label = Self::lsp_inlay_label_to_project(lsp_hint.label, server_id)
2816            .await
2817            .context("lsp to project inlay hint conversion")?;
2818        let padding_left = if force_no_type_left_padding && kind == Some(InlayHintKind::Type) {
2819            false
2820        } else {
2821            lsp_hint.padding_left.unwrap_or(false)
2822        };
2823
2824        Ok(InlayHint {
2825            position,
2826            padding_left,
2827            padding_right: lsp_hint.padding_right.unwrap_or(false),
2828            label,
2829            kind,
2830            tooltip: lsp_hint.tooltip.map(|tooltip| match tooltip {
2831                lsp::InlayHintTooltip::String(s) => InlayHintTooltip::String(s),
2832                lsp::InlayHintTooltip::MarkupContent(markup_content) => {
2833                    InlayHintTooltip::MarkupContent(MarkupContent {
2834                        kind: match markup_content.kind {
2835                            lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
2836                            lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
2837                        },
2838                        value: markup_content.value,
2839                    })
2840                }
2841            }),
2842            resolve_state,
2843        })
2844    }
2845
2846    async fn lsp_inlay_label_to_project(
2847        lsp_label: lsp::InlayHintLabel,
2848        server_id: LanguageServerId,
2849    ) -> anyhow::Result<InlayHintLabel> {
2850        let label = match lsp_label {
2851            lsp::InlayHintLabel::String(s) => InlayHintLabel::String(s),
2852            lsp::InlayHintLabel::LabelParts(lsp_parts) => {
2853                let mut parts = Vec::with_capacity(lsp_parts.len());
2854                for lsp_part in lsp_parts {
2855                    parts.push(InlayHintLabelPart {
2856                        value: lsp_part.value,
2857                        tooltip: lsp_part.tooltip.map(|tooltip| match tooltip {
2858                            lsp::InlayHintLabelPartTooltip::String(s) => {
2859                                InlayHintLabelPartTooltip::String(s)
2860                            }
2861                            lsp::InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
2862                                InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
2863                                    kind: match markup_content.kind {
2864                                        lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
2865                                        lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
2866                                    },
2867                                    value: markup_content.value,
2868                                })
2869                            }
2870                        }),
2871                        location: Some(server_id).zip(lsp_part.location),
2872                    });
2873                }
2874                InlayHintLabel::LabelParts(parts)
2875            }
2876        };
2877
2878        Ok(label)
2879    }
2880
2881    pub fn project_to_proto_hint(response_hint: InlayHint) -> proto::InlayHint {
2882        let (state, lsp_resolve_state) = match response_hint.resolve_state {
2883            ResolveState::Resolved => (0, None),
2884            ResolveState::CanResolve(server_id, resolve_data) => (
2885                1,
2886                Some(proto::resolve_state::LspResolveState {
2887                    server_id: server_id.0 as u64,
2888                    value: resolve_data.map(|json_data| {
2889                        serde_json::to_string(&json_data)
2890                            .expect("failed to serialize resolve json data")
2891                    }),
2892                }),
2893            ),
2894            ResolveState::Resolving => (2, None),
2895        };
2896        let resolve_state = Some(proto::ResolveState {
2897            state,
2898            lsp_resolve_state,
2899        });
2900        proto::InlayHint {
2901            position: Some(language::proto::serialize_anchor(&response_hint.position)),
2902            padding_left: response_hint.padding_left,
2903            padding_right: response_hint.padding_right,
2904            label: Some(proto::InlayHintLabel {
2905                label: Some(match response_hint.label {
2906                    InlayHintLabel::String(s) => proto::inlay_hint_label::Label::Value(s),
2907                    InlayHintLabel::LabelParts(label_parts) => {
2908                        proto::inlay_hint_label::Label::LabelParts(proto::InlayHintLabelParts {
2909                            parts: label_parts.into_iter().map(|label_part| {
2910                                let location_url = label_part.location.as_ref().map(|(_, location)| location.uri.to_string());
2911                                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 });
2912                                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 });
2913                                proto::InlayHintLabelPart {
2914                                value: label_part.value,
2915                                tooltip: label_part.tooltip.map(|tooltip| {
2916                                    let proto_tooltip = match tooltip {
2917                                        InlayHintLabelPartTooltip::String(s) => proto::inlay_hint_label_part_tooltip::Content::Value(s),
2918                                        InlayHintLabelPartTooltip::MarkupContent(markup_content) => proto::inlay_hint_label_part_tooltip::Content::MarkupContent(proto::MarkupContent {
2919                                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
2920                                            value: markup_content.value,
2921                                        }),
2922                                    };
2923                                    proto::InlayHintLabelPartTooltip {content: Some(proto_tooltip)}
2924                                }),
2925                                location_url,
2926                                location_range_start,
2927                                location_range_end,
2928                                language_server_id: label_part.location.as_ref().map(|(server_id, _)| server_id.0 as u64),
2929                            }}).collect()
2930                        })
2931                    }
2932                }),
2933            }),
2934            kind: response_hint.kind.map(|kind| kind.name().to_string()),
2935            tooltip: response_hint.tooltip.map(|response_tooltip| {
2936                let proto_tooltip = match response_tooltip {
2937                    InlayHintTooltip::String(s) => proto::inlay_hint_tooltip::Content::Value(s),
2938                    InlayHintTooltip::MarkupContent(markup_content) => {
2939                        proto::inlay_hint_tooltip::Content::MarkupContent(proto::MarkupContent {
2940                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
2941                            value: markup_content.value,
2942                        })
2943                    }
2944                };
2945                proto::InlayHintTooltip {
2946                    content: Some(proto_tooltip),
2947                }
2948            }),
2949            resolve_state,
2950        }
2951    }
2952
2953    pub fn proto_to_project_hint(message_hint: proto::InlayHint) -> anyhow::Result<InlayHint> {
2954        let resolve_state = message_hint.resolve_state.as_ref().unwrap_or_else(|| {
2955            panic!("incorrect proto inlay hint message: no resolve state in hint {message_hint:?}",)
2956        });
2957        let resolve_state_data = resolve_state
2958            .lsp_resolve_state.as_ref()
2959            .map(|lsp_resolve_state| {
2960                let value = lsp_resolve_state.value.as_deref().map(|value| {
2961                    serde_json::from_str::<Option<lsp::LSPAny>>(value)
2962                        .with_context(|| format!("incorrect proto inlay hint message: non-json resolve state {lsp_resolve_state:?}"))
2963                }).transpose()?.flatten();
2964                anyhow::Ok((LanguageServerId(lsp_resolve_state.server_id as usize), value))
2965            })
2966            .transpose()?;
2967        let resolve_state = match resolve_state.state {
2968            0 => ResolveState::Resolved,
2969            1 => {
2970                let (server_id, lsp_resolve_state) = resolve_state_data.with_context(|| {
2971                    format!(
2972                        "No lsp resolve data for the hint that can be resolved: {message_hint:?}"
2973                    )
2974                })?;
2975                ResolveState::CanResolve(server_id, lsp_resolve_state)
2976            }
2977            2 => ResolveState::Resolving,
2978            invalid => {
2979                anyhow::bail!("Unexpected resolve state {invalid} for hint {message_hint:?}")
2980            }
2981        };
2982        Ok(InlayHint {
2983            position: message_hint
2984                .position
2985                .and_then(language::proto::deserialize_anchor)
2986                .context("invalid position")?,
2987            label: match message_hint
2988                .label
2989                .and_then(|label| label.label)
2990                .context("missing label")?
2991            {
2992                proto::inlay_hint_label::Label::Value(s) => InlayHintLabel::String(s),
2993                proto::inlay_hint_label::Label::LabelParts(parts) => {
2994                    let mut label_parts = Vec::new();
2995                    for part in parts.parts {
2996                        label_parts.push(InlayHintLabelPart {
2997                            value: part.value,
2998                            tooltip: part.tooltip.map(|tooltip| match tooltip.content {
2999                                Some(proto::inlay_hint_label_part_tooltip::Content::Value(s)) => {
3000                                    InlayHintLabelPartTooltip::String(s)
3001                                }
3002                                Some(
3003                                    proto::inlay_hint_label_part_tooltip::Content::MarkupContent(
3004                                        markup_content,
3005                                    ),
3006                                ) => InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
3007                                    kind: if markup_content.is_markdown {
3008                                        HoverBlockKind::Markdown
3009                                    } else {
3010                                        HoverBlockKind::PlainText
3011                                    },
3012                                    value: markup_content.value,
3013                                }),
3014                                None => InlayHintLabelPartTooltip::String(String::new()),
3015                            }),
3016                            location: {
3017                                match part
3018                                    .location_url
3019                                    .zip(
3020                                        part.location_range_start.and_then(|start| {
3021                                            Some(start..part.location_range_end?)
3022                                        }),
3023                                    )
3024                                    .zip(part.language_server_id)
3025                                {
3026                                    Some(((uri, range), server_id)) => Some((
3027                                        LanguageServerId(server_id as usize),
3028                                        lsp::Location {
3029                                            uri: lsp::Url::parse(&uri)
3030                                                .context("invalid uri in hint part {part:?}")?,
3031                                            range: lsp::Range::new(
3032                                                point_to_lsp(PointUtf16::new(
3033                                                    range.start.row,
3034                                                    range.start.column,
3035                                                )),
3036                                                point_to_lsp(PointUtf16::new(
3037                                                    range.end.row,
3038                                                    range.end.column,
3039                                                )),
3040                                            ),
3041                                        },
3042                                    )),
3043                                    None => None,
3044                                }
3045                            },
3046                        });
3047                    }
3048
3049                    InlayHintLabel::LabelParts(label_parts)
3050                }
3051            },
3052            padding_left: message_hint.padding_left,
3053            padding_right: message_hint.padding_right,
3054            kind: message_hint
3055                .kind
3056                .as_deref()
3057                .and_then(InlayHintKind::from_name),
3058            tooltip: message_hint.tooltip.and_then(|tooltip| {
3059                Some(match tooltip.content? {
3060                    proto::inlay_hint_tooltip::Content::Value(s) => InlayHintTooltip::String(s),
3061                    proto::inlay_hint_tooltip::Content::MarkupContent(markup_content) => {
3062                        InlayHintTooltip::MarkupContent(MarkupContent {
3063                            kind: if markup_content.is_markdown {
3064                                HoverBlockKind::Markdown
3065                            } else {
3066                                HoverBlockKind::PlainText
3067                            },
3068                            value: markup_content.value,
3069                        })
3070                    }
3071                })
3072            }),
3073            resolve_state,
3074        })
3075    }
3076
3077    pub fn project_to_lsp_hint(hint: InlayHint, snapshot: &BufferSnapshot) -> lsp::InlayHint {
3078        lsp::InlayHint {
3079            position: point_to_lsp(hint.position.to_point_utf16(snapshot)),
3080            kind: hint.kind.map(|kind| match kind {
3081                InlayHintKind::Type => lsp::InlayHintKind::TYPE,
3082                InlayHintKind::Parameter => lsp::InlayHintKind::PARAMETER,
3083            }),
3084            text_edits: None,
3085            tooltip: hint.tooltip.and_then(|tooltip| {
3086                Some(match tooltip {
3087                    InlayHintTooltip::String(s) => lsp::InlayHintTooltip::String(s),
3088                    InlayHintTooltip::MarkupContent(markup_content) => {
3089                        lsp::InlayHintTooltip::MarkupContent(lsp::MarkupContent {
3090                            kind: match markup_content.kind {
3091                                HoverBlockKind::PlainText => lsp::MarkupKind::PlainText,
3092                                HoverBlockKind::Markdown => lsp::MarkupKind::Markdown,
3093                                HoverBlockKind::Code { .. } => return None,
3094                            },
3095                            value: markup_content.value,
3096                        })
3097                    }
3098                })
3099            }),
3100            label: match hint.label {
3101                InlayHintLabel::String(s) => lsp::InlayHintLabel::String(s),
3102                InlayHintLabel::LabelParts(label_parts) => lsp::InlayHintLabel::LabelParts(
3103                    label_parts
3104                        .into_iter()
3105                        .map(|part| lsp::InlayHintLabelPart {
3106                            value: part.value,
3107                            tooltip: part.tooltip.and_then(|tooltip| {
3108                                Some(match tooltip {
3109                                    InlayHintLabelPartTooltip::String(s) => {
3110                                        lsp::InlayHintLabelPartTooltip::String(s)
3111                                    }
3112                                    InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
3113                                        lsp::InlayHintLabelPartTooltip::MarkupContent(
3114                                            lsp::MarkupContent {
3115                                                kind: match markup_content.kind {
3116                                                    HoverBlockKind::PlainText => {
3117                                                        lsp::MarkupKind::PlainText
3118                                                    }
3119                                                    HoverBlockKind::Markdown => {
3120                                                        lsp::MarkupKind::Markdown
3121                                                    }
3122                                                    HoverBlockKind::Code { .. } => return None,
3123                                                },
3124                                                value: markup_content.value,
3125                                            },
3126                                        )
3127                                    }
3128                                })
3129                            }),
3130                            location: part.location.map(|(_, location)| location),
3131                            command: None,
3132                        })
3133                        .collect(),
3134                ),
3135            },
3136            padding_left: Some(hint.padding_left),
3137            padding_right: Some(hint.padding_right),
3138            data: match hint.resolve_state {
3139                ResolveState::CanResolve(_, data) => data,
3140                ResolveState::Resolving | ResolveState::Resolved => None,
3141            },
3142        }
3143    }
3144
3145    pub fn can_resolve_inlays(capabilities: &ServerCapabilities) -> bool {
3146        capabilities
3147            .inlay_hint_provider
3148            .as_ref()
3149            .and_then(|options| match options {
3150                OneOf::Left(_is_supported) => None,
3151                OneOf::Right(capabilities) => match capabilities {
3152                    lsp::InlayHintServerCapabilities::Options(o) => o.resolve_provider,
3153                    lsp::InlayHintServerCapabilities::RegistrationOptions(o) => {
3154                        o.inlay_hint_options.resolve_provider
3155                    }
3156                },
3157            })
3158            .unwrap_or(false)
3159    }
3160}
3161
3162#[async_trait(?Send)]
3163impl LspCommand for InlayHints {
3164    type Response = Vec<InlayHint>;
3165    type LspRequest = lsp::InlayHintRequest;
3166    type ProtoRequest = proto::InlayHints;
3167
3168    fn display_name(&self) -> &str {
3169        "Inlay hints"
3170    }
3171
3172    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3173        let Some(inlay_hint_provider) = &capabilities.server_capabilities.inlay_hint_provider
3174        else {
3175            return false;
3176        };
3177        match inlay_hint_provider {
3178            lsp::OneOf::Left(enabled) => *enabled,
3179            lsp::OneOf::Right(inlay_hint_capabilities) => match inlay_hint_capabilities {
3180                lsp::InlayHintServerCapabilities::Options(_) => true,
3181                lsp::InlayHintServerCapabilities::RegistrationOptions(_) => false,
3182            },
3183        }
3184    }
3185
3186    fn to_lsp(
3187        &self,
3188        path: &Path,
3189        buffer: &Buffer,
3190        _: &Arc<LanguageServer>,
3191        _: &App,
3192    ) -> Result<lsp::InlayHintParams> {
3193        Ok(lsp::InlayHintParams {
3194            text_document: lsp::TextDocumentIdentifier {
3195                uri: file_path_to_lsp_url(path)?,
3196            },
3197            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
3198            work_done_progress_params: Default::default(),
3199        })
3200    }
3201
3202    async fn response_from_lsp(
3203        self,
3204        message: Option<Vec<lsp::InlayHint>>,
3205        lsp_store: Entity<LspStore>,
3206        buffer: Entity<Buffer>,
3207        server_id: LanguageServerId,
3208        mut cx: AsyncApp,
3209    ) -> anyhow::Result<Vec<InlayHint>> {
3210        let (lsp_adapter, lsp_server) =
3211            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
3212        // `typescript-language-server` adds padding to the left for type hints, turning
3213        // `const foo: boolean` into `const foo : boolean` which looks odd.
3214        // `rust-analyzer` does not have the padding for this case, and we have to accommodate both.
3215        //
3216        // We could trim the whole string, but being pessimistic on par with the situation above,
3217        // there might be a hint with multiple whitespaces at the end(s) which we need to display properly.
3218        // Hence let's use a heuristic first to handle the most awkward case and look for more.
3219        let force_no_type_left_padding =
3220            lsp_adapter.name.0.as_ref() == "typescript-language-server";
3221
3222        let hints = message.unwrap_or_default().into_iter().map(|lsp_hint| {
3223            let resolve_state = if InlayHints::can_resolve_inlays(&lsp_server.capabilities()) {
3224                ResolveState::CanResolve(lsp_server.server_id(), lsp_hint.data.clone())
3225            } else {
3226                ResolveState::Resolved
3227            };
3228
3229            let buffer = buffer.clone();
3230            cx.spawn(async move |cx| {
3231                InlayHints::lsp_to_project_hint(
3232                    lsp_hint,
3233                    &buffer,
3234                    server_id,
3235                    resolve_state,
3236                    force_no_type_left_padding,
3237                    cx,
3238                )
3239                .await
3240            })
3241        });
3242        future::join_all(hints)
3243            .await
3244            .into_iter()
3245            .collect::<anyhow::Result<_>>()
3246            .context("lsp to project inlay hints conversion")
3247    }
3248
3249    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::InlayHints {
3250        proto::InlayHints {
3251            project_id,
3252            buffer_id: buffer.remote_id().into(),
3253            start: Some(language::proto::serialize_anchor(&self.range.start)),
3254            end: Some(language::proto::serialize_anchor(&self.range.end)),
3255            version: serialize_version(&buffer.version()),
3256        }
3257    }
3258
3259    async fn from_proto(
3260        message: proto::InlayHints,
3261        _: Entity<LspStore>,
3262        buffer: Entity<Buffer>,
3263        mut cx: AsyncApp,
3264    ) -> Result<Self> {
3265        let start = message
3266            .start
3267            .and_then(language::proto::deserialize_anchor)
3268            .context("invalid start")?;
3269        let end = message
3270            .end
3271            .and_then(language::proto::deserialize_anchor)
3272            .context("invalid end")?;
3273        buffer
3274            .update(&mut cx, |buffer, _| {
3275                buffer.wait_for_version(deserialize_version(&message.version))
3276            })?
3277            .await?;
3278
3279        Ok(Self { range: start..end })
3280    }
3281
3282    fn response_to_proto(
3283        response: Vec<InlayHint>,
3284        _: &mut LspStore,
3285        _: PeerId,
3286        buffer_version: &clock::Global,
3287        _: &mut App,
3288    ) -> proto::InlayHintsResponse {
3289        proto::InlayHintsResponse {
3290            hints: response
3291                .into_iter()
3292                .map(InlayHints::project_to_proto_hint)
3293                .collect(),
3294            version: serialize_version(buffer_version),
3295        }
3296    }
3297
3298    async fn response_from_proto(
3299        self,
3300        message: proto::InlayHintsResponse,
3301        _: Entity<LspStore>,
3302        buffer: Entity<Buffer>,
3303        mut cx: AsyncApp,
3304    ) -> anyhow::Result<Vec<InlayHint>> {
3305        buffer
3306            .update(&mut cx, |buffer, _| {
3307                buffer.wait_for_version(deserialize_version(&message.version))
3308            })?
3309            .await?;
3310
3311        let mut hints = Vec::new();
3312        for message_hint in message.hints {
3313            hints.push(InlayHints::proto_to_project_hint(message_hint)?);
3314        }
3315
3316        Ok(hints)
3317    }
3318
3319    fn buffer_id_from_proto(message: &proto::InlayHints) -> Result<BufferId> {
3320        BufferId::new(message.buffer_id)
3321    }
3322}
3323
3324#[async_trait(?Send)]
3325impl LspCommand for GetCodeLens {
3326    type Response = Vec<CodeAction>;
3327    type LspRequest = lsp::CodeLensRequest;
3328    type ProtoRequest = proto::GetCodeLens;
3329
3330    fn display_name(&self) -> &str {
3331        "Code Lens"
3332    }
3333
3334    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3335        capabilities
3336            .server_capabilities
3337            .code_lens_provider
3338            .as_ref()
3339            .map_or(false, |code_lens_options| {
3340                code_lens_options.resolve_provider.unwrap_or(false)
3341            })
3342    }
3343
3344    fn to_lsp(
3345        &self,
3346        path: &Path,
3347        _: &Buffer,
3348        _: &Arc<LanguageServer>,
3349        _: &App,
3350    ) -> Result<lsp::CodeLensParams> {
3351        Ok(lsp::CodeLensParams {
3352            text_document: lsp::TextDocumentIdentifier {
3353                uri: file_path_to_lsp_url(path)?,
3354            },
3355            work_done_progress_params: lsp::WorkDoneProgressParams::default(),
3356            partial_result_params: lsp::PartialResultParams::default(),
3357        })
3358    }
3359
3360    async fn response_from_lsp(
3361        self,
3362        message: Option<Vec<lsp::CodeLens>>,
3363        lsp_store: Entity<LspStore>,
3364        buffer: Entity<Buffer>,
3365        server_id: LanguageServerId,
3366        mut cx: AsyncApp,
3367    ) -> anyhow::Result<Vec<CodeAction>> {
3368        let snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot())?;
3369        let language_server = cx.update(|cx| {
3370            lsp_store
3371                .read(cx)
3372                .language_server_for_id(server_id)
3373                .with_context(|| {
3374                    format!("Missing the language server that just returned a response {server_id}")
3375                })
3376        })??;
3377        let server_capabilities = language_server.capabilities();
3378        let available_commands = server_capabilities
3379            .execute_command_provider
3380            .as_ref()
3381            .map(|options| options.commands.as_slice())
3382            .unwrap_or_default();
3383        Ok(message
3384            .unwrap_or_default()
3385            .into_iter()
3386            .filter(|code_lens| {
3387                code_lens
3388                    .command
3389                    .as_ref()
3390                    .is_none_or(|command| available_commands.contains(&command.command))
3391            })
3392            .map(|code_lens| {
3393                let code_lens_range = range_from_lsp(code_lens.range);
3394                let start = snapshot.clip_point_utf16(code_lens_range.start, Bias::Left);
3395                let end = snapshot.clip_point_utf16(code_lens_range.end, Bias::Right);
3396                let range = snapshot.anchor_before(start)..snapshot.anchor_after(end);
3397                CodeAction {
3398                    server_id,
3399                    range,
3400                    lsp_action: LspAction::CodeLens(code_lens),
3401                    resolved: false,
3402                }
3403            })
3404            .collect())
3405    }
3406
3407    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeLens {
3408        proto::GetCodeLens {
3409            project_id,
3410            buffer_id: buffer.remote_id().into(),
3411            version: serialize_version(&buffer.version()),
3412        }
3413    }
3414
3415    async fn from_proto(
3416        message: proto::GetCodeLens,
3417        _: Entity<LspStore>,
3418        buffer: Entity<Buffer>,
3419        mut cx: AsyncApp,
3420    ) -> Result<Self> {
3421        buffer
3422            .update(&mut cx, |buffer, _| {
3423                buffer.wait_for_version(deserialize_version(&message.version))
3424            })?
3425            .await?;
3426        Ok(Self)
3427    }
3428
3429    fn response_to_proto(
3430        response: Vec<CodeAction>,
3431        _: &mut LspStore,
3432        _: PeerId,
3433        buffer_version: &clock::Global,
3434        _: &mut App,
3435    ) -> proto::GetCodeLensResponse {
3436        proto::GetCodeLensResponse {
3437            lens_actions: response
3438                .iter()
3439                .map(LspStore::serialize_code_action)
3440                .collect(),
3441            version: serialize_version(buffer_version),
3442        }
3443    }
3444
3445    async fn response_from_proto(
3446        self,
3447        message: proto::GetCodeLensResponse,
3448        _: Entity<LspStore>,
3449        buffer: Entity<Buffer>,
3450        mut cx: AsyncApp,
3451    ) -> anyhow::Result<Vec<CodeAction>> {
3452        buffer
3453            .update(&mut cx, |buffer, _| {
3454                buffer.wait_for_version(deserialize_version(&message.version))
3455            })?
3456            .await?;
3457        message
3458            .lens_actions
3459            .into_iter()
3460            .map(LspStore::deserialize_code_action)
3461            .collect::<Result<Vec<_>>>()
3462            .context("deserializing proto code lens response")
3463    }
3464
3465    fn buffer_id_from_proto(message: &proto::GetCodeLens) -> Result<BufferId> {
3466        BufferId::new(message.buffer_id)
3467    }
3468}
3469
3470#[async_trait(?Send)]
3471impl LspCommand for LinkedEditingRange {
3472    type Response = Vec<Range<Anchor>>;
3473    type LspRequest = lsp::request::LinkedEditingRange;
3474    type ProtoRequest = proto::LinkedEditingRange;
3475
3476    fn display_name(&self) -> &str {
3477        "Linked editing range"
3478    }
3479
3480    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3481        let Some(linked_editing_options) = &capabilities
3482            .server_capabilities
3483            .linked_editing_range_provider
3484        else {
3485            return false;
3486        };
3487        if let LinkedEditingRangeServerCapabilities::Simple(false) = linked_editing_options {
3488            return false;
3489        }
3490        true
3491    }
3492
3493    fn to_lsp(
3494        &self,
3495        path: &Path,
3496        buffer: &Buffer,
3497        _server: &Arc<LanguageServer>,
3498        _: &App,
3499    ) -> Result<lsp::LinkedEditingRangeParams> {
3500        let position = self.position.to_point_utf16(&buffer.snapshot());
3501        Ok(lsp::LinkedEditingRangeParams {
3502            text_document_position_params: make_lsp_text_document_position(path, position)?,
3503            work_done_progress_params: Default::default(),
3504        })
3505    }
3506
3507    async fn response_from_lsp(
3508        self,
3509        message: Option<lsp::LinkedEditingRanges>,
3510        _: Entity<LspStore>,
3511        buffer: Entity<Buffer>,
3512        _server_id: LanguageServerId,
3513        cx: AsyncApp,
3514    ) -> Result<Vec<Range<Anchor>>> {
3515        if let Some(lsp::LinkedEditingRanges { mut ranges, .. }) = message {
3516            ranges.sort_by_key(|range| range.start);
3517
3518            buffer.read_with(&cx, |buffer, _| {
3519                ranges
3520                    .into_iter()
3521                    .map(|range| {
3522                        let start =
3523                            buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
3524                        let end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
3525                        buffer.anchor_before(start)..buffer.anchor_after(end)
3526                    })
3527                    .collect()
3528            })
3529        } else {
3530            Ok(vec![])
3531        }
3532    }
3533
3534    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::LinkedEditingRange {
3535        proto::LinkedEditingRange {
3536            project_id,
3537            buffer_id: buffer.remote_id().to_proto(),
3538            position: Some(serialize_anchor(&self.position)),
3539            version: serialize_version(&buffer.version()),
3540        }
3541    }
3542
3543    async fn from_proto(
3544        message: proto::LinkedEditingRange,
3545        _: Entity<LspStore>,
3546        buffer: Entity<Buffer>,
3547        mut cx: AsyncApp,
3548    ) -> Result<Self> {
3549        let position = message
3550            .position
3551            .ok_or_else(|| anyhow!("invalid position"))?;
3552        buffer
3553            .update(&mut cx, |buffer, _| {
3554                buffer.wait_for_version(deserialize_version(&message.version))
3555            })?
3556            .await?;
3557        let position = deserialize_anchor(position).ok_or_else(|| anyhow!("invalid position"))?;
3558        buffer
3559            .update(&mut cx, |buffer, _| buffer.wait_for_anchors([position]))?
3560            .await?;
3561        Ok(Self { position })
3562    }
3563
3564    fn response_to_proto(
3565        response: Vec<Range<Anchor>>,
3566        _: &mut LspStore,
3567        _: PeerId,
3568        buffer_version: &clock::Global,
3569        _: &mut App,
3570    ) -> proto::LinkedEditingRangeResponse {
3571        proto::LinkedEditingRangeResponse {
3572            items: response
3573                .into_iter()
3574                .map(|range| proto::AnchorRange {
3575                    start: Some(serialize_anchor(&range.start)),
3576                    end: Some(serialize_anchor(&range.end)),
3577                })
3578                .collect(),
3579            version: serialize_version(buffer_version),
3580        }
3581    }
3582
3583    async fn response_from_proto(
3584        self,
3585        message: proto::LinkedEditingRangeResponse,
3586        _: Entity<LspStore>,
3587        buffer: Entity<Buffer>,
3588        mut cx: AsyncApp,
3589    ) -> Result<Vec<Range<Anchor>>> {
3590        buffer
3591            .update(&mut cx, |buffer, _| {
3592                buffer.wait_for_version(deserialize_version(&message.version))
3593            })?
3594            .await?;
3595        let items: Vec<Range<Anchor>> = message
3596            .items
3597            .into_iter()
3598            .filter_map(|range| {
3599                let start = deserialize_anchor(range.start?)?;
3600                let end = deserialize_anchor(range.end?)?;
3601                Some(start..end)
3602            })
3603            .collect();
3604        for range in &items {
3605            buffer
3606                .update(&mut cx, |buffer, _| {
3607                    buffer.wait_for_anchors([range.start, range.end])
3608                })?
3609                .await?;
3610        }
3611        Ok(items)
3612    }
3613
3614    fn buffer_id_from_proto(message: &proto::LinkedEditingRange) -> Result<BufferId> {
3615        BufferId::new(message.buffer_id)
3616    }
3617}