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