aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src
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/code/src
parent913a623281ed4cd190ca04845c64e5054d176a2a (diff)
Add hover actions as LSP extension
Diffstat (limited to 'editors/code/src')
-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
3 files changed, 66 insertions, 4 deletions
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}