lsp_command.rs

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