diff options
-rw-r--r-- | editors/code/package.json | 14 | ||||
-rw-r--r-- | editors/code/src/commands/index.ts | 4 | ||||
-rw-r--r-- | editors/code/src/commands/inlay_hints.ts | 104 | ||||
-rw-r--r-- | editors/code/src/config.ts | 5 | ||||
-rw-r--r-- | editors/code/src/extension.ts | 24 |
5 files changed, 150 insertions, 1 deletions
diff --git a/editors/code/package.json b/editors/code/package.json index fd30c7946..060a3a247 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -238,6 +238,11 @@ | |||
238 | "type": "number", | 238 | "type": "number", |
239 | "default": null, | 239 | "default": null, |
240 | "description": "Number of syntax trees rust-analyzer keeps in memory" | 240 | "description": "Number of syntax trees rust-analyzer keeps in memory" |
241 | }, | ||
242 | "rust-analyzer.displayInlayHints": { | ||
243 | "type": "boolean", | ||
244 | "default": true, | ||
245 | "description": "Display additional type information in the editor" | ||
241 | } | 246 | } |
242 | } | 247 | } |
243 | }, | 248 | }, |
@@ -444,6 +449,15 @@ | |||
444 | "light": "#000000", | 449 | "light": "#000000", |
445 | "highContrast": "#FFFFFF" | 450 | "highContrast": "#FFFFFF" |
446 | } | 451 | } |
452 | }, | ||
453 | { | ||
454 | "id": "ralsp.inlayHint", | ||
455 | "description": "Color for inlay hints", | ||
456 | "defaults": { | ||
457 | "dark": "#A0A0A0F0", | ||
458 | "light": "#747474", | ||
459 | "highContrast": "#BEBEBE" | ||
460 | } | ||
447 | } | 461 | } |
448 | ] | 462 | ] |
449 | } | 463 | } |
diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts index 194658497..c194bd2ea 100644 --- a/editors/code/src/commands/index.ts +++ b/editors/code/src/commands/index.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import * as analyzerStatus from './analyzer_status'; | 1 | import * as analyzerStatus from './analyzer_status'; |
2 | import * as applySourceChange from './apply_source_change'; | 2 | import * as applySourceChange from './apply_source_change'; |
3 | import * as inlayHints from './inlay_hints'; | ||
3 | import * as joinLines from './join_lines'; | 4 | import * as joinLines from './join_lines'; |
4 | import * as matchingBrace from './matching_brace'; | 5 | import * as matchingBrace from './matching_brace'; |
5 | import * as onEnter from './on_enter'; | 6 | import * as onEnter from './on_enter'; |
@@ -15,5 +16,6 @@ export { | |||
15 | parentModule, | 16 | parentModule, |
16 | runnables, | 17 | runnables, |
17 | syntaxTree, | 18 | syntaxTree, |
18 | onEnter | 19 | onEnter, |
20 | inlayHints | ||
19 | }; | 21 | }; |
diff --git a/editors/code/src/commands/inlay_hints.ts b/editors/code/src/commands/inlay_hints.ts new file mode 100644 index 000000000..8154af8dc --- /dev/null +++ b/editors/code/src/commands/inlay_hints.ts | |||
@@ -0,0 +1,104 @@ | |||
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 | const newDecorations = newHints.map(hint => ({ | ||
84 | range: hint.range, | ||
85 | renderOptions: { after: { contentText: `: ${hint.label}` } } | ||
86 | })); | ||
87 | return editor.setDecorations(typeHintDecorationType, newDecorations); | ||
88 | } | ||
89 | |||
90 | private async queryHints(documentUri: string): Promise<InlayHint[] | null> { | ||
91 | const request: InlayHintsParams = { | ||
92 | textDocument: { uri: documentUri } | ||
93 | }; | ||
94 | const client = Server.client; | ||
95 | return client | ||
96 | .onReady() | ||
97 | .then(() => | ||
98 | client.sendRequest<InlayHint[] | null>( | ||
99 | 'rust-analyzer/inlayHints', | ||
100 | request | ||
101 | ) | ||
102 | ); | ||
103 | } | ||
104 | } | ||
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 3f1b482e3..4d58a1a93 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts | |||
@@ -21,6 +21,7 @@ export class Config { | |||
21 | public raLspServerPath = RA_LSP_DEBUG || 'ra_lsp_server'; | 21 | public raLspServerPath = RA_LSP_DEBUG || 'ra_lsp_server'; |
22 | public showWorkspaceLoadedNotification = true; | 22 | public showWorkspaceLoadedNotification = true; |
23 | public lruCapacity: null | number = null; | 23 | public lruCapacity: null | number = null; |
24 | public displayInlayHints = true; | ||
24 | public cargoWatchOptions: CargoWatchOptions = { | 25 | public cargoWatchOptions: CargoWatchOptions = { |
25 | enableOnStartup: 'ask', | 26 | enableOnStartup: 'ask', |
26 | trace: 'off', | 27 | trace: 'off', |
@@ -123,5 +124,9 @@ export class Config { | |||
123 | if (config.has('lruCapacity')) { | 124 | if (config.has('lruCapacity')) { |
124 | this.lruCapacity = config.get('lruCapacity') as number; | 125 | this.lruCapacity = config.get('lruCapacity') as number; |
125 | } | 126 | } |
127 | |||
128 | if (config.has('displayInlayHints')) { | ||
129 | this.displayInlayHints = config.get('displayInlayHints') as boolean; | ||
130 | } | ||
126 | } | 131 | } |
127 | } | 132 | } |
diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index c8c3004a7..c6efc2e7e 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts | |||
@@ -3,6 +3,7 @@ import * as lc from 'vscode-languageclient'; | |||
3 | 3 | ||
4 | import * as commands from './commands'; | 4 | import * as commands from './commands'; |
5 | import { CargoWatchProvider } from './commands/cargo_watch'; | 5 | import { CargoWatchProvider } from './commands/cargo_watch'; |
6 | import { HintsUpdater } from './commands/inlay_hints'; | ||
6 | import { | 7 | import { |
7 | interactivelyStartCargoWatch, | 8 | interactivelyStartCargoWatch, |
8 | startCargoWatch | 9 | startCargoWatch |
@@ -147,6 +148,29 @@ export function activate(context: vscode.ExtensionContext) { | |||
147 | 148 | ||
148 | // Start the language server, finally! | 149 | // Start the language server, finally! |
149 | startServer(); | 150 | startServer(); |
151 | |||
152 | if (Server.config.displayInlayHints) { | ||
153 | const hintsUpdater = new HintsUpdater(); | ||
154 | hintsUpdater.loadHints(vscode.window.activeTextEditor).then(() => { | ||
155 | disposeOnDeactivation( | ||
156 | vscode.window.onDidChangeActiveTextEditor(editor => | ||
157 | hintsUpdater.loadHints(editor) | ||
158 | ) | ||
159 | ); | ||
160 | disposeOnDeactivation( | ||
161 | vscode.workspace.onDidChangeTextDocument(e => | ||
162 | hintsUpdater.updateHints(e) | ||
163 | ) | ||
164 | ); | ||
165 | disposeOnDeactivation( | ||
166 | vscode.workspace.onDidChangeConfiguration(_ => | ||
167 | hintsUpdater.toggleHintsDisplay( | ||
168 | Server.config.displayInlayHints | ||
169 | ) | ||
170 | ) | ||
171 | ); | ||
172 | }); | ||
173 | } | ||
150 | } | 174 | } |
151 | 175 | ||
152 | export function deactivate(): Thenable<void> { | 176 | export function deactivate(): Thenable<void> { |