lsp_command.rs

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