lsp: Retrieve links to documentation for the given symbol (#19233)

Closes #18924 

Release Notes:

- Added an `editor:OpenDocs` action to open links to documentation via
rust-analyzer
This commit is contained in:
Lu Wan 2024-11-16 10:23:49 -08:00 committed by GitHub
parent f9990b42fa
commit 2d3476530e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 213 additions and 2 deletions

View file

@ -134,6 +134,132 @@ impl LspCommand for ExpandMacro {
}
}
pub enum LspOpenDocs {}
impl lsp::request::Request for LspOpenDocs {
type Params = OpenDocsParams;
type Result = Option<DocsUrls>;
const METHOD: &'static str = "experimental/externalDocs";
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct OpenDocsParams {
pub text_document: lsp::TextDocumentIdentifier,
pub position: lsp::Position,
}
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct DocsUrls {
pub web: Option<String>,
pub local: Option<String>,
}
impl DocsUrls {
pub fn is_empty(&self) -> bool {
self.web.is_none() && self.local.is_none()
}
}
#[derive(Debug)]
pub struct OpenDocs {
pub position: PointUtf16,
}
#[async_trait(?Send)]
impl LspCommand for OpenDocs {
type Response = DocsUrls;
type LspRequest = LspOpenDocs;
type ProtoRequest = proto::LspExtOpenDocs;
fn to_lsp(
&self,
path: &Path,
_: &Buffer,
_: &Arc<LanguageServer>,
_: &AppContext,
) -> OpenDocsParams {
OpenDocsParams {
text_document: lsp::TextDocumentIdentifier {
uri: lsp::Url::from_file_path(path).unwrap(),
},
position: point_to_lsp(self.position),
}
}
async fn response_from_lsp(
self,
message: Option<DocsUrls>,
_: Model<LspStore>,
_: Model<Buffer>,
_: LanguageServerId,
_: AsyncAppContext,
) -> anyhow::Result<DocsUrls> {
Ok(message
.map(|message| DocsUrls {
web: message.web,
local: message.local,
})
.unwrap_or_default())
}
fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::LspExtOpenDocs {
proto::LspExtOpenDocs {
project_id,
buffer_id: buffer.remote_id().into(),
position: Some(language::proto::serialize_anchor(
&buffer.anchor_before(self.position),
)),
}
}
async fn from_proto(
message: Self::ProtoRequest,
_: Model<LspStore>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> anyhow::Result<Self> {
let position = message
.position
.and_then(deserialize_anchor)
.context("invalid position")?;
Ok(Self {
position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
})
}
fn response_to_proto(
response: DocsUrls,
_: &mut LspStore,
_: PeerId,
_: &clock::Global,
_: &mut AppContext,
) -> proto::LspExtOpenDocsResponse {
proto::LspExtOpenDocsResponse {
web: response.web,
local: response.local,
}
}
async fn response_from_proto(
self,
message: proto::LspExtOpenDocsResponse,
_: Model<LspStore>,
_: Model<Buffer>,
_: AsyncAppContext,
) -> anyhow::Result<DocsUrls> {
Ok(DocsUrls {
web: message.web,
local: message.local,
})
}
fn buffer_id_from_proto(message: &proto::LspExtOpenDocs) -> Result<BufferId> {
BufferId::new(message.buffer_id)
}
}
pub enum LspSwitchSourceHeader {}
impl lsp::request::Request for LspSwitchSourceHeader {