Skip to content

Commit 7e19d99

Browse files
committed
Add a localDocs capability
1 parent 4ac39f0 commit 7e19d99

File tree

4 files changed

+61
-22
lines changed

4 files changed

+61
-22
lines changed

crates/rust-analyzer/src/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,10 @@ impl Config {
10361036
self.experimental("codeActionGroup")
10371037
}
10381038

1039+
pub fn local_docs(&self) -> bool {
1040+
self.experimental("localDocs")
1041+
}
1042+
10391043
pub fn open_server_logs(&self) -> bool {
10401044
self.experimental("openServerLogs")
10411045
}

crates/rust-analyzer/src/handlers/request.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ use crate::{
4040
global_state::{GlobalState, GlobalStateSnapshot},
4141
line_index::LineEndings,
4242
lsp_ext::{
43-
self, CrateInfoResult, FetchDependencyListParams, FetchDependencyListResult,
44-
PositionOrRange, ViewCrateGraphParams, WorkspaceSymbolParams,
43+
self, CrateInfoResult, ExternalDocsPair, ExternalDocsResponse, FetchDependencyListParams,
44+
FetchDependencyListResult, PositionOrRange, ViewCrateGraphParams, WorkspaceSymbolParams,
4545
},
4646
lsp_utils::{all_edits_are_disjoint, invalid_params_error},
4747
to_proto, LspError, Result,
@@ -1534,34 +1534,43 @@ pub(crate) fn handle_semantic_tokens_range(
15341534

15351535
pub(crate) fn handle_open_docs(
15361536
snap: GlobalStateSnapshot,
1537-
params: lsp_types::TextDocumentPositionParams,
1538-
) -> Result<(Option<lsp_types::Url>, Option<lsp_types::Url>)> {
1537+
params: lsp_types::TextDocumentPositionParams,
1538+
) -> Result<ExternalDocsResponse> {
15391539
let _p = profile::span("handle_open_docs");
15401540
let position = from_proto::file_position(&snap, params)?;
15411541

15421542
let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match ws {
1543-
ProjectWorkspace::Cargo { cargo, sysroot, .. } => Some((cargo, sysroot.as_ref().ok())),
1544-
ProjectWorkspace::Json { .. } => None,
1545-
ProjectWorkspace::DetachedFiles { .. } => None,
1546-
});
1543+
ProjectWorkspace::Cargo { cargo, sysroot, .. } => Some((cargo, sysroot.as_ref().ok())),
1544+
ProjectWorkspace::Json { .. } => None,
1545+
ProjectWorkspace::DetachedFiles { .. } => None,
1546+
});
15471547

15481548
let (cargo, sysroot) = match ws_and_sysroot {
1549-
Some((ws, Some(sysroot))) => (Some(ws), Some(sysroot)),
1550-
_ => (None, None),
1551-
};
1549+
Some((ws, Some(sysroot))) => (Some(ws), Some(sysroot)),
1550+
_ => (None, None),
1551+
};
15521552

15531553
let sysroot = sysroot.map(|p| p.root().as_os_str());
15541554
let target_dir = cargo.map(|cargo| cargo.target_directory()).map(|p| p.as_os_str());
15551555

1556-
let Ok(remote_urls) = snap.analysis.external_docs(position, target_dir, sysroot) else { return Ok((None, None)); };
1556+
let Ok(remote_urls) = snap.analysis.external_docs(position, target_dir, sysroot) else {
1557+
return if snap.config.local_docs() {
1558+
Ok(ExternalDocsResponse::WithLocal(Default::default()))
1559+
} else {
1560+
Ok(ExternalDocsResponse::Simple(None))
1561+
}
1562+
};
15571563

1558-
let web_url = remote_urls.web_url.and_then(|it| Url::parse(&it).ok());
1559-
let local_url = remote_urls.local_url.and_then(|it| Url::parse(&it).ok());
1564+
let web = remote_urls.web_url.and_then(|it| Url::parse(&it).ok());
1565+
let local = remote_urls.local_url.and_then(|it| Url::parse(&it).ok());
15601566

1561-
Ok((web_url, local_url))
1567+
if snap.config.local_docs() {
1568+
Ok(ExternalDocsResponse::WithLocal(ExternalDocsPair { web, local }))
1569+
} else {
1570+
Ok(ExternalDocsResponse::Simple(web))
1571+
}
15621572
}
15631573

1564-
15651574
pub(crate) fn handle_open_cargo_toml(
15661575
snap: GlobalStateSnapshot,
15671576
params: lsp_ext::OpenCargoTomlParams,

crates/rust-analyzer/src/lsp_ext.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,10 +508,24 @@ pub enum ExternalDocs {}
508508

509509
impl Request for ExternalDocs {
510510
type Params = lsp_types::TextDocumentPositionParams;
511-
type Result = (Option<lsp_types::Url>, Option<lsp_types::Url>);
511+
type Result = ExternalDocsResponse;
512512
const METHOD: &'static str = "experimental/externalDocs";
513513
}
514514

515+
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
516+
#[serde(untagged)]
517+
pub enum ExternalDocsResponse {
518+
Simple(Option<lsp_types::Url>),
519+
WithLocal(ExternalDocsPair),
520+
}
521+
522+
#[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)]
523+
#[serde(rename_all = "camelCase")]
524+
pub struct ExternalDocsPair {
525+
pub web: Option<lsp_types::Url>,
526+
pub local: Option<lsp_types::Url>,
527+
}
528+
515529
pub enum OpenCargoToml {}
516530

517531
impl Request for OpenCargoToml {

docs/dev/lsp-extensions.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!---
2-
lsp_ext.rs hash: 4e825bd8f3921c87
2+
lsp_ext.rs hash: 2d60bbffe70ae198
33
44
If you need to change the above hash to make the test pass, please check if you
55
need to adjust this doc as well and ping this issue:
@@ -386,14 +386,26 @@ rust-analyzer supports only one `kind`, `"cargo"`. The `args` for `"cargo"` look
386386

387387
## Open External Documentation
388388

389-
This request is sent from client to server to get a web and local URL(s) to documentation for the symbol under the cursor, if available.
389+
This request is sent from the client to the server to obtain web and local URL(s) for documentation related to the symbol under the cursor, if available.
390390

391-
**Method** `experimental/externalDocs`
391+
**Method:** `experimental/externalDocs`
392392

393-
**Request:**: `TextDocumentPositionParams`
393+
**Request:** `TextDocumentPositionParams`
394+
395+
**Response:** `string | null`
396+
397+
## Local Documentation
394398

395-
**Response** `[string | null, string | null]`
399+
**Experimental Client Capability:** `{ "localDocs": boolean }`
396400

401+
If this capability is set, the `Open External Documentation` request returned from the server will have the following structure:
402+
403+
```typescript
404+
interface ExternalDocsResponse {
405+
web?: string;
406+
local?: string;
407+
}
408+
```
397409

398410
## Analyzer Status
399411

0 commit comments

Comments
 (0)