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