diff options
author | vsrs <[email protected]> | 2020-06-03 12:15:54 +0100 |
---|---|---|
committer | vsrs <[email protected]> | 2020-06-05 12:59:26 +0100 |
commit | 7d0dd17b09240385333805637ea17992a8089cf2 (patch) | |
tree | 605249f14a8d7c8071362e31be28ca9c17b55173 /editors | |
parent | 913a623281ed4cd190ca04845c64e5054d176a2a (diff) |
Add hover actions as LSP extension
Diffstat (limited to 'editors')
-rw-r--r-- | editors/code/package.json | 16 | ||||
-rw-r--r-- | editors/code/src/client.ts | 45 | ||||
-rw-r--r-- | editors/code/src/config.ts | 13 | ||||
-rw-r--r-- | editors/code/src/lsp_ext.ts | 12 |
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 | |||
7 | import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed'; | 7 | import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed'; |
8 | import { assert } from './util'; | 8 | import { assert } from './util'; |
9 | 9 | ||
10 | function 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 | |||
19 | function renderCommand(cmd: CommandLink) { | ||
20 | return `[${cmd.title}](command:${cmd.command}?${encodeURIComponent(JSON.stringify(cmd.arguments))} '${cmd.tooltip!}')`; | ||
21 | } | ||
22 | |||
23 | function 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 | |||
10 | export function createClient(serverPath: string, cwd: string): lc.LanguageClient { | 33 | export 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 | } |
92 | export const ssr = new lc.RequestType<SsrParams, lc.WorkspaceEdit, void>('experimental/ssr'); | 92 | export const ssr = new lc.RequestType<SsrParams, lc.WorkspaceEdit, void>('experimental/ssr'); |
93 | |||
94 | export interface CommandLink extends lc.Command { | ||
95 | /** | ||
96 | * A tooltip for the command, when represented in the UI. | ||
97 | */ | ||
98 | tooltip?: string; | ||
99 | } | ||
100 | |||
101 | export interface CommandLinkGroup { | ||
102 | title?: string; | ||
103 | commands: CommandLink[]; | ||
104 | } | ||