mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2026-04-17 21:24:52 +00:00
Add hover actions as LSP extension
This commit is contained in:
@@ -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
|
||||
},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<boolean>("lens.implementations"),
|
||||
};
|
||||
}
|
||||
|
||||
get hoverActions() {
|
||||
return {
|
||||
enable: this.get<boolean>("hoverActions.enable"),
|
||||
implementations: this.get<boolean>("hoverActions.implementations"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,3 +90,15 @@ export interface SsrParams {
|
||||
parseOnly: boolean;
|
||||
}
|
||||
export const ssr = new lc.RequestType<SsrParams, lc.WorkspaceEdit, void>('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[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user