about summary refs log tree commit diff
path: root/editors/code/src/client.ts
diff options
context:
space:
mode:
authorvsrs <vit@conrlab.com>2020-06-03 14:15:54 +0300
committervsrs <vit@conrlab.com>2020-06-05 14:59:26 +0300
commit7d0dd17b09240385333805637ea17992a8089cf2 (patch)
tree605249f14a8d7c8071362e31be28ca9c17b55173 /editors/code/src/client.ts
parent913a623281ed4cd190ca04845c64e5054d176a2a (diff)
downloadrust-7d0dd17b09240385333805637ea17992a8089cf2.tar.gz
rust-7d0dd17b09240385333805637ea17992a8089cf2.zip
Add hover actions as LSP extension
Diffstat (limited to 'editors/code/src/client.ts')
-rw-r--r--editors/code/src/client.ts45
1 files changed, 45 insertions, 0 deletions
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index 40ad1e3cd84..9df6702839b 100644
--- a/editors/code/src/client.ts
+++ b/editors/code/src/client.ts
@@ -7,6 +7,29 @@ import { CallHierarchyFeature } from 'vscode-languageclient/lib/callHierarchy.pr
 import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed';
 import { assert } from './util';
 
+function toTrusted(obj: vscode.MarkedString): vscode.MarkedString {
+    const md = <vscode.MarkdownString>obj;
+    if (md && md.value.includes("```rust")) {
+        md.isTrusted = true;
+        return md;
+    }
+    return obj;
+}
+
+function renderCommand(cmd: CommandLink) {
+    return `[${cmd.title}](command:${cmd.command}?${encodeURIComponent(JSON.stringify(cmd.arguments))} '${cmd.tooltip!}')`;
+}
+
+function renderHoverActions(actions: CommandLinkGroup[]): vscode.MarkdownString {
+    const text = actions.map(group =>
+        (group.title ? (group.title + " ") : "") + group.commands.map(renderCommand).join(' | ')
+    ).join('___');
+
+    const result = new vscode.MarkdownString(text);
+    result.isTrusted = true;
+    return result;
+}
+
 export function createClient(serverPath: string, cwd: string): lc.LanguageClient {
     // '.' Is the fallback if no folder is open
     // TODO?: Workspace folders support Uri's (eg: file://test.txt).
@@ -35,6 +58,27 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient
                 if (res === undefined) throw new Error('busy');
                 return res;
             },
+            async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, _next: lc.ProvideHoverSignature) {
+                return client.sendRequest(lc.HoverRequest.type, client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token).then(
+                    (result) => {
+                        const hover = client.protocol2CodeConverter.asHover(result);
+                        if (hover) {
+                            // Workaround to support command links (trusted vscode.MarkdownString) in hovers
+                            // https://github.com/microsoft/vscode/issues/33577
+                            hover.contents = hover.contents.map(toTrusted);
+                            
+                            const actions = (<any>result).actions;
+                            if (actions) {
+                                hover.contents.push(renderHoverActions(actions));
+                            }
+                        }
+                        return hover;
+                    },
+                    (error) => {
+                        client.logFailedRequest(lc.HoverRequest.type, error);
+                        return Promise.resolve(null);
+                    });
+            },
             // Using custom handling of CodeActions where each code action is resloved lazily
             // That's why we are not waiting for any command or edits
             async provideCodeActions(document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken, _next: lc.ProvideCodeActionsSignature) {
@@ -129,6 +173,7 @@ class ExperimentalFeatures implements lc.StaticFeature {
         caps.snippetTextEdit = true;
         caps.codeActionGroup = true;
         caps.resolveCodeAction = true;
+        caps.hoverActions = true;
         capabilities.experimental = caps;
     }
     initialize(_capabilities: lc.ServerCapabilities<any>, _documentSelector: lc.DocumentSelector | undefined): void {