Add hover actions as LSP extension

This commit is contained in:
vsrs 2020-06-03 14:15:54 +03:00
parent 913a623281
commit 7d0dd17b09
11 changed files with 351 additions and 56 deletions

View file

@ -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 {