diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-08-06 17:50:49 +0100 |
---|---|---|
committer | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-08-06 17:50:49 +0100 |
commit | 7e12422fa2c8ba7b3df63b4e4297464a0071a359 (patch) | |
tree | f88de34c48e08ea8cf481a29f5764f13492a9ac9 /editors/code | |
parent | 811492aa546d83daf56f61d334d6ee295651f111 (diff) | |
parent | c5598d9ade92e9ec4474a14229bb34a44a4edad5 (diff) |
Merge #1652
1652: Improve type hints behavior r=matklad a=SomeoneToIgnore
This PR fixed the following type hints issues:
* Restructures the `InlayKind` enum contents based on the discussion here: https://github.com/rust-analyzer/rust-analyzer/pull/1606#issuecomment-515968055
* Races described in #1639
* Caches the latest decorations received for each file to show them the next time the file is opened (instead of a new server request)
Co-authored-by: Kirill Bulatov <[email protected]>
Diffstat (limited to 'editors/code')
-rw-r--r-- | editors/code/src/commands/inlay_hints.ts | 76 | ||||
-rw-r--r-- | editors/code/src/extension.ts | 20 |
2 files changed, 55 insertions, 41 deletions
diff --git a/editors/code/src/commands/inlay_hints.ts b/editors/code/src/commands/inlay_hints.ts index 3ba9da48b..5393a2bc9 100644 --- a/editors/code/src/commands/inlay_hints.ts +++ b/editors/code/src/commands/inlay_hints.ts | |||
@@ -22,53 +22,56 @@ const typeHintDecorationType = vscode.window.createTextEditorDecorationType({ | |||
22 | export class HintsUpdater { | 22 | export class HintsUpdater { |
23 | private displayHints = true; | 23 | private displayHints = true; |
24 | 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> { | 25 | public async toggleHintsDisplay(displayHints: boolean): Promise<void> { |
41 | if (this.displayHints !== displayHints) { | 26 | if (this.displayHints !== displayHints) { |
42 | this.displayHints = displayHints; | 27 | this.displayHints = displayHints; |
43 | 28 | return this.refreshVisibleEditorsHints( | |
44 | if (displayHints) { | 29 | displayHints ? undefined : [] |
45 | return this.updateHints(); | 30 | ); |
46 | } else { | ||
47 | const editor = vscode.window.activeTextEditor; | ||
48 | if (editor != null) { | ||
49 | return editor.setDecorations(typeHintDecorationType, []); | ||
50 | } | ||
51 | } | ||
52 | } | 31 | } |
53 | } | 32 | } |
54 | 33 | ||
55 | public async updateHints(cause?: TextDocumentChangeEvent): Promise<void> { | 34 | public async refreshHintsForVisibleEditors( |
35 | cause?: TextDocumentChangeEvent | ||
36 | ): Promise<void> { | ||
56 | if (!this.displayHints) { | 37 | if (!this.displayHints) { |
57 | return; | 38 | return; |
58 | } | 39 | } |
59 | const editor = vscode.window.activeTextEditor; | 40 | if ( |
60 | if (editor == null) { | 41 | cause !== undefined && |
42 | (cause.contentChanges.length === 0 || | ||
43 | !this.isRustDocument(cause.document)) | ||
44 | ) { | ||
61 | return; | 45 | return; |
62 | } | 46 | } |
63 | const document = cause == null ? editor.document : cause.document; | 47 | return this.refreshVisibleEditorsHints(); |
64 | if (!this.isRustDocument(document)) { | 48 | } |
65 | return; | 49 | |
50 | private async refreshVisibleEditorsHints( | ||
51 | newDecorations?: vscode.DecorationOptions[] | ||
52 | ) { | ||
53 | const promises: Array<Promise<void>> = []; | ||
54 | |||
55 | for (const rustEditor of vscode.window.visibleTextEditors.filter( | ||
56 | editor => this.isRustDocument(editor.document) | ||
57 | )) { | ||
58 | if (newDecorations !== undefined) { | ||
59 | promises.push( | ||
60 | Promise.resolve( | ||
61 | rustEditor.setDecorations( | ||
62 | typeHintDecorationType, | ||
63 | newDecorations | ||
64 | ) | ||
65 | ) | ||
66 | ); | ||
67 | } else { | ||
68 | promises.push(this.updateDecorationsFromServer(rustEditor)); | ||
69 | } | ||
66 | } | 70 | } |
67 | 71 | ||
68 | return await this.updateDecorationsFromServer( | 72 | for (const promise of promises) { |
69 | document.uri.toString(), | 73 | await promise; |
70 | editor | 74 | } |
71 | ); | ||
72 | } | 75 | } |
73 | 76 | ||
74 | private isRustDocument(document: vscode.TextDocument): boolean { | 77 | private isRustDocument(document: vscode.TextDocument): boolean { |
@@ -76,11 +79,10 @@ export class HintsUpdater { | |||
76 | } | 79 | } |
77 | 80 | ||
78 | private async updateDecorationsFromServer( | 81 | private async updateDecorationsFromServer( |
79 | documentUri: string, | ||
80 | editor: TextEditor | 82 | editor: TextEditor |
81 | ): Promise<void> { | 83 | ): Promise<void> { |
82 | const newHints = await this.queryHints(documentUri); | 84 | const newHints = await this.queryHints(editor.document.uri.toString()); |
83 | if (newHints != null) { | 85 | if (newHints !== null) { |
84 | const newDecorations = newHints.map(hint => ({ | 86 | const newDecorations = newHints.map(hint => ({ |
85 | range: hint.range, | 87 | range: hint.range, |
86 | renderOptions: { after: { contentText: `: ${hint.label}` } } | 88 | renderOptions: { after: { contentText: `: ${hint.label}` } } |
diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index c6efc2e7e..39fe6efd8 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts | |||
@@ -151,15 +151,27 @@ export function activate(context: vscode.ExtensionContext) { | |||
151 | 151 | ||
152 | if (Server.config.displayInlayHints) { | 152 | if (Server.config.displayInlayHints) { |
153 | const hintsUpdater = new HintsUpdater(); | 153 | const hintsUpdater = new HintsUpdater(); |
154 | hintsUpdater.loadHints(vscode.window.activeTextEditor).then(() => { | 154 | hintsUpdater.refreshHintsForVisibleEditors().then(() => { |
155 | // vscode may ignore top level hintsUpdater.refreshHintsForVisibleEditors() | ||
156 | // so update the hints once when the focus changes to guarantee their presence | ||
157 | let editorChangeDisposable: vscode.Disposable | null = null; | ||
158 | editorChangeDisposable = vscode.window.onDidChangeActiveTextEditor( | ||
159 | _ => { | ||
160 | if (editorChangeDisposable !== null) { | ||
161 | editorChangeDisposable.dispose(); | ||
162 | } | ||
163 | return hintsUpdater.refreshHintsForVisibleEditors(); | ||
164 | } | ||
165 | ); | ||
166 | |||
155 | disposeOnDeactivation( | 167 | disposeOnDeactivation( |
156 | vscode.window.onDidChangeActiveTextEditor(editor => | 168 | vscode.window.onDidChangeVisibleTextEditors(_ => |
157 | hintsUpdater.loadHints(editor) | 169 | hintsUpdater.refreshHintsForVisibleEditors() |
158 | ) | 170 | ) |
159 | ); | 171 | ); |
160 | disposeOnDeactivation( | 172 | disposeOnDeactivation( |
161 | vscode.workspace.onDidChangeTextDocument(e => | 173 | vscode.workspace.onDidChangeTextDocument(e => |
162 | hintsUpdater.updateHints(e) | 174 | hintsUpdater.refreshHintsForVisibleEditors(e) |
163 | ) | 175 | ) |
164 | ); | 176 | ); |
165 | disposeOnDeactivation( | 177 | disposeOnDeactivation( |