about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-10-10 06:33:10 +0000
committerbors <bors@rust-lang.org>2023-10-10 06:33:10 +0000
commit8a2331450a2fa269aa60818b224a2beaef7d7198 (patch)
treee2f535c85021481bedfd7f58e884e502fcddad26
parentaaa1e8e1b82d742b876d164a30dda02f318ce809 (diff)
parente8372e04840a113c7aedb9cc5c7f387014d09e0b (diff)
downloadrust-8a2331450a2fa269aa60818b224a2beaef7d7198.tar.gz
rust-8a2331450a2fa269aa60818b224a2beaef7d7198.zip
Auto merge of #15728 - EliasHolzmann:feature/local_documentation_vscode, r=Veykril
feat: vscode: Support opening local documentation if available

This PR implements the VS code support for opening local documentation (server side support was already implemented in #14662).

[local_docs.webm](https://github.com/rust-lang/rust-analyzer/assets/9659253/715b84dd-4f14-4ba0-a904-749b847eb3d5)

Displaying local instead of web docs can have many benefits:
- the web version may have different features enabled than locally selected
- the standard library may be a different version than is available online
- the user may not be online and therefore cannot access the web documentation
- the documentation may not be available online at all, for example because it is for a new feature in a library the user is currently developing

If the documentation is not available locally, the extension still falls back to the web version.

Closes #12867.

-----

If my implementation isn't really idiomatic TypeScript: Sorry, I'm not much of a TypeScript developer. I am open to feedback, however.
-rw-r--r--editors/code/src/client.ts1
-rw-r--r--editors/code/src/commands.ts22
-rw-r--r--editors/code/src/lsp_ext.ts6
3 files changed, 26 insertions, 3 deletions
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index ba8546763ec..96e888402ba 100644
--- a/editors/code/src/client.ts
+++ b/editors/code/src/client.ts
@@ -389,6 +389,7 @@ class ExperimentalFeatures implements lc.StaticFeature {
             serverStatusNotification: true,
             colorDiagnosticOutput: true,
             openServerLogs: true,
+            localDocs: true,
             commands: {
                 commands: [
                     "rust-analyzer.runSingle",
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 245557b1e88..4d5c3cf4576 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -21,6 +21,7 @@ import type { LanguageClient } from "vscode-languageclient/node";
 import { LINKED_COMMANDS } from "./client";
 import type { DependencyId } from "./dependencies_provider";
 import { unwrapUndefinable } from "./undefinable";
+import { log } from "./util";
 
 export * from "./ast_inspector";
 export * from "./run";
@@ -947,10 +948,27 @@ export function openDocs(ctx: CtxInit): Cmd {
         const position = editor.selection.active;
         const textDocument = { uri: editor.document.uri.toString() };
 
-        const doclink = await client.sendRequest(ra.openDocs, { position, textDocument });
+        const doclinks = await client.sendRequest(ra.openDocs, { position, textDocument });
+
+        let fileType = vscode.FileType.Unknown;
+        if (typeof doclinks.local === "string") {
+            try {
+                fileType = (await vscode.workspace.fs.stat(vscode.Uri.parse(doclinks.local))).type;
+            } catch (e) {
+                log.debug("stat() threw error. Falling back to web version", e);
+            }
+        }
+
+        let doclink;
+        if (fileType & vscode.FileType.File) {
+            // file does exist locally
+            doclink = doclinks.local;
+        } else {
+            doclink = doclinks.web;
+        }
 
         if (doclink != null) {
-            await vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(doclink));
+            await vscode.env.openExternal(vscode.Uri.parse(doclink));
         }
     };
 }
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index bb7896973f1..a1cd88b89c9 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -135,7 +135,11 @@ export const onEnter = new lc.RequestType<lc.TextDocumentPositionParams, lc.Text
 export const openCargoToml = new lc.RequestType<OpenCargoTomlParams, lc.Location, void>(
     "experimental/openCargoToml",
 );
-export const openDocs = new lc.RequestType<lc.TextDocumentPositionParams, string | void, void>(
+export interface DocsUrls {
+    local: string | void;
+    web: string | void;
+}
+export const openDocs = new lc.RequestType<lc.TextDocumentPositionParams, DocsUrls, void>(
     "experimental/externalDocs",
 );
 export const parentModule = new lc.RequestType<