lsp_command.rs

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