Skip to content

Commit 2a8dee1

Browse files
committed
Add a localDocs capability
1 parent 2bb29b9 commit 2a8dee1

File tree

4 files changed

+55
-12
lines changed

4 files changed

+55
-12
lines changed

crates/rust-analyzer/src/config.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,10 @@ impl Config {
10341034
self.experimental("codeActionGroup")
10351035
}
10361036

1037+
pub fn local_docs(&self) -> bool {
1038+
self.experimental("localDocs")
1039+
}
1040+
10371041
pub fn open_server_logs(&self) -> bool {
10381042
self.experimental("openServerLogs")
10391043
}

crates/rust-analyzer/src/handlers.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ use crate::{
3939
from_proto,
4040
global_state::{GlobalState, GlobalStateSnapshot},
4141
line_index::LineEndings,
42-
lsp_ext::{self, PositionOrRange, ViewCrateGraphParams, WorkspaceSymbolParams},
42+
lsp_ext::{
43+
self, ExternalDocsPair, ExternalDocsResponse, PositionOrRange, ViewCrateGraphParams,
44+
WorkspaceSymbolParams,
45+
},
4346
lsp_utils::{all_edits_are_disjoint, invalid_params_error},
4447
to_proto, LspError, Result,
4548
};
@@ -1560,7 +1563,7 @@ pub(crate) fn handle_semantic_tokens_range(
15601563
pub(crate) fn handle_open_docs(
15611564
snap: GlobalStateSnapshot,
15621565
params: lsp_types::TextDocumentPositionParams,
1563-
) -> Result<(Option<lsp_types::Url>, Option<lsp_types::Url>)> {
1566+
) -> Result<ExternalDocsResponse> {
15641567
let _p = profile::span("handle_open_docs");
15651568
let position = from_proto::file_position(&snap, params)?;
15661569

@@ -1578,12 +1581,22 @@ pub(crate) fn handle_open_docs(
15781581
let sysroot = sysroot.map(|p| p.root().as_os_str());
15791582
let target_dir = cargo.map(|cargo| cargo.target_directory()).map(|p| p.as_os_str());
15801583

1581-
let Ok(remote_urls) = snap.analysis.external_docs(position, target_dir, sysroot) else { return Ok((None, None)); };
1584+
let Ok(remote_urls) = snap.analysis.external_docs(position, target_dir, sysroot) else {
1585+
return if snap.config.local_docs() {
1586+
Ok(ExternalDocsResponse::WithLocal(Default::default()))
1587+
} else {
1588+
Ok(ExternalDocsResponse::Simple(None))
1589+
}
1590+
};
15821591

1583-
let web_url = remote_urls.web_url.and_then(|it| Url::parse(&it).ok());
1584-
let local_url = remote_urls.local_url.and_then(|it| Url::parse(&it).ok());
1592+
let web = remote_urls.web_url.and_then(|it| Url::parse(&it).ok());
1593+
let local = remote_urls.local_url.and_then(|it| Url::parse(&it).ok());
15851594

1586-
Ok((web_url, local_url))
1595+
if snap.config.local_docs() {
1596+
Ok(ExternalDocsResponse::WithLocal(ExternalDocsPair { web, local }))
1597+
} else {
1598+
Ok(ExternalDocsResponse::Simple(web))
1599+
}
15871600
}
15881601

15891602
pub(crate) fn handle_open_cargo_toml(

crates/rust-analyzer/src/lsp_ext.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -474,10 +474,24 @@ pub enum ExternalDocs {}
474474

475475
impl Request for ExternalDocs {
476476
type Params = lsp_types::TextDocumentPositionParams;
477-
type Result = (Option<lsp_types::Url>, Option<lsp_types::Url>);
477+
type Result = ExternalDocsResponse;
478478
const METHOD: &'static str = "experimental/externalDocs";
479479
}
480480

481+
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
482+
#[serde(untagged)]
483+
pub enum ExternalDocsResponse {
484+
Simple(Option<lsp_types::Url>),
485+
WithLocal(ExternalDocsPair),
486+
}
487+
488+
#[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)]
489+
#[serde(rename_all = "camelCase")]
490+
pub struct ExternalDocsPair {
491+
pub web: Option<lsp_types::Url>,
492+
pub local: Option<lsp_types::Url>,
493+
}
494+
481495
pub enum OpenCargoToml {}
482496

483497
impl Request for OpenCargoToml {

docs/dev/lsp-extensions.md

+17-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!---
2-
lsp_ext.rs hash: a1e4d79b919f0f16
2+
lsp_ext.rs hash: 411627c9db1e02c9
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)