Extension types and rendering

This commit is contained in:
Matt Hooper 2020-03-23 23:32:50 +01:00
parent a197abbc7a
commit 6f239a581a
5 changed files with 39 additions and 4 deletions

View file

@ -333,6 +333,11 @@
"default": true, "default": true,
"description": "Whether to show inlay type hints" "description": "Whether to show inlay type hints"
}, },
"rust-analyzer.inlayHints.chainingHints": {
"type": "boolean",
"default": true,
"description": "Whether to show inlay type hints for method chains"
},
"rust-analyzer.inlayHints.parameterHints": { "rust-analyzer.inlayHints.parameterHints": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,

View file

@ -32,6 +32,7 @@ export async function createClient(config: Config, serverPath: string): Promise<
inlayHintsType: config.inlayHints.typeHints, inlayHintsType: config.inlayHints.typeHints,
inlayHintsParameter: config.inlayHints.parameterHints, inlayHintsParameter: config.inlayHints.parameterHints,
inlayHintsChaining: config.inlayHints.chainingHints,
inlayHintsMaxLength: config.inlayHints.maxLength, inlayHintsMaxLength: config.inlayHints.maxLength,
cargoWatchEnable: cargoWatchOpts.enable, cargoWatchEnable: cargoWatchOpts.enable,

View file

@ -88,6 +88,7 @@ export class Config {
return { return {
typeHints: this.cfg.get<boolean>("inlayHints.typeHints")!, typeHints: this.cfg.get<boolean>("inlayHints.typeHints")!,
parameterHints: this.cfg.get<boolean>("inlayHints.parameterHints")!, parameterHints: this.cfg.get<boolean>("inlayHints.parameterHints")!,
chainingHints: this.cfg.get<boolean>("inlayHints.chainingHints")!,
maxLength: this.cfg.get<null | number>("inlayHints.maxLength")!, maxLength: this.cfg.get<null | number>("inlayHints.maxLength")!,
}; };
} }

View file

@ -10,7 +10,11 @@ export function activateInlayHints(ctx: Ctx) {
const maybeUpdater = { const maybeUpdater = {
updater: null as null | HintsUpdater, updater: null as null | HintsUpdater,
onConfigChange() { onConfigChange() {
if (!ctx.config.inlayHints.typeHints && !ctx.config.inlayHints.parameterHints) { if (
!ctx.config.inlayHints.typeHints &&
!ctx.config.inlayHints.parameterHints &&
!ctx.config.inlayHints.chainingHints
) {
return this.dispose(); return this.dispose();
} }
if (!this.updater) this.updater = new HintsUpdater(ctx); if (!this.updater) this.updater = new HintsUpdater(ctx);
@ -63,6 +67,22 @@ const paramHints = {
} }
}; };
const chainingHints = {
decorationType: vscode.window.createTextEditorDecorationType({
after: {
color: new vscode.ThemeColor('rust_analyzer.inlayHint'),
fontStyle: "normal",
}
}),
toDecoration(hint: ra.InlayHint.ChainingHint, conv: lc.Protocol2CodeConverter): vscode.DecorationOptions {
return {
range: conv.asRange(hint.range),
renderOptions: { after: { contentText: ` ${hint.label}` } }
};
}
};
class HintsUpdater implements Disposable { class HintsUpdater implements Disposable {
private sourceFiles = new Map<string, RustSourceFile>(); // map Uri -> RustSourceFile private sourceFiles = new Map<string, RustSourceFile>(); // map Uri -> RustSourceFile
private readonly disposables: Disposable[] = []; private readonly disposables: Disposable[] = [];
@ -95,7 +115,7 @@ class HintsUpdater implements Disposable {
dispose() { dispose() {
this.sourceFiles.forEach(file => file.inlaysRequest?.cancel()); this.sourceFiles.forEach(file => file.inlaysRequest?.cancel());
this.ctx.visibleRustEditors.forEach(editor => this.renderDecorations(editor, { param: [], type: [] })); this.ctx.visibleRustEditors.forEach(editor => this.renderDecorations(editor, { param: [], type: [], chaining: [] }));
this.disposables.forEach(d => d.dispose()); this.disposables.forEach(d => d.dispose());
} }
@ -154,10 +174,11 @@ class HintsUpdater implements Disposable {
private renderDecorations(editor: RustEditor, decorations: InlaysDecorations) { private renderDecorations(editor: RustEditor, decorations: InlaysDecorations) {
editor.setDecorations(typeHints.decorationType, decorations.type); editor.setDecorations(typeHints.decorationType, decorations.type);
editor.setDecorations(paramHints.decorationType, decorations.param); editor.setDecorations(paramHints.decorationType, decorations.param);
editor.setDecorations(chainingHints.decorationType, decorations.chaining);
} }
private hintsToDecorations(hints: ra.InlayHint[]): InlaysDecorations { private hintsToDecorations(hints: ra.InlayHint[]): InlaysDecorations {
const decorations: InlaysDecorations = { type: [], param: [] }; const decorations: InlaysDecorations = { type: [], param: [], chaining: [] };
const conv = this.ctx.client.protocol2CodeConverter; const conv = this.ctx.client.protocol2CodeConverter;
for (const hint of hints) { for (const hint of hints) {
@ -170,6 +191,10 @@ class HintsUpdater implements Disposable {
decorations.param.push(paramHints.toDecoration(hint, conv)); decorations.param.push(paramHints.toDecoration(hint, conv));
continue; continue;
} }
case ra.InlayHint.Kind.ChainingHint: {
decorations.chaining.push(chainingHints.toDecoration(hint, conv));
continue;
}
} }
} }
return decorations; return decorations;
@ -196,6 +221,7 @@ class HintsUpdater implements Disposable {
interface InlaysDecorations { interface InlaysDecorations {
type: vscode.DecorationOptions[]; type: vscode.DecorationOptions[];
param: vscode.DecorationOptions[]; param: vscode.DecorationOptions[];
chaining: vscode.DecorationOptions[];
} }
interface RustSourceFile { interface RustSourceFile {

View file

@ -86,12 +86,13 @@ export interface Runnable {
} }
export const runnables = request<RunnablesParams, Vec<Runnable>>("runnables"); export const runnables = request<RunnablesParams, Vec<Runnable>>("runnables");
export type InlayHint = InlayHint.TypeHint | InlayHint.ParamHint; export type InlayHint = InlayHint.TypeHint | InlayHint.ParamHint | InlayHint.ChainingHint;
export namespace InlayHint { export namespace InlayHint {
export const enum Kind { export const enum Kind {
TypeHint = "TypeHint", TypeHint = "TypeHint",
ParamHint = "ParameterHint", ParamHint = "ParameterHint",
ChainingHint = "ChainingHint",
} }
interface Common { interface Common {
range: lc.Range; range: lc.Range;
@ -99,6 +100,7 @@ export namespace InlayHint {
} }
export type TypeHint = Common & { kind: Kind.TypeHint }; export type TypeHint = Common & { kind: Kind.TypeHint };
export type ParamHint = Common & { kind: Kind.ParamHint }; export type ParamHint = Common & { kind: Kind.ParamHint };
export type ChainingHint = Common & { kind: Kind.ChainingHint };
} }
export interface InlayHintsParams { export interface InlayHintsParams {
textDocument: lc.TextDocumentIdentifier; textDocument: lc.TextDocumentIdentifier;