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 to_lsp(
 491        &self,
 492        path: &Path,
 493        _: &Buffer,
 494        _: &Arc<LanguageServer>,
 495        _: &AppContext,
 496    ) -> lsp::GotoTypeDefinitionParams {
 497        lsp::GotoTypeDefinitionParams {
 498            text_document_position_params: lsp::TextDocumentPositionParams {
 499                text_document: lsp::TextDocumentIdentifier {
 500                    uri: lsp::Url::from_file_path(path).unwrap(),
 501                },
 502                position: point_to_lsp(self.position),
 503            },
 504            work_done_progress_params: Default::default(),
 505            partial_result_params: Default::default(),
 506        }
 507    }
 508
 509    async fn response_from_lsp(
 510        self,
 511        message: Option<lsp::GotoTypeDefinitionResponse>,
 512        project: ModelHandle<Project>,
 513        buffer: ModelHandle<Buffer>,
 514        server_id: LanguageServerId,
 515        cx: AsyncAppContext,
 516    ) -> Result<Vec<LocationLink>> {
 517        location_links_from_lsp(message, project, buffer, server_id, cx).await
 518    }
 519
 520    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetTypeDefinition {
 521        proto::GetTypeDefinition {
 522            project_id,
 523            buffer_id: buffer.remote_id(),
 524            position: Some(language::proto::serialize_anchor(
 525                &buffer.anchor_before(self.position),
 526            )),
 527            version: serialize_version(&buffer.version()),
 528        }
 529    }
 530
 531    async fn from_proto(
 532        message: proto::GetTypeDefinition,
 533        _: ModelHandle<Project>,
 534        buffer: ModelHandle<Buffer>,
 535        mut cx: AsyncAppContext,
 536    ) -> Result<Self> {
 537        let position = message
 538            .position
 539            .and_then(deserialize_anchor)
 540            .ok_or_else(|| anyhow!("invalid position"))?;
 541        buffer
 542            .update(&mut cx, |buffer, _| {
 543                buffer.wait_for_version(deserialize_version(&message.version))
 544            })
 545            .await?;
 546        Ok(Self {
 547            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 548        })
 549    }
 550
 551    fn response_to_proto(
 552        response: Vec<LocationLink>,
 553        project: &mut Project,
 554        peer_id: PeerId,
 555        _: &clock::Global,
 556        cx: &mut AppContext,
 557    ) -> proto::GetTypeDefinitionResponse {
 558        let links = location_links_to_proto(response, project, peer_id, cx);
 559        proto::GetTypeDefinitionResponse { links }
 560    }
 561
 562    async fn response_from_proto(
 563        self,
 564        message: proto::GetTypeDefinitionResponse,
 565        project: ModelHandle<Project>,
 566        _: ModelHandle<Buffer>,
 567        cx: AsyncAppContext,
 568    ) -> Result<Vec<LocationLink>> {
 569        location_links_from_proto(message.links, project, cx).await
 570    }
 571
 572    fn buffer_id_from_proto(message: &proto::GetTypeDefinition) -> u64 {
 573        message.buffer_id
 574    }
 575}
 576
 577fn language_server_for_buffer(
 578    project: &ModelHandle<Project>,
 579    buffer: &ModelHandle<Buffer>,
 580    server_id: LanguageServerId,
 581    cx: &mut AsyncAppContext,
 582) -> Result<(Arc<CachedLspAdapter>, Arc<LanguageServer>)> {
 583    project
 584        .read_with(cx, |project, cx| {
 585            project
 586                .language_server_for_buffer(buffer.read(cx), server_id, cx)
 587                .map(|(adapter, server)| (adapter.clone(), server.clone()))
 588        })
 589        .ok_or_else(|| anyhow!("no language server found for buffer"))
 590}
 591
 592async fn location_links_from_proto(
 593    proto_links: Vec<proto::LocationLink>,
 594    project: ModelHandle<Project>,
 595    mut cx: AsyncAppContext,
 596) -> Result<Vec<LocationLink>> {
 597    let mut links = Vec::new();
 598
 599    for link in proto_links {
 600        let origin = match link.origin {
 601            Some(origin) => {
 602                let buffer = project
 603                    .update(&mut cx, |this, cx| {
 604                        this.wait_for_remote_buffer(origin.buffer_id, cx)
 605                    })
 606                    .await?;
 607                let start = origin
 608                    .start
 609                    .and_then(deserialize_anchor)
 610                    .ok_or_else(|| anyhow!("missing origin start"))?;
 611                let end = origin
 612                    .end
 613                    .and_then(deserialize_anchor)
 614                    .ok_or_else(|| anyhow!("missing origin end"))?;
 615                buffer
 616                    .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
 617                    .await?;
 618                Some(Location {
 619                    buffer,
 620                    range: start..end,
 621                })
 622            }
 623            None => None,
 624        };
 625
 626        let target = link.target.ok_or_else(|| anyhow!("missing target"))?;
 627        let buffer = project
 628            .update(&mut cx, |this, cx| {
 629                this.wait_for_remote_buffer(target.buffer_id, cx)
 630            })
 631            .await?;
 632        let start = target
 633            .start
 634            .and_then(deserialize_anchor)
 635            .ok_or_else(|| anyhow!("missing target start"))?;
 636        let end = target
 637            .end
 638            .and_then(deserialize_anchor)
 639            .ok_or_else(|| anyhow!("missing target end"))?;
 640        buffer
 641            .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
 642            .await?;
 643        let target = Location {
 644            buffer,
 645            range: start..end,
 646        };
 647
 648        links.push(LocationLink { origin, target })
 649    }
 650
 651    Ok(links)
 652}
 653
 654async fn location_links_from_lsp(
 655    message: Option<lsp::GotoDefinitionResponse>,
 656    project: ModelHandle<Project>,
 657    buffer: ModelHandle<Buffer>,
 658    server_id: LanguageServerId,
 659    mut cx: AsyncAppContext,
 660) -> Result<Vec<LocationLink>> {
 661    let message = match message {
 662        Some(message) => message,
 663        None => return Ok(Vec::new()),
 664    };
 665
 666    let mut unresolved_links = Vec::new();
 667    match message {
 668        lsp::GotoDefinitionResponse::Scalar(loc) => {
 669            unresolved_links.push((None, loc.uri, loc.range));
 670        }
 671
 672        lsp::GotoDefinitionResponse::Array(locs) => {
 673            unresolved_links.extend(locs.into_iter().map(|l| (None, l.uri, l.range)));
 674        }
 675
 676        lsp::GotoDefinitionResponse::Link(links) => {
 677            unresolved_links.extend(links.into_iter().map(|l| {
 678                (
 679                    l.origin_selection_range,
 680                    l.target_uri,
 681                    l.target_selection_range,
 682                )
 683            }));
 684        }
 685    }
 686
 687    let (lsp_adapter, language_server) =
 688        language_server_for_buffer(&project, &buffer, server_id, &mut cx)?;
 689    let mut definitions = Vec::new();
 690    for (origin_range, target_uri, target_range) in unresolved_links {
 691        let target_buffer_handle = project
 692            .update(&mut cx, |this, cx| {
 693                this.open_local_buffer_via_lsp(
 694                    target_uri,
 695                    language_server.server_id(),
 696                    lsp_adapter.name.clone(),
 697                    cx,
 698                )
 699            })
 700            .await?;
 701
 702        cx.read(|cx| {
 703            let origin_location = origin_range.map(|origin_range| {
 704                let origin_buffer = buffer.read(cx);
 705                let origin_start =
 706                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
 707                let origin_end =
 708                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
 709                Location {
 710                    buffer: buffer.clone(),
 711                    range: origin_buffer.anchor_after(origin_start)
 712                        ..origin_buffer.anchor_before(origin_end),
 713                }
 714            });
 715
 716            let target_buffer = target_buffer_handle.read(cx);
 717            let target_start =
 718                target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
 719            let target_end =
 720                target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
 721            let target_location = Location {
 722                buffer: target_buffer_handle,
 723                range: target_buffer.anchor_after(target_start)
 724                    ..target_buffer.anchor_before(target_end),
 725            };
 726
 727            definitions.push(LocationLink {
 728                origin: origin_location,
 729                target: target_location,
 730            })
 731        });
 732    }
 733    Ok(definitions)
 734}
 735
 736fn location_links_to_proto(
 737    links: Vec<LocationLink>,
 738    project: &mut Project,
 739    peer_id: PeerId,
 740    cx: &mut AppContext,
 741) -> Vec<proto::LocationLink> {
 742    links
 743        .into_iter()
 744        .map(|definition| {
 745            let origin = definition.origin.map(|origin| {
 746                let buffer_id = project.create_buffer_for_peer(&origin.buffer, peer_id, cx);
 747                proto::Location {
 748                    start: Some(serialize_anchor(&origin.range.start)),
 749                    end: Some(serialize_anchor(&origin.range.end)),
 750                    buffer_id,
 751                }
 752            });
 753
 754            let buffer_id = project.create_buffer_for_peer(&definition.target.buffer, peer_id, cx);
 755            let target = proto::Location {
 756                start: Some(serialize_anchor(&definition.target.range.start)),
 757                end: Some(serialize_anchor(&definition.target.range.end)),
 758                buffer_id,
 759            };
 760
 761            proto::LocationLink {
 762                origin,
 763                target: Some(target),
 764            }
 765        })
 766        .collect()
 767}
 768
 769#[async_trait(?Send)]
 770impl LspCommand for GetReferences {
 771    type Response = Vec<Location>;
 772    type LspRequest = lsp::request::References;
 773    type ProtoRequest = proto::GetReferences;
 774
 775    fn to_lsp(
 776        &self,
 777        path: &Path,
 778        _: &Buffer,
 779        _: &Arc<LanguageServer>,
 780        _: &AppContext,
 781    ) -> lsp::ReferenceParams {
 782        lsp::ReferenceParams {
 783            text_document_position: lsp::TextDocumentPositionParams {
 784                text_document: lsp::TextDocumentIdentifier {
 785                    uri: lsp::Url::from_file_path(path).unwrap(),
 786                },
 787                position: point_to_lsp(self.position),
 788            },
 789            work_done_progress_params: Default::default(),
 790            partial_result_params: Default::default(),
 791            context: lsp::ReferenceContext {
 792                include_declaration: true,
 793            },
 794        }
 795    }
 796
 797    async fn response_from_lsp(
 798        self,
 799        locations: Option<Vec<lsp::Location>>,
 800        project: ModelHandle<Project>,
 801        buffer: ModelHandle<Buffer>,
 802        server_id: LanguageServerId,
 803        mut cx: AsyncAppContext,
 804    ) -> Result<Vec<Location>> {
 805        let mut references = Vec::new();
 806        let (lsp_adapter, language_server) =
 807            language_server_for_buffer(&project, &buffer, server_id, &mut cx)?;
 808
 809        if let Some(locations) = locations {
 810            for lsp_location in locations {
 811                let target_buffer_handle = project
 812                    .update(&mut cx, |this, cx| {
 813                        this.open_local_buffer_via_lsp(
 814                            lsp_location.uri,
 815                            language_server.server_id(),
 816                            lsp_adapter.name.clone(),
 817                            cx,
 818                        )
 819                    })
 820                    .await?;
 821
 822                cx.read(|cx| {
 823                    let target_buffer = target_buffer_handle.read(cx);
 824                    let target_start = target_buffer
 825                        .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
 826                    let target_end = target_buffer
 827                        .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
 828                    references.push(Location {
 829                        buffer: target_buffer_handle,
 830                        range: target_buffer.anchor_after(target_start)
 831                            ..target_buffer.anchor_before(target_end),
 832                    });
 833                });
 834            }
 835        }
 836
 837        Ok(references)
 838    }
 839
 840    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetReferences {
 841        proto::GetReferences {
 842            project_id,
 843            buffer_id: buffer.remote_id(),
 844            position: Some(language::proto::serialize_anchor(
 845                &buffer.anchor_before(self.position),
 846            )),
 847            version: serialize_version(&buffer.version()),
 848        }
 849    }
 850
 851    async fn from_proto(
 852        message: proto::GetReferences,
 853        _: ModelHandle<Project>,
 854        buffer: ModelHandle<Buffer>,
 855        mut cx: AsyncAppContext,
 856    ) -> Result<Self> {
 857        let position = message
 858            .position
 859            .and_then(deserialize_anchor)
 860            .ok_or_else(|| anyhow!("invalid position"))?;
 861        buffer
 862            .update(&mut cx, |buffer, _| {
 863                buffer.wait_for_version(deserialize_version(&message.version))
 864            })
 865            .await?;
 866        Ok(Self {
 867            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
 868        })
 869    }
 870
 871    fn response_to_proto(
 872        response: Vec<Location>,
 873        project: &mut Project,
 874        peer_id: PeerId,
 875        _: &clock::Global,
 876        cx: &mut AppContext,
 877    ) -> proto::GetReferencesResponse {
 878        let locations = response
 879            .into_iter()
 880            .map(|definition| {
 881                let buffer_id = project.create_buffer_for_peer(&definition.buffer, peer_id, cx);
 882                proto::Location {
 883                    start: Some(serialize_anchor(&definition.range.start)),
 884                    end: Some(serialize_anchor(&definition.range.end)),
 885                    buffer_id,
 886                }
 887            })
 888            .collect();
 889        proto::GetReferencesResponse { locations }
 890    }
 891
 892    async fn response_from_proto(
 893        self,
 894        message: proto::GetReferencesResponse,
 895        project: ModelHandle<Project>,
 896        _: ModelHandle<Buffer>,
 897        mut cx: AsyncAppContext,
 898    ) -> Result<Vec<Location>> {
 899        let mut locations = Vec::new();
 900        for location in message.locations {
 901            let target_buffer = project
 902                .update(&mut cx, |this, cx| {
 903                    this.wait_for_remote_buffer(location.buffer_id, cx)
 904                })
 905                .await?;
 906            let start = location
 907                .start
 908                .and_then(deserialize_anchor)
 909                .ok_or_else(|| anyhow!("missing target start"))?;
 910            let end = location
 911                .end
 912                .and_then(deserialize_anchor)
 913                .ok_or_else(|| anyhow!("missing target end"))?;
 914            target_buffer
 915                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
 916                .await?;
 917            locations.push(Location {
 918                buffer: target_buffer,
 919                range: start..end,
 920            })
 921        }
 922        Ok(locations)
 923    }
 924
 925    fn buffer_id_from_proto(message: &proto::GetReferences) -> u64 {
 926        message.buffer_id
 927    }
 928}
 929
 930#[async_trait(?Send)]
 931impl LspCommand for GetDocumentHighlights {
 932    type Response = Vec<DocumentHighlight>;
 933    type LspRequest = lsp::request::DocumentHighlightRequest;
 934    type ProtoRequest = proto::GetDocumentHighlights;
 935
 936    fn check_capabilities(&self, capabilities: &ServerCapabilities) -> bool {
 937        capabilities.document_highlight_provider.is_some()
 938    }
 939
 940    fn to_lsp(
 941        &self,
 942        path: &Path,
 943        _: &Buffer,
 944        _: &Arc<LanguageServer>,
 945        _: &AppContext,
 946    ) -> lsp::DocumentHighlightParams {
 947        lsp::DocumentHighlightParams {
 948            text_document_position_params: lsp::TextDocumentPositionParams {
 949                text_document: lsp::TextDocumentIdentifier {
 950                    uri: lsp::Url::from_file_path(path).unwrap(),
 951                },
 952                position: point_to_lsp(self.position),
 953            },
 954            work_done_progress_params: Default::default(),
 955            partial_result_params: Default::default(),
 956        }
 957    }
 958
 959    async fn response_from_lsp(
 960        self,
 961        lsp_highlights: Option<Vec<lsp::DocumentHighlight>>,
 962        _: ModelHandle<Project>,
 963        buffer: ModelHandle<Buffer>,
 964        _: LanguageServerId,
 965        cx: AsyncAppContext,
 966    ) -> Result<Vec<DocumentHighlight>> {
 967        buffer.read_with(&cx, |buffer, _| {
 968            let mut lsp_highlights = lsp_highlights.unwrap_or_default();
 969            lsp_highlights.sort_unstable_by_key(|h| (h.range.start, Reverse(h.range.end)));
 970            Ok(lsp_highlights
 971                .into_iter()
 972                .map(|lsp_highlight| {
 973                    let start = buffer
 974                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.start), Bias::Left);
 975                    let end = buffer
 976                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.end), Bias::Left);
 977                    DocumentHighlight {
 978                        range: buffer.anchor_after(start)..buffer.anchor_before(end),
 979                        kind: lsp_highlight
 980                            .kind
 981                            .unwrap_or(lsp::DocumentHighlightKind::READ),
 982                    }
 983                })
 984                .collect())
 985        })
 986    }
 987
 988    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentHighlights {
 989        proto::GetDocumentHighlights {
 990            project_id,
 991            buffer_id: buffer.remote_id(),
 992            position: Some(language::proto::serialize_anchor(
 993                &buffer.anchor_before(self.position),
 994            )),
 995            version: serialize_version(&buffer.version()),
 996        }
 997    }
 998
 999    async fn from_proto(
1000        message: proto::GetDocumentHighlights,
1001        _: ModelHandle<Project>,
1002        buffer: ModelHandle<Buffer>,
1003        mut cx: AsyncAppContext,
1004    ) -> Result<Self> {
1005        let position = message
1006            .position
1007            .and_then(deserialize_anchor)
1008            .ok_or_else(|| anyhow!("invalid position"))?;
1009        buffer
1010            .update(&mut cx, |buffer, _| {
1011                buffer.wait_for_version(deserialize_version(&message.version))
1012            })
1013            .await?;
1014        Ok(Self {
1015            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1016        })
1017    }
1018
1019    fn response_to_proto(
1020        response: Vec<DocumentHighlight>,
1021        _: &mut Project,
1022        _: PeerId,
1023        _: &clock::Global,
1024        _: &mut AppContext,
1025    ) -> proto::GetDocumentHighlightsResponse {
1026        let highlights = response
1027            .into_iter()
1028            .map(|highlight| proto::DocumentHighlight {
1029                start: Some(serialize_anchor(&highlight.range.start)),
1030                end: Some(serialize_anchor(&highlight.range.end)),
1031                kind: match highlight.kind {
1032                    DocumentHighlightKind::TEXT => proto::document_highlight::Kind::Text.into(),
1033                    DocumentHighlightKind::WRITE => proto::document_highlight::Kind::Write.into(),
1034                    DocumentHighlightKind::READ => proto::document_highlight::Kind::Read.into(),
1035                    _ => proto::document_highlight::Kind::Text.into(),
1036                },
1037            })
1038            .collect();
1039        proto::GetDocumentHighlightsResponse { highlights }
1040    }
1041
1042    async fn response_from_proto(
1043        self,
1044        message: proto::GetDocumentHighlightsResponse,
1045        _: ModelHandle<Project>,
1046        buffer: ModelHandle<Buffer>,
1047        mut cx: AsyncAppContext,
1048    ) -> Result<Vec<DocumentHighlight>> {
1049        let mut highlights = Vec::new();
1050        for highlight in message.highlights {
1051            let start = highlight
1052                .start
1053                .and_then(deserialize_anchor)
1054                .ok_or_else(|| anyhow!("missing target start"))?;
1055            let end = highlight
1056                .end
1057                .and_then(deserialize_anchor)
1058                .ok_or_else(|| anyhow!("missing target end"))?;
1059            buffer
1060                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1061                .await?;
1062            let kind = match proto::document_highlight::Kind::from_i32(highlight.kind) {
1063                Some(proto::document_highlight::Kind::Text) => DocumentHighlightKind::TEXT,
1064                Some(proto::document_highlight::Kind::Read) => DocumentHighlightKind::READ,
1065                Some(proto::document_highlight::Kind::Write) => DocumentHighlightKind::WRITE,
1066                None => DocumentHighlightKind::TEXT,
1067            };
1068            highlights.push(DocumentHighlight {
1069                range: start..end,
1070                kind,
1071            });
1072        }
1073        Ok(highlights)
1074    }
1075
1076    fn buffer_id_from_proto(message: &proto::GetDocumentHighlights) -> u64 {
1077        message.buffer_id
1078    }
1079}
1080
1081#[async_trait(?Send)]
1082impl LspCommand for GetHover {
1083    type Response = Option<Hover>;
1084    type LspRequest = lsp::request::HoverRequest;
1085    type ProtoRequest = proto::GetHover;
1086
1087    fn to_lsp(
1088        &self,
1089        path: &Path,
1090        _: &Buffer,
1091        _: &Arc<LanguageServer>,
1092        _: &AppContext,
1093    ) -> lsp::HoverParams {
1094        lsp::HoverParams {
1095            text_document_position_params: lsp::TextDocumentPositionParams {
1096                text_document: lsp::TextDocumentIdentifier {
1097                    uri: lsp::Url::from_file_path(path).unwrap(),
1098                },
1099                position: point_to_lsp(self.position),
1100            },
1101            work_done_progress_params: Default::default(),
1102        }
1103    }
1104
1105    async fn response_from_lsp(
1106        self,
1107        message: Option<lsp::Hover>,
1108        _: ModelHandle<Project>,
1109        buffer: ModelHandle<Buffer>,
1110        _: LanguageServerId,
1111        cx: AsyncAppContext,
1112    ) -> Result<Self::Response> {
1113        Ok(message.and_then(|hover| {
1114            let range = hover.range.map(|range| {
1115                cx.read(|cx| {
1116                    let buffer = buffer.read(cx);
1117                    let token_start =
1118                        buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
1119                    let token_end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
1120                    buffer.anchor_after(token_start)..buffer.anchor_before(token_end)
1121                })
1122            });
1123
1124            fn hover_blocks_from_marked_string(
1125                marked_string: lsp::MarkedString,
1126            ) -> Option<HoverBlock> {
1127                let block = match marked_string {
1128                    lsp::MarkedString::String(content) => HoverBlock {
1129                        text: content,
1130                        kind: HoverBlockKind::Markdown,
1131                    },
1132                    lsp::MarkedString::LanguageString(lsp::LanguageString { language, value }) => {
1133                        HoverBlock {
1134                            text: value,
1135                            kind: HoverBlockKind::Code { language },
1136                        }
1137                    }
1138                };
1139                if block.text.is_empty() {
1140                    None
1141                } else {
1142                    Some(block)
1143                }
1144            }
1145
1146            let contents = cx.read(|_| match hover.contents {
1147                lsp::HoverContents::Scalar(marked_string) => {
1148                    hover_blocks_from_marked_string(marked_string)
1149                        .into_iter()
1150                        .collect()
1151                }
1152                lsp::HoverContents::Array(marked_strings) => marked_strings
1153                    .into_iter()
1154                    .filter_map(hover_blocks_from_marked_string)
1155                    .collect(),
1156                lsp::HoverContents::Markup(markup_content) => vec![HoverBlock {
1157                    text: markup_content.value,
1158                    kind: if markup_content.kind == lsp::MarkupKind::Markdown {
1159                        HoverBlockKind::Markdown
1160                    } else {
1161                        HoverBlockKind::PlainText
1162                    },
1163                }],
1164            });
1165
1166            Some(Hover { contents, range })
1167        }))
1168    }
1169
1170    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
1171        proto::GetHover {
1172            project_id,
1173            buffer_id: buffer.remote_id(),
1174            position: Some(language::proto::serialize_anchor(
1175                &buffer.anchor_before(self.position),
1176            )),
1177            version: serialize_version(&buffer.version),
1178        }
1179    }
1180
1181    async fn from_proto(
1182        message: Self::ProtoRequest,
1183        _: ModelHandle<Project>,
1184        buffer: ModelHandle<Buffer>,
1185        mut cx: AsyncAppContext,
1186    ) -> Result<Self> {
1187        let position = message
1188            .position
1189            .and_then(deserialize_anchor)
1190            .ok_or_else(|| anyhow!("invalid position"))?;
1191        buffer
1192            .update(&mut cx, |buffer, _| {
1193                buffer.wait_for_version(deserialize_version(&message.version))
1194            })
1195            .await?;
1196        Ok(Self {
1197            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1198        })
1199    }
1200
1201    fn response_to_proto(
1202        response: Self::Response,
1203        _: &mut Project,
1204        _: PeerId,
1205        _: &clock::Global,
1206        _: &mut AppContext,
1207    ) -> proto::GetHoverResponse {
1208        if let Some(response) = response {
1209            let (start, end) = if let Some(range) = response.range {
1210                (
1211                    Some(language::proto::serialize_anchor(&range.start)),
1212                    Some(language::proto::serialize_anchor(&range.end)),
1213                )
1214            } else {
1215                (None, None)
1216            };
1217
1218            let contents = response
1219                .contents
1220                .into_iter()
1221                .map(|block| proto::HoverBlock {
1222                    text: block.text,
1223                    is_markdown: block.kind == HoverBlockKind::Markdown,
1224                    language: if let HoverBlockKind::Code { language } = block.kind {
1225                        Some(language)
1226                    } else {
1227                        None
1228                    },
1229                })
1230                .collect();
1231
1232            proto::GetHoverResponse {
1233                start,
1234                end,
1235                contents,
1236            }
1237        } else {
1238            proto::GetHoverResponse {
1239                start: None,
1240                end: None,
1241                contents: Vec::new(),
1242            }
1243        }
1244    }
1245
1246    async fn response_from_proto(
1247        self,
1248        message: proto::GetHoverResponse,
1249        _: ModelHandle<Project>,
1250        _: ModelHandle<Buffer>,
1251        _: AsyncAppContext,
1252    ) -> Result<Self::Response> {
1253        let range = if let (Some(start), Some(end)) = (message.start, message.end) {
1254            language::proto::deserialize_anchor(start)
1255                .and_then(|start| language::proto::deserialize_anchor(end).map(|end| start..end))
1256        } else {
1257            None
1258        };
1259
1260        let contents: Vec<_> = message
1261            .contents
1262            .into_iter()
1263            .map(|block| HoverBlock {
1264                text: block.text,
1265                kind: if let Some(language) = block.language {
1266                    HoverBlockKind::Code { language }
1267                } else if block.is_markdown {
1268                    HoverBlockKind::Markdown
1269                } else {
1270                    HoverBlockKind::PlainText
1271                },
1272            })
1273            .collect();
1274
1275        Ok(if contents.is_empty() {
1276            None
1277        } else {
1278            Some(Hover { contents, range })
1279        })
1280    }
1281
1282    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> u64 {
1283        message.buffer_id
1284    }
1285}
1286
1287#[async_trait(?Send)]
1288impl LspCommand for GetCompletions {
1289    type Response = Vec<Completion>;
1290    type LspRequest = lsp::request::Completion;
1291    type ProtoRequest = proto::GetCompletions;
1292
1293    fn to_lsp(
1294        &self,
1295        path: &Path,
1296        _: &Buffer,
1297        _: &Arc<LanguageServer>,
1298        _: &AppContext,
1299    ) -> lsp::CompletionParams {
1300        lsp::CompletionParams {
1301            text_document_position: lsp::TextDocumentPositionParams::new(
1302                lsp::TextDocumentIdentifier::new(lsp::Url::from_file_path(path).unwrap()),
1303                point_to_lsp(self.position),
1304            ),
1305            context: Default::default(),
1306            work_done_progress_params: Default::default(),
1307            partial_result_params: Default::default(),
1308        }
1309    }
1310
1311    async fn response_from_lsp(
1312        self,
1313        completions: Option<lsp::CompletionResponse>,
1314        _: ModelHandle<Project>,
1315        buffer: ModelHandle<Buffer>,
1316        _: LanguageServerId,
1317        cx: AsyncAppContext,
1318    ) -> Result<Vec<Completion>> {
1319        let completions = if let Some(completions) = completions {
1320            match completions {
1321                lsp::CompletionResponse::Array(completions) => completions,
1322                lsp::CompletionResponse::List(list) => list.items,
1323            }
1324        } else {
1325            Default::default()
1326        };
1327
1328        let completions = buffer.read_with(&cx, |buffer, _| {
1329            let language = buffer.language().cloned();
1330            let snapshot = buffer.snapshot();
1331            let clipped_position = buffer.clip_point_utf16(Unclipped(self.position), Bias::Left);
1332            let mut range_for_token = None;
1333            completions
1334                .into_iter()
1335                .filter_map(move |mut lsp_completion| {
1336                    // For now, we can only handle additional edits if they are returned
1337                    // when resolving the completion, not if they are present initially.
1338                    if lsp_completion
1339                        .additional_text_edits
1340                        .as_ref()
1341                        .map_or(false, |edits| !edits.is_empty())
1342                    {
1343                        return None;
1344                    }
1345
1346                    let (old_range, mut new_text) = match lsp_completion.text_edit.as_ref() {
1347                        // If the language server provides a range to overwrite, then
1348                        // check that the range is valid.
1349                        Some(lsp::CompletionTextEdit::Edit(edit)) => {
1350                            let range = range_from_lsp(edit.range);
1351                            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
1352                            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
1353                            if start != range.start.0 || end != range.end.0 {
1354                                log::info!("completion out of expected range");
1355                                return None;
1356                            }
1357                            (
1358                                snapshot.anchor_before(start)..snapshot.anchor_after(end),
1359                                edit.new_text.clone(),
1360                            )
1361                        }
1362                        // If the language server does not provide a range, then infer
1363                        // the range based on the syntax tree.
1364                        None => {
1365                            if self.position != clipped_position {
1366                                log::info!("completion out of expected range");
1367                                return None;
1368                            }
1369                            let Range { start, end } = range_for_token
1370                                .get_or_insert_with(|| {
1371                                    let offset = self.position.to_offset(&snapshot);
1372                                    let (range, kind) = snapshot.surrounding_word(offset);
1373                                    if kind == Some(CharKind::Word) {
1374                                        range
1375                                    } else {
1376                                        offset..offset
1377                                    }
1378                                })
1379                                .clone();
1380                            let text = lsp_completion
1381                                .insert_text
1382                                .as_ref()
1383                                .unwrap_or(&lsp_completion.label)
1384                                .clone();
1385                            (
1386                                snapshot.anchor_before(start)..snapshot.anchor_after(end),
1387                                text,
1388                            )
1389                        }
1390                        Some(lsp::CompletionTextEdit::InsertAndReplace(_)) => {
1391                            log::info!("unsupported insert/replace completion");
1392                            return None;
1393                        }
1394                    };
1395
1396                    let language = language.clone();
1397                    LineEnding::normalize(&mut new_text);
1398                    Some(async move {
1399                        let mut label = None;
1400                        if let Some(language) = language {
1401                            language.process_completion(&mut lsp_completion).await;
1402                            label = language.label_for_completion(&lsp_completion).await;
1403                        }
1404                        Completion {
1405                            old_range,
1406                            new_text,
1407                            label: label.unwrap_or_else(|| {
1408                                language::CodeLabel::plain(
1409                                    lsp_completion.label.clone(),
1410                                    lsp_completion.filter_text.as_deref(),
1411                                )
1412                            }),
1413                            lsp_completion,
1414                        }
1415                    })
1416                })
1417        });
1418
1419        Ok(futures::future::join_all(completions).await)
1420    }
1421
1422    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCompletions {
1423        let anchor = buffer.anchor_after(self.position);
1424        proto::GetCompletions {
1425            project_id,
1426            buffer_id: buffer.remote_id(),
1427            position: Some(language::proto::serialize_anchor(&anchor)),
1428            version: serialize_version(&buffer.version()),
1429        }
1430    }
1431
1432    async fn from_proto(
1433        message: proto::GetCompletions,
1434        _: ModelHandle<Project>,
1435        buffer: ModelHandle<Buffer>,
1436        mut cx: AsyncAppContext,
1437    ) -> Result<Self> {
1438        let version = deserialize_version(&message.version);
1439        buffer
1440            .update(&mut cx, |buffer, _| buffer.wait_for_version(version))
1441            .await?;
1442        let position = message
1443            .position
1444            .and_then(language::proto::deserialize_anchor)
1445            .map(|p| {
1446                buffer.read_with(&cx, |buffer, _| {
1447                    buffer.clip_point_utf16(Unclipped(p.to_point_utf16(buffer)), Bias::Left)
1448                })
1449            })
1450            .ok_or_else(|| anyhow!("invalid position"))?;
1451        Ok(Self { position })
1452    }
1453
1454    fn response_to_proto(
1455        completions: Vec<Completion>,
1456        _: &mut Project,
1457        _: PeerId,
1458        buffer_version: &clock::Global,
1459        _: &mut AppContext,
1460    ) -> proto::GetCompletionsResponse {
1461        proto::GetCompletionsResponse {
1462            completions: completions
1463                .iter()
1464                .map(language::proto::serialize_completion)
1465                .collect(),
1466            version: serialize_version(&buffer_version),
1467        }
1468    }
1469
1470    async fn response_from_proto(
1471        self,
1472        message: proto::GetCompletionsResponse,
1473        _: ModelHandle<Project>,
1474        buffer: ModelHandle<Buffer>,
1475        mut cx: AsyncAppContext,
1476    ) -> Result<Vec<Completion>> {
1477        buffer
1478            .update(&mut cx, |buffer, _| {
1479                buffer.wait_for_version(deserialize_version(&message.version))
1480            })
1481            .await?;
1482
1483        let language = buffer.read_with(&cx, |buffer, _| buffer.language().cloned());
1484        let completions = message.completions.into_iter().map(|completion| {
1485            language::proto::deserialize_completion(completion, language.clone())
1486        });
1487        futures::future::try_join_all(completions).await
1488    }
1489
1490    fn buffer_id_from_proto(message: &proto::GetCompletions) -> u64 {
1491        message.buffer_id
1492    }
1493}
1494
1495#[async_trait(?Send)]
1496impl LspCommand for GetCodeActions {
1497    type Response = Vec<CodeAction>;
1498    type LspRequest = lsp::request::CodeActionRequest;
1499    type ProtoRequest = proto::GetCodeActions;
1500
1501    fn check_capabilities(&self, capabilities: &ServerCapabilities) -> bool {
1502        capabilities.code_action_provider.is_some()
1503    }
1504
1505    fn to_lsp(
1506        &self,
1507        path: &Path,
1508        buffer: &Buffer,
1509        language_server: &Arc<LanguageServer>,
1510        _: &AppContext,
1511    ) -> lsp::CodeActionParams {
1512        let relevant_diagnostics = buffer
1513            .snapshot()
1514            .diagnostics_in_range::<_, usize>(self.range.clone(), false)
1515            .map(|entry| entry.to_lsp_diagnostic_stub())
1516            .collect();
1517        lsp::CodeActionParams {
1518            text_document: lsp::TextDocumentIdentifier::new(
1519                lsp::Url::from_file_path(path).unwrap(),
1520            ),
1521            range: range_to_lsp(self.range.to_point_utf16(buffer)),
1522            work_done_progress_params: Default::default(),
1523            partial_result_params: Default::default(),
1524            context: lsp::CodeActionContext {
1525                diagnostics: relevant_diagnostics,
1526                only: language_server.code_action_kinds(),
1527                ..lsp::CodeActionContext::default()
1528            },
1529        }
1530    }
1531
1532    async fn response_from_lsp(
1533        self,
1534        actions: Option<lsp::CodeActionResponse>,
1535        _: ModelHandle<Project>,
1536        _: ModelHandle<Buffer>,
1537        server_id: LanguageServerId,
1538        _: AsyncAppContext,
1539    ) -> Result<Vec<CodeAction>> {
1540        Ok(actions
1541            .unwrap_or_default()
1542            .into_iter()
1543            .filter_map(|entry| {
1544                if let lsp::CodeActionOrCommand::CodeAction(lsp_action) = entry {
1545                    Some(CodeAction {
1546                        server_id,
1547                        range: self.range.clone(),
1548                        lsp_action,
1549                    })
1550                } else {
1551                    None
1552                }
1553            })
1554            .collect())
1555    }
1556
1557    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeActions {
1558        proto::GetCodeActions {
1559            project_id,
1560            buffer_id: buffer.remote_id(),
1561            start: Some(language::proto::serialize_anchor(&self.range.start)),
1562            end: Some(language::proto::serialize_anchor(&self.range.end)),
1563            version: serialize_version(&buffer.version()),
1564        }
1565    }
1566
1567    async fn from_proto(
1568        message: proto::GetCodeActions,
1569        _: ModelHandle<Project>,
1570        buffer: ModelHandle<Buffer>,
1571        mut cx: AsyncAppContext,
1572    ) -> Result<Self> {
1573        let start = message
1574            .start
1575            .and_then(language::proto::deserialize_anchor)
1576            .ok_or_else(|| anyhow!("invalid start"))?;
1577        let end = message
1578            .end
1579            .and_then(language::proto::deserialize_anchor)
1580            .ok_or_else(|| anyhow!("invalid end"))?;
1581        buffer
1582            .update(&mut cx, |buffer, _| {
1583                buffer.wait_for_version(deserialize_version(&message.version))
1584            })
1585            .await?;
1586
1587        Ok(Self { range: start..end })
1588    }
1589
1590    fn response_to_proto(
1591        code_actions: Vec<CodeAction>,
1592        _: &mut Project,
1593        _: PeerId,
1594        buffer_version: &clock::Global,
1595        _: &mut AppContext,
1596    ) -> proto::GetCodeActionsResponse {
1597        proto::GetCodeActionsResponse {
1598            actions: code_actions
1599                .iter()
1600                .map(language::proto::serialize_code_action)
1601                .collect(),
1602            version: serialize_version(&buffer_version),
1603        }
1604    }
1605
1606    async fn response_from_proto(
1607        self,
1608        message: proto::GetCodeActionsResponse,
1609        _: ModelHandle<Project>,
1610        buffer: ModelHandle<Buffer>,
1611        mut cx: AsyncAppContext,
1612    ) -> Result<Vec<CodeAction>> {
1613        buffer
1614            .update(&mut cx, |buffer, _| {
1615                buffer.wait_for_version(deserialize_version(&message.version))
1616            })
1617            .await?;
1618        message
1619            .actions
1620            .into_iter()
1621            .map(language::proto::deserialize_code_action)
1622            .collect()
1623    }
1624
1625    fn buffer_id_from_proto(message: &proto::GetCodeActions) -> u64 {
1626        message.buffer_id
1627    }
1628}
1629
1630#[async_trait(?Send)]
1631impl LspCommand for OnTypeFormatting {
1632    type Response = Option<Transaction>;
1633    type LspRequest = lsp::request::OnTypeFormatting;
1634    type ProtoRequest = proto::OnTypeFormatting;
1635
1636    fn check_capabilities(&self, server_capabilities: &lsp::ServerCapabilities) -> bool {
1637        let Some(on_type_formatting_options) = &server_capabilities.document_on_type_formatting_provider else { return false };
1638        on_type_formatting_options
1639            .first_trigger_character
1640            .contains(&self.trigger)
1641            || on_type_formatting_options
1642                .more_trigger_character
1643                .iter()
1644                .flatten()
1645                .any(|chars| chars.contains(&self.trigger))
1646    }
1647
1648    fn to_lsp(
1649        &self,
1650        path: &Path,
1651        _: &Buffer,
1652        _: &Arc<LanguageServer>,
1653        _: &AppContext,
1654    ) -> lsp::DocumentOnTypeFormattingParams {
1655        lsp::DocumentOnTypeFormattingParams {
1656            text_document_position: lsp::TextDocumentPositionParams::new(
1657                lsp::TextDocumentIdentifier::new(lsp::Url::from_file_path(path).unwrap()),
1658                point_to_lsp(self.position),
1659            ),
1660            ch: self.trigger.clone(),
1661            options: lsp_formatting_options(self.options.tab_size),
1662        }
1663    }
1664
1665    async fn response_from_lsp(
1666        self,
1667        message: Option<Vec<lsp::TextEdit>>,
1668        project: ModelHandle<Project>,
1669        buffer: ModelHandle<Buffer>,
1670        server_id: LanguageServerId,
1671        mut cx: AsyncAppContext,
1672    ) -> Result<Option<Transaction>> {
1673        if let Some(edits) = message {
1674            let (lsp_adapter, lsp_server) =
1675                language_server_for_buffer(&project, &buffer, server_id, &mut cx)?;
1676            Project::deserialize_edits(
1677                project,
1678                buffer,
1679                edits,
1680                self.push_to_history,
1681                lsp_adapter,
1682                lsp_server,
1683                &mut cx,
1684            )
1685            .await
1686        } else {
1687            Ok(None)
1688        }
1689    }
1690
1691    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::OnTypeFormatting {
1692        proto::OnTypeFormatting {
1693            project_id,
1694            buffer_id: buffer.remote_id(),
1695            position: Some(language::proto::serialize_anchor(
1696                &buffer.anchor_before(self.position),
1697            )),
1698            trigger: self.trigger.clone(),
1699            version: serialize_version(&buffer.version()),
1700        }
1701    }
1702
1703    async fn from_proto(
1704        message: proto::OnTypeFormatting,
1705        _: ModelHandle<Project>,
1706        buffer: ModelHandle<Buffer>,
1707        mut cx: AsyncAppContext,
1708    ) -> Result<Self> {
1709        let position = message
1710            .position
1711            .and_then(deserialize_anchor)
1712            .ok_or_else(|| anyhow!("invalid position"))?;
1713        buffer
1714            .update(&mut cx, |buffer, _| {
1715                buffer.wait_for_version(deserialize_version(&message.version))
1716            })
1717            .await?;
1718
1719        let tab_size = buffer.read_with(&cx, |buffer, cx| {
1720            let language_name = buffer.language().map(|language| language.name());
1721            language_settings(language_name.as_deref(), cx).tab_size
1722        });
1723
1724        Ok(Self {
1725            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1726            trigger: message.trigger.clone(),
1727            options: lsp_formatting_options(tab_size.get()).into(),
1728            push_to_history: false,
1729        })
1730    }
1731
1732    fn response_to_proto(
1733        response: Option<Transaction>,
1734        _: &mut Project,
1735        _: PeerId,
1736        _: &clock::Global,
1737        _: &mut AppContext,
1738    ) -> proto::OnTypeFormattingResponse {
1739        proto::OnTypeFormattingResponse {
1740            transaction: response
1741                .map(|transaction| language::proto::serialize_transaction(&transaction)),
1742        }
1743    }
1744
1745    async fn response_from_proto(
1746        self,
1747        message: proto::OnTypeFormattingResponse,
1748        _: ModelHandle<Project>,
1749        _: ModelHandle<Buffer>,
1750        _: AsyncAppContext,
1751    ) -> Result<Option<Transaction>> {
1752        let Some(transaction) = message.transaction else { return Ok(None) };
1753        Ok(Some(language::proto::deserialize_transaction(transaction)?))
1754    }
1755
1756    fn buffer_id_from_proto(message: &proto::OnTypeFormatting) -> u64 {
1757        message.buffer_id
1758    }
1759}