aboutsummaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
authorvsrs <[email protected]>2020-06-03 12:15:54 +0100
committervsrs <[email protected]>2020-06-05 12:59:26 +0100
commit7d0dd17b09240385333805637ea17992a8089cf2 (patch)
tree605249f14a8d7c8071362e31be28ca9c17b55173 /editors
parent913a623281ed4cd190ca04845c64e5054d176a2a (diff)
Add hover actions as LSP extension
Diffstat (limited to 'editors')
-rw-r--r--editors/code/package.json16
-rw-r--r--editors/code/src/client.ts45
-rw-r--r--editors/code/src/config.ts13
-rw-r--r--editors/code/src/lsp_ext.ts12
4 files changed, 79 insertions, 7 deletions
diff --git a/editors/code/package.json b/editors/code/package.json
index 30ab7ba4a..b9c57db3b 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -462,17 +462,27 @@
462 "default": true 462 "default": true
463 }, 463 },
464 "rust-analyzer.lens.run": { 464 "rust-analyzer.lens.run": {
465 "markdownDescription": "Whether to show Run lens. Only applies when `#rust-analyzer.lens.enable#` is set.", 465 "markdownDescription": "Whether to show `Run` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
466 "type": "boolean", 466 "type": "boolean",
467 "default": true 467 "default": true
468 }, 468 },
469 "rust-analyzer.lens.debug": { 469 "rust-analyzer.lens.debug": {
470 "markdownDescription": "Whether to show Debug lens. Only applies when `#rust-analyzer.lens.enable#` is set.", 470 "markdownDescription": "Whether to show `Debug` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
471 "type": "boolean", 471 "type": "boolean",
472 "default": true 472 "default": true
473 }, 473 },
474 "rust-analyzer.lens.implementations": { 474 "rust-analyzer.lens.implementations": {
475 "markdownDescription": "Whether to show Implementations lens. Only applies when `#rust-analyzer.lens.enable#` is set.", 475 "markdownDescription": "Whether to show `Implementations` lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
476 "type": "boolean",
477 "default": true
478 },
479 "rust-analyzer.hoverActions.enable": {
480 "description": "Whether to show HoverActions in Rust files.",
481 "type": "boolean",
482 "default": true
483 },
484 "rust-analyzer.hoverActions.implementations": {
485 "markdownDescription": "Whether to show `Implementations` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
476 "type": "boolean", 486 "type": "boolean",
477 "default": true 487 "default": true
478 }, 488 },
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index 40ad1e3cd..9df670283 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
7import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed'; 7import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed';
8import { assert } from './util'; 8import { assert } from './util';
9 9
10function toTrusted(obj: vscode.MarkedString): vscode.MarkedString {
11 const md = <vscode.MarkdownString>obj;
12 if (md && md.value.includes("```rust")) {
13 md.isTrusted = true;
14 return md;
15 }
16 return obj;
17}
18
19function renderCommand(cmd: CommandLink) {
20 return `[${cmd.title}](command:${cmd.command}?${encodeURIComponent(JSON.stringify(cmd.arguments))} '${cmd.tooltip!}')`;
21}
22
23function renderHoverActions(actions: CommandLinkGroup[]): vscode.MarkdownString {
24 const text = actions.map(group =>
25 (group.title ? (group.title + " ") : "") + group.commands.map(renderCommand).join(' | ')
26 ).join('___');
27
28 const result = new vscode.MarkdownString(text);
29 result.isTrusted = true;
30 return result;
31}
32
10export function createClient(serverPath: string, cwd: string): lc.LanguageClient { 33export function createClient(serverPath: string, cwd: string): lc.LanguageClient {
11 // '.' Is the fallback if no folder is open 34 // '.' Is the fallback if no folder is open
12 // TODO?: Workspace folders support Uri's (eg: file://test.txt). 35 // TODO?: Workspace folders support Uri's (eg: file://test.txt).
@@ -35,6 +58,27 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient
35 if (res === undefined) throw new Error('busy'); 58 if (res === undefined) throw new Error('busy');
36 return res; 59 return res;
37 }, 60 },
61 async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, _next: lc.ProvideHoverSignature) {
62 return client.sendRequest(lc.HoverRequest.type, client.code2ProtocolConverter.asTextDocumentPositionParams(document, position), token).then(
63 (result) => {
64 const hover = client.protocol2CodeConverter.asHover(result);
65 if (hover) {
66 // Workaround to support command links (trusted vscode.MarkdownString) in hovers
67 // https://github.com/microsoft/vscode/issues/33577
68 hover.contents = hover.contents.map(toTrusted);
69
70 const actions = (<any>result).actions;
71 if (actions) {
72 hover.contents.push(renderHoverActions(actions));
73 }
74 }
75 return hover;
76 },
77 (error) => {
78 client.logFailedRequest(lc.HoverRequest.type, error);
79 return Promise.resolve(null);
80 });
81 },
38 // Using custom handling of CodeActions where each code action is resloved lazily 82 // Using custom handling of CodeActions where each code action is resloved lazily
39 // That's why we are not waiting for any command or edits 83 // That's why we are not waiting for any command or edits
40 async provideCodeActions(document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken, _next: lc.ProvideCodeActionsSignature) { 84 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 {
129 caps.snippetTextEdit = true; 173 caps.snippetTextEdit = true;
130 caps.codeActionGroup = true; 174 caps.codeActionGroup = true;
131 caps.resolveCodeAction = true; 175 caps.resolveCodeAction = true;
176 caps.hoverActions = true;
132 capabilities.experimental = caps; 177 capabilities.experimental = caps;
133 } 178 }
134 initialize(_capabilities: lc.ServerCapabilities<any>, _documentSelector: lc.DocumentSelector | undefined): void { 179 initialize(_capabilities: lc.ServerCapabilities<any>, _documentSelector: lc.DocumentSelector | undefined): void {
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index e8abf8284..d8f0037d4 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -16,10 +16,8 @@ export class Config {
16 "files", 16 "files",
17 "highlighting", 17 "highlighting",
18 "updates.channel", 18 "updates.channel",
19 "lens.enable", 19 "lens", // works as lens.*
20 "lens.run", 20 "hoverActions", // works as hoverActions.*
21 "lens.debug",
22 "lens.implementations",
23 ] 21 ]
24 .map(opt => `${this.rootSection}.${opt}`); 22 .map(opt => `${this.rootSection}.${opt}`);
25 23
@@ -132,4 +130,11 @@ export class Config {
132 implementations: this.get<boolean>("lens.implementations"), 130 implementations: this.get<boolean>("lens.implementations"),
133 }; 131 };
134 } 132 }
133
134 get hoverActions() {
135 return {
136 enable: this.get<boolean>("hoverActions.enable"),
137 implementations: this.get<boolean>("hoverActions.implementations"),
138 };
139 }
135} 140}
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 9793b926c..e16ea799c 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -90,3 +90,15 @@ export interface SsrParams {
90 parseOnly: boolean; 90 parseOnly: boolean;
91} 91}
92export const ssr = new lc.RequestType<SsrParams, lc.WorkspaceEdit, void>('experimental/ssr'); 92export const ssr = new lc.RequestType<SsrParams, lc.WorkspaceEdit, void>('experimental/ssr');
93
94export interface CommandLink extends lc.Command {
95 /**
96 * A tooltip for the command, when represented in the UI.
97 */
98 tooltip?: string;
99}
100
101export interface CommandLinkGroup {
102 title?: string;
103 commands: CommandLink[];
104}