lsp_command.rs

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