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