1 import * as vscode from 'vscode';
2 import * as lc from 'vscode-languageclient';
4 import { Ctx } from './ctx';
6 export function activateInlayHints(ctx: Ctx) {
7 const hintsUpdater = new HintsUpdater(ctx);
8 vscode.window.onDidChangeVisibleTextEditors(async _ => {
9 await hintsUpdater.refresh();
10 }, ctx.subscriptions);
12 vscode.workspace.onDidChangeTextDocument(async e => {
13 if (e.contentChanges.length === 0) return;
14 if (e.document.languageId !== 'rust') return;
15 await hintsUpdater.refresh();
16 }, ctx.subscriptions);
18 vscode.workspace.onDidChangeConfiguration(_ => {
19 hintsUpdater.setEnabled(ctx.config.displayInlayHints);
20 }, ctx.subscriptions);
22 // XXX: don't await here;
23 // Who knows what happens if an exception is thrown here...
24 hintsUpdater.refresh();
27 interface InlayHintsParams {
28 textDocument: lc.TextDocumentIdentifier;
37 const typeHintDecorationType = vscode.window.createTextEditorDecorationType({
39 color: new vscode.ThemeColor('rust-analyzer.inlayHint'),
44 private pending: Map<string, vscode.CancellationTokenSource> = new Map();
46 private enabled = true;
48 constructor(ctx: Ctx) {
52 async setEnabled(enabled: boolean) {
53 if (this.enabled == enabled) return;
54 this.enabled = enabled;
59 this.allEditors.forEach(it => this.setDecorations(it, []));
64 if (!this.enabled) return;
65 const promises = this.allEditors.map(it => this.refreshEditor(it));
66 await Promise.all(promises);
69 private async refreshEditor(editor: vscode.TextEditor): Promise<void> {
70 const newHints = await this.queryHints(editor.document.uri.toString());
71 if (newHints == null) return;
72 const newDecorations = newHints.map(hint => ({
76 contentText: `: ${hint.label}`,
80 this.setDecorations(editor, newDecorations);
83 private get allEditors(): vscode.TextEditor[] {
84 return vscode.window.visibleTextEditors.filter(
85 editor => editor.document.languageId === 'rust',
89 private setDecorations(
90 editor: vscode.TextEditor,
91 decorations: vscode.DecorationOptions[],
93 editor.setDecorations(
94 typeHintDecorationType,
95 this.enabled ? decorations : [],
99 private async queryHints(documentUri: string): Promise<InlayHint[] | null> {
100 const request: InlayHintsParams = {
101 textDocument: { uri: documentUri },
103 let tokenSource = new vscode.CancellationTokenSource();
104 let prev = this.pending.get(documentUri);
105 if (prev) prev.cancel();
106 this.pending.set(documentUri, tokenSource);
108 return await this.ctx.sendRequestWithRetry<InlayHint[] | null>(
109 'rust-analyzer/inlayHints',
114 if (!tokenSource.token.isCancellationRequested) {
115 this.pending.delete(documentUri);