lsp_ext_command.rs

  1use std::{path::Path, sync::Arc};
  2
  3use anyhow::{Context, Result};
  4use async_trait::async_trait;
  5use gpui::{AppContext, AsyncAppContext, Model};
  6use language::{point_to_lsp, proto::deserialize_anchor, Buffer};
  7use lsp::{LanguageServer, LanguageServerId};
  8use rpc::proto::{self, PeerId};
  9use serde::{Deserialize, Serialize};
 10use text::{BufferId, PointUtf16, ToPointUtf16};
 11
 12use crate::{lsp_command::LspCommand, Project};
 13
 14pub enum LspExpandMacro {}
 15
 16impl lsp::request::Request for LspExpandMacro {
 17    type Params = ExpandMacroParams;
 18    type Result = Option<ExpandedMacro>;
 19    const METHOD: &'static str = "rust-analyzer/expandMacro";
 20}
 21
 22#[derive(Deserialize, Serialize, Debug)]
 23#[serde(rename_all = "camelCase")]
 24pub struct ExpandMacroParams {
 25    pub text_document: lsp::TextDocumentIdentifier,
 26    pub position: lsp::Position,
 27}
 28
 29#[derive(Default, Deserialize, Serialize, Debug)]
 30#[serde(rename_all = "camelCase")]
 31pub struct ExpandedMacro {
 32    pub name: String,
 33    pub expansion: String,
 34}
 35
 36impl ExpandedMacro {
 37    pub fn is_empty(&self) -> bool {
 38        self.name.is_empty() && self.expansion.is_empty()
 39    }
 40}
 41
 42pub struct ExpandMacro {
 43    pub position: PointUtf16,
 44}
 45
 46#[async_trait(?Send)]
 47impl LspCommand for ExpandMacro {
 48    type Response = ExpandedMacro;
 49    type LspRequest = LspExpandMacro;
 50    type ProtoRequest = proto::LspExtExpandMacro;
 51
 52    fn to_lsp(
 53        &self,
 54        path: &Path,
 55        _: &Buffer,
 56        _: &Arc<LanguageServer>,
 57        _: &AppContext,
 58    ) -> ExpandMacroParams {
 59        ExpandMacroParams {
 60            text_document: lsp::TextDocumentIdentifier {
 61                uri: lsp::Url::from_file_path(path).unwrap(),
 62            },
 63            position: point_to_lsp(self.position),
 64        }
 65    }
 66
 67    async fn response_from_lsp(
 68        self,
 69        message: Option<ExpandedMacro>,
 70        _: Model<Project>,
 71        _: Model<Buffer>,
 72        _: LanguageServerId,
 73        _: AsyncAppContext,
 74    ) -> anyhow::Result<ExpandedMacro> {
 75        Ok(message
 76            .map(|message| ExpandedMacro {
 77                name: message.name,
 78                expansion: message.expansion,
 79            })
 80            .unwrap_or_default())
 81    }
 82
 83    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::LspExtExpandMacro {
 84        proto::LspExtExpandMacro {
 85            project_id,
 86            buffer_id: buffer.remote_id().into(),
 87            position: Some(language::proto::serialize_anchor(
 88                &buffer.anchor_before(self.position),
 89            )),
 90        }
 91    }
 92
 93    async fn from_proto(
 94        message: Self::ProtoRequest,
 95        _: Model<Project>,
 96        buffer: Model<Buffer>,
 97        mut cx: AsyncAppContext,
 98    ) -> anyhow::Result<Self> {
 99        let position = message
100            .position
101            .and_then(deserialize_anchor)
102            .context("invalid position")?;
103        Ok(Self {
104            position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
105        })
106    }
107
108    fn response_to_proto(
109        response: ExpandedMacro,
110        _: &mut Project,
111        _: PeerId,
112        _: &clock::Global,
113        _: &mut AppContext,
114    ) -> proto::LspExtExpandMacroResponse {
115        proto::LspExtExpandMacroResponse {
116            name: response.name,
117            expansion: response.expansion,
118        }
119    }
120
121    async fn response_from_proto(
122        self,
123        message: proto::LspExtExpandMacroResponse,
124        _: Model<Project>,
125        _: Model<Buffer>,
126        _: AsyncAppContext,
127    ) -> anyhow::Result<ExpandedMacro> {
128        Ok(ExpandedMacro {
129            name: message.name,
130            expansion: message.expansion,
131        })
132    }
133
134    fn buffer_id_from_proto(message: &proto::LspExtExpandMacro) -> Result<BufferId> {
135        BufferId::new(message.buffer_id)
136    }
137}