lsp_command.rs

   1pub mod signature_help;
   2
   3use crate::{
   4    CodeAction, CompletionSource, CoreCompletion, CoreCompletionResponse, DocumentColor,
   5    DocumentHighlight, DocumentSymbol, Hover, HoverBlock, HoverBlockKind, InlayHint,
   6    InlayHintLabel, InlayHintLabelPart, InlayHintLabelPartTooltip, InlayHintTooltip, Location,
   7    LocationLink, LspAction, LspPullDiagnostics, MarkupContent, PrepareRenameResponse,
   8    ProjectTransaction, PulledDiagnostics, ResolveState,
   9    lsp_store::{LocalLspStore, LspStore},
  10};
  11use anyhow::{Context as _, Result};
  12use async_trait::async_trait;
  13use client::proto::{self, PeerId};
  14use clock::Global;
  15use collections::HashMap;
  16use futures::future;
  17use gpui::{App, AsyncApp, Entity, SharedString, Task, prelude::FluentBuilder};
  18use language::{
  19    Anchor, Bias, Buffer, BufferSnapshot, CachedLspAdapter, CharKind, CharScopeContext,
  20    OffsetRangeExt, PointUtf16, ToOffset, ToPointUtf16, Transaction, Unclipped,
  21    language_settings::{InlayHintKind, LanguageSettings, language_settings},
  22    point_from_lsp, point_to_lsp,
  23    proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
  24    range_from_lsp, range_to_lsp,
  25};
  26use lsp::{
  27    AdapterServerCapabilities, CodeActionKind, CodeActionOptions, CodeDescription,
  28    CompletionContext, CompletionListItemDefaultsEditRange, CompletionTriggerKind,
  29    DocumentHighlightKind, LanguageServer, LanguageServerId, LinkedEditingRangeServerCapabilities,
  30    OneOf, RenameOptions, ServerCapabilities,
  31};
  32use serde_json::Value;
  33use signature_help::{lsp_to_proto_signature, proto_to_lsp_signature};
  34use std::{
  35    cmp::Reverse, collections::hash_map, mem, ops::Range, path::Path, str::FromStr, sync::Arc,
  36};
  37use text::{BufferId, LineEnding};
  38use util::{ResultExt as _, debug_panic};
  39
  40pub use signature_help::SignatureHelp;
  41
  42fn code_action_kind_matches(requested: &lsp::CodeActionKind, actual: &lsp::CodeActionKind) -> bool {
  43    let requested_str = requested.as_str();
  44    let actual_str = actual.as_str();
  45
  46    // Exact match or hierarchical match
  47    actual_str == requested_str
  48        || actual_str
  49            .strip_prefix(requested_str)
  50            .is_some_and(|suffix| suffix.starts_with('.'))
  51}
  52
  53pub fn lsp_formatting_options(settings: &LanguageSettings) -> lsp::FormattingOptions {
  54    lsp::FormattingOptions {
  55        tab_size: settings.tab_size.into(),
  56        insert_spaces: !settings.hard_tabs,
  57        trim_trailing_whitespace: Some(settings.remove_trailing_whitespace_on_save),
  58        trim_final_newlines: Some(settings.ensure_final_newline_on_save),
  59        insert_final_newline: Some(settings.ensure_final_newline_on_save),
  60        ..lsp::FormattingOptions::default()
  61    }
  62}
  63
  64pub fn file_path_to_lsp_url(path: &Path) -> Result<lsp::Uri> {
  65    match lsp::Uri::from_file_path(path) {
  66        Ok(url) => Ok(url),
  67        Err(()) => anyhow::bail!("Invalid file path provided to LSP request: {path:?}"),
  68    }
  69}
  70
  71pub(crate) fn make_text_document_identifier(path: &Path) -> Result<lsp::TextDocumentIdentifier> {
  72    Ok(lsp::TextDocumentIdentifier {
  73        uri: file_path_to_lsp_url(path)?,
  74    })
  75}
  76
  77pub(crate) fn make_lsp_text_document_position(
  78    path: &Path,
  79    position: PointUtf16,
  80) -> Result<lsp::TextDocumentPositionParams> {
  81    Ok(lsp::TextDocumentPositionParams {
  82        text_document: make_text_document_identifier(path)?,
  83        position: point_to_lsp(position),
  84    })
  85}
  86
  87#[async_trait(?Send)]
  88pub trait LspCommand: 'static + Sized + Send + std::fmt::Debug {
  89    type Response: 'static + Default + Send + std::fmt::Debug;
  90    type LspRequest: 'static + Send + lsp::request::Request;
  91    type ProtoRequest: 'static + Send + proto::RequestMessage;
  92
  93    fn display_name(&self) -> &str;
  94
  95    fn status(&self) -> Option<String> {
  96        None
  97    }
  98
  99    fn to_lsp_params_or_response(
 100        &self,
 101        path: &Path,
 102        buffer: &Buffer,
 103        language_server: &Arc<LanguageServer>,
 104        cx: &App,
 105    ) -> Result<
 106        LspParamsOrResponse<<Self::LspRequest as lsp::request::Request>::Params, Self::Response>,
 107    > {
 108        if self.check_capabilities(language_server.adapter_server_capabilities()) {
 109            Ok(LspParamsOrResponse::Params(self.to_lsp(
 110                path,
 111                buffer,
 112                language_server,
 113                cx,
 114            )?))
 115        } else {
 116            Ok(LspParamsOrResponse::Response(Default::default()))
 117        }
 118    }
 119
 120    /// When false, `to_lsp_params_or_response` default implementation will return the default response.
 121    fn check_capabilities(&self, _: AdapterServerCapabilities) -> bool;
 122
 123    fn to_lsp(
 124        &self,
 125        path: &Path,
 126        buffer: &Buffer,
 127        language_server: &Arc<LanguageServer>,
 128        cx: &App,
 129    ) -> Result<<Self::LspRequest as lsp::request::Request>::Params>;
 130
 131    async fn response_from_lsp(
 132        self,
 133        message: <Self::LspRequest as lsp::request::Request>::Result,
 134        lsp_store: Entity<LspStore>,
 135        buffer: Entity<Buffer>,
 136        server_id: LanguageServerId,
 137        cx: AsyncApp,
 138    ) -> Result<Self::Response>;
 139
 140    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest;
 141
 142    async fn from_proto(
 143        message: Self::ProtoRequest,
 144        lsp_store: Entity<LspStore>,
 145        buffer: Entity<Buffer>,
 146        cx: AsyncApp,
 147    ) -> Result<Self>;
 148
 149    fn response_to_proto(
 150        response: Self::Response,
 151        lsp_store: &mut LspStore,
 152        peer_id: PeerId,
 153        buffer_version: &clock::Global,
 154        cx: &mut App,
 155    ) -> <Self::ProtoRequest as proto::RequestMessage>::Response;
 156
 157    async fn response_from_proto(
 158        self,
 159        message: <Self::ProtoRequest as proto::RequestMessage>::Response,
 160        lsp_store: Entity<LspStore>,
 161        buffer: Entity<Buffer>,
 162        cx: AsyncApp,
 163    ) -> Result<Self::Response>;
 164
 165    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId>;
 166}
 167
 168pub enum LspParamsOrResponse<P, R> {
 169    Params(P),
 170    Response(R),
 171}
 172
 173#[derive(Debug)]
 174pub(crate) struct PrepareRename {
 175    pub position: PointUtf16,
 176}
 177
 178#[derive(Debug)]
 179pub(crate) struct PerformRename {
 180    pub position: PointUtf16,
 181    pub new_name: String,
 182    pub push_to_history: bool,
 183}
 184
 185#[derive(Debug, Clone, Copy)]
 186pub struct GetDefinitions {
 187    pub position: PointUtf16,
 188}
 189
 190#[derive(Debug, Clone, Copy)]
 191pub(crate) struct GetDeclarations {
 192    pub position: PointUtf16,
 193}
 194
 195#[derive(Debug, Clone, Copy)]
 196pub(crate) struct GetTypeDefinitions {
 197    pub position: PointUtf16,
 198}
 199
 200#[derive(Debug, Clone, Copy)]
 201pub(crate) struct GetImplementations {
 202    pub position: PointUtf16,
 203}
 204
 205#[derive(Debug, Clone, Copy)]
 206pub(crate) struct GetReferences {
 207    pub position: PointUtf16,
 208}
 209
 210#[derive(Debug)]
 211pub(crate) struct GetDocumentHighlights {
 212    pub position: PointUtf16,
 213}
 214
 215#[derive(Debug, Copy, Clone)]
 216pub(crate) struct GetDocumentSymbols;
 217
 218#[derive(Clone, Debug)]
 219pub(crate) struct GetSignatureHelp {
 220    pub position: PointUtf16,
 221}
 222
 223#[derive(Clone, Debug)]
 224pub(crate) struct GetHover {
 225    pub position: PointUtf16,
 226}
 227
 228#[derive(Debug)]
 229pub(crate) struct GetCompletions {
 230    pub position: PointUtf16,
 231    pub context: CompletionContext,
 232    pub server_id: Option<lsp::LanguageServerId>,
 233}
 234
 235#[derive(Clone, Debug)]
 236pub(crate) struct GetCodeActions {
 237    pub range: Range<Anchor>,
 238    pub kinds: Option<Vec<lsp::CodeActionKind>>,
 239}
 240
 241#[derive(Debug)]
 242pub(crate) struct OnTypeFormatting {
 243    pub position: PointUtf16,
 244    pub trigger: String,
 245    pub options: lsp::FormattingOptions,
 246    pub push_to_history: bool,
 247}
 248
 249#[derive(Clone, Debug)]
 250pub(crate) struct InlayHints {
 251    pub range: Range<Anchor>,
 252}
 253
 254#[derive(Debug, Clone, Copy)]
 255pub(crate) struct SemanticTokensFull {
 256    pub for_server: Option<LanguageServerId>,
 257}
 258
 259#[derive(Debug, Clone)]
 260pub(crate) struct SemanticTokensDelta {
 261    pub previous_result_id: SharedString,
 262}
 263
 264#[derive(Debug)]
 265pub(crate) enum SemanticTokensResponse {
 266    Full {
 267        data: Vec<u32>,
 268        result_id: Option<SharedString>,
 269    },
 270    Delta {
 271        edits: Vec<SemanticTokensEdit>,
 272        result_id: Option<SharedString>,
 273    },
 274}
 275
 276impl Default for SemanticTokensResponse {
 277    fn default() -> Self {
 278        Self::Delta {
 279            edits: Vec::new(),
 280            result_id: None,
 281        }
 282    }
 283}
 284
 285#[derive(Debug)]
 286pub(crate) struct SemanticTokensEdit {
 287    pub start: u32,
 288    pub delete_count: u32,
 289    pub data: Vec<u32>,
 290}
 291
 292#[derive(Debug, Copy, Clone)]
 293pub(crate) struct GetCodeLens;
 294
 295#[derive(Debug, Copy, Clone)]
 296pub(crate) struct GetDocumentColor;
 297
 298impl GetCodeLens {
 299    pub(crate) fn can_resolve_lens(capabilities: &ServerCapabilities) -> bool {
 300        capabilities
 301            .code_lens_provider
 302            .as_ref()
 303            .and_then(|code_lens_options| code_lens_options.resolve_provider)
 304            .unwrap_or(false)
 305    }
 306}
 307
 308#[derive(Debug)]
 309pub(crate) struct LinkedEditingRange {
 310    pub position: Anchor,
 311}
 312
 313#[derive(Clone, Debug)]
 314pub struct GetDocumentDiagnostics {
 315    /// We cannot blindly rely on server's capabilities.diagnostic_provider, as they're a singular field, whereas
 316    /// a server can register multiple diagnostic providers post-mortem.
 317    pub registration_id: Option<SharedString>,
 318    pub identifier: Option<SharedString>,
 319    pub previous_result_id: Option<SharedString>,
 320}
 321
 322#[async_trait(?Send)]
 323impl LspCommand for PrepareRename {
 324    type Response = PrepareRenameResponse;
 325    type LspRequest = lsp::request::PrepareRenameRequest;
 326    type ProtoRequest = proto::PrepareRename;
 327
 328    fn display_name(&self) -> &str {
 329        "Prepare rename"
 330    }
 331
 332    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 333        capabilities
 334            .server_capabilities
 335            .rename_provider
 336            .is_some_and(|capability| match capability {
 337                OneOf::Left(enabled) => enabled,
 338                OneOf::Right(options) => options.prepare_provider.unwrap_or(false),
 339            })
 340    }
 341
 342    fn to_lsp_params_or_response(
 343        &self,
 344        path: &Path,
 345        buffer: &Buffer,
 346        language_server: &Arc<LanguageServer>,
 347        cx: &App,
 348    ) -> Result<LspParamsOrResponse<lsp::TextDocumentPositionParams, PrepareRenameResponse>> {
 349        let rename_provider = language_server
 350            .adapter_server_capabilities()
 351            .server_capabilities
 352            .rename_provider;
 353        match rename_provider {
 354            Some(lsp::OneOf::Right(RenameOptions {
 355                prepare_provider: Some(true),
 356                ..
 357            })) => Ok(LspParamsOrResponse::Params(self.to_lsp(
 358                path,
 359                buffer,
 360                language_server,
 361                cx,
 362            )?)),
 363            Some(lsp::OneOf::Right(_)) => Ok(LspParamsOrResponse::Response(
 364                PrepareRenameResponse::OnlyUnpreparedRenameSupported,
 365            )),
 366            Some(lsp::OneOf::Left(true)) => Ok(LspParamsOrResponse::Response(
 367                PrepareRenameResponse::OnlyUnpreparedRenameSupported,
 368            )),
 369            _ => anyhow::bail!("Rename not supported"),
 370        }
 371    }
 372
 373    fn to_lsp(
 374        &self,
 375        path: &Path,
 376        _: &Buffer,
 377        _: &Arc<LanguageServer>,
 378        _: &App,
 379    ) -> Result<lsp::TextDocumentPositionParams> {
 380        make_lsp_text_document_position(path, self.position)
 381    }
 382
 383    async fn response_from_lsp(
 384        self,
 385        message: Option<lsp::PrepareRenameResponse>,
 386        _: Entity<LspStore>,
 387        buffer: Entity<Buffer>,
 388        _: LanguageServerId,
 389        cx: AsyncApp,
 390    ) -> Result<PrepareRenameResponse> {
 391        buffer.read_with(&cx, |buffer, _| match message {
 392            Some(lsp::PrepareRenameResponse::Range(range))
 393            | Some(lsp::PrepareRenameResponse::RangeWithPlaceholder { range, .. }) => {
 394                let Range { start, end } = range_from_lsp(range);
 395                if buffer.clip_point_utf16(start, Bias::Left) == start.0
 396                    && buffer.clip_point_utf16(end, Bias::Left) == end.0
 397                {
 398                    Ok(PrepareRenameResponse::Success(
 399                        buffer.anchor_after(start)..buffer.anchor_before(end),
 400                    ))
 401                } else {
 402                    Ok(PrepareRenameResponse::InvalidPosition)
 403                }
 404            }
 405            Some(lsp::PrepareRenameResponse::DefaultBehavior { .. }) => {
 406                let snapshot = buffer.snapshot();
 407                let (range, _) = snapshot.surrounding_word(self.position, None);
 408                let range = snapshot.anchor_after(range.start)..snapshot.anchor_before(range.end);
 409                Ok(PrepareRenameResponse::Success(range))
 410            }
 411            None => Ok(PrepareRenameResponse::InvalidPosition),
 412        })
 413    }
 414
 415    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::PrepareRename {
 416        proto::PrepareRename {
 417            project_id,
 418            buffer_id: buffer.remote_id().into(),
 419            position: Some(language::proto::serialize_anchor(
 420                &buffer.anchor_before(self.position),
 421            )),
 422            version: serialize_version(&buffer.version()),
 423        }
 424    }
 425
 426    async fn from_proto(
 427        message: proto::PrepareRename,
 428        _: Entity<LspStore>,
 429        buffer: Entity<Buffer>,
 430        mut cx: AsyncApp,
 431    ) -> Result<Self> {
 432        let position = message
 433            .position
 434            .and_then(deserialize_anchor)
 435            .context("invalid position")?;
 436        buffer
 437            .update(&mut cx, |buffer, _| {
 438                buffer.wait_for_version(deserialize_version(&message.version))
 439            })
 440            .await?;
 441
 442        Ok(Self {
 443            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 444        })
 445    }
 446
 447    fn response_to_proto(
 448        response: PrepareRenameResponse,
 449        _: &mut LspStore,
 450        _: PeerId,
 451        buffer_version: &clock::Global,
 452        _: &mut App,
 453    ) -> proto::PrepareRenameResponse {
 454        match response {
 455            PrepareRenameResponse::Success(range) => proto::PrepareRenameResponse {
 456                can_rename: true,
 457                only_unprepared_rename_supported: false,
 458                start: Some(language::proto::serialize_anchor(&range.start)),
 459                end: Some(language::proto::serialize_anchor(&range.end)),
 460                version: serialize_version(buffer_version),
 461            },
 462            PrepareRenameResponse::OnlyUnpreparedRenameSupported => proto::PrepareRenameResponse {
 463                can_rename: false,
 464                only_unprepared_rename_supported: true,
 465                start: None,
 466                end: None,
 467                version: vec![],
 468            },
 469            PrepareRenameResponse::InvalidPosition => proto::PrepareRenameResponse {
 470                can_rename: false,
 471                only_unprepared_rename_supported: false,
 472                start: None,
 473                end: None,
 474                version: vec![],
 475            },
 476        }
 477    }
 478
 479    async fn response_from_proto(
 480        self,
 481        message: proto::PrepareRenameResponse,
 482        _: Entity<LspStore>,
 483        buffer: Entity<Buffer>,
 484        mut cx: AsyncApp,
 485    ) -> Result<PrepareRenameResponse> {
 486        if message.can_rename {
 487            buffer
 488                .update(&mut cx, |buffer, _| {
 489                    buffer.wait_for_version(deserialize_version(&message.version))
 490                })
 491                .await?;
 492            if let (Some(start), Some(end)) = (
 493                message.start.and_then(deserialize_anchor),
 494                message.end.and_then(deserialize_anchor),
 495            ) {
 496                Ok(PrepareRenameResponse::Success(start..end))
 497            } else {
 498                anyhow::bail!(
 499                    "Missing start or end position in remote project PrepareRenameResponse"
 500                );
 501            }
 502        } else if message.only_unprepared_rename_supported {
 503            Ok(PrepareRenameResponse::OnlyUnpreparedRenameSupported)
 504        } else {
 505            Ok(PrepareRenameResponse::InvalidPosition)
 506        }
 507    }
 508
 509    fn buffer_id_from_proto(message: &proto::PrepareRename) -> Result<BufferId> {
 510        BufferId::new(message.buffer_id)
 511    }
 512}
 513
 514#[async_trait(?Send)]
 515impl LspCommand for PerformRename {
 516    type Response = ProjectTransaction;
 517    type LspRequest = lsp::request::Rename;
 518    type ProtoRequest = proto::PerformRename;
 519
 520    fn display_name(&self) -> &str {
 521        "Rename"
 522    }
 523
 524    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 525        capabilities
 526            .server_capabilities
 527            .rename_provider
 528            .is_some_and(|capability| match capability {
 529                OneOf::Left(enabled) => enabled,
 530                OneOf::Right(_options) => true,
 531            })
 532    }
 533
 534    fn to_lsp(
 535        &self,
 536        path: &Path,
 537        _: &Buffer,
 538        _: &Arc<LanguageServer>,
 539        _: &App,
 540    ) -> Result<lsp::RenameParams> {
 541        Ok(lsp::RenameParams {
 542            text_document_position: make_lsp_text_document_position(path, self.position)?,
 543            new_name: self.new_name.clone(),
 544            work_done_progress_params: Default::default(),
 545        })
 546    }
 547
 548    async fn response_from_lsp(
 549        self,
 550        message: Option<lsp::WorkspaceEdit>,
 551        lsp_store: Entity<LspStore>,
 552        buffer: Entity<Buffer>,
 553        server_id: LanguageServerId,
 554        mut cx: AsyncApp,
 555    ) -> Result<ProjectTransaction> {
 556        if let Some(edit) = message {
 557            let (_, lsp_server) =
 558                language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
 559            LocalLspStore::deserialize_workspace_edit(
 560                lsp_store,
 561                edit,
 562                self.push_to_history,
 563                lsp_server,
 564                &mut cx,
 565            )
 566            .await
 567        } else {
 568            Ok(ProjectTransaction::default())
 569        }
 570    }
 571
 572    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::PerformRename {
 573        proto::PerformRename {
 574            project_id,
 575            buffer_id: buffer.remote_id().into(),
 576            position: Some(language::proto::serialize_anchor(
 577                &buffer.anchor_before(self.position),
 578            )),
 579            new_name: self.new_name.clone(),
 580            version: serialize_version(&buffer.version()),
 581        }
 582    }
 583
 584    async fn from_proto(
 585        message: proto::PerformRename,
 586        _: Entity<LspStore>,
 587        buffer: Entity<Buffer>,
 588        mut cx: AsyncApp,
 589    ) -> Result<Self> {
 590        let position = message
 591            .position
 592            .and_then(deserialize_anchor)
 593            .context("invalid position")?;
 594        buffer
 595            .update(&mut cx, |buffer, _| {
 596                buffer.wait_for_version(deserialize_version(&message.version))
 597            })
 598            .await?;
 599        Ok(Self {
 600            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 601            new_name: message.new_name,
 602            push_to_history: false,
 603        })
 604    }
 605
 606    fn response_to_proto(
 607        response: ProjectTransaction,
 608        lsp_store: &mut LspStore,
 609        peer_id: PeerId,
 610        _: &clock::Global,
 611        cx: &mut App,
 612    ) -> proto::PerformRenameResponse {
 613        let transaction = lsp_store.buffer_store().update(cx, |buffer_store, cx| {
 614            buffer_store.serialize_project_transaction_for_peer(response, peer_id, cx)
 615        });
 616        proto::PerformRenameResponse {
 617            transaction: Some(transaction),
 618        }
 619    }
 620
 621    async fn response_from_proto(
 622        self,
 623        message: proto::PerformRenameResponse,
 624        lsp_store: Entity<LspStore>,
 625        _: Entity<Buffer>,
 626        mut cx: AsyncApp,
 627    ) -> Result<ProjectTransaction> {
 628        let message = message.transaction.context("missing transaction")?;
 629        lsp_store
 630            .update(&mut cx, |lsp_store, cx| {
 631                lsp_store.buffer_store().update(cx, |buffer_store, cx| {
 632                    buffer_store.deserialize_project_transaction(message, self.push_to_history, cx)
 633                })
 634            })
 635            .await
 636    }
 637
 638    fn buffer_id_from_proto(message: &proto::PerformRename) -> Result<BufferId> {
 639        BufferId::new(message.buffer_id)
 640    }
 641}
 642
 643#[async_trait(?Send)]
 644impl LspCommand for GetDefinitions {
 645    type Response = Vec<LocationLink>;
 646    type LspRequest = lsp::request::GotoDefinition;
 647    type ProtoRequest = proto::GetDefinition;
 648
 649    fn display_name(&self) -> &str {
 650        "Get definition"
 651    }
 652
 653    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 654        capabilities
 655            .server_capabilities
 656            .definition_provider
 657            .is_some_and(|capability| match capability {
 658                OneOf::Left(supported) => supported,
 659                OneOf::Right(_options) => true,
 660            })
 661    }
 662
 663    fn to_lsp(
 664        &self,
 665        path: &Path,
 666        _: &Buffer,
 667        _: &Arc<LanguageServer>,
 668        _: &App,
 669    ) -> Result<lsp::GotoDefinitionParams> {
 670        Ok(lsp::GotoDefinitionParams {
 671            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 672            work_done_progress_params: Default::default(),
 673            partial_result_params: Default::default(),
 674        })
 675    }
 676
 677    async fn response_from_lsp(
 678        self,
 679        message: Option<lsp::GotoDefinitionResponse>,
 680        lsp_store: Entity<LspStore>,
 681        buffer: Entity<Buffer>,
 682        server_id: LanguageServerId,
 683        cx: AsyncApp,
 684    ) -> Result<Vec<LocationLink>> {
 685        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
 686    }
 687
 688    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDefinition {
 689        proto::GetDefinition {
 690            project_id,
 691            buffer_id: buffer.remote_id().into(),
 692            position: Some(language::proto::serialize_anchor(
 693                &buffer.anchor_before(self.position),
 694            )),
 695            version: serialize_version(&buffer.version()),
 696        }
 697    }
 698
 699    async fn from_proto(
 700        message: proto::GetDefinition,
 701        _: Entity<LspStore>,
 702        buffer: Entity<Buffer>,
 703        mut cx: AsyncApp,
 704    ) -> Result<Self> {
 705        let position = message
 706            .position
 707            .and_then(deserialize_anchor)
 708            .context("invalid position")?;
 709        buffer
 710            .update(&mut cx, |buffer, _| {
 711                buffer.wait_for_version(deserialize_version(&message.version))
 712            })
 713            .await?;
 714        Ok(Self {
 715            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 716        })
 717    }
 718
 719    fn response_to_proto(
 720        response: Vec<LocationLink>,
 721        lsp_store: &mut LspStore,
 722        peer_id: PeerId,
 723        _: &clock::Global,
 724        cx: &mut App,
 725    ) -> proto::GetDefinitionResponse {
 726        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
 727        proto::GetDefinitionResponse { links }
 728    }
 729
 730    async fn response_from_proto(
 731        self,
 732        message: proto::GetDefinitionResponse,
 733        lsp_store: Entity<LspStore>,
 734        _: Entity<Buffer>,
 735        cx: AsyncApp,
 736    ) -> Result<Vec<LocationLink>> {
 737        location_links_from_proto(message.links, lsp_store, cx).await
 738    }
 739
 740    fn buffer_id_from_proto(message: &proto::GetDefinition) -> Result<BufferId> {
 741        BufferId::new(message.buffer_id)
 742    }
 743}
 744
 745#[async_trait(?Send)]
 746impl LspCommand for GetDeclarations {
 747    type Response = Vec<LocationLink>;
 748    type LspRequest = lsp::request::GotoDeclaration;
 749    type ProtoRequest = proto::GetDeclaration;
 750
 751    fn display_name(&self) -> &str {
 752        "Get declaration"
 753    }
 754
 755    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 756        capabilities
 757            .server_capabilities
 758            .declaration_provider
 759            .is_some_and(|capability| match capability {
 760                lsp::DeclarationCapability::Simple(supported) => supported,
 761                lsp::DeclarationCapability::RegistrationOptions(..) => true,
 762                lsp::DeclarationCapability::Options(..) => true,
 763            })
 764    }
 765
 766    fn to_lsp(
 767        &self,
 768        path: &Path,
 769        _: &Buffer,
 770        _: &Arc<LanguageServer>,
 771        _: &App,
 772    ) -> Result<lsp::GotoDeclarationParams> {
 773        Ok(lsp::GotoDeclarationParams {
 774            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 775            work_done_progress_params: Default::default(),
 776            partial_result_params: Default::default(),
 777        })
 778    }
 779
 780    async fn response_from_lsp(
 781        self,
 782        message: Option<lsp::GotoDeclarationResponse>,
 783        lsp_store: Entity<LspStore>,
 784        buffer: Entity<Buffer>,
 785        server_id: LanguageServerId,
 786        cx: AsyncApp,
 787    ) -> Result<Vec<LocationLink>> {
 788        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
 789    }
 790
 791    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDeclaration {
 792        proto::GetDeclaration {
 793            project_id,
 794            buffer_id: buffer.remote_id().into(),
 795            position: Some(language::proto::serialize_anchor(
 796                &buffer.anchor_before(self.position),
 797            )),
 798            version: serialize_version(&buffer.version()),
 799        }
 800    }
 801
 802    async fn from_proto(
 803        message: proto::GetDeclaration,
 804        _: Entity<LspStore>,
 805        buffer: Entity<Buffer>,
 806        mut cx: AsyncApp,
 807    ) -> Result<Self> {
 808        let position = message
 809            .position
 810            .and_then(deserialize_anchor)
 811            .context("invalid position")?;
 812        buffer
 813            .update(&mut cx, |buffer, _| {
 814                buffer.wait_for_version(deserialize_version(&message.version))
 815            })
 816            .await?;
 817        Ok(Self {
 818            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 819        })
 820    }
 821
 822    fn response_to_proto(
 823        response: Vec<LocationLink>,
 824        lsp_store: &mut LspStore,
 825        peer_id: PeerId,
 826        _: &clock::Global,
 827        cx: &mut App,
 828    ) -> proto::GetDeclarationResponse {
 829        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
 830        proto::GetDeclarationResponse { links }
 831    }
 832
 833    async fn response_from_proto(
 834        self,
 835        message: proto::GetDeclarationResponse,
 836        lsp_store: Entity<LspStore>,
 837        _: Entity<Buffer>,
 838        cx: AsyncApp,
 839    ) -> Result<Vec<LocationLink>> {
 840        location_links_from_proto(message.links, lsp_store, cx).await
 841    }
 842
 843    fn buffer_id_from_proto(message: &proto::GetDeclaration) -> Result<BufferId> {
 844        BufferId::new(message.buffer_id)
 845    }
 846}
 847
 848#[async_trait(?Send)]
 849impl LspCommand for GetImplementations {
 850    type Response = Vec<LocationLink>;
 851    type LspRequest = lsp::request::GotoImplementation;
 852    type ProtoRequest = proto::GetImplementation;
 853
 854    fn display_name(&self) -> &str {
 855        "Get implementation"
 856    }
 857
 858    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 859        capabilities
 860            .server_capabilities
 861            .implementation_provider
 862            .is_some_and(|capability| match capability {
 863                lsp::ImplementationProviderCapability::Simple(enabled) => enabled,
 864                lsp::ImplementationProviderCapability::Options(_options) => true,
 865            })
 866    }
 867
 868    fn to_lsp(
 869        &self,
 870        path: &Path,
 871        _: &Buffer,
 872        _: &Arc<LanguageServer>,
 873        _: &App,
 874    ) -> Result<lsp::GotoImplementationParams> {
 875        Ok(lsp::GotoImplementationParams {
 876            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 877            work_done_progress_params: Default::default(),
 878            partial_result_params: Default::default(),
 879        })
 880    }
 881
 882    async fn response_from_lsp(
 883        self,
 884        message: Option<lsp::GotoImplementationResponse>,
 885        lsp_store: Entity<LspStore>,
 886        buffer: Entity<Buffer>,
 887        server_id: LanguageServerId,
 888        cx: AsyncApp,
 889    ) -> Result<Vec<LocationLink>> {
 890        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
 891    }
 892
 893    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetImplementation {
 894        proto::GetImplementation {
 895            project_id,
 896            buffer_id: buffer.remote_id().into(),
 897            position: Some(language::proto::serialize_anchor(
 898                &buffer.anchor_before(self.position),
 899            )),
 900            version: serialize_version(&buffer.version()),
 901        }
 902    }
 903
 904    async fn from_proto(
 905        message: proto::GetImplementation,
 906        _: Entity<LspStore>,
 907        buffer: Entity<Buffer>,
 908        mut cx: AsyncApp,
 909    ) -> Result<Self> {
 910        let position = message
 911            .position
 912            .and_then(deserialize_anchor)
 913            .context("invalid position")?;
 914        buffer
 915            .update(&mut cx, |buffer, _| {
 916                buffer.wait_for_version(deserialize_version(&message.version))
 917            })
 918            .await?;
 919        Ok(Self {
 920            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 921        })
 922    }
 923
 924    fn response_to_proto(
 925        response: Vec<LocationLink>,
 926        lsp_store: &mut LspStore,
 927        peer_id: PeerId,
 928        _: &clock::Global,
 929        cx: &mut App,
 930    ) -> proto::GetImplementationResponse {
 931        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
 932        proto::GetImplementationResponse { links }
 933    }
 934
 935    async fn response_from_proto(
 936        self,
 937        message: proto::GetImplementationResponse,
 938        project: Entity<LspStore>,
 939        _: Entity<Buffer>,
 940        cx: AsyncApp,
 941    ) -> Result<Vec<LocationLink>> {
 942        location_links_from_proto(message.links, project, cx).await
 943    }
 944
 945    fn buffer_id_from_proto(message: &proto::GetImplementation) -> Result<BufferId> {
 946        BufferId::new(message.buffer_id)
 947    }
 948}
 949
 950#[async_trait(?Send)]
 951impl LspCommand for GetTypeDefinitions {
 952    type Response = Vec<LocationLink>;
 953    type LspRequest = lsp::request::GotoTypeDefinition;
 954    type ProtoRequest = proto::GetTypeDefinition;
 955
 956    fn display_name(&self) -> &str {
 957        "Get type definition"
 958    }
 959
 960    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
 961        !matches!(
 962            &capabilities.server_capabilities.type_definition_provider,
 963            None | Some(lsp::TypeDefinitionProviderCapability::Simple(false))
 964        )
 965    }
 966
 967    fn to_lsp(
 968        &self,
 969        path: &Path,
 970        _: &Buffer,
 971        _: &Arc<LanguageServer>,
 972        _: &App,
 973    ) -> Result<lsp::GotoTypeDefinitionParams> {
 974        Ok(lsp::GotoTypeDefinitionParams {
 975            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
 976            work_done_progress_params: Default::default(),
 977            partial_result_params: Default::default(),
 978        })
 979    }
 980
 981    async fn response_from_lsp(
 982        self,
 983        message: Option<lsp::GotoTypeDefinitionResponse>,
 984        project: Entity<LspStore>,
 985        buffer: Entity<Buffer>,
 986        server_id: LanguageServerId,
 987        cx: AsyncApp,
 988    ) -> Result<Vec<LocationLink>> {
 989        location_links_from_lsp(message, project, buffer, server_id, cx).await
 990    }
 991
 992    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetTypeDefinition {
 993        proto::GetTypeDefinition {
 994            project_id,
 995            buffer_id: buffer.remote_id().into(),
 996            position: Some(language::proto::serialize_anchor(
 997                &buffer.anchor_before(self.position),
 998            )),
 999            version: serialize_version(&buffer.version()),
1000        }
1001    }
1002
1003    async fn from_proto(
1004        message: proto::GetTypeDefinition,
1005        _: Entity<LspStore>,
1006        buffer: Entity<Buffer>,
1007        mut cx: AsyncApp,
1008    ) -> Result<Self> {
1009        let position = message
1010            .position
1011            .and_then(deserialize_anchor)
1012            .context("invalid position")?;
1013        buffer
1014            .update(&mut cx, |buffer, _| {
1015                buffer.wait_for_version(deserialize_version(&message.version))
1016            })
1017            .await?;
1018        Ok(Self {
1019            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1020        })
1021    }
1022
1023    fn response_to_proto(
1024        response: Vec<LocationLink>,
1025        lsp_store: &mut LspStore,
1026        peer_id: PeerId,
1027        _: &clock::Global,
1028        cx: &mut App,
1029    ) -> proto::GetTypeDefinitionResponse {
1030        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
1031        proto::GetTypeDefinitionResponse { links }
1032    }
1033
1034    async fn response_from_proto(
1035        self,
1036        message: proto::GetTypeDefinitionResponse,
1037        project: Entity<LspStore>,
1038        _: Entity<Buffer>,
1039        cx: AsyncApp,
1040    ) -> Result<Vec<LocationLink>> {
1041        location_links_from_proto(message.links, project, cx).await
1042    }
1043
1044    fn buffer_id_from_proto(message: &proto::GetTypeDefinition) -> Result<BufferId> {
1045        BufferId::new(message.buffer_id)
1046    }
1047}
1048
1049fn language_server_for_buffer(
1050    lsp_store: &Entity<LspStore>,
1051    buffer: &Entity<Buffer>,
1052    server_id: LanguageServerId,
1053    cx: &mut AsyncApp,
1054) -> Result<(Arc<CachedLspAdapter>, Arc<LanguageServer>)> {
1055    lsp_store
1056        .update(cx, |lsp_store, cx| {
1057            buffer.update(cx, |buffer, cx| {
1058                lsp_store
1059                    .language_server_for_local_buffer(buffer, server_id, cx)
1060                    .map(|(adapter, server)| (adapter.clone(), server.clone()))
1061            })
1062        })
1063        .context("no language server found for buffer")
1064}
1065
1066pub async fn location_links_from_proto(
1067    proto_links: Vec<proto::LocationLink>,
1068    lsp_store: Entity<LspStore>,
1069    mut cx: AsyncApp,
1070) -> Result<Vec<LocationLink>> {
1071    let mut links = Vec::new();
1072
1073    for link in proto_links {
1074        links.push(location_link_from_proto(link, lsp_store.clone(), &mut cx).await?)
1075    }
1076
1077    Ok(links)
1078}
1079
1080pub fn location_link_from_proto(
1081    link: proto::LocationLink,
1082    lsp_store: Entity<LspStore>,
1083    cx: &mut AsyncApp,
1084) -> Task<Result<LocationLink>> {
1085    cx.spawn(async move |cx| {
1086        let origin = match link.origin {
1087            Some(origin) => {
1088                let buffer_id = BufferId::new(origin.buffer_id)?;
1089                let buffer = lsp_store
1090                    .update(cx, |lsp_store, cx| {
1091                        lsp_store.wait_for_remote_buffer(buffer_id, cx)
1092                    })
1093                    .await?;
1094                let start = origin
1095                    .start
1096                    .and_then(deserialize_anchor)
1097                    .context("missing origin start")?;
1098                let end = origin
1099                    .end
1100                    .and_then(deserialize_anchor)
1101                    .context("missing origin end")?;
1102                buffer
1103                    .update(cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1104                    .await?;
1105                Some(Location {
1106                    buffer,
1107                    range: start..end,
1108                })
1109            }
1110            None => None,
1111        };
1112
1113        let target = link.target.context("missing target")?;
1114        let buffer_id = BufferId::new(target.buffer_id)?;
1115        let buffer = lsp_store
1116            .update(cx, |lsp_store, cx| {
1117                lsp_store.wait_for_remote_buffer(buffer_id, cx)
1118            })
1119            .await?;
1120        let start = target
1121            .start
1122            .and_then(deserialize_anchor)
1123            .context("missing target start")?;
1124        let end = target
1125            .end
1126            .and_then(deserialize_anchor)
1127            .context("missing target end")?;
1128        buffer
1129            .update(cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1130            .await?;
1131        let target = Location {
1132            buffer,
1133            range: start..end,
1134        };
1135        Ok(LocationLink { origin, target })
1136    })
1137}
1138
1139pub async fn location_links_from_lsp(
1140    message: Option<lsp::GotoDefinitionResponse>,
1141    lsp_store: Entity<LspStore>,
1142    buffer: Entity<Buffer>,
1143    server_id: LanguageServerId,
1144    mut cx: AsyncApp,
1145) -> Result<Vec<LocationLink>> {
1146    let message = match message {
1147        Some(message) => message,
1148        None => return Ok(Vec::new()),
1149    };
1150
1151    let mut unresolved_links = Vec::new();
1152    match message {
1153        lsp::GotoDefinitionResponse::Scalar(loc) => {
1154            unresolved_links.push((None, loc.uri, loc.range));
1155        }
1156
1157        lsp::GotoDefinitionResponse::Array(locs) => {
1158            unresolved_links.extend(locs.into_iter().map(|l| (None, l.uri, l.range)));
1159        }
1160
1161        lsp::GotoDefinitionResponse::Link(links) => {
1162            unresolved_links.extend(links.into_iter().map(|l| {
1163                (
1164                    l.origin_selection_range,
1165                    l.target_uri,
1166                    l.target_selection_range,
1167                )
1168            }));
1169        }
1170    }
1171
1172    let (_, language_server) = language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1173    let mut definitions = Vec::new();
1174    for (origin_range, target_uri, target_range) in unresolved_links {
1175        let target_buffer_handle = lsp_store
1176            .update(&mut cx, |this, cx| {
1177                this.open_local_buffer_via_lsp(target_uri, language_server.server_id(), cx)
1178            })
1179            .await?;
1180
1181        cx.update(|cx| {
1182            let origin_location = origin_range.map(|origin_range| {
1183                let origin_buffer = buffer.read(cx);
1184                let origin_start =
1185                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
1186                let origin_end =
1187                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
1188                Location {
1189                    buffer: buffer.clone(),
1190                    range: origin_buffer.anchor_after(origin_start)
1191                        ..origin_buffer.anchor_before(origin_end),
1192                }
1193            });
1194
1195            let target_buffer = target_buffer_handle.read(cx);
1196            let target_start =
1197                target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
1198            let target_end =
1199                target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
1200            let target_location = Location {
1201                buffer: target_buffer_handle,
1202                range: target_buffer.anchor_after(target_start)
1203                    ..target_buffer.anchor_before(target_end),
1204            };
1205
1206            definitions.push(LocationLink {
1207                origin: origin_location,
1208                target: target_location,
1209            })
1210        });
1211    }
1212    Ok(definitions)
1213}
1214
1215pub async fn location_link_from_lsp(
1216    link: lsp::LocationLink,
1217    lsp_store: &Entity<LspStore>,
1218    buffer: &Entity<Buffer>,
1219    server_id: LanguageServerId,
1220    cx: &mut AsyncApp,
1221) -> Result<LocationLink> {
1222    let (_, language_server) = language_server_for_buffer(lsp_store, buffer, server_id, cx)?;
1223
1224    let (origin_range, target_uri, target_range) = (
1225        link.origin_selection_range,
1226        link.target_uri,
1227        link.target_selection_range,
1228    );
1229
1230    let target_buffer_handle = lsp_store
1231        .update(cx, |lsp_store, cx| {
1232            lsp_store.open_local_buffer_via_lsp(target_uri, language_server.server_id(), cx)
1233        })
1234        .await?;
1235
1236    Ok(cx.update(|cx| {
1237        let origin_location = origin_range.map(|origin_range| {
1238            let origin_buffer = buffer.read(cx);
1239            let origin_start =
1240                origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
1241            let origin_end =
1242                origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
1243            Location {
1244                buffer: buffer.clone(),
1245                range: origin_buffer.anchor_after(origin_start)
1246                    ..origin_buffer.anchor_before(origin_end),
1247            }
1248        });
1249
1250        let target_buffer = target_buffer_handle.read(cx);
1251        let target_start =
1252            target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
1253        let target_end =
1254            target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
1255        let target_location = Location {
1256            buffer: target_buffer_handle,
1257            range: target_buffer.anchor_after(target_start)
1258                ..target_buffer.anchor_before(target_end),
1259        };
1260
1261        LocationLink {
1262            origin: origin_location,
1263            target: target_location,
1264        }
1265    }))
1266}
1267
1268pub fn location_links_to_proto(
1269    links: Vec<LocationLink>,
1270    lsp_store: &mut LspStore,
1271    peer_id: PeerId,
1272    cx: &mut App,
1273) -> Vec<proto::LocationLink> {
1274    links
1275        .into_iter()
1276        .map(|definition| location_link_to_proto(definition, lsp_store, peer_id, cx))
1277        .collect()
1278}
1279
1280pub fn location_link_to_proto(
1281    location: LocationLink,
1282    lsp_store: &mut LspStore,
1283    peer_id: PeerId,
1284    cx: &mut App,
1285) -> proto::LocationLink {
1286    let origin = location.origin.map(|origin| {
1287        lsp_store
1288            .buffer_store()
1289            .update(cx, |buffer_store, cx| {
1290                buffer_store.create_buffer_for_peer(&origin.buffer, peer_id, cx)
1291            })
1292            .detach_and_log_err(cx);
1293
1294        let buffer_id = origin.buffer.read(cx).remote_id().into();
1295        proto::Location {
1296            start: Some(serialize_anchor(&origin.range.start)),
1297            end: Some(serialize_anchor(&origin.range.end)),
1298            buffer_id,
1299        }
1300    });
1301
1302    lsp_store
1303        .buffer_store()
1304        .update(cx, |buffer_store, cx| {
1305            buffer_store.create_buffer_for_peer(&location.target.buffer, peer_id, cx)
1306        })
1307        .detach_and_log_err(cx);
1308
1309    let buffer_id = location.target.buffer.read(cx).remote_id().into();
1310    let target = proto::Location {
1311        start: Some(serialize_anchor(&location.target.range.start)),
1312        end: Some(serialize_anchor(&location.target.range.end)),
1313        buffer_id,
1314    };
1315
1316    proto::LocationLink {
1317        origin,
1318        target: Some(target),
1319    }
1320}
1321
1322#[async_trait(?Send)]
1323impl LspCommand for GetReferences {
1324    type Response = Vec<Location>;
1325    type LspRequest = lsp::request::References;
1326    type ProtoRequest = proto::GetReferences;
1327
1328    fn display_name(&self) -> &str {
1329        "Find all references"
1330    }
1331
1332    fn status(&self) -> Option<String> {
1333        Some("Finding references...".to_owned())
1334    }
1335
1336    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1337        match &capabilities.server_capabilities.references_provider {
1338            Some(OneOf::Left(has_support)) => *has_support,
1339            Some(OneOf::Right(_)) => true,
1340            None => false,
1341        }
1342    }
1343
1344    fn to_lsp(
1345        &self,
1346        path: &Path,
1347        _: &Buffer,
1348        _: &Arc<LanguageServer>,
1349        _: &App,
1350    ) -> Result<lsp::ReferenceParams> {
1351        Ok(lsp::ReferenceParams {
1352            text_document_position: make_lsp_text_document_position(path, self.position)?,
1353            work_done_progress_params: Default::default(),
1354            partial_result_params: Default::default(),
1355            context: lsp::ReferenceContext {
1356                include_declaration: true,
1357            },
1358        })
1359    }
1360
1361    async fn response_from_lsp(
1362        self,
1363        locations: Option<Vec<lsp::Location>>,
1364        lsp_store: Entity<LspStore>,
1365        buffer: Entity<Buffer>,
1366        server_id: LanguageServerId,
1367        mut cx: AsyncApp,
1368    ) -> Result<Vec<Location>> {
1369        let mut references = Vec::new();
1370        let (_, language_server) =
1371            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1372
1373        if let Some(locations) = locations {
1374            for lsp_location in locations {
1375                let target_buffer_handle = lsp_store
1376                    .update(&mut cx, |lsp_store, cx| {
1377                        lsp_store.open_local_buffer_via_lsp(
1378                            lsp_location.uri,
1379                            language_server.server_id(),
1380                            cx,
1381                        )
1382                    })
1383                    .await?;
1384
1385                target_buffer_handle
1386                    .clone()
1387                    .read_with(&cx, |target_buffer, _| {
1388                        let target_start = target_buffer
1389                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
1390                        let target_end = target_buffer
1391                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
1392                        references.push(Location {
1393                            buffer: target_buffer_handle,
1394                            range: target_buffer.anchor_after(target_start)
1395                                ..target_buffer.anchor_before(target_end),
1396                        });
1397                    });
1398            }
1399        }
1400
1401        Ok(references)
1402    }
1403
1404    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetReferences {
1405        proto::GetReferences {
1406            project_id,
1407            buffer_id: buffer.remote_id().into(),
1408            position: Some(language::proto::serialize_anchor(
1409                &buffer.anchor_before(self.position),
1410            )),
1411            version: serialize_version(&buffer.version()),
1412        }
1413    }
1414
1415    async fn from_proto(
1416        message: proto::GetReferences,
1417        _: Entity<LspStore>,
1418        buffer: Entity<Buffer>,
1419        mut cx: AsyncApp,
1420    ) -> Result<Self> {
1421        let position = message
1422            .position
1423            .and_then(deserialize_anchor)
1424            .context("invalid position")?;
1425        buffer
1426            .update(&mut cx, |buffer, _| {
1427                buffer.wait_for_version(deserialize_version(&message.version))
1428            })
1429            .await?;
1430        Ok(Self {
1431            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1432        })
1433    }
1434
1435    fn response_to_proto(
1436        response: Vec<Location>,
1437        lsp_store: &mut LspStore,
1438        peer_id: PeerId,
1439        _: &clock::Global,
1440        cx: &mut App,
1441    ) -> proto::GetReferencesResponse {
1442        let locations = response
1443            .into_iter()
1444            .map(|definition| {
1445                lsp_store
1446                    .buffer_store()
1447                    .update(cx, |buffer_store, cx| {
1448                        buffer_store.create_buffer_for_peer(&definition.buffer, peer_id, cx)
1449                    })
1450                    .detach_and_log_err(cx);
1451                let buffer_id = definition.buffer.read(cx).remote_id();
1452                proto::Location {
1453                    start: Some(serialize_anchor(&definition.range.start)),
1454                    end: Some(serialize_anchor(&definition.range.end)),
1455                    buffer_id: buffer_id.into(),
1456                }
1457            })
1458            .collect();
1459        proto::GetReferencesResponse { locations }
1460    }
1461
1462    async fn response_from_proto(
1463        self,
1464        message: proto::GetReferencesResponse,
1465        project: Entity<LspStore>,
1466        _: Entity<Buffer>,
1467        mut cx: AsyncApp,
1468    ) -> Result<Vec<Location>> {
1469        let mut locations = Vec::new();
1470        for location in message.locations {
1471            let buffer_id = BufferId::new(location.buffer_id)?;
1472            let target_buffer = project
1473                .update(&mut cx, |this, cx| {
1474                    this.wait_for_remote_buffer(buffer_id, cx)
1475                })
1476                .await?;
1477            let start = location
1478                .start
1479                .and_then(deserialize_anchor)
1480                .context("missing target start")?;
1481            let end = location
1482                .end
1483                .and_then(deserialize_anchor)
1484                .context("missing target end")?;
1485            target_buffer
1486                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1487                .await?;
1488            locations.push(Location {
1489                buffer: target_buffer,
1490                range: start..end,
1491            })
1492        }
1493        Ok(locations)
1494    }
1495
1496    fn buffer_id_from_proto(message: &proto::GetReferences) -> Result<BufferId> {
1497        BufferId::new(message.buffer_id)
1498    }
1499}
1500
1501#[async_trait(?Send)]
1502impl LspCommand for GetDocumentHighlights {
1503    type Response = Vec<DocumentHighlight>;
1504    type LspRequest = lsp::request::DocumentHighlightRequest;
1505    type ProtoRequest = proto::GetDocumentHighlights;
1506
1507    fn display_name(&self) -> &str {
1508        "Get document highlights"
1509    }
1510
1511    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1512        capabilities
1513            .server_capabilities
1514            .document_highlight_provider
1515            .is_some_and(|capability| match capability {
1516                OneOf::Left(supported) => supported,
1517                OneOf::Right(_options) => true,
1518            })
1519    }
1520
1521    fn to_lsp(
1522        &self,
1523        path: &Path,
1524        _: &Buffer,
1525        _: &Arc<LanguageServer>,
1526        _: &App,
1527    ) -> Result<lsp::DocumentHighlightParams> {
1528        Ok(lsp::DocumentHighlightParams {
1529            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1530            work_done_progress_params: Default::default(),
1531            partial_result_params: Default::default(),
1532        })
1533    }
1534
1535    async fn response_from_lsp(
1536        self,
1537        lsp_highlights: Option<Vec<lsp::DocumentHighlight>>,
1538        _: Entity<LspStore>,
1539        buffer: Entity<Buffer>,
1540        _: LanguageServerId,
1541        cx: AsyncApp,
1542    ) -> Result<Vec<DocumentHighlight>> {
1543        Ok(buffer.read_with(&cx, |buffer, _| {
1544            let mut lsp_highlights = lsp_highlights.unwrap_or_default();
1545            lsp_highlights.sort_unstable_by_key(|h| (h.range.start, Reverse(h.range.end)));
1546            lsp_highlights
1547                .into_iter()
1548                .map(|lsp_highlight| {
1549                    let start = buffer
1550                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.start), Bias::Left);
1551                    let end = buffer
1552                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.end), Bias::Left);
1553                    DocumentHighlight {
1554                        range: buffer.anchor_after(start)..buffer.anchor_before(end),
1555                        kind: lsp_highlight
1556                            .kind
1557                            .unwrap_or(lsp::DocumentHighlightKind::READ),
1558                    }
1559                })
1560                .collect()
1561        }))
1562    }
1563
1564    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentHighlights {
1565        proto::GetDocumentHighlights {
1566            project_id,
1567            buffer_id: buffer.remote_id().into(),
1568            position: Some(language::proto::serialize_anchor(
1569                &buffer.anchor_before(self.position),
1570            )),
1571            version: serialize_version(&buffer.version()),
1572        }
1573    }
1574
1575    async fn from_proto(
1576        message: proto::GetDocumentHighlights,
1577        _: Entity<LspStore>,
1578        buffer: Entity<Buffer>,
1579        mut cx: AsyncApp,
1580    ) -> Result<Self> {
1581        let position = message
1582            .position
1583            .and_then(deserialize_anchor)
1584            .context("invalid position")?;
1585        buffer
1586            .update(&mut cx, |buffer, _| {
1587                buffer.wait_for_version(deserialize_version(&message.version))
1588            })
1589            .await?;
1590        Ok(Self {
1591            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1592        })
1593    }
1594
1595    fn response_to_proto(
1596        response: Vec<DocumentHighlight>,
1597        _: &mut LspStore,
1598        _: PeerId,
1599        _: &clock::Global,
1600        _: &mut App,
1601    ) -> proto::GetDocumentHighlightsResponse {
1602        let highlights = response
1603            .into_iter()
1604            .map(|highlight| proto::DocumentHighlight {
1605                start: Some(serialize_anchor(&highlight.range.start)),
1606                end: Some(serialize_anchor(&highlight.range.end)),
1607                kind: match highlight.kind {
1608                    DocumentHighlightKind::TEXT => proto::document_highlight::Kind::Text.into(),
1609                    DocumentHighlightKind::WRITE => proto::document_highlight::Kind::Write.into(),
1610                    DocumentHighlightKind::READ => proto::document_highlight::Kind::Read.into(),
1611                    _ => proto::document_highlight::Kind::Text.into(),
1612                },
1613            })
1614            .collect();
1615        proto::GetDocumentHighlightsResponse { highlights }
1616    }
1617
1618    async fn response_from_proto(
1619        self,
1620        message: proto::GetDocumentHighlightsResponse,
1621        _: Entity<LspStore>,
1622        buffer: Entity<Buffer>,
1623        mut cx: AsyncApp,
1624    ) -> Result<Vec<DocumentHighlight>> {
1625        let mut highlights = Vec::new();
1626        for highlight in message.highlights {
1627            let start = highlight
1628                .start
1629                .and_then(deserialize_anchor)
1630                .context("missing target start")?;
1631            let end = highlight
1632                .end
1633                .and_then(deserialize_anchor)
1634                .context("missing target end")?;
1635            buffer
1636                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1637                .await?;
1638            let kind = match proto::document_highlight::Kind::from_i32(highlight.kind) {
1639                Some(proto::document_highlight::Kind::Text) => DocumentHighlightKind::TEXT,
1640                Some(proto::document_highlight::Kind::Read) => DocumentHighlightKind::READ,
1641                Some(proto::document_highlight::Kind::Write) => DocumentHighlightKind::WRITE,
1642                None => DocumentHighlightKind::TEXT,
1643            };
1644            highlights.push(DocumentHighlight {
1645                range: start..end,
1646                kind,
1647            });
1648        }
1649        Ok(highlights)
1650    }
1651
1652    fn buffer_id_from_proto(message: &proto::GetDocumentHighlights) -> Result<BufferId> {
1653        BufferId::new(message.buffer_id)
1654    }
1655}
1656
1657#[async_trait(?Send)]
1658impl LspCommand for GetDocumentSymbols {
1659    type Response = Vec<DocumentSymbol>;
1660    type LspRequest = lsp::request::DocumentSymbolRequest;
1661    type ProtoRequest = proto::GetDocumentSymbols;
1662
1663    fn display_name(&self) -> &str {
1664        "Get document symbols"
1665    }
1666
1667    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1668        capabilities
1669            .server_capabilities
1670            .document_symbol_provider
1671            .is_some_and(|capability| match capability {
1672                OneOf::Left(supported) => supported,
1673                OneOf::Right(_options) => true,
1674            })
1675    }
1676
1677    fn to_lsp(
1678        &self,
1679        path: &Path,
1680        _: &Buffer,
1681        _: &Arc<LanguageServer>,
1682        _: &App,
1683    ) -> Result<lsp::DocumentSymbolParams> {
1684        Ok(lsp::DocumentSymbolParams {
1685            text_document: make_text_document_identifier(path)?,
1686            work_done_progress_params: Default::default(),
1687            partial_result_params: Default::default(),
1688        })
1689    }
1690
1691    async fn response_from_lsp(
1692        self,
1693        lsp_symbols: Option<lsp::DocumentSymbolResponse>,
1694        _: Entity<LspStore>,
1695        _: Entity<Buffer>,
1696        _: LanguageServerId,
1697        _: AsyncApp,
1698    ) -> Result<Vec<DocumentSymbol>> {
1699        let Some(lsp_symbols) = lsp_symbols else {
1700            return Ok(Vec::new());
1701        };
1702
1703        let symbols: Vec<_> = match lsp_symbols {
1704            lsp::DocumentSymbolResponse::Flat(symbol_information) => symbol_information
1705                .into_iter()
1706                .map(|lsp_symbol| DocumentSymbol {
1707                    name: lsp_symbol.name,
1708                    kind: lsp_symbol.kind,
1709                    range: range_from_lsp(lsp_symbol.location.range),
1710                    selection_range: range_from_lsp(lsp_symbol.location.range),
1711                    children: Vec::new(),
1712                })
1713                .collect(),
1714            lsp::DocumentSymbolResponse::Nested(nested_responses) => {
1715                fn convert_symbol(lsp_symbol: lsp::DocumentSymbol) -> DocumentSymbol {
1716                    DocumentSymbol {
1717                        name: lsp_symbol.name,
1718                        kind: lsp_symbol.kind,
1719                        range: range_from_lsp(lsp_symbol.range),
1720                        selection_range: range_from_lsp(lsp_symbol.selection_range),
1721                        children: lsp_symbol
1722                            .children
1723                            .map(|children| {
1724                                children.into_iter().map(convert_symbol).collect::<Vec<_>>()
1725                            })
1726                            .unwrap_or_default(),
1727                    }
1728                }
1729                nested_responses.into_iter().map(convert_symbol).collect()
1730            }
1731        };
1732        Ok(symbols)
1733    }
1734
1735    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentSymbols {
1736        proto::GetDocumentSymbols {
1737            project_id,
1738            buffer_id: buffer.remote_id().into(),
1739            version: serialize_version(&buffer.version()),
1740        }
1741    }
1742
1743    async fn from_proto(
1744        message: proto::GetDocumentSymbols,
1745        _: Entity<LspStore>,
1746        buffer: Entity<Buffer>,
1747        mut cx: AsyncApp,
1748    ) -> Result<Self> {
1749        buffer
1750            .update(&mut cx, |buffer, _| {
1751                buffer.wait_for_version(deserialize_version(&message.version))
1752            })
1753            .await?;
1754        Ok(Self)
1755    }
1756
1757    fn response_to_proto(
1758        response: Vec<DocumentSymbol>,
1759        _: &mut LspStore,
1760        _: PeerId,
1761        _: &clock::Global,
1762        _: &mut App,
1763    ) -> proto::GetDocumentSymbolsResponse {
1764        let symbols = response
1765            .into_iter()
1766            .map(|symbol| {
1767                fn convert_symbol_to_proto(symbol: DocumentSymbol) -> proto::DocumentSymbol {
1768                    proto::DocumentSymbol {
1769                        name: symbol.name.clone(),
1770                        kind: unsafe { mem::transmute::<lsp::SymbolKind, i32>(symbol.kind) },
1771                        start: Some(proto::PointUtf16 {
1772                            row: symbol.range.start.0.row,
1773                            column: symbol.range.start.0.column,
1774                        }),
1775                        end: Some(proto::PointUtf16 {
1776                            row: symbol.range.end.0.row,
1777                            column: symbol.range.end.0.column,
1778                        }),
1779                        selection_start: Some(proto::PointUtf16 {
1780                            row: symbol.selection_range.start.0.row,
1781                            column: symbol.selection_range.start.0.column,
1782                        }),
1783                        selection_end: Some(proto::PointUtf16 {
1784                            row: symbol.selection_range.end.0.row,
1785                            column: symbol.selection_range.end.0.column,
1786                        }),
1787                        children: symbol
1788                            .children
1789                            .into_iter()
1790                            .map(convert_symbol_to_proto)
1791                            .collect(),
1792                    }
1793                }
1794                convert_symbol_to_proto(symbol)
1795            })
1796            .collect::<Vec<_>>();
1797
1798        proto::GetDocumentSymbolsResponse { symbols }
1799    }
1800
1801    async fn response_from_proto(
1802        self,
1803        message: proto::GetDocumentSymbolsResponse,
1804        _: Entity<LspStore>,
1805        _: Entity<Buffer>,
1806        _: AsyncApp,
1807    ) -> Result<Vec<DocumentSymbol>> {
1808        let mut symbols = Vec::with_capacity(message.symbols.len());
1809        for serialized_symbol in message.symbols {
1810            fn deserialize_symbol_with_children(
1811                serialized_symbol: proto::DocumentSymbol,
1812            ) -> Result<DocumentSymbol> {
1813                let kind =
1814                    unsafe { mem::transmute::<i32, lsp::SymbolKind>(serialized_symbol.kind) };
1815
1816                let start = serialized_symbol.start.context("invalid start")?;
1817                let end = serialized_symbol.end.context("invalid end")?;
1818
1819                let selection_start = serialized_symbol
1820                    .selection_start
1821                    .context("invalid selection start")?;
1822                let selection_end = serialized_symbol
1823                    .selection_end
1824                    .context("invalid selection end")?;
1825
1826                Ok(DocumentSymbol {
1827                    name: serialized_symbol.name,
1828                    kind,
1829                    range: Unclipped(PointUtf16::new(start.row, start.column))
1830                        ..Unclipped(PointUtf16::new(end.row, end.column)),
1831                    selection_range: Unclipped(PointUtf16::new(
1832                        selection_start.row,
1833                        selection_start.column,
1834                    ))
1835                        ..Unclipped(PointUtf16::new(selection_end.row, selection_end.column)),
1836                    children: serialized_symbol
1837                        .children
1838                        .into_iter()
1839                        .filter_map(|symbol| deserialize_symbol_with_children(symbol).ok())
1840                        .collect::<Vec<_>>(),
1841                })
1842            }
1843
1844            symbols.push(deserialize_symbol_with_children(serialized_symbol)?);
1845        }
1846
1847        Ok(symbols)
1848    }
1849
1850    fn buffer_id_from_proto(message: &proto::GetDocumentSymbols) -> Result<BufferId> {
1851        BufferId::new(message.buffer_id)
1852    }
1853}
1854
1855#[async_trait(?Send)]
1856impl LspCommand for GetSignatureHelp {
1857    type Response = Option<SignatureHelp>;
1858    type LspRequest = lsp::SignatureHelpRequest;
1859    type ProtoRequest = proto::GetSignatureHelp;
1860
1861    fn display_name(&self) -> &str {
1862        "Get signature help"
1863    }
1864
1865    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1866        capabilities
1867            .server_capabilities
1868            .signature_help_provider
1869            .is_some()
1870    }
1871
1872    fn to_lsp(
1873        &self,
1874        path: &Path,
1875        _: &Buffer,
1876        _: &Arc<LanguageServer>,
1877        _cx: &App,
1878    ) -> Result<lsp::SignatureHelpParams> {
1879        Ok(lsp::SignatureHelpParams {
1880            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1881            context: None,
1882            work_done_progress_params: Default::default(),
1883        })
1884    }
1885
1886    async fn response_from_lsp(
1887        self,
1888        message: Option<lsp::SignatureHelp>,
1889        lsp_store: Entity<LspStore>,
1890        _: Entity<Buffer>,
1891        id: LanguageServerId,
1892        cx: AsyncApp,
1893    ) -> Result<Self::Response> {
1894        let Some(message) = message else {
1895            return Ok(None);
1896        };
1897        Ok(cx.update(|cx| {
1898            SignatureHelp::new(
1899                message,
1900                Some(lsp_store.read(cx).languages.clone()),
1901                Some(id),
1902                cx,
1903            )
1904        }))
1905    }
1906
1907    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
1908        let offset = buffer.point_utf16_to_offset(self.position);
1909        proto::GetSignatureHelp {
1910            project_id,
1911            buffer_id: buffer.remote_id().to_proto(),
1912            position: Some(serialize_anchor(&buffer.anchor_after(offset))),
1913            version: serialize_version(&buffer.version()),
1914        }
1915    }
1916
1917    async fn from_proto(
1918        payload: Self::ProtoRequest,
1919        _: Entity<LspStore>,
1920        buffer: Entity<Buffer>,
1921        mut cx: AsyncApp,
1922    ) -> Result<Self> {
1923        buffer
1924            .update(&mut cx, |buffer, _| {
1925                buffer.wait_for_version(deserialize_version(&payload.version))
1926            })
1927            .await
1928            .with_context(|| format!("waiting for version for buffer {}", buffer.entity_id()))?;
1929        let buffer_snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
1930        Ok(Self {
1931            position: payload
1932                .position
1933                .and_then(deserialize_anchor)
1934                .context("invalid position")?
1935                .to_point_utf16(&buffer_snapshot),
1936        })
1937    }
1938
1939    fn response_to_proto(
1940        response: Self::Response,
1941        _: &mut LspStore,
1942        _: PeerId,
1943        _: &Global,
1944        _: &mut App,
1945    ) -> proto::GetSignatureHelpResponse {
1946        proto::GetSignatureHelpResponse {
1947            signature_help: response
1948                .map(|signature_help| lsp_to_proto_signature(signature_help.original_data)),
1949        }
1950    }
1951
1952    async fn response_from_proto(
1953        self,
1954        response: proto::GetSignatureHelpResponse,
1955        lsp_store: Entity<LspStore>,
1956        _: Entity<Buffer>,
1957        cx: AsyncApp,
1958    ) -> Result<Self::Response> {
1959        Ok(cx.update(|cx| {
1960            response
1961                .signature_help
1962                .map(proto_to_lsp_signature)
1963                .and_then(|signature| {
1964                    SignatureHelp::new(
1965                        signature,
1966                        Some(lsp_store.read(cx).languages.clone()),
1967                        None,
1968                        cx,
1969                    )
1970                })
1971        }))
1972    }
1973
1974    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
1975        BufferId::new(message.buffer_id)
1976    }
1977}
1978
1979#[async_trait(?Send)]
1980impl LspCommand for GetHover {
1981    type Response = Option<Hover>;
1982    type LspRequest = lsp::request::HoverRequest;
1983    type ProtoRequest = proto::GetHover;
1984
1985    fn display_name(&self) -> &str {
1986        "Get hover"
1987    }
1988
1989    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1990        match capabilities.server_capabilities.hover_provider {
1991            Some(lsp::HoverProviderCapability::Simple(enabled)) => enabled,
1992            Some(lsp::HoverProviderCapability::Options(_)) => true,
1993            None => false,
1994        }
1995    }
1996
1997    fn to_lsp(
1998        &self,
1999        path: &Path,
2000        _: &Buffer,
2001        _: &Arc<LanguageServer>,
2002        _: &App,
2003    ) -> Result<lsp::HoverParams> {
2004        Ok(lsp::HoverParams {
2005            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
2006            work_done_progress_params: Default::default(),
2007        })
2008    }
2009
2010    async fn response_from_lsp(
2011        self,
2012        message: Option<lsp::Hover>,
2013        _: Entity<LspStore>,
2014        buffer: Entity<Buffer>,
2015        _: LanguageServerId,
2016        cx: AsyncApp,
2017    ) -> Result<Self::Response> {
2018        let Some(hover) = message else {
2019            return Ok(None);
2020        };
2021
2022        let (language, range) = buffer.read_with(&cx, |buffer, _| {
2023            (
2024                buffer.language().cloned(),
2025                hover.range.map(|range| {
2026                    let token_start =
2027                        buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
2028                    let token_end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
2029                    buffer.anchor_after(token_start)..buffer.anchor_before(token_end)
2030                }),
2031            )
2032        });
2033
2034        fn hover_blocks_from_marked_string(marked_string: lsp::MarkedString) -> Option<HoverBlock> {
2035            let block = match marked_string {
2036                lsp::MarkedString::String(content) => HoverBlock {
2037                    text: content,
2038                    kind: HoverBlockKind::Markdown,
2039                },
2040                lsp::MarkedString::LanguageString(lsp::LanguageString { language, value }) => {
2041                    HoverBlock {
2042                        text: value,
2043                        kind: HoverBlockKind::Code { language },
2044                    }
2045                }
2046            };
2047            if block.text.is_empty() {
2048                None
2049            } else {
2050                Some(block)
2051            }
2052        }
2053
2054        let contents = match hover.contents {
2055            lsp::HoverContents::Scalar(marked_string) => {
2056                hover_blocks_from_marked_string(marked_string)
2057                    .into_iter()
2058                    .collect()
2059            }
2060            lsp::HoverContents::Array(marked_strings) => marked_strings
2061                .into_iter()
2062                .filter_map(hover_blocks_from_marked_string)
2063                .collect(),
2064            lsp::HoverContents::Markup(markup_content) => vec![HoverBlock {
2065                text: markup_content.value,
2066                kind: if markup_content.kind == lsp::MarkupKind::Markdown {
2067                    HoverBlockKind::Markdown
2068                } else {
2069                    HoverBlockKind::PlainText
2070                },
2071            }],
2072        };
2073
2074        Ok(Some(Hover {
2075            contents,
2076            range,
2077            language,
2078        }))
2079    }
2080
2081    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
2082        proto::GetHover {
2083            project_id,
2084            buffer_id: buffer.remote_id().into(),
2085            position: Some(language::proto::serialize_anchor(
2086                &buffer.anchor_before(self.position),
2087            )),
2088            version: serialize_version(&buffer.version),
2089        }
2090    }
2091
2092    async fn from_proto(
2093        message: Self::ProtoRequest,
2094        _: Entity<LspStore>,
2095        buffer: Entity<Buffer>,
2096        mut cx: AsyncApp,
2097    ) -> Result<Self> {
2098        let position = message
2099            .position
2100            .and_then(deserialize_anchor)
2101            .context("invalid position")?;
2102        buffer
2103            .update(&mut cx, |buffer, _| {
2104                buffer.wait_for_version(deserialize_version(&message.version))
2105            })
2106            .await?;
2107        Ok(Self {
2108            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
2109        })
2110    }
2111
2112    fn response_to_proto(
2113        response: Self::Response,
2114        _: &mut LspStore,
2115        _: PeerId,
2116        _: &clock::Global,
2117        _: &mut App,
2118    ) -> proto::GetHoverResponse {
2119        if let Some(response) = response {
2120            let (start, end) = if let Some(range) = response.range {
2121                (
2122                    Some(language::proto::serialize_anchor(&range.start)),
2123                    Some(language::proto::serialize_anchor(&range.end)),
2124                )
2125            } else {
2126                (None, None)
2127            };
2128
2129            let contents = response
2130                .contents
2131                .into_iter()
2132                .map(|block| proto::HoverBlock {
2133                    text: block.text,
2134                    is_markdown: block.kind == HoverBlockKind::Markdown,
2135                    language: if let HoverBlockKind::Code { language } = block.kind {
2136                        Some(language)
2137                    } else {
2138                        None
2139                    },
2140                })
2141                .collect();
2142
2143            proto::GetHoverResponse {
2144                start,
2145                end,
2146                contents,
2147            }
2148        } else {
2149            proto::GetHoverResponse {
2150                start: None,
2151                end: None,
2152                contents: Vec::new(),
2153            }
2154        }
2155    }
2156
2157    async fn response_from_proto(
2158        self,
2159        message: proto::GetHoverResponse,
2160        _: Entity<LspStore>,
2161        buffer: Entity<Buffer>,
2162        mut cx: AsyncApp,
2163    ) -> Result<Self::Response> {
2164        let contents: Vec<_> = message
2165            .contents
2166            .into_iter()
2167            .map(|block| HoverBlock {
2168                text: block.text,
2169                kind: if let Some(language) = block.language {
2170                    HoverBlockKind::Code { language }
2171                } else if block.is_markdown {
2172                    HoverBlockKind::Markdown
2173                } else {
2174                    HoverBlockKind::PlainText
2175                },
2176            })
2177            .collect();
2178        if contents.is_empty() {
2179            return Ok(None);
2180        }
2181
2182        let language = buffer.read_with(&cx, |buffer, _| buffer.language().cloned());
2183        let range = if let (Some(start), Some(end)) = (message.start, message.end) {
2184            language::proto::deserialize_anchor(start)
2185                .and_then(|start| language::proto::deserialize_anchor(end).map(|end| start..end))
2186        } else {
2187            None
2188        };
2189        if let Some(range) = range.as_ref() {
2190            buffer
2191                .update(&mut cx, |buffer, _| {
2192                    buffer.wait_for_anchors([range.start, range.end])
2193                })
2194                .await?;
2195        }
2196
2197        Ok(Some(Hover {
2198            contents,
2199            range,
2200            language,
2201        }))
2202    }
2203
2204    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
2205        BufferId::new(message.buffer_id)
2206    }
2207}
2208
2209impl GetCompletions {
2210    pub fn can_resolve_completions(capabilities: &lsp::ServerCapabilities) -> bool {
2211        capabilities
2212            .completion_provider
2213            .as_ref()
2214            .and_then(|options| options.resolve_provider)
2215            .unwrap_or(false)
2216    }
2217}
2218
2219#[async_trait(?Send)]
2220impl LspCommand for GetCompletions {
2221    type Response = CoreCompletionResponse;
2222    type LspRequest = lsp::request::Completion;
2223    type ProtoRequest = proto::GetCompletions;
2224
2225    fn display_name(&self) -> &str {
2226        "Get completion"
2227    }
2228
2229    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2230        capabilities
2231            .server_capabilities
2232            .completion_provider
2233            .is_some()
2234    }
2235
2236    fn to_lsp(
2237        &self,
2238        path: &Path,
2239        _: &Buffer,
2240        _: &Arc<LanguageServer>,
2241        _: &App,
2242    ) -> Result<lsp::CompletionParams> {
2243        Ok(lsp::CompletionParams {
2244            text_document_position: make_lsp_text_document_position(path, self.position)?,
2245            context: Some(self.context.clone()),
2246            work_done_progress_params: Default::default(),
2247            partial_result_params: Default::default(),
2248        })
2249    }
2250
2251    async fn response_from_lsp(
2252        self,
2253        completions: Option<lsp::CompletionResponse>,
2254        lsp_store: Entity<LspStore>,
2255        buffer: Entity<Buffer>,
2256        server_id: LanguageServerId,
2257        mut cx: AsyncApp,
2258    ) -> Result<Self::Response> {
2259        let mut response_list = None;
2260        let (mut completions, mut is_incomplete) = if let Some(completions) = completions {
2261            match completions {
2262                lsp::CompletionResponse::Array(completions) => (completions, false),
2263                lsp::CompletionResponse::List(mut list) => {
2264                    let is_incomplete = list.is_incomplete;
2265                    let items = std::mem::take(&mut list.items);
2266                    response_list = Some(list);
2267                    (items, is_incomplete)
2268                }
2269            }
2270        } else {
2271            (Vec::new(), false)
2272        };
2273
2274        let unfiltered_completions_count = completions.len();
2275
2276        let language_server_adapter = lsp_store
2277            .read_with(&cx, |lsp_store, _| {
2278                lsp_store.language_server_adapter_for_id(server_id)
2279            })
2280            .with_context(|| format!("no language server with id {server_id}"))?;
2281
2282        let lsp_defaults = response_list
2283            .as_ref()
2284            .and_then(|list| list.item_defaults.clone())
2285            .map(Arc::new);
2286
2287        let mut completion_edits = Vec::new();
2288        buffer.update(&mut cx, |buffer, _cx| {
2289            let snapshot = buffer.snapshot();
2290            let clipped_position = buffer.clip_point_utf16(Unclipped(self.position), Bias::Left);
2291
2292            let mut range_for_token = None;
2293            completions.retain(|lsp_completion| {
2294                let lsp_edit = lsp_completion.text_edit.clone().or_else(|| {
2295                    let default_text_edit = lsp_defaults.as_deref()?.edit_range.as_ref()?;
2296                    let new_text = lsp_completion
2297                        .text_edit_text
2298                        .as_ref()
2299                        .unwrap_or(&lsp_completion.label)
2300                        .clone();
2301                    match default_text_edit {
2302                        CompletionListItemDefaultsEditRange::Range(range) => {
2303                            Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
2304                                range: *range,
2305                                new_text,
2306                            }))
2307                        }
2308                        CompletionListItemDefaultsEditRange::InsertAndReplace {
2309                            insert,
2310                            replace,
2311                        } => Some(lsp::CompletionTextEdit::InsertAndReplace(
2312                            lsp::InsertReplaceEdit {
2313                                new_text,
2314                                insert: *insert,
2315                                replace: *replace,
2316                            },
2317                        )),
2318                    }
2319                });
2320
2321                let edit = match lsp_edit {
2322                    // If the language server provides a range to overwrite, then
2323                    // check that the range is valid.
2324                    Some(completion_text_edit) => {
2325                        match parse_completion_text_edit(&completion_text_edit, &snapshot) {
2326                            Some(edit) => edit,
2327                            None => return false,
2328                        }
2329                    }
2330                    // If the language server does not provide a range, then infer
2331                    // the range based on the syntax tree.
2332                    None => {
2333                        if self.position != clipped_position {
2334                            log::info!("completion out of expected range ");
2335                            return false;
2336                        }
2337
2338                        let default_edit_range = lsp_defaults.as_ref().and_then(|lsp_defaults| {
2339                            lsp_defaults
2340                                .edit_range
2341                                .as_ref()
2342                                .and_then(|range| match range {
2343                                    CompletionListItemDefaultsEditRange::Range(r) => Some(r),
2344                                    _ => None,
2345                                })
2346                        });
2347
2348                        let range = if let Some(range) = default_edit_range {
2349                            let range = range_from_lsp(*range);
2350                            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2351                            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2352                            if start != range.start.0 || end != range.end.0 {
2353                                log::info!("completion out of expected range");
2354                                return false;
2355                            }
2356
2357                            snapshot.anchor_before(start)..snapshot.anchor_after(end)
2358                        } else {
2359                            range_for_token
2360                                .get_or_insert_with(|| {
2361                                    let offset = self.position.to_offset(&snapshot);
2362                                    let (range, kind) = snapshot.surrounding_word(
2363                                        offset,
2364                                        Some(CharScopeContext::Completion),
2365                                    );
2366                                    let range = if kind == Some(CharKind::Word) {
2367                                        range
2368                                    } else {
2369                                        offset..offset
2370                                    };
2371
2372                                    snapshot.anchor_before(range.start)
2373                                        ..snapshot.anchor_after(range.end)
2374                                })
2375                                .clone()
2376                        };
2377
2378                        // We already know text_edit is None here
2379                        let text = lsp_completion
2380                            .insert_text
2381                            .as_ref()
2382                            .unwrap_or(&lsp_completion.label)
2383                            .clone();
2384
2385                        ParsedCompletionEdit {
2386                            replace_range: range,
2387                            insert_range: None,
2388                            new_text: text,
2389                        }
2390                    }
2391                };
2392
2393                completion_edits.push(edit);
2394                true
2395            });
2396        });
2397
2398        // If completions were filtered out due to errors that may be transient, mark the result
2399        // incomplete so that it is re-queried.
2400        if unfiltered_completions_count != completions.len() {
2401            is_incomplete = true;
2402        }
2403
2404        language_server_adapter
2405            .process_completions(&mut completions)
2406            .await;
2407
2408        let completions = completions
2409            .into_iter()
2410            .zip(completion_edits)
2411            .map(|(mut lsp_completion, mut edit)| {
2412                LineEnding::normalize(&mut edit.new_text);
2413                if lsp_completion.data.is_none()
2414                    && let Some(default_data) = lsp_defaults
2415                        .as_ref()
2416                        .and_then(|item_defaults| item_defaults.data.clone())
2417                {
2418                    // Servers (e.g. JDTLS) prefer unchanged completions, when resolving the items later,
2419                    // so we do not insert the defaults here, but `data` is needed for resolving, so this is an exception.
2420                    lsp_completion.data = Some(default_data);
2421                }
2422                CoreCompletion {
2423                    replace_range: edit.replace_range,
2424                    new_text: edit.new_text,
2425                    source: CompletionSource::Lsp {
2426                        insert_range: edit.insert_range,
2427                        server_id,
2428                        lsp_completion: Box::new(lsp_completion),
2429                        lsp_defaults: lsp_defaults.clone(),
2430                        resolved: false,
2431                    },
2432                }
2433            })
2434            .collect();
2435
2436        Ok(CoreCompletionResponse {
2437            completions,
2438            is_incomplete,
2439        })
2440    }
2441
2442    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCompletions {
2443        let anchor = buffer.anchor_after(self.position);
2444        proto::GetCompletions {
2445            project_id,
2446            buffer_id: buffer.remote_id().into(),
2447            position: Some(language::proto::serialize_anchor(&anchor)),
2448            version: serialize_version(&buffer.version()),
2449            server_id: self.server_id.map(|id| id.to_proto()),
2450        }
2451    }
2452
2453    async fn from_proto(
2454        message: proto::GetCompletions,
2455        _: Entity<LspStore>,
2456        buffer: Entity<Buffer>,
2457        mut cx: AsyncApp,
2458    ) -> Result<Self> {
2459        let version = deserialize_version(&message.version);
2460        buffer
2461            .update(&mut cx, |buffer, _| buffer.wait_for_version(version))
2462            .await?;
2463        let position = message
2464            .position
2465            .and_then(language::proto::deserialize_anchor)
2466            .map(|p| {
2467                buffer.read_with(&cx, |buffer, _| {
2468                    buffer.clip_point_utf16(Unclipped(p.to_point_utf16(buffer)), Bias::Left)
2469                })
2470            })
2471            .context("invalid position")?;
2472        Ok(Self {
2473            position,
2474            context: CompletionContext {
2475                trigger_kind: CompletionTriggerKind::INVOKED,
2476                trigger_character: None,
2477            },
2478            server_id: message
2479                .server_id
2480                .map(|id| lsp::LanguageServerId::from_proto(id)),
2481        })
2482    }
2483
2484    fn response_to_proto(
2485        response: CoreCompletionResponse,
2486        _: &mut LspStore,
2487        _: PeerId,
2488        buffer_version: &clock::Global,
2489        _: &mut App,
2490    ) -> proto::GetCompletionsResponse {
2491        proto::GetCompletionsResponse {
2492            completions: response
2493                .completions
2494                .iter()
2495                .map(LspStore::serialize_completion)
2496                .collect(),
2497            version: serialize_version(buffer_version),
2498            can_reuse: !response.is_incomplete,
2499        }
2500    }
2501
2502    async fn response_from_proto(
2503        self,
2504        message: proto::GetCompletionsResponse,
2505        _project: Entity<LspStore>,
2506        buffer: Entity<Buffer>,
2507        mut cx: AsyncApp,
2508    ) -> Result<Self::Response> {
2509        buffer
2510            .update(&mut cx, |buffer, _| {
2511                buffer.wait_for_version(deserialize_version(&message.version))
2512            })
2513            .await?;
2514
2515        let completions = message
2516            .completions
2517            .into_iter()
2518            .map(LspStore::deserialize_completion)
2519            .collect::<Result<Vec<_>>>()?;
2520
2521        Ok(CoreCompletionResponse {
2522            completions,
2523            is_incomplete: !message.can_reuse,
2524        })
2525    }
2526
2527    fn buffer_id_from_proto(message: &proto::GetCompletions) -> Result<BufferId> {
2528        BufferId::new(message.buffer_id)
2529    }
2530}
2531
2532pub struct ParsedCompletionEdit {
2533    pub replace_range: Range<Anchor>,
2534    pub insert_range: Option<Range<Anchor>>,
2535    pub new_text: String,
2536}
2537
2538pub(crate) fn parse_completion_text_edit(
2539    edit: &lsp::CompletionTextEdit,
2540    snapshot: &BufferSnapshot,
2541) -> Option<ParsedCompletionEdit> {
2542    let (replace_range, insert_range, new_text) = match edit {
2543        lsp::CompletionTextEdit::Edit(edit) => (edit.range, None, &edit.new_text),
2544        lsp::CompletionTextEdit::InsertAndReplace(edit) => {
2545            (edit.replace, Some(edit.insert), &edit.new_text)
2546        }
2547    };
2548
2549    let replace_range = {
2550        let range = range_from_lsp(replace_range);
2551        let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2552        let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2553        if start != range.start.0 || end != range.end.0 {
2554            log::info!(
2555                "completion out of expected range, start: {start:?}, end: {end:?}, range: {range:?}"
2556            );
2557            return None;
2558        }
2559        snapshot.anchor_before(start)..snapshot.anchor_after(end)
2560    };
2561
2562    let insert_range = match insert_range {
2563        None => None,
2564        Some(insert_range) => {
2565            let range = range_from_lsp(insert_range);
2566            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2567            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2568            if start != range.start.0 || end != range.end.0 {
2569                log::info!("completion (insert) out of expected range");
2570                return None;
2571            }
2572            Some(snapshot.anchor_before(start)..snapshot.anchor_after(end))
2573        }
2574    };
2575
2576    Some(ParsedCompletionEdit {
2577        insert_range,
2578        replace_range,
2579        new_text: new_text.clone(),
2580    })
2581}
2582
2583#[async_trait(?Send)]
2584impl LspCommand for GetCodeActions {
2585    type Response = Vec<CodeAction>;
2586    type LspRequest = lsp::request::CodeActionRequest;
2587    type ProtoRequest = proto::GetCodeActions;
2588
2589    fn display_name(&self) -> &str {
2590        "Get code actions"
2591    }
2592
2593    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2594        match &capabilities.server_capabilities.code_action_provider {
2595            None => false,
2596            Some(lsp::CodeActionProviderCapability::Simple(false)) => false,
2597            _ => {
2598                // If we do know that we want specific code actions AND we know that
2599                // the server only supports specific code actions, then we want to filter
2600                // down to the ones that are supported.
2601                if let Some((requested, supported)) = self
2602                    .kinds
2603                    .as_ref()
2604                    .zip(Self::supported_code_action_kinds(capabilities))
2605                {
2606                    requested.iter().any(|requested_kind| {
2607                        supported.iter().any(|supported_kind| {
2608                            code_action_kind_matches(requested_kind, supported_kind)
2609                        })
2610                    })
2611                } else {
2612                    true
2613                }
2614            }
2615        }
2616    }
2617
2618    fn to_lsp(
2619        &self,
2620        path: &Path,
2621        buffer: &Buffer,
2622        language_server: &Arc<LanguageServer>,
2623        _: &App,
2624    ) -> Result<lsp::CodeActionParams> {
2625        let mut relevant_diagnostics = Vec::new();
2626        for entry in buffer
2627            .snapshot()
2628            .diagnostics_in_range::<_, language::PointUtf16>(self.range.clone(), false)
2629        {
2630            relevant_diagnostics.push(entry.to_lsp_diagnostic_stub()?);
2631        }
2632
2633        let supported =
2634            Self::supported_code_action_kinds(language_server.adapter_server_capabilities());
2635
2636        let only = if let Some(requested) = &self.kinds {
2637            if let Some(supported_kinds) = supported {
2638                let filtered = requested
2639                    .iter()
2640                    .filter(|requested_kind| {
2641                        supported_kinds.iter().any(|supported_kind| {
2642                            code_action_kind_matches(requested_kind, supported_kind)
2643                        })
2644                    })
2645                    .cloned()
2646                    .collect();
2647                Some(filtered)
2648            } else {
2649                Some(requested.clone())
2650            }
2651        } else {
2652            supported
2653        };
2654
2655        Ok(lsp::CodeActionParams {
2656            text_document: make_text_document_identifier(path)?,
2657            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
2658            work_done_progress_params: Default::default(),
2659            partial_result_params: Default::default(),
2660            context: lsp::CodeActionContext {
2661                diagnostics: relevant_diagnostics,
2662                only,
2663                ..lsp::CodeActionContext::default()
2664            },
2665        })
2666    }
2667
2668    async fn response_from_lsp(
2669        self,
2670        actions: Option<lsp::CodeActionResponse>,
2671        lsp_store: Entity<LspStore>,
2672        _: Entity<Buffer>,
2673        server_id: LanguageServerId,
2674        cx: AsyncApp,
2675    ) -> Result<Vec<CodeAction>> {
2676        let requested_kinds = self.kinds.as_ref();
2677
2678        let language_server = cx.update(|cx| {
2679            lsp_store
2680                .read(cx)
2681                .language_server_for_id(server_id)
2682                .with_context(|| {
2683                    format!("Missing the language server that just returned a response {server_id}")
2684                })
2685        })?;
2686
2687        let server_capabilities = language_server.capabilities();
2688        let available_commands = server_capabilities
2689            .execute_command_provider
2690            .as_ref()
2691            .map(|options| options.commands.as_slice())
2692            .unwrap_or_default();
2693        Ok(actions
2694            .unwrap_or_default()
2695            .into_iter()
2696            .filter_map(|entry| {
2697                let (lsp_action, resolved) = match entry {
2698                    lsp::CodeActionOrCommand::CodeAction(lsp_action) => {
2699                        if let Some(command) = lsp_action.command.as_ref()
2700                            && !available_commands.contains(&command.command)
2701                        {
2702                            return None;
2703                        }
2704                        (LspAction::Action(Box::new(lsp_action)), false)
2705                    }
2706                    lsp::CodeActionOrCommand::Command(command) => {
2707                        if available_commands.contains(&command.command) {
2708                            (LspAction::Command(command), true)
2709                        } else {
2710                            return None;
2711                        }
2712                    }
2713                };
2714
2715                if let Some((kinds, kind)) = requested_kinds.zip(lsp_action.action_kind())
2716                    && !kinds
2717                        .iter()
2718                        .any(|requested_kind| code_action_kind_matches(requested_kind, &kind))
2719                {
2720                    return None;
2721                }
2722
2723                Some(CodeAction {
2724                    server_id,
2725                    range: self.range.clone(),
2726                    lsp_action,
2727                    resolved,
2728                })
2729            })
2730            .collect())
2731    }
2732
2733    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeActions {
2734        proto::GetCodeActions {
2735            project_id,
2736            buffer_id: buffer.remote_id().into(),
2737            start: Some(language::proto::serialize_anchor(&self.range.start)),
2738            end: Some(language::proto::serialize_anchor(&self.range.end)),
2739            version: serialize_version(&buffer.version()),
2740        }
2741    }
2742
2743    async fn from_proto(
2744        message: proto::GetCodeActions,
2745        _: Entity<LspStore>,
2746        buffer: Entity<Buffer>,
2747        mut cx: AsyncApp,
2748    ) -> Result<Self> {
2749        let start = message
2750            .start
2751            .and_then(language::proto::deserialize_anchor)
2752            .context("invalid start")?;
2753        let end = message
2754            .end
2755            .and_then(language::proto::deserialize_anchor)
2756            .context("invalid end")?;
2757        buffer
2758            .update(&mut cx, |buffer, _| {
2759                buffer.wait_for_version(deserialize_version(&message.version))
2760            })
2761            .await?;
2762
2763        Ok(Self {
2764            range: start..end,
2765            kinds: None,
2766        })
2767    }
2768
2769    fn response_to_proto(
2770        code_actions: Vec<CodeAction>,
2771        _: &mut LspStore,
2772        _: PeerId,
2773        buffer_version: &clock::Global,
2774        _: &mut App,
2775    ) -> proto::GetCodeActionsResponse {
2776        proto::GetCodeActionsResponse {
2777            actions: code_actions
2778                .iter()
2779                .map(LspStore::serialize_code_action)
2780                .collect(),
2781            version: serialize_version(buffer_version),
2782        }
2783    }
2784
2785    async fn response_from_proto(
2786        self,
2787        message: proto::GetCodeActionsResponse,
2788        _: Entity<LspStore>,
2789        buffer: Entity<Buffer>,
2790        mut cx: AsyncApp,
2791    ) -> Result<Vec<CodeAction>> {
2792        buffer
2793            .update(&mut cx, |buffer, _| {
2794                buffer.wait_for_version(deserialize_version(&message.version))
2795            })
2796            .await?;
2797        message
2798            .actions
2799            .into_iter()
2800            .map(LspStore::deserialize_code_action)
2801            .collect()
2802    }
2803
2804    fn buffer_id_from_proto(message: &proto::GetCodeActions) -> Result<BufferId> {
2805        BufferId::new(message.buffer_id)
2806    }
2807}
2808
2809impl GetCodeActions {
2810    fn supported_code_action_kinds(
2811        capabilities: AdapterServerCapabilities,
2812    ) -> Option<Vec<CodeActionKind>> {
2813        match capabilities.server_capabilities.code_action_provider {
2814            Some(lsp::CodeActionProviderCapability::Options(CodeActionOptions {
2815                code_action_kinds: Some(supported_action_kinds),
2816                ..
2817            })) => Some(supported_action_kinds),
2818            _ => capabilities.code_action_kinds,
2819        }
2820    }
2821
2822    pub fn can_resolve_actions(capabilities: &ServerCapabilities) -> bool {
2823        capabilities
2824            .code_action_provider
2825            .as_ref()
2826            .and_then(|options| match options {
2827                lsp::CodeActionProviderCapability::Simple(_is_supported) => None,
2828                lsp::CodeActionProviderCapability::Options(options) => options.resolve_provider,
2829            })
2830            .unwrap_or(false)
2831    }
2832}
2833
2834impl OnTypeFormatting {
2835    pub fn supports_on_type_formatting(trigger: &str, capabilities: &ServerCapabilities) -> bool {
2836        let Some(on_type_formatting_options) = &capabilities.document_on_type_formatting_provider
2837        else {
2838            return false;
2839        };
2840        on_type_formatting_options
2841            .first_trigger_character
2842            .contains(trigger)
2843            || on_type_formatting_options
2844                .more_trigger_character
2845                .iter()
2846                .flatten()
2847                .any(|chars| chars.contains(trigger))
2848    }
2849}
2850
2851#[async_trait(?Send)]
2852impl LspCommand for OnTypeFormatting {
2853    type Response = Option<Transaction>;
2854    type LspRequest = lsp::request::OnTypeFormatting;
2855    type ProtoRequest = proto::OnTypeFormatting;
2856
2857    fn display_name(&self) -> &str {
2858        "Formatting on typing"
2859    }
2860
2861    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2862        Self::supports_on_type_formatting(&self.trigger, &capabilities.server_capabilities)
2863    }
2864
2865    fn to_lsp(
2866        &self,
2867        path: &Path,
2868        _: &Buffer,
2869        _: &Arc<LanguageServer>,
2870        _: &App,
2871    ) -> Result<lsp::DocumentOnTypeFormattingParams> {
2872        Ok(lsp::DocumentOnTypeFormattingParams {
2873            text_document_position: make_lsp_text_document_position(path, self.position)?,
2874            ch: self.trigger.clone(),
2875            options: self.options.clone(),
2876        })
2877    }
2878
2879    async fn response_from_lsp(
2880        self,
2881        message: Option<Vec<lsp::TextEdit>>,
2882        lsp_store: Entity<LspStore>,
2883        buffer: Entity<Buffer>,
2884        server_id: LanguageServerId,
2885        mut cx: AsyncApp,
2886    ) -> Result<Option<Transaction>> {
2887        if let Some(edits) = message {
2888            let (lsp_adapter, lsp_server) =
2889                language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
2890            LocalLspStore::deserialize_text_edits(
2891                lsp_store,
2892                buffer,
2893                edits,
2894                self.push_to_history,
2895                lsp_adapter,
2896                lsp_server,
2897                &mut cx,
2898            )
2899            .await
2900        } else {
2901            Ok(None)
2902        }
2903    }
2904
2905    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::OnTypeFormatting {
2906        proto::OnTypeFormatting {
2907            project_id,
2908            buffer_id: buffer.remote_id().into(),
2909            position: Some(language::proto::serialize_anchor(
2910                &buffer.anchor_before(self.position),
2911            )),
2912            trigger: self.trigger.clone(),
2913            version: serialize_version(&buffer.version()),
2914        }
2915    }
2916
2917    async fn from_proto(
2918        message: proto::OnTypeFormatting,
2919        _: Entity<LspStore>,
2920        buffer: Entity<Buffer>,
2921        mut cx: AsyncApp,
2922    ) -> Result<Self> {
2923        let position = message
2924            .position
2925            .and_then(deserialize_anchor)
2926            .context("invalid position")?;
2927        buffer
2928            .update(&mut cx, |buffer, _| {
2929                buffer.wait_for_version(deserialize_version(&message.version))
2930            })
2931            .await?;
2932
2933        let options = buffer.update(&mut cx, |buffer, cx| {
2934            lsp_formatting_options(
2935                language_settings(buffer.language().map(|l| l.name()), buffer.file(), cx).as_ref(),
2936            )
2937        });
2938
2939        Ok(Self {
2940            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
2941            trigger: message.trigger.clone(),
2942            options,
2943            push_to_history: false,
2944        })
2945    }
2946
2947    fn response_to_proto(
2948        response: Option<Transaction>,
2949        _: &mut LspStore,
2950        _: PeerId,
2951        _: &clock::Global,
2952        _: &mut App,
2953    ) -> proto::OnTypeFormattingResponse {
2954        proto::OnTypeFormattingResponse {
2955            transaction: response
2956                .map(|transaction| language::proto::serialize_transaction(&transaction)),
2957        }
2958    }
2959
2960    async fn response_from_proto(
2961        self,
2962        message: proto::OnTypeFormattingResponse,
2963        _: Entity<LspStore>,
2964        _: Entity<Buffer>,
2965        _: AsyncApp,
2966    ) -> Result<Option<Transaction>> {
2967        let Some(transaction) = message.transaction else {
2968            return Ok(None);
2969        };
2970        Ok(Some(language::proto::deserialize_transaction(transaction)?))
2971    }
2972
2973    fn buffer_id_from_proto(message: &proto::OnTypeFormatting) -> Result<BufferId> {
2974        BufferId::new(message.buffer_id)
2975    }
2976}
2977
2978impl InlayHints {
2979    pub async fn lsp_to_project_hint(
2980        lsp_hint: lsp::InlayHint,
2981        buffer_handle: &Entity<Buffer>,
2982        server_id: LanguageServerId,
2983        resolve_state: ResolveState,
2984        force_no_type_left_padding: bool,
2985        cx: &mut AsyncApp,
2986    ) -> anyhow::Result<InlayHint> {
2987        let kind = lsp_hint.kind.and_then(|kind| match kind {
2988            lsp::InlayHintKind::TYPE => Some(InlayHintKind::Type),
2989            lsp::InlayHintKind::PARAMETER => Some(InlayHintKind::Parameter),
2990            _ => None,
2991        });
2992
2993        let position = buffer_handle.read_with(cx, |buffer, _| {
2994            let position = buffer.clip_point_utf16(point_from_lsp(lsp_hint.position), Bias::Left);
2995            if kind == Some(InlayHintKind::Parameter) {
2996                buffer.anchor_before(position)
2997            } else {
2998                buffer.anchor_after(position)
2999            }
3000        });
3001        let label = Self::lsp_inlay_label_to_project(lsp_hint.label, server_id)
3002            .await
3003            .context("lsp to project inlay hint conversion")?;
3004        let padding_left = if force_no_type_left_padding && kind == Some(InlayHintKind::Type) {
3005            false
3006        } else {
3007            lsp_hint.padding_left.unwrap_or(false)
3008        };
3009
3010        Ok(InlayHint {
3011            position,
3012            padding_left,
3013            padding_right: lsp_hint.padding_right.unwrap_or(false),
3014            label,
3015            kind,
3016            tooltip: lsp_hint.tooltip.map(|tooltip| match tooltip {
3017                lsp::InlayHintTooltip::String(s) => InlayHintTooltip::String(s),
3018                lsp::InlayHintTooltip::MarkupContent(markup_content) => {
3019                    InlayHintTooltip::MarkupContent(MarkupContent {
3020                        kind: match markup_content.kind {
3021                            lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
3022                            lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
3023                        },
3024                        value: markup_content.value,
3025                    })
3026                }
3027            }),
3028            resolve_state,
3029        })
3030    }
3031
3032    async fn lsp_inlay_label_to_project(
3033        lsp_label: lsp::InlayHintLabel,
3034        server_id: LanguageServerId,
3035    ) -> anyhow::Result<InlayHintLabel> {
3036        let label = match lsp_label {
3037            lsp::InlayHintLabel::String(s) => InlayHintLabel::String(s),
3038            lsp::InlayHintLabel::LabelParts(lsp_parts) => {
3039                let mut parts = Vec::with_capacity(lsp_parts.len());
3040                for lsp_part in lsp_parts {
3041                    parts.push(InlayHintLabelPart {
3042                        value: lsp_part.value,
3043                        tooltip: lsp_part.tooltip.map(|tooltip| match tooltip {
3044                            lsp::InlayHintLabelPartTooltip::String(s) => {
3045                                InlayHintLabelPartTooltip::String(s)
3046                            }
3047                            lsp::InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
3048                                InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
3049                                    kind: match markup_content.kind {
3050                                        lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
3051                                        lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
3052                                    },
3053                                    value: markup_content.value,
3054                                })
3055                            }
3056                        }),
3057                        location: Some(server_id).zip(lsp_part.location),
3058                    });
3059                }
3060                InlayHintLabel::LabelParts(parts)
3061            }
3062        };
3063
3064        Ok(label)
3065    }
3066
3067    pub fn project_to_proto_hint(response_hint: InlayHint) -> proto::InlayHint {
3068        let (state, lsp_resolve_state) = match response_hint.resolve_state {
3069            ResolveState::Resolved => (0, None),
3070            ResolveState::CanResolve(server_id, resolve_data) => (
3071                1,
3072                Some(proto::resolve_state::LspResolveState {
3073                    server_id: server_id.0 as u64,
3074                    value: resolve_data.map(|json_data| {
3075                        serde_json::to_string(&json_data)
3076                            .expect("failed to serialize resolve json data")
3077                    }),
3078                }),
3079            ),
3080            ResolveState::Resolving => (2, None),
3081        };
3082        let resolve_state = Some(proto::ResolveState {
3083            state,
3084            lsp_resolve_state,
3085        });
3086        proto::InlayHint {
3087            position: Some(language::proto::serialize_anchor(&response_hint.position)),
3088            padding_left: response_hint.padding_left,
3089            padding_right: response_hint.padding_right,
3090            label: Some(proto::InlayHintLabel {
3091                label: Some(match response_hint.label {
3092                    InlayHintLabel::String(s) => proto::inlay_hint_label::Label::Value(s),
3093                    InlayHintLabel::LabelParts(label_parts) => {
3094                        proto::inlay_hint_label::Label::LabelParts(proto::InlayHintLabelParts {
3095                            parts: label_parts.into_iter().map(|label_part| {
3096                                let location_url = label_part.location.as_ref().map(|(_, location)| location.uri.to_string());
3097                                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 });
3098                                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 });
3099                                proto::InlayHintLabelPart {
3100                                value: label_part.value,
3101                                tooltip: label_part.tooltip.map(|tooltip| {
3102                                    let proto_tooltip = match tooltip {
3103                                        InlayHintLabelPartTooltip::String(s) => proto::inlay_hint_label_part_tooltip::Content::Value(s),
3104                                        InlayHintLabelPartTooltip::MarkupContent(markup_content) => proto::inlay_hint_label_part_tooltip::Content::MarkupContent(proto::MarkupContent {
3105                                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
3106                                            value: markup_content.value,
3107                                        }),
3108                                    };
3109                                    proto::InlayHintLabelPartTooltip {content: Some(proto_tooltip)}
3110                                }),
3111                                location_url,
3112                                location_range_start,
3113                                location_range_end,
3114                                language_server_id: label_part.location.as_ref().map(|(server_id, _)| server_id.0 as u64),
3115                            }}).collect()
3116                        })
3117                    }
3118                }),
3119            }),
3120            kind: response_hint.kind.map(|kind| kind.name().to_string()),
3121            tooltip: response_hint.tooltip.map(|response_tooltip| {
3122                let proto_tooltip = match response_tooltip {
3123                    InlayHintTooltip::String(s) => proto::inlay_hint_tooltip::Content::Value(s),
3124                    InlayHintTooltip::MarkupContent(markup_content) => {
3125                        proto::inlay_hint_tooltip::Content::MarkupContent(proto::MarkupContent {
3126                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
3127                            value: markup_content.value,
3128                        })
3129                    }
3130                };
3131                proto::InlayHintTooltip {
3132                    content: Some(proto_tooltip),
3133                }
3134            }),
3135            resolve_state,
3136        }
3137    }
3138
3139    pub fn proto_to_project_hint(message_hint: proto::InlayHint) -> anyhow::Result<InlayHint> {
3140        let resolve_state = message_hint.resolve_state.as_ref().unwrap_or_else(|| {
3141            panic!("incorrect proto inlay hint message: no resolve state in hint {message_hint:?}",)
3142        });
3143        let resolve_state_data = resolve_state
3144            .lsp_resolve_state.as_ref()
3145            .map(|lsp_resolve_state| {
3146                let value = lsp_resolve_state.value.as_deref().map(|value| {
3147                    serde_json::from_str::<Option<lsp::LSPAny>>(value)
3148                        .with_context(|| format!("incorrect proto inlay hint message: non-json resolve state {lsp_resolve_state:?}"))
3149                }).transpose()?.flatten();
3150                anyhow::Ok((LanguageServerId(lsp_resolve_state.server_id as usize), value))
3151            })
3152            .transpose()?;
3153        let resolve_state = match resolve_state.state {
3154            0 => ResolveState::Resolved,
3155            1 => {
3156                let (server_id, lsp_resolve_state) = resolve_state_data.with_context(|| {
3157                    format!(
3158                        "No lsp resolve data for the hint that can be resolved: {message_hint:?}"
3159                    )
3160                })?;
3161                ResolveState::CanResolve(server_id, lsp_resolve_state)
3162            }
3163            2 => ResolveState::Resolving,
3164            invalid => {
3165                anyhow::bail!("Unexpected resolve state {invalid} for hint {message_hint:?}")
3166            }
3167        };
3168        Ok(InlayHint {
3169            position: message_hint
3170                .position
3171                .and_then(language::proto::deserialize_anchor)
3172                .context("invalid position")?,
3173            label: match message_hint
3174                .label
3175                .and_then(|label| label.label)
3176                .context("missing label")?
3177            {
3178                proto::inlay_hint_label::Label::Value(s) => InlayHintLabel::String(s),
3179                proto::inlay_hint_label::Label::LabelParts(parts) => {
3180                    let mut label_parts = Vec::new();
3181                    for part in parts.parts {
3182                        label_parts.push(InlayHintLabelPart {
3183                            value: part.value,
3184                            tooltip: part.tooltip.map(|tooltip| match tooltip.content {
3185                                Some(proto::inlay_hint_label_part_tooltip::Content::Value(s)) => {
3186                                    InlayHintLabelPartTooltip::String(s)
3187                                }
3188                                Some(
3189                                    proto::inlay_hint_label_part_tooltip::Content::MarkupContent(
3190                                        markup_content,
3191                                    ),
3192                                ) => InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
3193                                    kind: if markup_content.is_markdown {
3194                                        HoverBlockKind::Markdown
3195                                    } else {
3196                                        HoverBlockKind::PlainText
3197                                    },
3198                                    value: markup_content.value,
3199                                }),
3200                                None => InlayHintLabelPartTooltip::String(String::new()),
3201                            }),
3202                            location: {
3203                                match part
3204                                    .location_url
3205                                    .zip(
3206                                        part.location_range_start.and_then(|start| {
3207                                            Some(start..part.location_range_end?)
3208                                        }),
3209                                    )
3210                                    .zip(part.language_server_id)
3211                                {
3212                                    Some(((uri, range), server_id)) => Some((
3213                                        LanguageServerId(server_id as usize),
3214                                        lsp::Location {
3215                                            uri: lsp::Uri::from_str(&uri)
3216                                                .context("invalid uri in hint part {part:?}")?,
3217                                            range: lsp::Range::new(
3218                                                point_to_lsp(PointUtf16::new(
3219                                                    range.start.row,
3220                                                    range.start.column,
3221                                                )),
3222                                                point_to_lsp(PointUtf16::new(
3223                                                    range.end.row,
3224                                                    range.end.column,
3225                                                )),
3226                                            ),
3227                                        },
3228                                    )),
3229                                    None => None,
3230                                }
3231                            },
3232                        });
3233                    }
3234
3235                    InlayHintLabel::LabelParts(label_parts)
3236                }
3237            },
3238            padding_left: message_hint.padding_left,
3239            padding_right: message_hint.padding_right,
3240            kind: message_hint
3241                .kind
3242                .as_deref()
3243                .and_then(InlayHintKind::from_name),
3244            tooltip: message_hint.tooltip.and_then(|tooltip| {
3245                Some(match tooltip.content? {
3246                    proto::inlay_hint_tooltip::Content::Value(s) => InlayHintTooltip::String(s),
3247                    proto::inlay_hint_tooltip::Content::MarkupContent(markup_content) => {
3248                        InlayHintTooltip::MarkupContent(MarkupContent {
3249                            kind: if markup_content.is_markdown {
3250                                HoverBlockKind::Markdown
3251                            } else {
3252                                HoverBlockKind::PlainText
3253                            },
3254                            value: markup_content.value,
3255                        })
3256                    }
3257                })
3258            }),
3259            resolve_state,
3260        })
3261    }
3262
3263    pub fn project_to_lsp_hint(hint: InlayHint, snapshot: &BufferSnapshot) -> lsp::InlayHint {
3264        lsp::InlayHint {
3265            position: point_to_lsp(hint.position.to_point_utf16(snapshot)),
3266            kind: hint.kind.map(|kind| match kind {
3267                InlayHintKind::Type => lsp::InlayHintKind::TYPE,
3268                InlayHintKind::Parameter => lsp::InlayHintKind::PARAMETER,
3269            }),
3270            text_edits: None,
3271            tooltip: hint.tooltip.and_then(|tooltip| {
3272                Some(match tooltip {
3273                    InlayHintTooltip::String(s) => lsp::InlayHintTooltip::String(s),
3274                    InlayHintTooltip::MarkupContent(markup_content) => {
3275                        lsp::InlayHintTooltip::MarkupContent(lsp::MarkupContent {
3276                            kind: match markup_content.kind {
3277                                HoverBlockKind::PlainText => lsp::MarkupKind::PlainText,
3278                                HoverBlockKind::Markdown => lsp::MarkupKind::Markdown,
3279                                HoverBlockKind::Code { .. } => return None,
3280                            },
3281                            value: markup_content.value,
3282                        })
3283                    }
3284                })
3285            }),
3286            label: match hint.label {
3287                InlayHintLabel::String(s) => lsp::InlayHintLabel::String(s),
3288                InlayHintLabel::LabelParts(label_parts) => lsp::InlayHintLabel::LabelParts(
3289                    label_parts
3290                        .into_iter()
3291                        .map(|part| lsp::InlayHintLabelPart {
3292                            value: part.value,
3293                            tooltip: part.tooltip.and_then(|tooltip| {
3294                                Some(match tooltip {
3295                                    InlayHintLabelPartTooltip::String(s) => {
3296                                        lsp::InlayHintLabelPartTooltip::String(s)
3297                                    }
3298                                    InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
3299                                        lsp::InlayHintLabelPartTooltip::MarkupContent(
3300                                            lsp::MarkupContent {
3301                                                kind: match markup_content.kind {
3302                                                    HoverBlockKind::PlainText => {
3303                                                        lsp::MarkupKind::PlainText
3304                                                    }
3305                                                    HoverBlockKind::Markdown => {
3306                                                        lsp::MarkupKind::Markdown
3307                                                    }
3308                                                    HoverBlockKind::Code { .. } => return None,
3309                                                },
3310                                                value: markup_content.value,
3311                                            },
3312                                        )
3313                                    }
3314                                })
3315                            }),
3316                            location: part.location.map(|(_, location)| location),
3317                            command: None,
3318                        })
3319                        .collect(),
3320                ),
3321            },
3322            padding_left: Some(hint.padding_left),
3323            padding_right: Some(hint.padding_right),
3324            data: match hint.resolve_state {
3325                ResolveState::CanResolve(_, data) => data,
3326                ResolveState::Resolving | ResolveState::Resolved => None,
3327            },
3328        }
3329    }
3330
3331    pub fn can_resolve_inlays(capabilities: &ServerCapabilities) -> bool {
3332        capabilities
3333            .inlay_hint_provider
3334            .as_ref()
3335            .and_then(|options| match options {
3336                OneOf::Left(_is_supported) => None,
3337                OneOf::Right(capabilities) => match capabilities {
3338                    lsp::InlayHintServerCapabilities::Options(o) => o.resolve_provider,
3339                    lsp::InlayHintServerCapabilities::RegistrationOptions(o) => {
3340                        o.inlay_hint_options.resolve_provider
3341                    }
3342                },
3343            })
3344            .unwrap_or(false)
3345    }
3346
3347    pub fn check_capabilities(capabilities: &ServerCapabilities) -> bool {
3348        capabilities
3349            .inlay_hint_provider
3350            .as_ref()
3351            .is_some_and(|inlay_hint_provider| match inlay_hint_provider {
3352                lsp::OneOf::Left(enabled) => *enabled,
3353                lsp::OneOf::Right(_) => true,
3354            })
3355    }
3356}
3357
3358#[async_trait(?Send)]
3359impl LspCommand for InlayHints {
3360    type Response = Vec<InlayHint>;
3361    type LspRequest = lsp::InlayHintRequest;
3362    type ProtoRequest = proto::InlayHints;
3363
3364    fn display_name(&self) -> &str {
3365        "Inlay hints"
3366    }
3367
3368    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3369        Self::check_capabilities(&capabilities.server_capabilities)
3370    }
3371
3372    fn to_lsp(
3373        &self,
3374        path: &Path,
3375        buffer: &Buffer,
3376        _: &Arc<LanguageServer>,
3377        _: &App,
3378    ) -> Result<lsp::InlayHintParams> {
3379        Ok(lsp::InlayHintParams {
3380            text_document: lsp::TextDocumentIdentifier {
3381                uri: file_path_to_lsp_url(path)?,
3382            },
3383            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
3384            work_done_progress_params: Default::default(),
3385        })
3386    }
3387
3388    async fn response_from_lsp(
3389        self,
3390        message: Option<Vec<lsp::InlayHint>>,
3391        lsp_store: Entity<LspStore>,
3392        buffer: Entity<Buffer>,
3393        server_id: LanguageServerId,
3394        mut cx: AsyncApp,
3395    ) -> anyhow::Result<Vec<InlayHint>> {
3396        let (lsp_adapter, lsp_server) =
3397            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
3398        // `typescript-language-server` adds padding to the left for type hints, turning
3399        // `const foo: boolean` into `const foo : boolean` which looks odd.
3400        // `rust-analyzer` does not have the padding for this case, and we have to accommodate both.
3401        //
3402        // We could trim the whole string, but being pessimistic on par with the situation above,
3403        // there might be a hint with multiple whitespaces at the end(s) which we need to display properly.
3404        // Hence let's use a heuristic first to handle the most awkward case and look for more.
3405        let force_no_type_left_padding =
3406            lsp_adapter.name.0.as_ref() == "typescript-language-server";
3407
3408        let hints = message.unwrap_or_default().into_iter().map(|lsp_hint| {
3409            let resolve_state = if InlayHints::can_resolve_inlays(&lsp_server.capabilities()) {
3410                ResolveState::CanResolve(lsp_server.server_id(), lsp_hint.data.clone())
3411            } else {
3412                ResolveState::Resolved
3413            };
3414
3415            let buffer = buffer.clone();
3416            cx.spawn(async move |cx| {
3417                InlayHints::lsp_to_project_hint(
3418                    lsp_hint,
3419                    &buffer,
3420                    server_id,
3421                    resolve_state,
3422                    force_no_type_left_padding,
3423                    cx,
3424                )
3425                .await
3426            })
3427        });
3428        future::join_all(hints)
3429            .await
3430            .into_iter()
3431            .collect::<anyhow::Result<_>>()
3432            .context("lsp to project inlay hints conversion")
3433    }
3434
3435    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::InlayHints {
3436        proto::InlayHints {
3437            project_id,
3438            buffer_id: buffer.remote_id().into(),
3439            start: Some(language::proto::serialize_anchor(&self.range.start)),
3440            end: Some(language::proto::serialize_anchor(&self.range.end)),
3441            version: serialize_version(&buffer.version()),
3442        }
3443    }
3444
3445    async fn from_proto(
3446        message: proto::InlayHints,
3447        _: Entity<LspStore>,
3448        buffer: Entity<Buffer>,
3449        mut cx: AsyncApp,
3450    ) -> Result<Self> {
3451        let start = message
3452            .start
3453            .and_then(language::proto::deserialize_anchor)
3454            .context("invalid start")?;
3455        let end = message
3456            .end
3457            .and_then(language::proto::deserialize_anchor)
3458            .context("invalid end")?;
3459        buffer
3460            .update(&mut cx, |buffer, _| {
3461                buffer.wait_for_version(deserialize_version(&message.version))
3462            })
3463            .await?;
3464
3465        Ok(Self { range: start..end })
3466    }
3467
3468    fn response_to_proto(
3469        response: Vec<InlayHint>,
3470        _: &mut LspStore,
3471        _: PeerId,
3472        buffer_version: &clock::Global,
3473        _: &mut App,
3474    ) -> proto::InlayHintsResponse {
3475        proto::InlayHintsResponse {
3476            hints: response
3477                .into_iter()
3478                .map(InlayHints::project_to_proto_hint)
3479                .collect(),
3480            version: serialize_version(buffer_version),
3481        }
3482    }
3483
3484    async fn response_from_proto(
3485        self,
3486        message: proto::InlayHintsResponse,
3487        _: Entity<LspStore>,
3488        buffer: Entity<Buffer>,
3489        mut cx: AsyncApp,
3490    ) -> anyhow::Result<Vec<InlayHint>> {
3491        buffer
3492            .update(&mut cx, |buffer, _| {
3493                buffer.wait_for_version(deserialize_version(&message.version))
3494            })
3495            .await?;
3496
3497        let mut hints = Vec::new();
3498        for message_hint in message.hints {
3499            hints.push(InlayHints::proto_to_project_hint(message_hint)?);
3500        }
3501
3502        Ok(hints)
3503    }
3504
3505    fn buffer_id_from_proto(message: &proto::InlayHints) -> Result<BufferId> {
3506        BufferId::new(message.buffer_id)
3507    }
3508}
3509
3510#[async_trait(?Send)]
3511impl LspCommand for SemanticTokensFull {
3512    type Response = SemanticTokensResponse;
3513    type LspRequest = lsp::SemanticTokensFullRequest;
3514    type ProtoRequest = proto::SemanticTokens;
3515
3516    fn display_name(&self) -> &str {
3517        "Semantic tokens full"
3518    }
3519
3520    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3521        capabilities
3522            .server_capabilities
3523            .semantic_tokens_provider
3524            .as_ref()
3525            .is_some_and(|semantic_tokens_provider| {
3526                let options = match semantic_tokens_provider {
3527                    lsp::SemanticTokensServerCapabilities::SemanticTokensOptions(opts) => opts,
3528                    lsp::SemanticTokensServerCapabilities::SemanticTokensRegistrationOptions(
3529                        opts,
3530                    ) => &opts.semantic_tokens_options,
3531                };
3532
3533                match options.full {
3534                    Some(lsp::SemanticTokensFullOptions::Bool(is_supported)) => is_supported,
3535                    Some(lsp::SemanticTokensFullOptions::Delta { .. }) => true,
3536                    None => false,
3537                }
3538            })
3539    }
3540
3541    fn to_lsp(
3542        &self,
3543        path: &Path,
3544        _: &Buffer,
3545        _: &Arc<LanguageServer>,
3546        _: &App,
3547    ) -> Result<lsp::SemanticTokensParams> {
3548        Ok(lsp::SemanticTokensParams {
3549            text_document: lsp::TextDocumentIdentifier {
3550                uri: file_path_to_lsp_url(path)?,
3551            },
3552            partial_result_params: Default::default(),
3553            work_done_progress_params: Default::default(),
3554        })
3555    }
3556
3557    async fn response_from_lsp(
3558        self,
3559        message: Option<lsp::SemanticTokensResult>,
3560        _: Entity<LspStore>,
3561        _: Entity<Buffer>,
3562        _: LanguageServerId,
3563        _: AsyncApp,
3564    ) -> anyhow::Result<SemanticTokensResponse> {
3565        match message {
3566            Some(lsp::SemanticTokensResult::Tokens(tokens)) => Ok(SemanticTokensResponse::Full {
3567                data: tokens.data,
3568                result_id: tokens.result_id.map(SharedString::new),
3569            }),
3570            Some(lsp::SemanticTokensResult::Partial(_)) => {
3571                anyhow::bail!(
3572                    "Unexpected semantic tokens response with partial result for inlay hints"
3573                )
3574            }
3575            None => Ok(Default::default()),
3576        }
3577    }
3578
3579    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::SemanticTokens {
3580        proto::SemanticTokens {
3581            project_id,
3582            buffer_id: buffer.remote_id().into(),
3583            version: serialize_version(&buffer.version()),
3584            for_server: self.for_server.map(|id| id.to_proto()),
3585        }
3586    }
3587
3588    async fn from_proto(
3589        message: proto::SemanticTokens,
3590        _: Entity<LspStore>,
3591        buffer: Entity<Buffer>,
3592        mut cx: AsyncApp,
3593    ) -> Result<Self> {
3594        buffer
3595            .update(&mut cx, |buffer, _| {
3596                buffer.wait_for_version(deserialize_version(&message.version))
3597            })
3598            .await?;
3599
3600        Ok(Self {
3601            for_server: message
3602                .for_server
3603                .map(|id| LanguageServerId::from_proto(id)),
3604        })
3605    }
3606
3607    fn response_to_proto(
3608        response: SemanticTokensResponse,
3609        _: &mut LspStore,
3610        _: PeerId,
3611        buffer_version: &clock::Global,
3612        _: &mut App,
3613    ) -> proto::SemanticTokensResponse {
3614        match response {
3615            SemanticTokensResponse::Full { data, result_id } => proto::SemanticTokensResponse {
3616                data,
3617                edits: Vec::new(),
3618                result_id: result_id.map(|s| s.to_string()),
3619                version: serialize_version(buffer_version),
3620            },
3621            SemanticTokensResponse::Delta { edits, result_id } => proto::SemanticTokensResponse {
3622                data: Vec::new(),
3623                edits: edits
3624                    .into_iter()
3625                    .map(|edit| proto::SemanticTokensEdit {
3626                        start: edit.start,
3627                        delete_count: edit.delete_count,
3628                        data: edit.data,
3629                    })
3630                    .collect(),
3631                result_id: result_id.map(|s| s.to_string()),
3632                version: serialize_version(buffer_version),
3633            },
3634        }
3635    }
3636
3637    async fn response_from_proto(
3638        self,
3639        message: proto::SemanticTokensResponse,
3640        _: Entity<LspStore>,
3641        buffer: Entity<Buffer>,
3642        mut cx: AsyncApp,
3643    ) -> anyhow::Result<SemanticTokensResponse> {
3644        buffer
3645            .update(&mut cx, |buffer, _| {
3646                buffer.wait_for_version(deserialize_version(&message.version))
3647            })
3648            .await?;
3649
3650        Ok(SemanticTokensResponse::Full {
3651            data: message.data,
3652            result_id: message.result_id.map(SharedString::new),
3653        })
3654    }
3655
3656    fn buffer_id_from_proto(message: &proto::SemanticTokens) -> Result<BufferId> {
3657        BufferId::new(message.buffer_id)
3658    }
3659}
3660
3661#[async_trait(?Send)]
3662impl LspCommand for SemanticTokensDelta {
3663    type Response = SemanticTokensResponse;
3664    type LspRequest = lsp::SemanticTokensFullDeltaRequest;
3665    type ProtoRequest = proto::SemanticTokens;
3666
3667    fn display_name(&self) -> &str {
3668        "Semantic tokens delta"
3669    }
3670
3671    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3672        capabilities
3673            .server_capabilities
3674            .semantic_tokens_provider
3675            .as_ref()
3676            .is_some_and(|semantic_tokens_provider| {
3677                let options = match semantic_tokens_provider {
3678                    lsp::SemanticTokensServerCapabilities::SemanticTokensOptions(opts) => opts,
3679                    lsp::SemanticTokensServerCapabilities::SemanticTokensRegistrationOptions(
3680                        opts,
3681                    ) => &opts.semantic_tokens_options,
3682                };
3683
3684                match options.full {
3685                    Some(lsp::SemanticTokensFullOptions::Delta { delta }) => delta.unwrap_or(false),
3686                    // `full: true` (instead of `full: { delta: true }`) means no support for delta.
3687                    _ => false,
3688                }
3689            })
3690    }
3691
3692    fn to_lsp(
3693        &self,
3694        path: &Path,
3695        _: &Buffer,
3696        _: &Arc<LanguageServer>,
3697        _: &App,
3698    ) -> Result<lsp::SemanticTokensDeltaParams> {
3699        Ok(lsp::SemanticTokensDeltaParams {
3700            text_document: lsp::TextDocumentIdentifier {
3701                uri: file_path_to_lsp_url(path)?,
3702            },
3703            previous_result_id: self.previous_result_id.clone().map(|s| s.to_string()),
3704            partial_result_params: Default::default(),
3705            work_done_progress_params: Default::default(),
3706        })
3707    }
3708
3709    async fn response_from_lsp(
3710        self,
3711        message: Option<lsp::SemanticTokensFullDeltaResult>,
3712        _: Entity<LspStore>,
3713        _: Entity<Buffer>,
3714        _: LanguageServerId,
3715        _: AsyncApp,
3716    ) -> anyhow::Result<SemanticTokensResponse> {
3717        match message {
3718            Some(lsp::SemanticTokensFullDeltaResult::Tokens(tokens)) => {
3719                Ok(SemanticTokensResponse::Full {
3720                    data: tokens.data,
3721                    result_id: tokens.result_id.map(SharedString::new),
3722                })
3723            }
3724            Some(lsp::SemanticTokensFullDeltaResult::TokensDelta(delta)) => {
3725                Ok(SemanticTokensResponse::Delta {
3726                    edits: delta
3727                        .edits
3728                        .into_iter()
3729                        .map(|e| SemanticTokensEdit {
3730                            start: e.start,
3731                            delete_count: e.delete_count,
3732                            data: e.data.unwrap_or_default(),
3733                        })
3734                        .collect(),
3735                    result_id: delta.result_id.map(SharedString::new),
3736                })
3737            }
3738            Some(lsp::SemanticTokensFullDeltaResult::PartialTokensDelta { .. }) => {
3739                anyhow::bail!(
3740                    "Unexpected semantic tokens response with partial result for inlay hints"
3741                )
3742            }
3743            None => Ok(Default::default()),
3744        }
3745    }
3746
3747    fn to_proto(&self, _: u64, _: &Buffer) -> proto::SemanticTokens {
3748        unimplemented!("Delta requests are never initialted on the remote client side")
3749    }
3750
3751    async fn from_proto(
3752        _: proto::SemanticTokens,
3753        _: Entity<LspStore>,
3754        _: Entity<Buffer>,
3755        _: AsyncApp,
3756    ) -> Result<Self> {
3757        unimplemented!("Delta requests are never initialted on the remote client side")
3758    }
3759
3760    fn response_to_proto(
3761        response: SemanticTokensResponse,
3762        _: &mut LspStore,
3763        _: PeerId,
3764        buffer_version: &clock::Global,
3765        _: &mut App,
3766    ) -> proto::SemanticTokensResponse {
3767        match response {
3768            SemanticTokensResponse::Full { data, result_id } => proto::SemanticTokensResponse {
3769                data,
3770                edits: Vec::new(),
3771                result_id: result_id.map(|s| s.to_string()),
3772                version: serialize_version(buffer_version),
3773            },
3774            SemanticTokensResponse::Delta { edits, result_id } => proto::SemanticTokensResponse {
3775                data: Vec::new(),
3776                edits: edits
3777                    .into_iter()
3778                    .map(|edit| proto::SemanticTokensEdit {
3779                        start: edit.start,
3780                        delete_count: edit.delete_count,
3781                        data: edit.data,
3782                    })
3783                    .collect(),
3784                result_id: result_id.map(|s| s.to_string()),
3785                version: serialize_version(buffer_version),
3786            },
3787        }
3788    }
3789
3790    async fn response_from_proto(
3791        self,
3792        message: proto::SemanticTokensResponse,
3793        _: Entity<LspStore>,
3794        buffer: Entity<Buffer>,
3795        mut cx: AsyncApp,
3796    ) -> anyhow::Result<SemanticTokensResponse> {
3797        buffer
3798            .update(&mut cx, |buffer, _| {
3799                buffer.wait_for_version(deserialize_version(&message.version))
3800            })
3801            .await?;
3802
3803        Ok(SemanticTokensResponse::Full {
3804            data: message.data,
3805            result_id: message.result_id.map(SharedString::new),
3806        })
3807    }
3808
3809    fn buffer_id_from_proto(message: &proto::SemanticTokens) -> Result<BufferId> {
3810        BufferId::new(message.buffer_id)
3811    }
3812}
3813
3814#[async_trait(?Send)]
3815impl LspCommand for GetCodeLens {
3816    type Response = Vec<CodeAction>;
3817    type LspRequest = lsp::CodeLensRequest;
3818    type ProtoRequest = proto::GetCodeLens;
3819
3820    fn display_name(&self) -> &str {
3821        "Code Lens"
3822    }
3823
3824    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3825        capabilities
3826            .server_capabilities
3827            .code_lens_provider
3828            .is_some()
3829    }
3830
3831    fn to_lsp(
3832        &self,
3833        path: &Path,
3834        _: &Buffer,
3835        _: &Arc<LanguageServer>,
3836        _: &App,
3837    ) -> Result<lsp::CodeLensParams> {
3838        Ok(lsp::CodeLensParams {
3839            text_document: lsp::TextDocumentIdentifier {
3840                uri: file_path_to_lsp_url(path)?,
3841            },
3842            work_done_progress_params: lsp::WorkDoneProgressParams::default(),
3843            partial_result_params: lsp::PartialResultParams::default(),
3844        })
3845    }
3846
3847    async fn response_from_lsp(
3848        self,
3849        message: Option<Vec<lsp::CodeLens>>,
3850        lsp_store: Entity<LspStore>,
3851        buffer: Entity<Buffer>,
3852        server_id: LanguageServerId,
3853        cx: AsyncApp,
3854    ) -> anyhow::Result<Vec<CodeAction>> {
3855        let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
3856        let language_server = cx.update(|cx| {
3857            lsp_store
3858                .read(cx)
3859                .language_server_for_id(server_id)
3860                .with_context(|| {
3861                    format!("Missing the language server that just returned a response {server_id}")
3862                })
3863        })?;
3864        let server_capabilities = language_server.capabilities();
3865        let available_commands = server_capabilities
3866            .execute_command_provider
3867            .as_ref()
3868            .map(|options| options.commands.as_slice())
3869            .unwrap_or_default();
3870        Ok(message
3871            .unwrap_or_default()
3872            .into_iter()
3873            .filter(|code_lens| {
3874                code_lens
3875                    .command
3876                    .as_ref()
3877                    .is_none_or(|command| available_commands.contains(&command.command))
3878            })
3879            .map(|code_lens| {
3880                let code_lens_range = range_from_lsp(code_lens.range);
3881                let start = snapshot.clip_point_utf16(code_lens_range.start, Bias::Left);
3882                let end = snapshot.clip_point_utf16(code_lens_range.end, Bias::Right);
3883                let range = snapshot.anchor_before(start)..snapshot.anchor_after(end);
3884                CodeAction {
3885                    server_id,
3886                    range,
3887                    lsp_action: LspAction::CodeLens(code_lens),
3888                    resolved: false,
3889                }
3890            })
3891            .collect())
3892    }
3893
3894    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeLens {
3895        proto::GetCodeLens {
3896            project_id,
3897            buffer_id: buffer.remote_id().into(),
3898            version: serialize_version(&buffer.version()),
3899        }
3900    }
3901
3902    async fn from_proto(
3903        message: proto::GetCodeLens,
3904        _: Entity<LspStore>,
3905        buffer: Entity<Buffer>,
3906        mut cx: AsyncApp,
3907    ) -> Result<Self> {
3908        buffer
3909            .update(&mut cx, |buffer, _| {
3910                buffer.wait_for_version(deserialize_version(&message.version))
3911            })
3912            .await?;
3913        Ok(Self)
3914    }
3915
3916    fn response_to_proto(
3917        response: Vec<CodeAction>,
3918        _: &mut LspStore,
3919        _: PeerId,
3920        buffer_version: &clock::Global,
3921        _: &mut App,
3922    ) -> proto::GetCodeLensResponse {
3923        proto::GetCodeLensResponse {
3924            lens_actions: response
3925                .iter()
3926                .map(LspStore::serialize_code_action)
3927                .collect(),
3928            version: serialize_version(buffer_version),
3929        }
3930    }
3931
3932    async fn response_from_proto(
3933        self,
3934        message: proto::GetCodeLensResponse,
3935        _: Entity<LspStore>,
3936        buffer: Entity<Buffer>,
3937        mut cx: AsyncApp,
3938    ) -> anyhow::Result<Vec<CodeAction>> {
3939        buffer
3940            .update(&mut cx, |buffer, _| {
3941                buffer.wait_for_version(deserialize_version(&message.version))
3942            })
3943            .await?;
3944        message
3945            .lens_actions
3946            .into_iter()
3947            .map(LspStore::deserialize_code_action)
3948            .collect::<Result<Vec<_>>>()
3949            .context("deserializing proto code lens response")
3950    }
3951
3952    fn buffer_id_from_proto(message: &proto::GetCodeLens) -> Result<BufferId> {
3953        BufferId::new(message.buffer_id)
3954    }
3955}
3956
3957impl LinkedEditingRange {
3958    pub fn check_server_capabilities(capabilities: ServerCapabilities) -> bool {
3959        let Some(linked_editing_options) = capabilities.linked_editing_range_provider else {
3960            return false;
3961        };
3962        if let LinkedEditingRangeServerCapabilities::Simple(false) = linked_editing_options {
3963            return false;
3964        }
3965        true
3966    }
3967}
3968
3969#[async_trait(?Send)]
3970impl LspCommand for LinkedEditingRange {
3971    type Response = Vec<Range<Anchor>>;
3972    type LspRequest = lsp::request::LinkedEditingRange;
3973    type ProtoRequest = proto::LinkedEditingRange;
3974
3975    fn display_name(&self) -> &str {
3976        "Linked editing range"
3977    }
3978
3979    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3980        Self::check_server_capabilities(capabilities.server_capabilities)
3981    }
3982
3983    fn to_lsp(
3984        &self,
3985        path: &Path,
3986        buffer: &Buffer,
3987        _server: &Arc<LanguageServer>,
3988        _: &App,
3989    ) -> Result<lsp::LinkedEditingRangeParams> {
3990        let position = self.position.to_point_utf16(&buffer.snapshot());
3991        Ok(lsp::LinkedEditingRangeParams {
3992            text_document_position_params: make_lsp_text_document_position(path, position)?,
3993            work_done_progress_params: Default::default(),
3994        })
3995    }
3996
3997    async fn response_from_lsp(
3998        self,
3999        message: Option<lsp::LinkedEditingRanges>,
4000        _: Entity<LspStore>,
4001        buffer: Entity<Buffer>,
4002        _server_id: LanguageServerId,
4003        cx: AsyncApp,
4004    ) -> Result<Vec<Range<Anchor>>> {
4005        if let Some(lsp::LinkedEditingRanges { mut ranges, .. }) = message {
4006            ranges.sort_by_key(|range| range.start);
4007
4008            Ok(buffer.read_with(&cx, |buffer, _| {
4009                ranges
4010                    .into_iter()
4011                    .map(|range| {
4012                        let start =
4013                            buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
4014                        let end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
4015                        buffer.anchor_before(start)..buffer.anchor_after(end)
4016                    })
4017                    .collect()
4018            }))
4019        } else {
4020            Ok(vec![])
4021        }
4022    }
4023
4024    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::LinkedEditingRange {
4025        proto::LinkedEditingRange {
4026            project_id,
4027            buffer_id: buffer.remote_id().to_proto(),
4028            position: Some(serialize_anchor(&self.position)),
4029            version: serialize_version(&buffer.version()),
4030        }
4031    }
4032
4033    async fn from_proto(
4034        message: proto::LinkedEditingRange,
4035        _: Entity<LspStore>,
4036        buffer: Entity<Buffer>,
4037        mut cx: AsyncApp,
4038    ) -> Result<Self> {
4039        let position = message.position.context("invalid position")?;
4040        buffer
4041            .update(&mut cx, |buffer, _| {
4042                buffer.wait_for_version(deserialize_version(&message.version))
4043            })
4044            .await?;
4045        let position = deserialize_anchor(position).context("invalid position")?;
4046        buffer
4047            .update(&mut cx, |buffer, _| buffer.wait_for_anchors([position]))
4048            .await?;
4049        Ok(Self { position })
4050    }
4051
4052    fn response_to_proto(
4053        response: Vec<Range<Anchor>>,
4054        _: &mut LspStore,
4055        _: PeerId,
4056        buffer_version: &clock::Global,
4057        _: &mut App,
4058    ) -> proto::LinkedEditingRangeResponse {
4059        proto::LinkedEditingRangeResponse {
4060            items: response
4061                .into_iter()
4062                .map(|range| proto::AnchorRange {
4063                    start: Some(serialize_anchor(&range.start)),
4064                    end: Some(serialize_anchor(&range.end)),
4065                })
4066                .collect(),
4067            version: serialize_version(buffer_version),
4068        }
4069    }
4070
4071    async fn response_from_proto(
4072        self,
4073        message: proto::LinkedEditingRangeResponse,
4074        _: Entity<LspStore>,
4075        buffer: Entity<Buffer>,
4076        mut cx: AsyncApp,
4077    ) -> Result<Vec<Range<Anchor>>> {
4078        buffer
4079            .update(&mut cx, |buffer, _| {
4080                buffer.wait_for_version(deserialize_version(&message.version))
4081            })
4082            .await?;
4083        let items: Vec<Range<Anchor>> = message
4084            .items
4085            .into_iter()
4086            .filter_map(|range| {
4087                let start = deserialize_anchor(range.start?)?;
4088                let end = deserialize_anchor(range.end?)?;
4089                Some(start..end)
4090            })
4091            .collect();
4092        for range in &items {
4093            buffer
4094                .update(&mut cx, |buffer, _| {
4095                    buffer.wait_for_anchors([range.start, range.end])
4096                })
4097                .await?;
4098        }
4099        Ok(items)
4100    }
4101
4102    fn buffer_id_from_proto(message: &proto::LinkedEditingRange) -> Result<BufferId> {
4103        BufferId::new(message.buffer_id)
4104    }
4105}
4106
4107impl GetDocumentDiagnostics {
4108    pub fn diagnostics_from_proto(
4109        response: proto::GetDocumentDiagnosticsResponse,
4110    ) -> Vec<LspPullDiagnostics> {
4111        response
4112            .pulled_diagnostics
4113            .into_iter()
4114            .filter_map(|diagnostics| {
4115                Some(LspPullDiagnostics::Response {
4116                    registration_id: diagnostics.registration_id.map(SharedString::from),
4117                    server_id: LanguageServerId::from_proto(diagnostics.server_id),
4118                    uri: lsp::Uri::from_str(diagnostics.uri.as_str()).log_err()?,
4119                    diagnostics: if diagnostics.changed {
4120                        PulledDiagnostics::Unchanged {
4121                            result_id: SharedString::new(diagnostics.result_id?),
4122                        }
4123                    } else {
4124                        PulledDiagnostics::Changed {
4125                            result_id: diagnostics.result_id.map(SharedString::new),
4126                            diagnostics: diagnostics
4127                                .diagnostics
4128                                .into_iter()
4129                                .filter_map(|diagnostic| {
4130                                    GetDocumentDiagnostics::deserialize_lsp_diagnostic(diagnostic)
4131                                        .context("deserializing diagnostics")
4132                                        .log_err()
4133                                })
4134                                .collect(),
4135                        }
4136                    },
4137                })
4138            })
4139            .collect()
4140    }
4141
4142    pub fn deserialize_lsp_diagnostic(diagnostic: proto::LspDiagnostic) -> Result<lsp::Diagnostic> {
4143        let start = diagnostic.start.context("invalid start range")?;
4144        let end = diagnostic.end.context("invalid end range")?;
4145
4146        let range = Range::<PointUtf16> {
4147            start: PointUtf16 {
4148                row: start.row,
4149                column: start.column,
4150            },
4151            end: PointUtf16 {
4152                row: end.row,
4153                column: end.column,
4154            },
4155        };
4156
4157        let data = diagnostic.data.and_then(|data| Value::from_str(&data).ok());
4158        let code = diagnostic.code.map(lsp::NumberOrString::String);
4159
4160        let related_information = diagnostic
4161            .related_information
4162            .into_iter()
4163            .map(|info| {
4164                let start = info.location_range_start.unwrap();
4165                let end = info.location_range_end.unwrap();
4166
4167                lsp::DiagnosticRelatedInformation {
4168                    location: lsp::Location {
4169                        range: lsp::Range {
4170                            start: point_to_lsp(PointUtf16::new(start.row, start.column)),
4171                            end: point_to_lsp(PointUtf16::new(end.row, end.column)),
4172                        },
4173                        uri: lsp::Uri::from_str(&info.location_url.unwrap()).unwrap(),
4174                    },
4175                    message: info.message,
4176                }
4177            })
4178            .collect::<Vec<_>>();
4179
4180        let tags = diagnostic
4181            .tags
4182            .into_iter()
4183            .filter_map(|tag| match proto::LspDiagnosticTag::from_i32(tag) {
4184                Some(proto::LspDiagnosticTag::Unnecessary) => Some(lsp::DiagnosticTag::UNNECESSARY),
4185                Some(proto::LspDiagnosticTag::Deprecated) => Some(lsp::DiagnosticTag::DEPRECATED),
4186                _ => None,
4187            })
4188            .collect::<Vec<_>>();
4189
4190        Ok(lsp::Diagnostic {
4191            range: language::range_to_lsp(range)?,
4192            severity: match proto::lsp_diagnostic::Severity::from_i32(diagnostic.severity).unwrap()
4193            {
4194                proto::lsp_diagnostic::Severity::Error => Some(lsp::DiagnosticSeverity::ERROR),
4195                proto::lsp_diagnostic::Severity::Warning => Some(lsp::DiagnosticSeverity::WARNING),
4196                proto::lsp_diagnostic::Severity::Information => {
4197                    Some(lsp::DiagnosticSeverity::INFORMATION)
4198                }
4199                proto::lsp_diagnostic::Severity::Hint => Some(lsp::DiagnosticSeverity::HINT),
4200                _ => None,
4201            },
4202            code,
4203            code_description: diagnostic
4204                .code_description
4205                .map(|code_description| CodeDescription {
4206                    href: Some(lsp::Uri::from_str(&code_description).unwrap()),
4207                }),
4208            related_information: Some(related_information),
4209            tags: Some(tags),
4210            source: diagnostic.source.clone(),
4211            message: diagnostic.message,
4212            data,
4213        })
4214    }
4215
4216    pub fn serialize_lsp_diagnostic(diagnostic: lsp::Diagnostic) -> Result<proto::LspDiagnostic> {
4217        let range = language::range_from_lsp(diagnostic.range);
4218        let related_information = diagnostic
4219            .related_information
4220            .unwrap_or_default()
4221            .into_iter()
4222            .map(|related_information| {
4223                let location_range_start =
4224                    point_from_lsp(related_information.location.range.start).0;
4225                let location_range_end = point_from_lsp(related_information.location.range.end).0;
4226
4227                Ok(proto::LspDiagnosticRelatedInformation {
4228                    location_url: Some(related_information.location.uri.to_string()),
4229                    location_range_start: Some(proto::PointUtf16 {
4230                        row: location_range_start.row,
4231                        column: location_range_start.column,
4232                    }),
4233                    location_range_end: Some(proto::PointUtf16 {
4234                        row: location_range_end.row,
4235                        column: location_range_end.column,
4236                    }),
4237                    message: related_information.message,
4238                })
4239            })
4240            .collect::<Result<Vec<_>>>()?;
4241
4242        let tags = diagnostic
4243            .tags
4244            .unwrap_or_default()
4245            .into_iter()
4246            .map(|tag| match tag {
4247                lsp::DiagnosticTag::UNNECESSARY => proto::LspDiagnosticTag::Unnecessary,
4248                lsp::DiagnosticTag::DEPRECATED => proto::LspDiagnosticTag::Deprecated,
4249                _ => proto::LspDiagnosticTag::None,
4250            } as i32)
4251            .collect();
4252
4253        Ok(proto::LspDiagnostic {
4254            start: Some(proto::PointUtf16 {
4255                row: range.start.0.row,
4256                column: range.start.0.column,
4257            }),
4258            end: Some(proto::PointUtf16 {
4259                row: range.end.0.row,
4260                column: range.end.0.column,
4261            }),
4262            severity: match diagnostic.severity {
4263                Some(lsp::DiagnosticSeverity::ERROR) => proto::lsp_diagnostic::Severity::Error,
4264                Some(lsp::DiagnosticSeverity::WARNING) => proto::lsp_diagnostic::Severity::Warning,
4265                Some(lsp::DiagnosticSeverity::INFORMATION) => {
4266                    proto::lsp_diagnostic::Severity::Information
4267                }
4268                Some(lsp::DiagnosticSeverity::HINT) => proto::lsp_diagnostic::Severity::Hint,
4269                _ => proto::lsp_diagnostic::Severity::None,
4270            } as i32,
4271            code: diagnostic.code.as_ref().map(|code| match code {
4272                lsp::NumberOrString::Number(code) => code.to_string(),
4273                lsp::NumberOrString::String(code) => code.clone(),
4274            }),
4275            source: diagnostic.source.clone(),
4276            related_information,
4277            tags,
4278            code_description: diagnostic
4279                .code_description
4280                .and_then(|desc| desc.href.map(|url| url.to_string())),
4281            message: diagnostic.message,
4282            data: diagnostic.data.as_ref().map(|data| data.to_string()),
4283        })
4284    }
4285
4286    pub fn deserialize_workspace_diagnostics_report(
4287        report: lsp::WorkspaceDiagnosticReportResult,
4288        server_id: LanguageServerId,
4289        registration_id: Option<SharedString>,
4290    ) -> Vec<WorkspaceLspPullDiagnostics> {
4291        let mut pulled_diagnostics = HashMap::default();
4292        match report {
4293            lsp::WorkspaceDiagnosticReportResult::Report(workspace_diagnostic_report) => {
4294                for report in workspace_diagnostic_report.items {
4295                    match report {
4296                        lsp::WorkspaceDocumentDiagnosticReport::Full(report) => {
4297                            process_full_workspace_diagnostics_report(
4298                                &mut pulled_diagnostics,
4299                                server_id,
4300                                report,
4301                                registration_id.clone(),
4302                            )
4303                        }
4304                        lsp::WorkspaceDocumentDiagnosticReport::Unchanged(report) => {
4305                            process_unchanged_workspace_diagnostics_report(
4306                                &mut pulled_diagnostics,
4307                                server_id,
4308                                report,
4309                                registration_id.clone(),
4310                            )
4311                        }
4312                    }
4313                }
4314            }
4315            lsp::WorkspaceDiagnosticReportResult::Partial(
4316                workspace_diagnostic_report_partial_result,
4317            ) => {
4318                for report in workspace_diagnostic_report_partial_result.items {
4319                    match report {
4320                        lsp::WorkspaceDocumentDiagnosticReport::Full(report) => {
4321                            process_full_workspace_diagnostics_report(
4322                                &mut pulled_diagnostics,
4323                                server_id,
4324                                report,
4325                                registration_id.clone(),
4326                            )
4327                        }
4328                        lsp::WorkspaceDocumentDiagnosticReport::Unchanged(report) => {
4329                            process_unchanged_workspace_diagnostics_report(
4330                                &mut pulled_diagnostics,
4331                                server_id,
4332                                report,
4333                                registration_id.clone(),
4334                            )
4335                        }
4336                    }
4337                }
4338            }
4339        }
4340        pulled_diagnostics.into_values().collect()
4341    }
4342}
4343
4344#[derive(Debug)]
4345pub struct WorkspaceLspPullDiagnostics {
4346    pub version: Option<i32>,
4347    pub diagnostics: LspPullDiagnostics,
4348}
4349
4350fn process_full_workspace_diagnostics_report(
4351    diagnostics: &mut HashMap<lsp::Uri, WorkspaceLspPullDiagnostics>,
4352    server_id: LanguageServerId,
4353    report: lsp::WorkspaceFullDocumentDiagnosticReport,
4354    registration_id: Option<SharedString>,
4355) {
4356    let mut new_diagnostics = HashMap::default();
4357    process_full_diagnostics_report(
4358        &mut new_diagnostics,
4359        server_id,
4360        report.uri,
4361        report.full_document_diagnostic_report,
4362        registration_id,
4363    );
4364    diagnostics.extend(new_diagnostics.into_iter().map(|(uri, diagnostics)| {
4365        (
4366            uri,
4367            WorkspaceLspPullDiagnostics {
4368                version: report.version.map(|v| v as i32),
4369                diagnostics,
4370            },
4371        )
4372    }));
4373}
4374
4375fn process_unchanged_workspace_diagnostics_report(
4376    diagnostics: &mut HashMap<lsp::Uri, WorkspaceLspPullDiagnostics>,
4377    server_id: LanguageServerId,
4378    report: lsp::WorkspaceUnchangedDocumentDiagnosticReport,
4379    registration_id: Option<SharedString>,
4380) {
4381    let mut new_diagnostics = HashMap::default();
4382    process_unchanged_diagnostics_report(
4383        &mut new_diagnostics,
4384        server_id,
4385        report.uri,
4386        report.unchanged_document_diagnostic_report,
4387        registration_id,
4388    );
4389    diagnostics.extend(new_diagnostics.into_iter().map(|(uri, diagnostics)| {
4390        (
4391            uri,
4392            WorkspaceLspPullDiagnostics {
4393                version: report.version.map(|v| v as i32),
4394                diagnostics,
4395            },
4396        )
4397    }));
4398}
4399
4400#[async_trait(?Send)]
4401impl LspCommand for GetDocumentDiagnostics {
4402    type Response = Vec<LspPullDiagnostics>;
4403    type LspRequest = lsp::request::DocumentDiagnosticRequest;
4404    type ProtoRequest = proto::GetDocumentDiagnostics;
4405
4406    fn display_name(&self) -> &str {
4407        "Get diagnostics"
4408    }
4409
4410    fn check_capabilities(&self, _: AdapterServerCapabilities) -> bool {
4411        true
4412    }
4413
4414    fn to_lsp(
4415        &self,
4416        path: &Path,
4417        _: &Buffer,
4418        _: &Arc<LanguageServer>,
4419        _: &App,
4420    ) -> Result<lsp::DocumentDiagnosticParams> {
4421        Ok(lsp::DocumentDiagnosticParams {
4422            text_document: lsp::TextDocumentIdentifier {
4423                uri: file_path_to_lsp_url(path)?,
4424            },
4425            identifier: self.identifier.as_ref().map(ToString::to_string),
4426            previous_result_id: self.previous_result_id.as_ref().map(ToString::to_string),
4427            partial_result_params: Default::default(),
4428            work_done_progress_params: Default::default(),
4429        })
4430    }
4431
4432    async fn response_from_lsp(
4433        self,
4434        message: lsp::DocumentDiagnosticReportResult,
4435        _: Entity<LspStore>,
4436        buffer: Entity<Buffer>,
4437        server_id: LanguageServerId,
4438        cx: AsyncApp,
4439    ) -> Result<Self::Response> {
4440        let url = buffer.read_with(&cx, |buffer, cx| {
4441            buffer
4442                .file()
4443                .and_then(|file| file.as_local())
4444                .map(|file| {
4445                    let abs_path = file.abs_path(cx);
4446                    file_path_to_lsp_url(&abs_path)
4447                })
4448                .transpose()?
4449                .with_context(|| format!("missing url on buffer {}", buffer.remote_id()))
4450        })?;
4451
4452        let mut pulled_diagnostics = HashMap::default();
4453        match message {
4454            lsp::DocumentDiagnosticReportResult::Report(report) => match report {
4455                lsp::DocumentDiagnosticReport::Full(report) => {
4456                    if let Some(related_documents) = report.related_documents {
4457                        process_related_documents(
4458                            &mut pulled_diagnostics,
4459                            server_id,
4460                            related_documents,
4461                            self.registration_id.clone(),
4462                        );
4463                    }
4464                    process_full_diagnostics_report(
4465                        &mut pulled_diagnostics,
4466                        server_id,
4467                        url,
4468                        report.full_document_diagnostic_report,
4469                        self.registration_id,
4470                    );
4471                }
4472                lsp::DocumentDiagnosticReport::Unchanged(report) => {
4473                    if let Some(related_documents) = report.related_documents {
4474                        process_related_documents(
4475                            &mut pulled_diagnostics,
4476                            server_id,
4477                            related_documents,
4478                            self.registration_id.clone(),
4479                        );
4480                    }
4481                    process_unchanged_diagnostics_report(
4482                        &mut pulled_diagnostics,
4483                        server_id,
4484                        url,
4485                        report.unchanged_document_diagnostic_report,
4486                        self.registration_id,
4487                    );
4488                }
4489            },
4490            lsp::DocumentDiagnosticReportResult::Partial(report) => {
4491                if let Some(related_documents) = report.related_documents {
4492                    process_related_documents(
4493                        &mut pulled_diagnostics,
4494                        server_id,
4495                        related_documents,
4496                        self.registration_id,
4497                    );
4498                }
4499            }
4500        }
4501
4502        Ok(pulled_diagnostics.into_values().collect())
4503    }
4504
4505    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentDiagnostics {
4506        proto::GetDocumentDiagnostics {
4507            project_id,
4508            buffer_id: buffer.remote_id().into(),
4509            version: serialize_version(&buffer.version()),
4510        }
4511    }
4512
4513    async fn from_proto(
4514        _: proto::GetDocumentDiagnostics,
4515        _: Entity<LspStore>,
4516        _: Entity<Buffer>,
4517        _: AsyncApp,
4518    ) -> Result<Self> {
4519        anyhow::bail!(
4520            "proto::GetDocumentDiagnostics is not expected to be converted from proto directly, as it needs `previous_result_id` fetched first"
4521        )
4522    }
4523
4524    fn response_to_proto(
4525        response: Self::Response,
4526        _: &mut LspStore,
4527        _: PeerId,
4528        _: &clock::Global,
4529        _: &mut App,
4530    ) -> proto::GetDocumentDiagnosticsResponse {
4531        let pulled_diagnostics = response
4532            .into_iter()
4533            .filter_map(|diagnostics| match diagnostics {
4534                LspPullDiagnostics::Default => None,
4535                LspPullDiagnostics::Response {
4536                    server_id,
4537                    uri,
4538                    diagnostics,
4539                    registration_id,
4540                } => {
4541                    let mut changed = false;
4542                    let (diagnostics, result_id) = match diagnostics {
4543                        PulledDiagnostics::Unchanged { result_id } => (Vec::new(), Some(result_id)),
4544                        PulledDiagnostics::Changed {
4545                            result_id,
4546                            diagnostics,
4547                        } => {
4548                            changed = true;
4549                            (diagnostics, result_id)
4550                        }
4551                    };
4552                    Some(proto::PulledDiagnostics {
4553                        changed,
4554                        result_id: result_id.map(|id| id.to_string()),
4555                        uri: uri.to_string(),
4556                        server_id: server_id.to_proto(),
4557                        diagnostics: diagnostics
4558                            .into_iter()
4559                            .filter_map(|diagnostic| {
4560                                GetDocumentDiagnostics::serialize_lsp_diagnostic(diagnostic)
4561                                    .context("serializing diagnostics")
4562                                    .log_err()
4563                            })
4564                            .collect(),
4565                        registration_id: registration_id.as_ref().map(ToString::to_string),
4566                    })
4567                }
4568            })
4569            .collect();
4570
4571        proto::GetDocumentDiagnosticsResponse { pulled_diagnostics }
4572    }
4573
4574    async fn response_from_proto(
4575        self,
4576        response: proto::GetDocumentDiagnosticsResponse,
4577        _: Entity<LspStore>,
4578        _: Entity<Buffer>,
4579        _: AsyncApp,
4580    ) -> Result<Self::Response> {
4581        Ok(Self::diagnostics_from_proto(response))
4582    }
4583
4584    fn buffer_id_from_proto(message: &proto::GetDocumentDiagnostics) -> Result<BufferId> {
4585        BufferId::new(message.buffer_id)
4586    }
4587}
4588
4589#[async_trait(?Send)]
4590impl LspCommand for GetDocumentColor {
4591    type Response = Vec<DocumentColor>;
4592    type LspRequest = lsp::request::DocumentColor;
4593    type ProtoRequest = proto::GetDocumentColor;
4594
4595    fn display_name(&self) -> &str {
4596        "Document color"
4597    }
4598
4599    fn check_capabilities(&self, server_capabilities: AdapterServerCapabilities) -> bool {
4600        server_capabilities
4601            .server_capabilities
4602            .color_provider
4603            .as_ref()
4604            .is_some_and(|capability| match capability {
4605                lsp::ColorProviderCapability::Simple(supported) => *supported,
4606                lsp::ColorProviderCapability::ColorProvider(..) => true,
4607                lsp::ColorProviderCapability::Options(..) => true,
4608            })
4609    }
4610
4611    fn to_lsp(
4612        &self,
4613        path: &Path,
4614        _: &Buffer,
4615        _: &Arc<LanguageServer>,
4616        _: &App,
4617    ) -> Result<lsp::DocumentColorParams> {
4618        Ok(lsp::DocumentColorParams {
4619            text_document: make_text_document_identifier(path)?,
4620            work_done_progress_params: Default::default(),
4621            partial_result_params: Default::default(),
4622        })
4623    }
4624
4625    async fn response_from_lsp(
4626        self,
4627        message: Vec<lsp::ColorInformation>,
4628        _: Entity<LspStore>,
4629        _: Entity<Buffer>,
4630        _: LanguageServerId,
4631        _: AsyncApp,
4632    ) -> Result<Self::Response> {
4633        Ok(message
4634            .into_iter()
4635            .map(|color| DocumentColor {
4636                lsp_range: color.range,
4637                color: color.color,
4638                resolved: false,
4639                color_presentations: Vec::new(),
4640            })
4641            .collect())
4642    }
4643
4644    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
4645        proto::GetDocumentColor {
4646            project_id,
4647            buffer_id: buffer.remote_id().to_proto(),
4648            version: serialize_version(&buffer.version()),
4649        }
4650    }
4651
4652    async fn from_proto(
4653        _: Self::ProtoRequest,
4654        _: Entity<LspStore>,
4655        _: Entity<Buffer>,
4656        _: AsyncApp,
4657    ) -> Result<Self> {
4658        Ok(Self {})
4659    }
4660
4661    fn response_to_proto(
4662        response: Self::Response,
4663        _: &mut LspStore,
4664        _: PeerId,
4665        buffer_version: &clock::Global,
4666        _: &mut App,
4667    ) -> proto::GetDocumentColorResponse {
4668        proto::GetDocumentColorResponse {
4669            colors: response
4670                .into_iter()
4671                .map(|color| {
4672                    let start = point_from_lsp(color.lsp_range.start).0;
4673                    let end = point_from_lsp(color.lsp_range.end).0;
4674                    proto::ColorInformation {
4675                        red: color.color.red,
4676                        green: color.color.green,
4677                        blue: color.color.blue,
4678                        alpha: color.color.alpha,
4679                        lsp_range_start: Some(proto::PointUtf16 {
4680                            row: start.row,
4681                            column: start.column,
4682                        }),
4683                        lsp_range_end: Some(proto::PointUtf16 {
4684                            row: end.row,
4685                            column: end.column,
4686                        }),
4687                    }
4688                })
4689                .collect(),
4690            version: serialize_version(buffer_version),
4691        }
4692    }
4693
4694    async fn response_from_proto(
4695        self,
4696        message: proto::GetDocumentColorResponse,
4697        _: Entity<LspStore>,
4698        _: Entity<Buffer>,
4699        _: AsyncApp,
4700    ) -> Result<Self::Response> {
4701        Ok(message
4702            .colors
4703            .into_iter()
4704            .filter_map(|color| {
4705                let start = color.lsp_range_start?;
4706                let start = PointUtf16::new(start.row, start.column);
4707                let end = color.lsp_range_end?;
4708                let end = PointUtf16::new(end.row, end.column);
4709                Some(DocumentColor {
4710                    resolved: false,
4711                    color_presentations: Vec::new(),
4712                    lsp_range: lsp::Range {
4713                        start: point_to_lsp(start),
4714                        end: point_to_lsp(end),
4715                    },
4716                    color: lsp::Color {
4717                        red: color.red,
4718                        green: color.green,
4719                        blue: color.blue,
4720                        alpha: color.alpha,
4721                    },
4722                })
4723            })
4724            .collect())
4725    }
4726
4727    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
4728        BufferId::new(message.buffer_id)
4729    }
4730}
4731
4732fn process_related_documents(
4733    diagnostics: &mut HashMap<lsp::Uri, LspPullDiagnostics>,
4734    server_id: LanguageServerId,
4735    documents: impl IntoIterator<Item = (lsp::Uri, lsp::DocumentDiagnosticReportKind)>,
4736    registration_id: Option<SharedString>,
4737) {
4738    for (url, report_kind) in documents {
4739        match report_kind {
4740            lsp::DocumentDiagnosticReportKind::Full(report) => process_full_diagnostics_report(
4741                diagnostics,
4742                server_id,
4743                url,
4744                report,
4745                registration_id.clone(),
4746            ),
4747            lsp::DocumentDiagnosticReportKind::Unchanged(report) => {
4748                process_unchanged_diagnostics_report(
4749                    diagnostics,
4750                    server_id,
4751                    url,
4752                    report,
4753                    registration_id.clone(),
4754                )
4755            }
4756        }
4757    }
4758}
4759
4760fn process_unchanged_diagnostics_report(
4761    diagnostics: &mut HashMap<lsp::Uri, LspPullDiagnostics>,
4762    server_id: LanguageServerId,
4763    uri: lsp::Uri,
4764    report: lsp::UnchangedDocumentDiagnosticReport,
4765    registration_id: Option<SharedString>,
4766) {
4767    let result_id = SharedString::new(report.result_id);
4768    match diagnostics.entry(uri.clone()) {
4769        hash_map::Entry::Occupied(mut o) => match o.get_mut() {
4770            LspPullDiagnostics::Default => {
4771                o.insert(LspPullDiagnostics::Response {
4772                    server_id,
4773                    uri,
4774                    diagnostics: PulledDiagnostics::Unchanged { result_id },
4775                    registration_id,
4776                });
4777            }
4778            LspPullDiagnostics::Response {
4779                server_id: existing_server_id,
4780                uri: existing_uri,
4781                diagnostics: existing_diagnostics,
4782                ..
4783            } => {
4784                if server_id != *existing_server_id || &uri != existing_uri {
4785                    debug_panic!(
4786                        "Unexpected state: file {uri} has two different sets of diagnostics reported"
4787                    );
4788                }
4789                match existing_diagnostics {
4790                    PulledDiagnostics::Unchanged { .. } => {
4791                        *existing_diagnostics = PulledDiagnostics::Unchanged { result_id };
4792                    }
4793                    PulledDiagnostics::Changed { .. } => {}
4794                }
4795            }
4796        },
4797        hash_map::Entry::Vacant(v) => {
4798            v.insert(LspPullDiagnostics::Response {
4799                server_id,
4800                uri,
4801                diagnostics: PulledDiagnostics::Unchanged { result_id },
4802                registration_id,
4803            });
4804        }
4805    }
4806}
4807
4808fn process_full_diagnostics_report(
4809    diagnostics: &mut HashMap<lsp::Uri, LspPullDiagnostics>,
4810    server_id: LanguageServerId,
4811    uri: lsp::Uri,
4812    report: lsp::FullDocumentDiagnosticReport,
4813    registration_id: Option<SharedString>,
4814) {
4815    let result_id = report.result_id.map(SharedString::new);
4816    match diagnostics.entry(uri.clone()) {
4817        hash_map::Entry::Occupied(mut o) => match o.get_mut() {
4818            LspPullDiagnostics::Default => {
4819                o.insert(LspPullDiagnostics::Response {
4820                    server_id,
4821                    uri,
4822                    diagnostics: PulledDiagnostics::Changed {
4823                        result_id,
4824                        diagnostics: report.items,
4825                    },
4826                    registration_id,
4827                });
4828            }
4829            LspPullDiagnostics::Response {
4830                server_id: existing_server_id,
4831                uri: existing_uri,
4832                diagnostics: existing_diagnostics,
4833                ..
4834            } => {
4835                if server_id != *existing_server_id || &uri != existing_uri {
4836                    debug_panic!(
4837                        "Unexpected state: file {uri} has two different sets of diagnostics reported"
4838                    );
4839                }
4840                match existing_diagnostics {
4841                    PulledDiagnostics::Unchanged { .. } => {
4842                        *existing_diagnostics = PulledDiagnostics::Changed {
4843                            result_id,
4844                            diagnostics: report.items,
4845                        };
4846                    }
4847                    PulledDiagnostics::Changed {
4848                        result_id: existing_result_id,
4849                        diagnostics: existing_diagnostics,
4850                    } => {
4851                        if result_id.is_some() {
4852                            *existing_result_id = result_id;
4853                        }
4854                        existing_diagnostics.extend(report.items);
4855                    }
4856                }
4857            }
4858        },
4859        hash_map::Entry::Vacant(v) => {
4860            v.insert(LspPullDiagnostics::Response {
4861                server_id,
4862                uri,
4863                diagnostics: PulledDiagnostics::Changed {
4864                    result_id,
4865                    diagnostics: report.items,
4866                },
4867                registration_id,
4868            });
4869        }
4870    }
4871}