diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index aa6beb6351..51874382a8 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -1036,6 +1036,10 @@ impl Config { self.experimental("codeActionGroup") } + pub fn local_docs(&self) -> bool { + self.experimental("localDocs") + } + pub fn open_server_logs(&self) -> bool { self.experimental("openServerLogs") } diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 65541bfe14..b8e7c85b04 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -40,8 +40,8 @@ use crate::{ global_state::{GlobalState, GlobalStateSnapshot}, line_index::LineEndings, lsp_ext::{ - self, CrateInfoResult, FetchDependencyListParams, FetchDependencyListResult, - PositionOrRange, ViewCrateGraphParams, WorkspaceSymbolParams, + self, CrateInfoResult, ExternalDocsPair, ExternalDocsResponse, FetchDependencyListParams, + FetchDependencyListResult, PositionOrRange, ViewCrateGraphParams, WorkspaceSymbolParams, }, lsp_utils::{all_edits_are_disjoint, invalid_params_error}, to_proto, LspError, Result, @@ -1534,34 +1534,43 @@ pub(crate) fn handle_semantic_tokens_range( pub(crate) fn handle_open_docs( snap: GlobalStateSnapshot, - params: lsp_types::TextDocumentPositionParams, - ) -> Result<(Option, Option)> { + params: lsp_types::TextDocumentPositionParams, +) -> Result { let _p = profile::span("handle_open_docs"); let position = from_proto::file_position(&snap, params)?; let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match ws { - ProjectWorkspace::Cargo { cargo, sysroot, .. } => Some((cargo, sysroot.as_ref().ok())), - ProjectWorkspace::Json { .. } => None, - ProjectWorkspace::DetachedFiles { .. } => None, - }); + ProjectWorkspace::Cargo { cargo, sysroot, .. } => Some((cargo, sysroot.as_ref().ok())), + ProjectWorkspace::Json { .. } => None, + ProjectWorkspace::DetachedFiles { .. } => None, + }); let (cargo, sysroot) = match ws_and_sysroot { - Some((ws, Some(sysroot))) => (Some(ws), Some(sysroot)), - _ => (None, None), - }; + Some((ws, Some(sysroot))) => (Some(ws), Some(sysroot)), + _ => (None, None), + }; let sysroot = sysroot.map(|p| p.root().as_os_str()); let target_dir = cargo.map(|cargo| cargo.target_directory()).map(|p| p.as_os_str()); - let Ok(remote_urls) = snap.analysis.external_docs(position, target_dir, sysroot) else { return Ok((None, None)); }; + let Ok(remote_urls) = snap.analysis.external_docs(position, target_dir, sysroot) else { + return if snap.config.local_docs() { + Ok(ExternalDocsResponse::WithLocal(Default::default())) + } else { + Ok(ExternalDocsResponse::Simple(None)) + } + }; - let web_url = remote_urls.web_url.and_then(|it| Url::parse(&it).ok()); - let local_url = remote_urls.local_url.and_then(|it| Url::parse(&it).ok()); + let web = remote_urls.web_url.and_then(|it| Url::parse(&it).ok()); + let local = remote_urls.local_url.and_then(|it| Url::parse(&it).ok()); - Ok((web_url, local_url)) + if snap.config.local_docs() { + Ok(ExternalDocsResponse::WithLocal(ExternalDocsPair { web, local })) + } else { + Ok(ExternalDocsResponse::Simple(web)) + } } - pub(crate) fn handle_open_cargo_toml( snap: GlobalStateSnapshot, params: lsp_ext::OpenCargoTomlParams, diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 9c27f6e1c3..4d67c8b305 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs @@ -508,10 +508,24 @@ pub enum ExternalDocs {} impl Request for ExternalDocs { type Params = lsp_types::TextDocumentPositionParams; - type Result = (Option, Option); + type Result = ExternalDocsResponse; const METHOD: &'static str = "experimental/externalDocs"; } +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] +#[serde(untagged)] +pub enum ExternalDocsResponse { + Simple(Option), + WithLocal(ExternalDocsPair), +} + +#[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct ExternalDocsPair { + pub web: Option, + pub local: Option, +} + pub enum OpenCargoToml {} impl Request for OpenCargoToml { diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 13407f80b2..bc58aa7220 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@