From 7d0dd17b09240385333805637ea17992a8089cf2 Mon Sep 17 00:00:00 2001 From: vsrs Date: Wed, 3 Jun 2020 14:15:54 +0300 Subject: Add hover actions as LSP extension --- editors/code/package.json | 16 +++++++++++++--- editors/code/src/client.ts | 45 +++++++++++++++++++++++++++++++++++++++++++++ editors/code/src/config.ts | 13 +++++++++---- editors/code/src/lsp_ext.ts | 12 ++++++++++++ 4 files changed, 79 insertions(+), 7 deletions(-) (limited to 'editors/code') 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 @@ "default": true }, "rust-analyzer.lens.run": { - "markdownDescription": "Whether to show Run lens. Only applies when `#rust-analyzer.lens.enable#` is set.", + "markdownDescription": "Whether to show `Run` lens. Only applies when `#rust-analyzer.lens.enable#` is set.", "type": "boolean", "default": true }, "rust-analyzer.lens.debug": { - "markdownDescription": "Whether to show Debug lens. Only applies when `#rust-analyzer.lens.enable#` is set.", + "markdownDescription": "Whether to show `Debug` lens. Only applies when `#rust-analyzer.lens.enable#` is set.", "type": "boolean", "default": true }, "rust-analyzer.lens.implementations": { - "markdownDescription": "Whether to show Implementations lens. Only applies when `#rust-analyzer.lens.enable#` is set.", + "markdownDescription": "Whether to show `Implementations` lens. Only applies when `#rust-analyzer.lens.enable#` is set.", + "type": "boolean", + "default": true + }, + "rust-analyzer.hoverActions.enable": { + "description": "Whether to show HoverActions in Rust files.", + "type": "boolean", + "default": true + }, + "rust-analyzer.hoverActions.implementations": { + "markdownDescription": "Whether to show `Implementations` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.", "type": "boolean", "default": true }, 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 import { SemanticTokensFeature, DocumentSemanticsTokensSignature } from 'vscode-languageclient/lib/semanticTokens.proposed'; import { assert } from './util'; +function toTrusted(obj: vscode.MarkedString): vscode.MarkedString { + const md = 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 = (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, _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 { "files", "highlighting", "updates.channel", - "lens.enable", - "lens.run", - "lens.debug", - "lens.implementations", + "lens", // works as lens.* + "hoverActions", // works as hoverActions.* ] .map(opt => `${this.rootSection}.${opt}`); @@ -132,4 +130,11 @@ export class Config { implementations: this.get("lens.implementations"), }; } + + get hoverActions() { + return { + enable: this.get("hoverActions.enable"), + implementations: this.get("hoverActions.implementations"), + }; + } } 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 { parseOnly: boolean; } export const ssr = new lc.RequestType('experimental/ssr'); + +export interface CommandLink extends lc.Command { + /** + * A tooltip for the command, when represented in the UI. + */ + tooltip?: string; +} + +export interface CommandLinkGroup { + title?: string; + commands: CommandLink[]; +} -- cgit v1.2.3