aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/inlay_hints.ts
diff options
context:
space:
mode:
Diffstat (limited to 'editors/code/src/inlay_hints.ts')
-rw-r--r--editors/code/src/inlay_hints.ts113
1 files changed, 113 insertions, 0 deletions
diff --git a/editors/code/src/inlay_hints.ts b/editors/code/src/inlay_hints.ts
new file mode 100644
index 000000000..b975915ca
--- /dev/null
+++ b/editors/code/src/inlay_hints.ts
@@ -0,0 +1,113 @@
1import * as vscode from 'vscode';
2import * as lc from 'vscode-languageclient';
3import { Server } from './server';
4
5interface InlayHintsParams {
6 textDocument: lc.TextDocumentIdentifier;
7}
8
9interface InlayHint {
10 range: vscode.Range;
11 kind: string;
12 label: string;
13}
14
15const typeHintDecorationType = vscode.window.createTextEditorDecorationType({
16 after: {
17 color: new vscode.ThemeColor('ralsp.inlayHint'),
18 },
19});
20
21export class HintsUpdater {
22 private displayHints = true;
23
24 public async toggleHintsDisplay(displayHints: boolean): Promise<void> {
25 if (this.displayHints !== displayHints) {
26 this.displayHints = displayHints;
27 return this.refreshVisibleEditorsHints(
28 displayHints ? undefined : [],
29 );
30 }
31 }
32
33 public async refreshHintsForVisibleEditors(
34 cause?: vscode.TextDocumentChangeEvent,
35 ): Promise<void> {
36 if (!this.displayHints) return;
37
38 if (
39 cause !== undefined &&
40 (cause.contentChanges.length === 0 ||
41 !this.isRustDocument(cause.document))
42 ) {
43 return;
44 }
45 return this.refreshVisibleEditorsHints();
46 }
47
48 private async refreshVisibleEditorsHints(
49 newDecorations?: vscode.DecorationOptions[],
50 ) {
51 const promises: Array<Promise<void>> = [];
52
53 for (const rustEditor of vscode.window.visibleTextEditors.filter(
54 editor => this.isRustDocument(editor.document),
55 )) {
56 if (newDecorations !== undefined) {
57 promises.push(
58 Promise.resolve(
59 rustEditor.setDecorations(
60 typeHintDecorationType,
61 newDecorations,
62 ),
63 ),
64 );
65 } else {
66 promises.push(this.updateDecorationsFromServer(rustEditor));
67 }
68 }
69
70 for (const promise of promises) {
71 await promise;
72 }
73 }
74
75 private isRustDocument(document: vscode.TextDocument): boolean {
76 return document && document.languageId === 'rust';
77 }
78
79 private async updateDecorationsFromServer(
80 editor: vscode.TextEditor,
81 ): Promise<void> {
82 const newHints = await this.queryHints(editor.document.uri.toString());
83 if (newHints !== null) {
84 const newDecorations = newHints.map(hint => ({
85 range: hint.range,
86 renderOptions: {
87 after: {
88 contentText: `: ${hint.label}`,
89 },
90 },
91 }));
92 return editor.setDecorations(
93 typeHintDecorationType,
94 newDecorations,
95 );
96 }
97 }
98
99 private async queryHints(documentUri: string): Promise<InlayHint[] | null> {
100 const request: InlayHintsParams = {
101 textDocument: { uri: documentUri },
102 };
103 const client = Server.client;
104 return client
105 .onReady()
106 .then(() =>
107 client.sendRequest<InlayHint[] | null>(
108 'rust-analyzer/inlayHints',
109 request,
110 ),
111 );
112 }
113}