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 (language, range) = cx.read(|cx| {
1115                let buffer = buffer.read(cx);
1116                (
1117                    buffer.language().cloned(),
1118                    hover.range.map(|range| {
1119                        let token_start =
1120                            buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
1121                        let token_end =
1122                            buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
1123                        buffer.anchor_after(token_start)..buffer.anchor_before(token_end)
1124                    }),
1125                )
1126            });
1127
1128            fn hover_blocks_from_marked_string(
1129                marked_string: lsp::MarkedString,
1130            ) -> Option<HoverBlock> {
1131                let block = match marked_string {
1132                    lsp::MarkedString::String(content) => HoverBlock {
1133                        text: content,
1134                        kind: HoverBlockKind::Markdown,
1135                    },
1136                    lsp::MarkedString::LanguageString(lsp::LanguageString { language, value }) => {
1137                        HoverBlock {
1138                            text: value,
1139                            kind: HoverBlockKind::Code { language },
1140                        }
1141                    }
1142                };
1143                if block.text.is_empty() {
1144                    None
1145                } else {
1146                    Some(block)
1147                }
1148            }
1149
1150            let contents = cx.read(|_| match hover.contents {
1151                lsp::HoverContents::Scalar(marked_string) => {
1152                    hover_blocks_from_marked_string(marked_string)
1153                        .into_iter()
1154                        .collect()
1155                }
1156                lsp::HoverContents::Array(marked_strings) => marked_strings
1157                    .into_iter()
1158                    .filter_map(hover_blocks_from_marked_string)
1159                    .collect(),
1160                lsp::HoverContents::Markup(markup_content) => vec![HoverBlock {
1161                    text: markup_content.value,
1162                    kind: if markup_content.kind == lsp::MarkupKind::Markdown {
1163                        HoverBlockKind::Markdown
1164                    } else {
1165                        HoverBlockKind::PlainText
1166                    },
1167                }],
1168            });
1169
1170            Some(Hover {
1171                contents,
1172                range,
1173                language,
1174            })
1175        }))
1176    }
1177
1178    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
1179        proto::GetHover {
1180            project_id,
1181            buffer_id: buffer.remote_id(),
1182            position: Some(language::proto::serialize_anchor(
1183                &buffer.anchor_before(self.position),
1184            )),
1185            version: serialize_version(&buffer.version),
1186        }
1187    }
1188
1189    async fn from_proto(
1190        message: Self::ProtoRequest,
1191        _: ModelHandle<Project>,
1192        buffer: ModelHandle<Buffer>,
1193        mut cx: AsyncAppContext,
1194    ) -> Result<Self> {
1195        let position = message
1196            .position
1197            .and_then(deserialize_anchor)
1198            .ok_or_else(|| anyhow!("invalid position"))?;
1199        buffer
1200            .update(&mut cx, |buffer, _| {
1201                buffer.wait_for_version(deserialize_version(&message.version))
1202            })
1203            .await?;
1204        Ok(Self {
1205            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1206        })
1207    }
1208
1209    fn response_to_proto(
1210        response: Self::Response,
1211        _: &mut Project,
1212        _: PeerId,
1213        _: &clock::Global,
1214        _: &mut AppContext,
1215    ) -> proto::GetHoverResponse {
1216        if let Some(response) = response {
1217            let (start, end) = if let Some(range) = response.range {
1218                (
1219                    Some(language::proto::serialize_anchor(&range.start)),
1220                    Some(language::proto::serialize_anchor(&range.end)),
1221                )
1222            } else {
1223                (None, None)
1224            };
1225
1226            let contents = response
1227                .contents
1228                .into_iter()
1229                .map(|block| proto::HoverBlock {
1230                    text: block.text,
1231                    is_markdown: block.kind == HoverBlockKind::Markdown,
1232                    language: if let HoverBlockKind::Code { language } = block.kind {
1233                        Some(language)
1234                    } else {
1235                        None
1236                    },
1237                })
1238                .collect();
1239
1240            proto::GetHoverResponse {
1241                start,
1242                end,
1243                contents,
1244            }
1245        } else {
1246            proto::GetHoverResponse {
1247                start: None,
1248                end: None,
1249                contents: Vec::new(),
1250            }
1251        }
1252    }
1253
1254    async fn response_from_proto(
1255        self,
1256        message: proto::GetHoverResponse,
1257        _: ModelHandle<Project>,
1258        buffer: ModelHandle<Buffer>,
1259        cx: AsyncAppContext,
1260    ) -> Result<Self::Response> {
1261        let contents: Vec<_> = message
1262            .contents
1263            .into_iter()
1264            .map(|block| HoverBlock {
1265                text: block.text,
1266                kind: if let Some(language) = block.language {
1267                    HoverBlockKind::Code { language }
1268                } else if block.is_markdown {
1269                    HoverBlockKind::Markdown
1270                } else {
1271                    HoverBlockKind::PlainText
1272                },
1273            })
1274            .collect();
1275        if contents.is_empty() {
1276            return Ok(None);
1277        }
1278
1279        let language = buffer.read_with(&cx, |buffer, _| buffer.language().cloned());
1280        let range = if let (Some(start), Some(end)) = (message.start, message.end) {
1281            language::proto::deserialize_anchor(start)
1282                .and_then(|start| language::proto::deserialize_anchor(end).map(|end| start..end))
1283        } else {
1284            None
1285        };
1286
1287        Ok(Some(Hover {
1288            contents,
1289            range,
1290            language,
1291        }))
1292    }
1293
1294    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> u64 {
1295        message.buffer_id
1296    }
1297}
1298
1299#[async_trait(?Send)]
1300impl LspCommand for GetCompletions {
1301    type Response = Vec<Completion>;
1302    type LspRequest = lsp::request::Completion;
1303    type ProtoRequest = proto::GetCompletions;
1304
1305    fn to_lsp(
1306        &self,
1307        path: &Path,
1308        _: &Buffer,
1309        _: &Arc<LanguageServer>,
1310        _: &AppContext,
1311    ) -> lsp::CompletionParams {
1312        lsp::CompletionParams {
1313            text_document_position: lsp::TextDocumentPositionParams::new(
1314                lsp::TextDocumentIdentifier::new(lsp::Url::from_file_path(path).unwrap()),
1315                point_to_lsp(self.position),
1316            ),
1317            context: Default::default(),
1318            work_done_progress_params: Default::default(),
1319            partial_result_params: Default::default(),
1320        }
1321    }
1322
1323    async fn response_from_lsp(
1324        self,
1325        completions: Option<lsp::CompletionResponse>,
1326        _: ModelHandle<Project>,
1327        buffer: ModelHandle<Buffer>,
1328        _: LanguageServerId,
1329        cx: AsyncAppContext,
1330    ) -> Result<Vec<Completion>> {
1331        let completions = if let Some(completions) = completions {
1332            match completions {
1333                lsp::CompletionResponse::Array(completions) => completions,
1334                lsp::CompletionResponse::List(list) => list.items,
1335            }
1336        } else {
1337            Default::default()
1338        };
1339
1340        let completions = buffer.read_with(&cx, |buffer, _| {
1341            let language = buffer.language().cloned();
1342            let snapshot = buffer.snapshot();
1343            let clipped_position = buffer.clip_point_utf16(Unclipped(self.position), Bias::Left);
1344            let mut range_for_token = None;
1345            completions
1346                .into_iter()
1347                .filter_map(move |mut lsp_completion| {
1348                    // For now, we can only handle additional edits if they are returned
1349                    // when resolving the completion, not if they are present initially.
1350                    if lsp_completion
1351                        .additional_text_edits
1352                        .as_ref()
1353                        .map_or(false, |edits| !edits.is_empty())
1354                    {
1355                        return None;
1356                    }
1357
1358                    let (old_range, mut new_text) = match lsp_completion.text_edit.as_ref() {
1359                        // If the language server provides a range to overwrite, then
1360                        // check that the range is valid.
1361                        Some(lsp::CompletionTextEdit::Edit(edit)) => {
1362                            let range = range_from_lsp(edit.range);
1363                            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
1364                            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
1365                            if start != range.start.0 || end != range.end.0 {
1366                                log::info!("completion out of expected range");
1367                                return None;
1368                            }
1369                            (
1370                                snapshot.anchor_before(start)..snapshot.anchor_after(end),
1371                                edit.new_text.clone(),
1372                            )
1373                        }
1374                        // If the language server does not provide a range, then infer
1375                        // the range based on the syntax tree.
1376                        None => {
1377                            if self.position != clipped_position {
1378                                log::info!("completion out of expected range");
1379                                return None;
1380                            }
1381                            let Range { start, end } = range_for_token
1382                                .get_or_insert_with(|| {
1383                                    let offset = self.position.to_offset(&snapshot);
1384                                    let (range, kind) = snapshot.surrounding_word(offset);
1385                                    if kind == Some(CharKind::Word) {
1386                                        range
1387                                    } else {
1388                                        offset..offset
1389                                    }
1390                                })
1391                                .clone();
1392                            let text = lsp_completion
1393                                .insert_text
1394                                .as_ref()
1395                                .unwrap_or(&lsp_completion.label)
1396                                .clone();
1397                            (
1398                                snapshot.anchor_before(start)..snapshot.anchor_after(end),
1399                                text,
1400                            )
1401                        }
1402                        Some(lsp::CompletionTextEdit::InsertAndReplace(_)) => {
1403                            log::info!("unsupported insert/replace completion");
1404                            return None;
1405                        }
1406                    };
1407
1408                    let language = language.clone();
1409                    LineEnding::normalize(&mut new_text);
1410                    Some(async move {
1411                        let mut label = None;
1412                        if let Some(language) = language {
1413                            language.process_completion(&mut lsp_completion).await;
1414                            label = language.label_for_completion(&lsp_completion).await;
1415                        }
1416                        Completion {
1417                            old_range,
1418                            new_text,
1419                            label: label.unwrap_or_else(|| {
1420                                language::CodeLabel::plain(
1421                                    lsp_completion.label.clone(),
1422                                    lsp_completion.filter_text.as_deref(),
1423                                )
1424                            }),
1425                            lsp_completion,
1426                        }
1427                    })
1428                })
1429        });
1430
1431        Ok(futures::future::join_all(completions).await)
1432    }
1433
1434    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCompletions {
1435        let anchor = buffer.anchor_after(self.position);
1436        proto::GetCompletions {
1437            project_id,
1438            buffer_id: buffer.remote_id(),
1439            position: Some(language::proto::serialize_anchor(&anchor)),
1440            version: serialize_version(&buffer.version()),
1441        }
1442    }
1443
1444    async fn from_proto(
1445        message: proto::GetCompletions,
1446        _: ModelHandle<Project>,
1447        buffer: ModelHandle<Buffer>,
1448        mut cx: AsyncAppContext,
1449    ) -> Result<Self> {
1450        let version = deserialize_version(&message.version);
1451        buffer
1452            .update(&mut cx, |buffer, _| buffer.wait_for_version(version))
1453            .await?;
1454        let position = message
1455            .position
1456            .and_then(language::proto::deserialize_anchor)
1457            .map(|p| {
1458                buffer.read_with(&cx, |buffer, _| {
1459                    buffer.clip_point_utf16(Unclipped(p.to_point_utf16(buffer)), Bias::Left)
1460                })
1461            })
1462            .ok_or_else(|| anyhow!("invalid position"))?;
1463        Ok(Self { position })
1464    }
1465
1466    fn response_to_proto(
1467        completions: Vec<Completion>,
1468        _: &mut Project,
1469        _: PeerId,
1470        buffer_version: &clock::Global,
1471        _: &mut AppContext,
1472    ) -> proto::GetCompletionsResponse {
1473        proto::GetCompletionsResponse {
1474            completions: completions
1475                .iter()
1476                .map(language::proto::serialize_completion)
1477                .collect(),
1478            version: serialize_version(&buffer_version),
1479        }
1480    }
1481
1482    async fn response_from_proto(
1483        self,
1484        message: proto::GetCompletionsResponse,
1485        _: ModelHandle<Project>,
1486        buffer: ModelHandle<Buffer>,
1487        mut cx: AsyncAppContext,
1488    ) -> Result<Vec<Completion>> {
1489        buffer
1490            .update(&mut cx, |buffer, _| {
1491                buffer.wait_for_version(deserialize_version(&message.version))
1492            })
1493            .await?;
1494
1495        let language = buffer.read_with(&cx, |buffer, _| buffer.language().cloned());
1496        let completions = message.completions.into_iter().map(|completion| {
1497            language::proto::deserialize_completion(completion, language.clone())
1498        });
1499        futures::future::try_join_all(completions).await
1500    }
1501
1502    fn buffer_id_from_proto(message: &proto::GetCompletions) -> u64 {
1503        message.buffer_id
1504    }
1505}
1506
1507#[async_trait(?Send)]
1508impl LspCommand for GetCodeActions {
1509    type Response = Vec<CodeAction>;
1510    type LspRequest = lsp::request::CodeActionRequest;
1511    type ProtoRequest = proto::GetCodeActions;
1512
1513    fn check_capabilities(&self, capabilities: &ServerCapabilities) -> bool {
1514        match &capabilities.code_action_provider {
1515            None => false,
1516            Some(lsp::CodeActionProviderCapability::Simple(false)) => false,
1517            _ => true,
1518        }
1519    }
1520
1521    fn to_lsp(
1522        &self,
1523        path: &Path,
1524        buffer: &Buffer,
1525        language_server: &Arc<LanguageServer>,
1526        _: &AppContext,
1527    ) -> lsp::CodeActionParams {
1528        let relevant_diagnostics = buffer
1529            .snapshot()
1530            .diagnostics_in_range::<_, usize>(self.range.clone(), false)
1531            .map(|entry| entry.to_lsp_diagnostic_stub())
1532            .collect();
1533        lsp::CodeActionParams {
1534            text_document: lsp::TextDocumentIdentifier::new(
1535                lsp::Url::from_file_path(path).unwrap(),
1536            ),
1537            range: range_to_lsp(self.range.to_point_utf16(buffer)),
1538            work_done_progress_params: Default::default(),
1539            partial_result_params: Default::default(),
1540            context: lsp::CodeActionContext {
1541                diagnostics: relevant_diagnostics,
1542                only: language_server.code_action_kinds(),
1543                ..lsp::CodeActionContext::default()
1544            },
1545        }
1546    }
1547
1548    async fn response_from_lsp(
1549        self,
1550        actions: Option<lsp::CodeActionResponse>,
1551        _: ModelHandle<Project>,
1552        _: ModelHandle<Buffer>,
1553        server_id: LanguageServerId,
1554        _: AsyncAppContext,
1555    ) -> Result<Vec<CodeAction>> {
1556        Ok(actions
1557            .unwrap_or_default()
1558            .into_iter()
1559            .filter_map(|entry| {
1560                if let lsp::CodeActionOrCommand::CodeAction(lsp_action) = entry {
1561                    Some(CodeAction {
1562                        server_id,
1563                        range: self.range.clone(),
1564                        lsp_action,
1565                    })
1566                } else {
1567                    None
1568                }
1569            })
1570            .collect())
1571    }
1572
1573    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeActions {
1574        proto::GetCodeActions {
1575            project_id,
1576            buffer_id: buffer.remote_id(),
1577            start: Some(language::proto::serialize_anchor(&self.range.start)),
1578            end: Some(language::proto::serialize_anchor(&self.range.end)),
1579            version: serialize_version(&buffer.version()),
1580        }
1581    }
1582
1583    async fn from_proto(
1584        message: proto::GetCodeActions,
1585        _: ModelHandle<Project>,
1586        buffer: ModelHandle<Buffer>,
1587        mut cx: AsyncAppContext,
1588    ) -> Result<Self> {
1589        let start = message
1590            .start
1591            .and_then(language::proto::deserialize_anchor)
1592            .ok_or_else(|| anyhow!("invalid start"))?;
1593        let end = message
1594            .end
1595            .and_then(language::proto::deserialize_anchor)
1596            .ok_or_else(|| anyhow!("invalid end"))?;
1597        buffer
1598            .update(&mut cx, |buffer, _| {
1599                buffer.wait_for_version(deserialize_version(&message.version))
1600            })
1601            .await?;
1602
1603        Ok(Self { range: start..end })
1604    }
1605
1606    fn response_to_proto(
1607        code_actions: Vec<CodeAction>,
1608        _: &mut Project,
1609        _: PeerId,
1610        buffer_version: &clock::Global,
1611        _: &mut AppContext,
1612    ) -> proto::GetCodeActionsResponse {
1613        proto::GetCodeActionsResponse {
1614            actions: code_actions
1615                .iter()
1616                .map(language::proto::serialize_code_action)
1617                .collect(),
1618            version: serialize_version(&buffer_version),
1619        }
1620    }
1621
1622    async fn response_from_proto(
1623        self,
1624        message: proto::GetCodeActionsResponse,
1625        _: ModelHandle<Project>,
1626        buffer: ModelHandle<Buffer>,
1627        mut cx: AsyncAppContext,
1628    ) -> Result<Vec<CodeAction>> {
1629        buffer
1630            .update(&mut cx, |buffer, _| {
1631                buffer.wait_for_version(deserialize_version(&message.version))
1632            })
1633            .await?;
1634        message
1635            .actions
1636            .into_iter()
1637            .map(language::proto::deserialize_code_action)
1638            .collect()
1639    }
1640
1641    fn buffer_id_from_proto(message: &proto::GetCodeActions) -> u64 {
1642        message.buffer_id
1643    }
1644}
1645
1646#[async_trait(?Send)]
1647impl LspCommand for OnTypeFormatting {
1648    type Response = Option<Transaction>;
1649    type LspRequest = lsp::request::OnTypeFormatting;
1650    type ProtoRequest = proto::OnTypeFormatting;
1651
1652    fn check_capabilities(&self, server_capabilities: &lsp::ServerCapabilities) -> bool {
1653        let Some(on_type_formatting_options) = &server_capabilities.document_on_type_formatting_provider else { return false };
1654        on_type_formatting_options
1655            .first_trigger_character
1656            .contains(&self.trigger)
1657            || on_type_formatting_options
1658                .more_trigger_character
1659                .iter()
1660                .flatten()
1661                .any(|chars| chars.contains(&self.trigger))
1662    }
1663
1664    fn to_lsp(
1665        &self,
1666        path: &Path,
1667        _: &Buffer,
1668        _: &Arc<LanguageServer>,
1669        _: &AppContext,
1670    ) -> lsp::DocumentOnTypeFormattingParams {
1671        lsp::DocumentOnTypeFormattingParams {
1672            text_document_position: lsp::TextDocumentPositionParams::new(
1673                lsp::TextDocumentIdentifier::new(lsp::Url::from_file_path(path).unwrap()),
1674                point_to_lsp(self.position),
1675            ),
1676            ch: self.trigger.clone(),
1677            options: lsp_formatting_options(self.options.tab_size),
1678        }
1679    }
1680
1681    async fn response_from_lsp(
1682        self,
1683        message: Option<Vec<lsp::TextEdit>>,
1684        project: ModelHandle<Project>,
1685        buffer: ModelHandle<Buffer>,
1686        server_id: LanguageServerId,
1687        mut cx: AsyncAppContext,
1688    ) -> Result<Option<Transaction>> {
1689        if let Some(edits) = message {
1690            let (lsp_adapter, lsp_server) =
1691                language_server_for_buffer(&project, &buffer, server_id, &mut cx)?;
1692            Project::deserialize_edits(
1693                project,
1694                buffer,
1695                edits,
1696                self.push_to_history,
1697                lsp_adapter,
1698                lsp_server,
1699                &mut cx,
1700            )
1701            .await
1702        } else {
1703            Ok(None)
1704        }
1705    }
1706
1707    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::OnTypeFormatting {
1708        proto::OnTypeFormatting {
1709            project_id,
1710            buffer_id: buffer.remote_id(),
1711            position: Some(language::proto::serialize_anchor(
1712                &buffer.anchor_before(self.position),
1713            )),
1714            trigger: self.trigger.clone(),
1715            version: serialize_version(&buffer.version()),
1716        }
1717    }
1718
1719    async fn from_proto(
1720        message: proto::OnTypeFormatting,
1721        _: ModelHandle<Project>,
1722        buffer: ModelHandle<Buffer>,
1723        mut cx: AsyncAppContext,
1724    ) -> Result<Self> {
1725        let position = message
1726            .position
1727            .and_then(deserialize_anchor)
1728            .ok_or_else(|| anyhow!("invalid position"))?;
1729        buffer
1730            .update(&mut cx, |buffer, _| {
1731                buffer.wait_for_version(deserialize_version(&message.version))
1732            })
1733            .await?;
1734
1735        let tab_size = buffer.read_with(&cx, |buffer, cx| {
1736            language_settings(buffer.language(), buffer.file(), cx).tab_size
1737        });
1738
1739        Ok(Self {
1740            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1741            trigger: message.trigger.clone(),
1742            options: lsp_formatting_options(tab_size.get()).into(),
1743            push_to_history: false,
1744        })
1745    }
1746
1747    fn response_to_proto(
1748        response: Option<Transaction>,
1749        _: &mut Project,
1750        _: PeerId,
1751        _: &clock::Global,
1752        _: &mut AppContext,
1753    ) -> proto::OnTypeFormattingResponse {
1754        proto::OnTypeFormattingResponse {
1755            transaction: response
1756                .map(|transaction| language::proto::serialize_transaction(&transaction)),
1757        }
1758    }
1759
1760    async fn response_from_proto(
1761        self,
1762        message: proto::OnTypeFormattingResponse,
1763        _: ModelHandle<Project>,
1764        _: ModelHandle<Buffer>,
1765        _: AsyncAppContext,
1766    ) -> Result<Option<Transaction>> {
1767        let Some(transaction) = message.transaction else { return Ok(None) };
1768        Ok(Some(language::proto::deserialize_transaction(transaction)?))
1769    }
1770
1771    fn buffer_id_from_proto(message: &proto::OnTypeFormatting) -> u64 {
1772        message.buffer_id
1773    }
1774}