lsp_command.rs

   1use crate::{
   2    DocumentHighlight, Hover, HoverBlock, HoverBlockKind, Location, LocationLink, Project,
   3    ProjectTransaction,
   4};
   5use anyhow::{anyhow, Context, Result};
   6use async_trait::async_trait;
   7use client::proto::{self, PeerId};
   8use fs::LineEnding;
   9use gpui::{AppContext, AsyncAppContext, ModelHandle};
  10use language::{
  11    point_from_lsp, point_to_lsp,
  12    proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
  13    range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CachedLspAdapter, CharKind, CodeAction,
  14    Completion, OffsetRangeExt, PointUtf16, ToOffset, ToPointUtf16, Unclipped,
  15};
  16use lsp::{DocumentHighlightKind, LanguageServer, LanguageServerId, ServerCapabilities};
  17use std::{cmp::Reverse, ops::Range, path::Path, sync::Arc};
  18
  19#[async_trait(?Send)]
  20pub(crate) trait LspCommand: 'static + Sized {
  21    type Response: 'static + Default + Send;
  22    type LspRequest: 'static + Send + lsp::request::Request;
  23    type ProtoRequest: 'static + Send + proto::RequestMessage;
  24
  25    fn check_capabilities(&self, _: &lsp::ServerCapabilities) -> bool {
  26        true
  27    }
  28
  29    fn to_lsp(
  30        &self,
  31        path: &Path,
  32        buffer: &Buffer,
  33        language_server: &Arc<LanguageServer>,
  34        cx: &AppContext,
  35    ) -> <Self::LspRequest as lsp::request::Request>::Params;
  36
  37    async fn response_from_lsp(
  38        self,
  39        message: <Self::LspRequest as lsp::request::Request>::Result,
  40        project: ModelHandle<Project>,
  41        buffer: ModelHandle<Buffer>,
  42        server_id: LanguageServerId,
  43        cx: AsyncAppContext,
  44    ) -> Result<Self::Response>;
  45
  46    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest;
  47
  48    async fn from_proto(
  49        message: Self::ProtoRequest,
  50        project: ModelHandle<Project>,
  51        buffer: ModelHandle<Buffer>,
  52        cx: AsyncAppContext,
  53    ) -> Result<Self>;
  54
  55    fn response_to_proto(
  56        response: Self::Response,
  57        project: &mut Project,
  58        peer_id: PeerId,
  59        buffer_version: &clock::Global,
  60        cx: &mut AppContext,
  61    ) -> <Self::ProtoRequest as proto::RequestMessage>::Response;
  62
  63    async fn response_from_proto(
  64        self,
  65        message: <Self::ProtoRequest as proto::RequestMessage>::Response,
  66        project: ModelHandle<Project>,
  67        buffer: ModelHandle<Buffer>,
  68        cx: AsyncAppContext,
  69    ) -> Result<Self::Response>;
  70
  71    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> u64;
  72}
  73
  74pub(crate) struct PrepareRename {
  75    pub position: PointUtf16,
  76}
  77
  78pub(crate) struct PerformRename {
  79    pub position: PointUtf16,
  80    pub new_name: String,
  81    pub push_to_history: bool,
  82}
  83
  84pub(crate) struct GetDefinition {
  85    pub position: PointUtf16,
  86}
  87
  88pub(crate) struct GetTypeDefinition {
  89    pub position: PointUtf16,
  90}
  91
  92pub(crate) struct GetReferences {
  93    pub position: PointUtf16,
  94}
  95
  96pub(crate) struct GetDocumentHighlights {
  97    pub position: PointUtf16,
  98}
  99
 100pub(crate) struct GetHover {
 101    pub position: PointUtf16,
 102}
 103
 104pub(crate) struct GetCompletions {
 105    pub position: PointUtf16,
 106}
 107
 108pub(crate) struct GetCodeActions {
 109    pub range: Range<Anchor>,
 110}
 111
 112pub(crate) struct OnTypeFormatting {
 113    pub position: PointUtf16,
 114    pub new_char: char,
 115    // TODO kb formatting options?
 116}
 117
 118#[async_trait(?Send)]
 119impl LspCommand for PrepareRename {
 120    type Response = Option<Range<Anchor>>;
 121    type LspRequest = lsp::request::PrepareRenameRequest;
 122    type ProtoRequest = proto::PrepareRename;
 123
 124    fn check_capabilities(&self, capabilities: &ServerCapabilities) -> bool {
 125        if let Some(lsp::OneOf::Right(rename)) = &capabilities.rename_provider {
 126            rename.prepare_provider == Some(true)
 127        } else {
 128            false
 129        }
 130    }
 131
 132    fn to_lsp(
 133        &self,
 134        path: &Path,
 135        _: &Buffer,
 136        _: &Arc<LanguageServer>,
 137        _: &AppContext,
 138    ) -> lsp::TextDocumentPositionParams {
 139        lsp::TextDocumentPositionParams {
 140            text_document: lsp::TextDocumentIdentifier {
 141                uri: lsp::Url::from_file_path(path).unwrap(),
 142            },
 143            position: point_to_lsp(self.position),
 144        }
 145    }
 146
 147    async fn response_from_lsp(
 148        self,
 149        message: Option<lsp::PrepareRenameResponse>,
 150        _: ModelHandle<Project>,
 151        buffer: ModelHandle<Buffer>,
 152        _: LanguageServerId,
 153        cx: AsyncAppContext,
 154    ) -> Result<Option<Range<Anchor>>> {
 155        buffer.read_with(&cx, |buffer, _| {
 156            if let Some(
 157                lsp::PrepareRenameResponse::Range(range)
 158                | lsp::PrepareRenameResponse::RangeWithPlaceholder { range, .. },
 159            ) = message
 160            {
 161                let Range { start, end } = range_from_lsp(range);
 162                if buffer.clip_point_utf16(start, Bias::Left) == start.0
 163                    && buffer.clip_point_utf16(end, Bias::Left) == end.0
 164                {
 165                    return Ok(Some(buffer.anchor_after(start)..buffer.anchor_before(end)));
 166                }
 167            }
 168            Ok(None)
 169        })
 170    }
 171
 172    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::PrepareRename {
 173        proto::PrepareRename {
 174            project_id,
 175            buffer_id: buffer.remote_id(),
 176            position: Some(language::proto::serialize_anchor(
 177                &buffer.anchor_before(self.position),
 178            )),
 179            version: serialize_version(&buffer.version()),
 180        }
 181    }
 182
 183    async fn from_proto(
 184        message: proto::PrepareRename,
 185        _: ModelHandle<Project>,
 186        buffer: ModelHandle<Buffer>,
 187        mut cx: AsyncAppContext,
 188    ) -> Result<Self> {
 189        let position = message
 190            .position
 191            .and_then(deserialize_anchor)
 192            .ok_or_else(|| anyhow!("invalid position"))?;
 193        buffer
 194            .update(&mut cx, |buffer, _| {
 195                buffer.wait_for_version(deserialize_version(&message.version))
 196            })
 197            .await?;
 198
 199        Ok(Self {
 200            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 201        })
 202    }
 203
 204    fn response_to_proto(
 205        range: Option<Range<Anchor>>,
 206        _: &mut Project,
 207        _: PeerId,
 208        buffer_version: &clock::Global,
 209        _: &mut AppContext,
 210    ) -> proto::PrepareRenameResponse {
 211        proto::PrepareRenameResponse {
 212            can_rename: range.is_some(),
 213            start: range
 214                .as_ref()
 215                .map(|range| language::proto::serialize_anchor(&range.start)),
 216            end: range
 217                .as_ref()
 218                .map(|range| language::proto::serialize_anchor(&range.end)),
 219            version: serialize_version(buffer_version),
 220        }
 221    }
 222
 223    async fn response_from_proto(
 224        self,
 225        message: proto::PrepareRenameResponse,
 226        _: ModelHandle<Project>,
 227        buffer: ModelHandle<Buffer>,
 228        mut cx: AsyncAppContext,
 229    ) -> Result<Option<Range<Anchor>>> {
 230        if message.can_rename {
 231            buffer
 232                .update(&mut cx, |buffer, _| {
 233                    buffer.wait_for_version(deserialize_version(&message.version))
 234                })
 235                .await?;
 236            let start = message.start.and_then(deserialize_anchor);
 237            let end = message.end.and_then(deserialize_anchor);
 238            Ok(start.zip(end).map(|(start, end)| start..end))
 239        } else {
 240            Ok(None)
 241        }
 242    }
 243
 244    fn buffer_id_from_proto(message: &proto::PrepareRename) -> u64 {
 245        message.buffer_id
 246    }
 247}
 248
 249#[async_trait(?Send)]
 250impl LspCommand for PerformRename {
 251    type Response = ProjectTransaction;
 252    type LspRequest = lsp::request::Rename;
 253    type ProtoRequest = proto::PerformRename;
 254
 255    fn to_lsp(
 256        &self,
 257        path: &Path,
 258        _: &Buffer,
 259        _: &Arc<LanguageServer>,
 260        _: &AppContext,
 261    ) -> lsp::RenameParams {
 262        lsp::RenameParams {
 263            text_document_position: lsp::TextDocumentPositionParams {
 264                text_document: lsp::TextDocumentIdentifier {
 265                    uri: lsp::Url::from_file_path(path).unwrap(),
 266                },
 267                position: point_to_lsp(self.position),
 268            },
 269            new_name: self.new_name.clone(),
 270            work_done_progress_params: Default::default(),
 271        }
 272    }
 273
 274    async fn response_from_lsp(
 275        self,
 276        message: Option<lsp::WorkspaceEdit>,
 277        project: ModelHandle<Project>,
 278        buffer: ModelHandle<Buffer>,
 279        server_id: LanguageServerId,
 280        mut cx: AsyncAppContext,
 281    ) -> Result<ProjectTransaction> {
 282        if let Some(edit) = message {
 283            let (lsp_adapter, lsp_server) =
 284                language_server_for_buffer(&project, &buffer, server_id, &mut cx)?;
 285            Project::deserialize_workspace_edit(
 286                project,
 287                edit,
 288                self.push_to_history,
 289                lsp_adapter,
 290                lsp_server,
 291                &mut cx,
 292            )
 293            .await
 294        } else {
 295            Ok(ProjectTransaction::default())
 296        }
 297    }
 298
 299    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::PerformRename {
 300        proto::PerformRename {
 301            project_id,
 302            buffer_id: buffer.remote_id(),
 303            position: Some(language::proto::serialize_anchor(
 304                &buffer.anchor_before(self.position),
 305            )),
 306            new_name: self.new_name.clone(),
 307            version: serialize_version(&buffer.version()),
 308        }
 309    }
 310
 311    async fn from_proto(
 312        message: proto::PerformRename,
 313        _: ModelHandle<Project>,
 314        buffer: ModelHandle<Buffer>,
 315        mut cx: AsyncAppContext,
 316    ) -> Result<Self> {
 317        let position = message
 318            .position
 319            .and_then(deserialize_anchor)
 320            .ok_or_else(|| anyhow!("invalid position"))?;
 321        buffer
 322            .update(&mut cx, |buffer, _| {
 323                buffer.wait_for_version(deserialize_version(&message.version))
 324            })
 325            .await?;
 326        Ok(Self {
 327            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 328            new_name: message.new_name,
 329            push_to_history: false,
 330        })
 331    }
 332
 333    fn response_to_proto(
 334        response: ProjectTransaction,
 335        project: &mut Project,
 336        peer_id: PeerId,
 337        _: &clock::Global,
 338        cx: &mut AppContext,
 339    ) -> proto::PerformRenameResponse {
 340        let transaction = project.serialize_project_transaction_for_peer(response, peer_id, cx);
 341        proto::PerformRenameResponse {
 342            transaction: Some(transaction),
 343        }
 344    }
 345
 346    async fn response_from_proto(
 347        self,
 348        message: proto::PerformRenameResponse,
 349        project: ModelHandle<Project>,
 350        _: ModelHandle<Buffer>,
 351        mut cx: AsyncAppContext,
 352    ) -> Result<ProjectTransaction> {
 353        let message = message
 354            .transaction
 355            .ok_or_else(|| anyhow!("missing transaction"))?;
 356        project
 357            .update(&mut cx, |project, cx| {
 358                project.deserialize_project_transaction(message, self.push_to_history, cx)
 359            })
 360            .await
 361    }
 362
 363    fn buffer_id_from_proto(message: &proto::PerformRename) -> u64 {
 364        message.buffer_id
 365    }
 366}
 367
 368#[async_trait(?Send)]
 369impl LspCommand for GetDefinition {
 370    type Response = Vec<LocationLink>;
 371    type LspRequest = lsp::request::GotoDefinition;
 372    type ProtoRequest = proto::GetDefinition;
 373
 374    fn to_lsp(
 375        &self,
 376        path: &Path,
 377        _: &Buffer,
 378        _: &Arc<LanguageServer>,
 379        _: &AppContext,
 380    ) -> lsp::GotoDefinitionParams {
 381        lsp::GotoDefinitionParams {
 382            text_document_position_params: lsp::TextDocumentPositionParams {
 383                text_document: lsp::TextDocumentIdentifier {
 384                    uri: lsp::Url::from_file_path(path).unwrap(),
 385                },
 386                position: point_to_lsp(self.position),
 387            },
 388            work_done_progress_params: Default::default(),
 389            partial_result_params: Default::default(),
 390        }
 391    }
 392
 393    async fn response_from_lsp(
 394        self,
 395        message: Option<lsp::GotoDefinitionResponse>,
 396        project: ModelHandle<Project>,
 397        buffer: ModelHandle<Buffer>,
 398        server_id: LanguageServerId,
 399        cx: AsyncAppContext,
 400    ) -> Result<Vec<LocationLink>> {
 401        location_links_from_lsp(message, project, buffer, server_id, cx).await
 402    }
 403
 404    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDefinition {
 405        proto::GetDefinition {
 406            project_id,
 407            buffer_id: buffer.remote_id(),
 408            position: Some(language::proto::serialize_anchor(
 409                &buffer.anchor_before(self.position),
 410            )),
 411            version: serialize_version(&buffer.version()),
 412        }
 413    }
 414
 415    async fn from_proto(
 416        message: proto::GetDefinition,
 417        _: ModelHandle<Project>,
 418        buffer: ModelHandle<Buffer>,
 419        mut cx: AsyncAppContext,
 420    ) -> Result<Self> {
 421        let position = message
 422            .position
 423            .and_then(deserialize_anchor)
 424            .ok_or_else(|| anyhow!("invalid position"))?;
 425        buffer
 426            .update(&mut cx, |buffer, _| {
 427                buffer.wait_for_version(deserialize_version(&message.version))
 428            })
 429            .await?;
 430        Ok(Self {
 431            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 432        })
 433    }
 434
 435    fn response_to_proto(
 436        response: Vec<LocationLink>,
 437        project: &mut Project,
 438        peer_id: PeerId,
 439        _: &clock::Global,
 440        cx: &mut AppContext,
 441    ) -> proto::GetDefinitionResponse {
 442        let links = location_links_to_proto(response, project, peer_id, cx);
 443        proto::GetDefinitionResponse { links }
 444    }
 445
 446    async fn response_from_proto(
 447        self,
 448        message: proto::GetDefinitionResponse,
 449        project: ModelHandle<Project>,
 450        _: ModelHandle<Buffer>,
 451        cx: AsyncAppContext,
 452    ) -> Result<Vec<LocationLink>> {
 453        location_links_from_proto(message.links, project, cx).await
 454    }
 455
 456    fn buffer_id_from_proto(message: &proto::GetDefinition) -> u64 {
 457        message.buffer_id
 458    }
 459}
 460
 461#[async_trait(?Send)]
 462impl LspCommand for GetTypeDefinition {
 463    type Response = Vec<LocationLink>;
 464    type LspRequest = lsp::request::GotoTypeDefinition;
 465    type ProtoRequest = proto::GetTypeDefinition;
 466
 467    fn to_lsp(
 468        &self,
 469        path: &Path,
 470        _: &Buffer,
 471        _: &Arc<LanguageServer>,
 472        _: &AppContext,
 473    ) -> lsp::GotoTypeDefinitionParams {
 474        lsp::GotoTypeDefinitionParams {
 475            text_document_position_params: lsp::TextDocumentPositionParams {
 476                text_document: lsp::TextDocumentIdentifier {
 477                    uri: lsp::Url::from_file_path(path).unwrap(),
 478                },
 479                position: point_to_lsp(self.position),
 480            },
 481            work_done_progress_params: Default::default(),
 482            partial_result_params: Default::default(),
 483        }
 484    }
 485
 486    async fn response_from_lsp(
 487        self,
 488        message: Option<lsp::GotoTypeDefinitionResponse>,
 489        project: ModelHandle<Project>,
 490        buffer: ModelHandle<Buffer>,
 491        server_id: LanguageServerId,
 492        cx: AsyncAppContext,
 493    ) -> Result<Vec<LocationLink>> {
 494        location_links_from_lsp(message, project, buffer, server_id, cx).await
 495    }
 496
 497    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetTypeDefinition {
 498        proto::GetTypeDefinition {
 499            project_id,
 500            buffer_id: buffer.remote_id(),
 501            position: Some(language::proto::serialize_anchor(
 502                &buffer.anchor_before(self.position),
 503            )),
 504            version: serialize_version(&buffer.version()),
 505        }
 506    }
 507
 508    async fn from_proto(
 509        message: proto::GetTypeDefinition,
 510        _: ModelHandle<Project>,
 511        buffer: ModelHandle<Buffer>,
 512        mut cx: AsyncAppContext,
 513    ) -> Result<Self> {
 514        let position = message
 515            .position
 516            .and_then(deserialize_anchor)
 517            .ok_or_else(|| anyhow!("invalid position"))?;
 518        buffer
 519            .update(&mut cx, |buffer, _| {
 520                buffer.wait_for_version(deserialize_version(&message.version))
 521            })
 522            .await?;
 523        Ok(Self {
 524            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 525        })
 526    }
 527
 528    fn response_to_proto(
 529        response: Vec<LocationLink>,
 530        project: &mut Project,
 531        peer_id: PeerId,
 532        _: &clock::Global,
 533        cx: &mut AppContext,
 534    ) -> proto::GetTypeDefinitionResponse {
 535        let links = location_links_to_proto(response, project, peer_id, cx);
 536        proto::GetTypeDefinitionResponse { links }
 537    }
 538
 539    async fn response_from_proto(
 540        self,
 541        message: proto::GetTypeDefinitionResponse,
 542        project: ModelHandle<Project>,
 543        _: ModelHandle<Buffer>,
 544        cx: AsyncAppContext,
 545    ) -> Result<Vec<LocationLink>> {
 546        location_links_from_proto(message.links, project, cx).await
 547    }
 548
 549    fn buffer_id_from_proto(message: &proto::GetTypeDefinition) -> u64 {
 550        message.buffer_id
 551    }
 552}
 553
 554fn language_server_for_buffer(
 555    project: &ModelHandle<Project>,
 556    buffer: &ModelHandle<Buffer>,
 557    server_id: LanguageServerId,
 558    cx: &mut AsyncAppContext,
 559) -> Result<(Arc<CachedLspAdapter>, Arc<LanguageServer>)> {
 560    project
 561        .read_with(cx, |project, cx| {
 562            project
 563                .language_server_for_buffer(buffer.read(cx), server_id, cx)
 564                .map(|(adapter, server)| (adapter.clone(), server.clone()))
 565        })
 566        .ok_or_else(|| anyhow!("no language server found for buffer"))
 567}
 568
 569async fn location_links_from_proto(
 570    proto_links: Vec<proto::LocationLink>,
 571    project: ModelHandle<Project>,
 572    mut cx: AsyncAppContext,
 573) -> Result<Vec<LocationLink>> {
 574    let mut links = Vec::new();
 575
 576    for link in proto_links {
 577        let origin = match link.origin {
 578            Some(origin) => {
 579                let buffer = project
 580                    .update(&mut cx, |this, cx| {
 581                        this.wait_for_remote_buffer(origin.buffer_id, cx)
 582                    })
 583                    .await?;
 584                let start = origin
 585                    .start
 586                    .and_then(deserialize_anchor)
 587                    .ok_or_else(|| anyhow!("missing origin start"))?;
 588                let end = origin
 589                    .end
 590                    .and_then(deserialize_anchor)
 591                    .ok_or_else(|| anyhow!("missing origin end"))?;
 592                buffer
 593                    .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
 594                    .await?;
 595                Some(Location {
 596                    buffer,
 597                    range: start..end,
 598                })
 599            }
 600            None => None,
 601        };
 602
 603        let target = link.target.ok_or_else(|| anyhow!("missing target"))?;
 604        let buffer = project
 605            .update(&mut cx, |this, cx| {
 606                this.wait_for_remote_buffer(target.buffer_id, cx)
 607            })
 608            .await?;
 609        let start = target
 610            .start
 611            .and_then(deserialize_anchor)
 612            .ok_or_else(|| anyhow!("missing target start"))?;
 613        let end = target
 614            .end
 615            .and_then(deserialize_anchor)
 616            .ok_or_else(|| anyhow!("missing target end"))?;
 617        buffer
 618            .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
 619            .await?;
 620        let target = Location {
 621            buffer,
 622            range: start..end,
 623        };
 624
 625        links.push(LocationLink { origin, target })
 626    }
 627
 628    Ok(links)
 629}
 630
 631async fn location_links_from_lsp(
 632    message: Option<lsp::GotoDefinitionResponse>,
 633    project: ModelHandle<Project>,
 634    buffer: ModelHandle<Buffer>,
 635    server_id: LanguageServerId,
 636    mut cx: AsyncAppContext,
 637) -> Result<Vec<LocationLink>> {
 638    let message = match message {
 639        Some(message) => message,
 640        None => return Ok(Vec::new()),
 641    };
 642
 643    let mut unresolved_links = Vec::new();
 644    match message {
 645        lsp::GotoDefinitionResponse::Scalar(loc) => {
 646            unresolved_links.push((None, loc.uri, loc.range));
 647        }
 648
 649        lsp::GotoDefinitionResponse::Array(locs) => {
 650            unresolved_links.extend(locs.into_iter().map(|l| (None, l.uri, l.range)));
 651        }
 652
 653        lsp::GotoDefinitionResponse::Link(links) => {
 654            unresolved_links.extend(links.into_iter().map(|l| {
 655                (
 656                    l.origin_selection_range,
 657                    l.target_uri,
 658                    l.target_selection_range,
 659                )
 660            }));
 661        }
 662    }
 663
 664    let (lsp_adapter, language_server) =
 665        language_server_for_buffer(&project, &buffer, server_id, &mut cx)?;
 666    let mut definitions = Vec::new();
 667    for (origin_range, target_uri, target_range) in unresolved_links {
 668        let target_buffer_handle = project
 669            .update(&mut cx, |this, cx| {
 670                this.open_local_buffer_via_lsp(
 671                    target_uri,
 672                    language_server.server_id(),
 673                    lsp_adapter.name.clone(),
 674                    cx,
 675                )
 676            })
 677            .await?;
 678
 679        cx.read(|cx| {
 680            let origin_location = origin_range.map(|origin_range| {
 681                let origin_buffer = buffer.read(cx);
 682                let origin_start =
 683                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
 684                let origin_end =
 685                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
 686                Location {
 687                    buffer: buffer.clone(),
 688                    range: origin_buffer.anchor_after(origin_start)
 689                        ..origin_buffer.anchor_before(origin_end),
 690                }
 691            });
 692
 693            let target_buffer = target_buffer_handle.read(cx);
 694            let target_start =
 695                target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
 696            let target_end =
 697                target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
 698            let target_location = Location {
 699                buffer: target_buffer_handle,
 700                range: target_buffer.anchor_after(target_start)
 701                    ..target_buffer.anchor_before(target_end),
 702            };
 703
 704            definitions.push(LocationLink {
 705                origin: origin_location,
 706                target: target_location,
 707            })
 708        });
 709    }
 710    Ok(definitions)
 711}
 712
 713fn location_links_to_proto(
 714    links: Vec<LocationLink>,
 715    project: &mut Project,
 716    peer_id: PeerId,
 717    cx: &mut AppContext,
 718) -> Vec<proto::LocationLink> {
 719    links
 720        .into_iter()
 721        .map(|definition| {
 722            let origin = definition.origin.map(|origin| {
 723                let buffer_id = project.create_buffer_for_peer(&origin.buffer, peer_id, cx);
 724                proto::Location {
 725                    start: Some(serialize_anchor(&origin.range.start)),
 726                    end: Some(serialize_anchor(&origin.range.end)),
 727                    buffer_id,
 728                }
 729            });
 730
 731            let buffer_id = project.create_buffer_for_peer(&definition.target.buffer, peer_id, cx);
 732            let target = proto::Location {
 733                start: Some(serialize_anchor(&definition.target.range.start)),
 734                end: Some(serialize_anchor(&definition.target.range.end)),
 735                buffer_id,
 736            };
 737
 738            proto::LocationLink {
 739                origin,
 740                target: Some(target),
 741            }
 742        })
 743        .collect()
 744}
 745
 746#[async_trait(?Send)]
 747impl LspCommand for GetReferences {
 748    type Response = Vec<Location>;
 749    type LspRequest = lsp::request::References;
 750    type ProtoRequest = proto::GetReferences;
 751
 752    fn to_lsp(
 753        &self,
 754        path: &Path,
 755        _: &Buffer,
 756        _: &Arc<LanguageServer>,
 757        _: &AppContext,
 758    ) -> lsp::ReferenceParams {
 759        lsp::ReferenceParams {
 760            text_document_position: lsp::TextDocumentPositionParams {
 761                text_document: lsp::TextDocumentIdentifier {
 762                    uri: lsp::Url::from_file_path(path).unwrap(),
 763                },
 764                position: point_to_lsp(self.position),
 765            },
 766            work_done_progress_params: Default::default(),
 767            partial_result_params: Default::default(),
 768            context: lsp::ReferenceContext {
 769                include_declaration: true,
 770            },
 771        }
 772    }
 773
 774    async fn response_from_lsp(
 775        self,
 776        locations: Option<Vec<lsp::Location>>,
 777        project: ModelHandle<Project>,
 778        buffer: ModelHandle<Buffer>,
 779        server_id: LanguageServerId,
 780        mut cx: AsyncAppContext,
 781    ) -> Result<Vec<Location>> {
 782        let mut references = Vec::new();
 783        let (lsp_adapter, language_server) =
 784            language_server_for_buffer(&project, &buffer, server_id, &mut cx)?;
 785
 786        if let Some(locations) = locations {
 787            for lsp_location in locations {
 788                let target_buffer_handle = project
 789                    .update(&mut cx, |this, cx| {
 790                        this.open_local_buffer_via_lsp(
 791                            lsp_location.uri,
 792                            language_server.server_id(),
 793                            lsp_adapter.name.clone(),
 794                            cx,
 795                        )
 796                    })
 797                    .await?;
 798
 799                cx.read(|cx| {
 800                    let target_buffer = target_buffer_handle.read(cx);
 801                    let target_start = target_buffer
 802                        .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
 803                    let target_end = target_buffer
 804                        .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
 805                    references.push(Location {
 806                        buffer: target_buffer_handle,
 807                        range: target_buffer.anchor_after(target_start)
 808                            ..target_buffer.anchor_before(target_end),
 809                    });
 810                });
 811            }
 812        }
 813
 814        Ok(references)
 815    }
 816
 817    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetReferences {
 818        proto::GetReferences {
 819            project_id,
 820            buffer_id: buffer.remote_id(),
 821            position: Some(language::proto::serialize_anchor(
 822                &buffer.anchor_before(self.position),
 823            )),
 824            version: serialize_version(&buffer.version()),
 825        }
 826    }
 827
 828    async fn from_proto(
 829        message: proto::GetReferences,
 830        _: ModelHandle<Project>,
 831        buffer: ModelHandle<Buffer>,
 832        mut cx: AsyncAppContext,
 833    ) -> Result<Self> {
 834        let position = message
 835            .position
 836            .and_then(deserialize_anchor)
 837            .ok_or_else(|| anyhow!("invalid position"))?;
 838        buffer
 839            .update(&mut cx, |buffer, _| {
 840                buffer.wait_for_version(deserialize_version(&message.version))
 841            })
 842            .await?;
 843        Ok(Self {
 844            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 845        })
 846    }
 847
 848    fn response_to_proto(
 849        response: Vec<Location>,
 850        project: &mut Project,
 851        peer_id: PeerId,
 852        _: &clock::Global,
 853        cx: &mut AppContext,
 854    ) -> proto::GetReferencesResponse {
 855        let locations = response
 856            .into_iter()
 857            .map(|definition| {
 858                let buffer_id = project.create_buffer_for_peer(&definition.buffer, peer_id, cx);
 859                proto::Location {
 860                    start: Some(serialize_anchor(&definition.range.start)),
 861                    end: Some(serialize_anchor(&definition.range.end)),
 862                    buffer_id,
 863                }
 864            })
 865            .collect();
 866        proto::GetReferencesResponse { locations }
 867    }
 868
 869    async fn response_from_proto(
 870        self,
 871        message: proto::GetReferencesResponse,
 872        project: ModelHandle<Project>,
 873        _: ModelHandle<Buffer>,
 874        mut cx: AsyncAppContext,
 875    ) -> Result<Vec<Location>> {
 876        let mut locations = Vec::new();
 877        for location in message.locations {
 878            let target_buffer = project
 879                .update(&mut cx, |this, cx| {
 880                    this.wait_for_remote_buffer(location.buffer_id, cx)
 881                })
 882                .await?;
 883            let start = location
 884                .start
 885                .and_then(deserialize_anchor)
 886                .ok_or_else(|| anyhow!("missing target start"))?;
 887            let end = location
 888                .end
 889                .and_then(deserialize_anchor)
 890                .ok_or_else(|| anyhow!("missing target end"))?;
 891            target_buffer
 892                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
 893                .await?;
 894            locations.push(Location {
 895                buffer: target_buffer,
 896                range: start..end,
 897            })
 898        }
 899        Ok(locations)
 900    }
 901
 902    fn buffer_id_from_proto(message: &proto::GetReferences) -> u64 {
 903        message.buffer_id
 904    }
 905}
 906
 907#[async_trait(?Send)]
 908impl LspCommand for GetDocumentHighlights {
 909    type Response = Vec<DocumentHighlight>;
 910    type LspRequest = lsp::request::DocumentHighlightRequest;
 911    type ProtoRequest = proto::GetDocumentHighlights;
 912
 913    fn check_capabilities(&self, capabilities: &ServerCapabilities) -> bool {
 914        capabilities.document_highlight_provider.is_some()
 915    }
 916
 917    fn to_lsp(
 918        &self,
 919        path: &Path,
 920        _: &Buffer,
 921        _: &Arc<LanguageServer>,
 922        _: &AppContext,
 923    ) -> lsp::DocumentHighlightParams {
 924        lsp::DocumentHighlightParams {
 925            text_document_position_params: lsp::TextDocumentPositionParams {
 926                text_document: lsp::TextDocumentIdentifier {
 927                    uri: lsp::Url::from_file_path(path).unwrap(),
 928                },
 929                position: point_to_lsp(self.position),
 930            },
 931            work_done_progress_params: Default::default(),
 932            partial_result_params: Default::default(),
 933        }
 934    }
 935
 936    async fn response_from_lsp(
 937        self,
 938        lsp_highlights: Option<Vec<lsp::DocumentHighlight>>,
 939        _: ModelHandle<Project>,
 940        buffer: ModelHandle<Buffer>,
 941        _: LanguageServerId,
 942        cx: AsyncAppContext,
 943    ) -> Result<Vec<DocumentHighlight>> {
 944        buffer.read_with(&cx, |buffer, _| {
 945            let mut lsp_highlights = lsp_highlights.unwrap_or_default();
 946            lsp_highlights.sort_unstable_by_key(|h| (h.range.start, Reverse(h.range.end)));
 947            Ok(lsp_highlights
 948                .into_iter()
 949                .map(|lsp_highlight| {
 950                    let start = buffer
 951                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.start), Bias::Left);
 952                    let end = buffer
 953                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.end), Bias::Left);
 954                    DocumentHighlight {
 955                        range: buffer.anchor_after(start)..buffer.anchor_before(end),
 956                        kind: lsp_highlight
 957                            .kind
 958                            .unwrap_or(lsp::DocumentHighlightKind::READ),
 959                    }
 960                })
 961                .collect())
 962        })
 963    }
 964
 965    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentHighlights {
 966        proto::GetDocumentHighlights {
 967            project_id,
 968            buffer_id: buffer.remote_id(),
 969            position: Some(language::proto::serialize_anchor(
 970                &buffer.anchor_before(self.position),
 971            )),
 972            version: serialize_version(&buffer.version()),
 973        }
 974    }
 975
 976    async fn from_proto(
 977        message: proto::GetDocumentHighlights,
 978        _: ModelHandle<Project>,
 979        buffer: ModelHandle<Buffer>,
 980        mut cx: AsyncAppContext,
 981    ) -> Result<Self> {
 982        let position = message
 983            .position
 984            .and_then(deserialize_anchor)
 985            .ok_or_else(|| anyhow!("invalid position"))?;
 986        buffer
 987            .update(&mut cx, |buffer, _| {
 988                buffer.wait_for_version(deserialize_version(&message.version))
 989            })
 990            .await?;
 991        Ok(Self {
 992            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 993        })
 994    }
 995
 996    fn response_to_proto(
 997        response: Vec<DocumentHighlight>,
 998        _: &mut Project,
 999        _: PeerId,
1000        _: &clock::Global,
1001        _: &mut AppContext,
1002    ) -> proto::GetDocumentHighlightsResponse {
1003        let highlights = response
1004            .into_iter()
1005            .map(|highlight| proto::DocumentHighlight {
1006                start: Some(serialize_anchor(&highlight.range.start)),
1007                end: Some(serialize_anchor(&highlight.range.end)),
1008                kind: match highlight.kind {
1009                    DocumentHighlightKind::TEXT => proto::document_highlight::Kind::Text.into(),
1010                    DocumentHighlightKind::WRITE => proto::document_highlight::Kind::Write.into(),
1011                    DocumentHighlightKind::READ => proto::document_highlight::Kind::Read.into(),
1012                    _ => proto::document_highlight::Kind::Text.into(),
1013                },
1014            })
1015            .collect();
1016        proto::GetDocumentHighlightsResponse { highlights }
1017    }
1018
1019    async fn response_from_proto(
1020        self,
1021        message: proto::GetDocumentHighlightsResponse,
1022        _: ModelHandle<Project>,
1023        buffer: ModelHandle<Buffer>,
1024        mut cx: AsyncAppContext,
1025    ) -> Result<Vec<DocumentHighlight>> {
1026        let mut highlights = Vec::new();
1027        for highlight in message.highlights {
1028            let start = highlight
1029                .start
1030                .and_then(deserialize_anchor)
1031                .ok_or_else(|| anyhow!("missing target start"))?;
1032            let end = highlight
1033                .end
1034                .and_then(deserialize_anchor)
1035                .ok_or_else(|| anyhow!("missing target end"))?;
1036            buffer
1037                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1038                .await?;
1039            let kind = match proto::document_highlight::Kind::from_i32(highlight.kind) {
1040                Some(proto::document_highlight::Kind::Text) => DocumentHighlightKind::TEXT,
1041                Some(proto::document_highlight::Kind::Read) => DocumentHighlightKind::READ,
1042                Some(proto::document_highlight::Kind::Write) => DocumentHighlightKind::WRITE,
1043                None => DocumentHighlightKind::TEXT,
1044            };
1045            highlights.push(DocumentHighlight {
1046                range: start..end,
1047                kind,
1048            });
1049        }
1050        Ok(highlights)
1051    }
1052
1053    fn buffer_id_from_proto(message: &proto::GetDocumentHighlights) -> u64 {
1054        message.buffer_id
1055    }
1056}
1057
1058#[async_trait(?Send)]
1059impl LspCommand for GetHover {
1060    type Response = Option<Hover>;
1061    type LspRequest = lsp::request::HoverRequest;
1062    type ProtoRequest = proto::GetHover;
1063
1064    fn to_lsp(
1065        &self,
1066        path: &Path,
1067        _: &Buffer,
1068        _: &Arc<LanguageServer>,
1069        _: &AppContext,
1070    ) -> lsp::HoverParams {
1071        lsp::HoverParams {
1072            text_document_position_params: lsp::TextDocumentPositionParams {
1073                text_document: lsp::TextDocumentIdentifier {
1074                    uri: lsp::Url::from_file_path(path).unwrap(),
1075                },
1076                position: point_to_lsp(self.position),
1077            },
1078            work_done_progress_params: Default::default(),
1079        }
1080    }
1081
1082    async fn response_from_lsp(
1083        self,
1084        message: Option<lsp::Hover>,
1085        _: ModelHandle<Project>,
1086        buffer: ModelHandle<Buffer>,
1087        _: LanguageServerId,
1088        cx: AsyncAppContext,
1089    ) -> Result<Self::Response> {
1090        Ok(message.and_then(|hover| {
1091            let range = hover.range.map(|range| {
1092                cx.read(|cx| {
1093                    let buffer = buffer.read(cx);
1094                    let token_start =
1095                        buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
1096                    let token_end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
1097                    buffer.anchor_after(token_start)..buffer.anchor_before(token_end)
1098                })
1099            });
1100
1101            fn hover_blocks_from_marked_string(
1102                marked_string: lsp::MarkedString,
1103            ) -> Option<HoverBlock> {
1104                let block = match marked_string {
1105                    lsp::MarkedString::String(content) => HoverBlock {
1106                        text: content,
1107                        kind: HoverBlockKind::Markdown,
1108                    },
1109                    lsp::MarkedString::LanguageString(lsp::LanguageString { language, value }) => {
1110                        HoverBlock {
1111                            text: value,
1112                            kind: HoverBlockKind::Code { language },
1113                        }
1114                    }
1115                };
1116                if block.text.is_empty() {
1117                    None
1118                } else {
1119                    Some(block)
1120                }
1121            }
1122
1123            let contents = cx.read(|_| match hover.contents {
1124                lsp::HoverContents::Scalar(marked_string) => {
1125                    hover_blocks_from_marked_string(marked_string)
1126                        .into_iter()
1127                        .collect()
1128                }
1129                lsp::HoverContents::Array(marked_strings) => marked_strings
1130                    .into_iter()
1131                    .filter_map(hover_blocks_from_marked_string)
1132                    .collect(),
1133                lsp::HoverContents::Markup(markup_content) => vec![HoverBlock {
1134                    text: markup_content.value,
1135                    kind: if markup_content.kind == lsp::MarkupKind::Markdown {
1136                        HoverBlockKind::Markdown
1137                    } else {
1138                        HoverBlockKind::PlainText
1139                    },
1140                }],
1141            });
1142
1143            Some(Hover { contents, range })
1144        }))
1145    }
1146
1147    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
1148        proto::GetHover {
1149            project_id,
1150            buffer_id: buffer.remote_id(),
1151            position: Some(language::proto::serialize_anchor(
1152                &buffer.anchor_before(self.position),
1153            )),
1154            version: serialize_version(&buffer.version),
1155        }
1156    }
1157
1158    async fn from_proto(
1159        message: Self::ProtoRequest,
1160        _: ModelHandle<Project>,
1161        buffer: ModelHandle<Buffer>,
1162        mut cx: AsyncAppContext,
1163    ) -> Result<Self> {
1164        let position = message
1165            .position
1166            .and_then(deserialize_anchor)
1167            .ok_or_else(|| anyhow!("invalid position"))?;
1168        buffer
1169            .update(&mut cx, |buffer, _| {
1170                buffer.wait_for_version(deserialize_version(&message.version))
1171            })
1172            .await?;
1173        Ok(Self {
1174            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1175        })
1176    }
1177
1178    fn response_to_proto(
1179        response: Self::Response,
1180        _: &mut Project,
1181        _: PeerId,
1182        _: &clock::Global,
1183        _: &mut AppContext,
1184    ) -> proto::GetHoverResponse {
1185        if let Some(response) = response {
1186            let (start, end) = if let Some(range) = response.range {
1187                (
1188                    Some(language::proto::serialize_anchor(&range.start)),
1189                    Some(language::proto::serialize_anchor(&range.end)),
1190                )
1191            } else {
1192                (None, None)
1193            };
1194
1195            let contents = response
1196                .contents
1197                .into_iter()
1198                .map(|block| proto::HoverBlock {
1199                    text: block.text,
1200                    is_markdown: block.kind == HoverBlockKind::Markdown,
1201                    language: if let HoverBlockKind::Code { language } = block.kind {
1202                        Some(language)
1203                    } else {
1204                        None
1205                    },
1206                })
1207                .collect();
1208
1209            proto::GetHoverResponse {
1210                start,
1211                end,
1212                contents,
1213            }
1214        } else {
1215            proto::GetHoverResponse {
1216                start: None,
1217                end: None,
1218                contents: Vec::new(),
1219            }
1220        }
1221    }
1222
1223    async fn response_from_proto(
1224        self,
1225        message: proto::GetHoverResponse,
1226        _: ModelHandle<Project>,
1227        _: ModelHandle<Buffer>,
1228        _: AsyncAppContext,
1229    ) -> Result<Self::Response> {
1230        let range = if let (Some(start), Some(end)) = (message.start, message.end) {
1231            language::proto::deserialize_anchor(start)
1232                .and_then(|start| language::proto::deserialize_anchor(end).map(|end| start..end))
1233        } else {
1234            None
1235        };
1236
1237        let contents: Vec<_> = message
1238            .contents
1239            .into_iter()
1240            .map(|block| HoverBlock {
1241                text: block.text,
1242                kind: if let Some(language) = block.language {
1243                    HoverBlockKind::Code { language }
1244                } else if block.is_markdown {
1245                    HoverBlockKind::Markdown
1246                } else {
1247                    HoverBlockKind::PlainText
1248                },
1249            })
1250            .collect();
1251
1252        Ok(if contents.is_empty() {
1253            None
1254        } else {
1255            Some(Hover { contents, range })
1256        })
1257    }
1258
1259    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> u64 {
1260        message.buffer_id
1261    }
1262}
1263
1264#[async_trait(?Send)]
1265impl LspCommand for GetCompletions {
1266    type Response = Vec<Completion>;
1267    type LspRequest = lsp::request::Completion;
1268    type ProtoRequest = proto::GetCompletions;
1269
1270    fn to_lsp(
1271        &self,
1272        path: &Path,
1273        _: &Buffer,
1274        _: &Arc<LanguageServer>,
1275        _: &AppContext,
1276    ) -> lsp::CompletionParams {
1277        lsp::CompletionParams {
1278            text_document_position: lsp::TextDocumentPositionParams::new(
1279                lsp::TextDocumentIdentifier::new(lsp::Url::from_file_path(path).unwrap()),
1280                point_to_lsp(self.position),
1281            ),
1282            context: Default::default(),
1283            work_done_progress_params: Default::default(),
1284            partial_result_params: Default::default(),
1285        }
1286    }
1287
1288    async fn response_from_lsp(
1289        self,
1290        completions: Option<lsp::CompletionResponse>,
1291        _: ModelHandle<Project>,
1292        buffer: ModelHandle<Buffer>,
1293        _: LanguageServerId,
1294        cx: AsyncAppContext,
1295    ) -> Result<Vec<Completion>> {
1296        let completions = if let Some(completions) = completions {
1297            match completions {
1298                lsp::CompletionResponse::Array(completions) => completions,
1299                lsp::CompletionResponse::List(list) => list.items,
1300            }
1301        } else {
1302            Default::default()
1303        };
1304
1305        let completions = buffer.read_with(&cx, |buffer, _| {
1306            let language = buffer.language().cloned();
1307            let snapshot = buffer.snapshot();
1308            let clipped_position = buffer.clip_point_utf16(Unclipped(self.position), Bias::Left);
1309            let mut range_for_token = None;
1310            completions
1311                .into_iter()
1312                .filter_map(move |mut lsp_completion| {
1313                    // For now, we can only handle additional edits if they are returned
1314                    // when resolving the completion, not if they are present initially.
1315                    if lsp_completion
1316                        .additional_text_edits
1317                        .as_ref()
1318                        .map_or(false, |edits| !edits.is_empty())
1319                    {
1320                        return None;
1321                    }
1322
1323                    let (old_range, mut new_text) = match lsp_completion.text_edit.as_ref() {
1324                        // If the language server provides a range to overwrite, then
1325                        // check that the range is valid.
1326                        Some(lsp::CompletionTextEdit::Edit(edit)) => {
1327                            let range = range_from_lsp(edit.range);
1328                            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
1329                            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
1330                            if start != range.start.0 || end != range.end.0 {
1331                                log::info!("completion out of expected range");
1332                                return None;
1333                            }
1334                            (
1335                                snapshot.anchor_before(start)..snapshot.anchor_after(end),
1336                                edit.new_text.clone(),
1337                            )
1338                        }
1339                        // If the language server does not provide a range, then infer
1340                        // the range based on the syntax tree.
1341                        None => {
1342                            if self.position != clipped_position {
1343                                log::info!("completion out of expected range");
1344                                return None;
1345                            }
1346                            let Range { start, end } = range_for_token
1347                                .get_or_insert_with(|| {
1348                                    let offset = self.position.to_offset(&snapshot);
1349                                    let (range, kind) = snapshot.surrounding_word(offset);
1350                                    if kind == Some(CharKind::Word) {
1351                                        range
1352                                    } else {
1353                                        offset..offset
1354                                    }
1355                                })
1356                                .clone();
1357                            let text = lsp_completion
1358                                .insert_text
1359                                .as_ref()
1360                                .unwrap_or(&lsp_completion.label)
1361                                .clone();
1362                            (
1363                                snapshot.anchor_before(start)..snapshot.anchor_after(end),
1364                                text,
1365                            )
1366                        }
1367                        Some(lsp::CompletionTextEdit::InsertAndReplace(_)) => {
1368                            log::info!("unsupported insert/replace completion");
1369                            return None;
1370                        }
1371                    };
1372
1373                    let language = language.clone();
1374                    LineEnding::normalize(&mut new_text);
1375                    Some(async move {
1376                        let mut label = None;
1377                        if let Some(language) = language {
1378                            language.process_completion(&mut lsp_completion).await;
1379                            label = language.label_for_completion(&lsp_completion).await;
1380                        }
1381                        Completion {
1382                            old_range,
1383                            new_text,
1384                            label: label.unwrap_or_else(|| {
1385                                language::CodeLabel::plain(
1386                                    lsp_completion.label.clone(),
1387                                    lsp_completion.filter_text.as_deref(),
1388                                )
1389                            }),
1390                            lsp_completion,
1391                        }
1392                    })
1393                })
1394        });
1395
1396        Ok(futures::future::join_all(completions).await)
1397    }
1398
1399    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCompletions {
1400        let anchor = buffer.anchor_after(self.position);
1401        proto::GetCompletions {
1402            project_id,
1403            buffer_id: buffer.remote_id(),
1404            position: Some(language::proto::serialize_anchor(&anchor)),
1405            version: serialize_version(&buffer.version()),
1406        }
1407    }
1408
1409    async fn from_proto(
1410        message: proto::GetCompletions,
1411        _: ModelHandle<Project>,
1412        buffer: ModelHandle<Buffer>,
1413        mut cx: AsyncAppContext,
1414    ) -> Result<Self> {
1415        let version = deserialize_version(&message.version);
1416        buffer
1417            .update(&mut cx, |buffer, _| buffer.wait_for_version(version))
1418            .await?;
1419        let position = message
1420            .position
1421            .and_then(language::proto::deserialize_anchor)
1422            .map(|p| {
1423                buffer.read_with(&cx, |buffer, _| {
1424                    buffer.clip_point_utf16(Unclipped(p.to_point_utf16(buffer)), Bias::Left)
1425                })
1426            })
1427            .ok_or_else(|| anyhow!("invalid position"))?;
1428        Ok(Self { position })
1429    }
1430
1431    fn response_to_proto(
1432        completions: Vec<Completion>,
1433        _: &mut Project,
1434        _: PeerId,
1435        buffer_version: &clock::Global,
1436        _: &mut AppContext,
1437    ) -> proto::GetCompletionsResponse {
1438        proto::GetCompletionsResponse {
1439            completions: completions
1440                .iter()
1441                .map(language::proto::serialize_completion)
1442                .collect(),
1443            version: serialize_version(&buffer_version),
1444        }
1445    }
1446
1447    async fn response_from_proto(
1448        self,
1449        message: proto::GetCompletionsResponse,
1450        _: ModelHandle<Project>,
1451        buffer: ModelHandle<Buffer>,
1452        mut cx: AsyncAppContext,
1453    ) -> Result<Vec<Completion>> {
1454        buffer
1455            .update(&mut cx, |buffer, _| {
1456                buffer.wait_for_version(deserialize_version(&message.version))
1457            })
1458            .await?;
1459
1460        let language = buffer.read_with(&cx, |buffer, _| buffer.language().cloned());
1461        let completions = message.completions.into_iter().map(|completion| {
1462            language::proto::deserialize_completion(completion, language.clone())
1463        });
1464        futures::future::try_join_all(completions).await
1465    }
1466
1467    fn buffer_id_from_proto(message: &proto::GetCompletions) -> u64 {
1468        message.buffer_id
1469    }
1470}
1471
1472#[async_trait(?Send)]
1473impl LspCommand for GetCodeActions {
1474    type Response = Vec<CodeAction>;
1475    type LspRequest = lsp::request::CodeActionRequest;
1476    type ProtoRequest = proto::GetCodeActions;
1477
1478    fn check_capabilities(&self, capabilities: &ServerCapabilities) -> bool {
1479        capabilities.code_action_provider.is_some()
1480    }
1481
1482    fn to_lsp(
1483        &self,
1484        path: &Path,
1485        buffer: &Buffer,
1486        language_server: &Arc<LanguageServer>,
1487        _: &AppContext,
1488    ) -> lsp::CodeActionParams {
1489        let relevant_diagnostics = buffer
1490            .snapshot()
1491            .diagnostics_in_range::<_, usize>(self.range.clone(), false)
1492            .map(|entry| entry.to_lsp_diagnostic_stub())
1493            .collect();
1494        lsp::CodeActionParams {
1495            text_document: lsp::TextDocumentIdentifier::new(
1496                lsp::Url::from_file_path(path).unwrap(),
1497            ),
1498            range: range_to_lsp(self.range.to_point_utf16(buffer)),
1499            work_done_progress_params: Default::default(),
1500            partial_result_params: Default::default(),
1501            context: lsp::CodeActionContext {
1502                diagnostics: relevant_diagnostics,
1503                only: language_server.code_action_kinds(),
1504            },
1505        }
1506    }
1507
1508    async fn response_from_lsp(
1509        self,
1510        actions: Option<lsp::CodeActionResponse>,
1511        _: ModelHandle<Project>,
1512        _: ModelHandle<Buffer>,
1513        server_id: LanguageServerId,
1514        _: AsyncAppContext,
1515    ) -> Result<Vec<CodeAction>> {
1516        Ok(actions
1517            .unwrap_or_default()
1518            .into_iter()
1519            .filter_map(|entry| {
1520                if let lsp::CodeActionOrCommand::CodeAction(lsp_action) = entry {
1521                    Some(CodeAction {
1522                        server_id,
1523                        range: self.range.clone(),
1524                        lsp_action,
1525                    })
1526                } else {
1527                    None
1528                }
1529            })
1530            .collect())
1531    }
1532
1533    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeActions {
1534        proto::GetCodeActions {
1535            project_id,
1536            buffer_id: buffer.remote_id(),
1537            start: Some(language::proto::serialize_anchor(&self.range.start)),
1538            end: Some(language::proto::serialize_anchor(&self.range.end)),
1539            version: serialize_version(&buffer.version()),
1540        }
1541    }
1542
1543    async fn from_proto(
1544        message: proto::GetCodeActions,
1545        _: ModelHandle<Project>,
1546        buffer: ModelHandle<Buffer>,
1547        mut cx: AsyncAppContext,
1548    ) -> Result<Self> {
1549        let start = message
1550            .start
1551            .and_then(language::proto::deserialize_anchor)
1552            .ok_or_else(|| anyhow!("invalid start"))?;
1553        let end = message
1554            .end
1555            .and_then(language::proto::deserialize_anchor)
1556            .ok_or_else(|| anyhow!("invalid end"))?;
1557        buffer
1558            .update(&mut cx, |buffer, _| {
1559                buffer.wait_for_version(deserialize_version(&message.version))
1560            })
1561            .await?;
1562
1563        Ok(Self { range: start..end })
1564    }
1565
1566    fn response_to_proto(
1567        code_actions: Vec<CodeAction>,
1568        _: &mut Project,
1569        _: PeerId,
1570        buffer_version: &clock::Global,
1571        _: &mut AppContext,
1572    ) -> proto::GetCodeActionsResponse {
1573        proto::GetCodeActionsResponse {
1574            actions: code_actions
1575                .iter()
1576                .map(language::proto::serialize_code_action)
1577                .collect(),
1578            version: serialize_version(&buffer_version),
1579        }
1580    }
1581
1582    async fn response_from_proto(
1583        self,
1584        message: proto::GetCodeActionsResponse,
1585        _: ModelHandle<Project>,
1586        buffer: ModelHandle<Buffer>,
1587        mut cx: AsyncAppContext,
1588    ) -> Result<Vec<CodeAction>> {
1589        buffer
1590            .update(&mut cx, |buffer, _| {
1591                buffer.wait_for_version(deserialize_version(&message.version))
1592            })
1593            .await?;
1594        message
1595            .actions
1596            .into_iter()
1597            .map(language::proto::deserialize_code_action)
1598            .collect()
1599    }
1600
1601    fn buffer_id_from_proto(message: &proto::GetCodeActions) -> u64 {
1602        message.buffer_id
1603    }
1604}
1605
1606#[async_trait(?Send)]
1607impl LspCommand for OnTypeFormatting {
1608    type Response = Vec<(Range<Anchor>, String)>;
1609    type LspRequest = lsp::request::OnTypeFormatting;
1610    type ProtoRequest = proto::PerformRename;
1611
1612    fn check_capabilities(&self, server_capabilities: &lsp::ServerCapabilities) -> bool {
1613        let Some(on_type_formatting_options) = &server_capabilities.document_on_type_formatting_provider else { return false };
1614        on_type_formatting_options
1615            .first_trigger_character
1616            .contains(self.new_char)
1617            || on_type_formatting_options
1618                .more_trigger_character
1619                .iter()
1620                .flatten()
1621                .any(|chars| chars.contains(self.new_char))
1622    }
1623
1624    fn to_lsp(
1625        &self,
1626        path: &Path,
1627        _: &Buffer,
1628        _: &Arc<LanguageServer>,
1629        _: &AppContext,
1630    ) -> lsp::DocumentOnTypeFormattingParams {
1631        lsp::DocumentOnTypeFormattingParams {
1632            text_document_position: lsp::TextDocumentPositionParams::new(
1633                lsp::TextDocumentIdentifier::new(lsp::Url::from_file_path(path).unwrap()),
1634                point_to_lsp(self.position),
1635            ),
1636            ch: self.new_char.to_string(),
1637            // TODO kb pass current editor ones
1638            options: lsp::FormattingOptions::default(),
1639        }
1640    }
1641
1642    async fn response_from_lsp(
1643        self,
1644        message: Option<Vec<lsp::TextEdit>>,
1645        project: ModelHandle<Project>,
1646        buffer: ModelHandle<Buffer>,
1647        server_id: LanguageServerId,
1648        mut cx: AsyncAppContext,
1649    ) -> Result<Vec<(Range<Anchor>, String)>> {
1650        cx.update(|cx| {
1651            project.update(cx, |project, cx| {
1652                project.edits_from_lsp(&buffer, message.into_iter().flatten(), server_id, None, cx)
1653            })
1654        })
1655        .await
1656        .context("LSP edits conversion")
1657    }
1658
1659    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::PerformRename {
1660        todo!("TODO kb")
1661    }
1662
1663    async fn from_proto(
1664        message: proto::PerformRename,
1665        _: ModelHandle<Project>,
1666        buffer: ModelHandle<Buffer>,
1667        mut cx: AsyncAppContext,
1668    ) -> Result<Self> {
1669        todo!("TODO kb")
1670    }
1671
1672    fn response_to_proto(
1673        response: Vec<(Range<Anchor>, String)>,
1674        project: &mut Project,
1675        peer_id: PeerId,
1676        _: &clock::Global,
1677        cx: &mut AppContext,
1678    ) -> proto::PerformRenameResponse {
1679        // let transaction = project.serialize_project_transaction_for_peer(response, peer_id, cx);
1680        // proto::PerformRenameResponse {
1681        //     transaction: Some(transaction),
1682        // }
1683        todo!("TODO kb")
1684    }
1685
1686    async fn response_from_proto(
1687        self,
1688        message: proto::PerformRenameResponse,
1689        project: ModelHandle<Project>,
1690        _: ModelHandle<Buffer>,
1691        mut cx: AsyncAppContext,
1692    ) -> Result<Vec<(Range<Anchor>, String)>> {
1693        todo!("TODO kb")
1694    }
1695
1696    fn buffer_id_from_proto(message: &proto::PerformRename) -> u64 {
1697        message.buffer_id
1698    }
1699}