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