diff options
author | Kirill Bulatov <[email protected]> | 2019-08-05 20:31:12 +0100 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2019-08-05 21:11:16 +0100 |
commit | c5598d9ade92e9ec4474a14229bb34a44a4edad5 (patch) | |
tree | 96b6a9f1b6b4c1b8c31cbba32a74eaaa26c8f9ea | |
parent | 777552b6a8e534ef3780ecf30a432df1a48fd25c (diff) |
Avoid shared mutable state
-rw-r--r-- | editors/code/src/commands/inlay_hints.ts | 106 | ||||
-rw-r--r-- | editors/code/src/extension.ts | 20 |
2 files changed, 55 insertions, 71 deletions
diff --git a/editors/code/src/commands/inlay_hints.ts b/editors/code/src/commands/inlay_hints.ts index d6d1f61f9..5393a2bc9 100644 --- a/editors/code/src/commands/inlay_hints.ts +++ b/editors/code/src/commands/inlay_hints.ts | |||
@@ -21,67 +21,57 @@ const typeHintDecorationType = vscode.window.createTextEditorDecorationType({ | |||
21 | 21 | ||
22 | export class HintsUpdater { | 22 | export class HintsUpdater { |
23 | private displayHints = true; | 23 | private displayHints = true; |
24 | private decorationsSinceLastChange = new Map< | ||
25 | string, | ||
26 | vscode.DecorationOptions[] | ||
27 | >(); | ||
28 | |||
29 | public async loadHints(editor?: vscode.TextEditor): Promise<void> { | ||
30 | if (this.displayHints) { | ||
31 | const documentUri = this.getEditorDocumentUri(editor); | ||
32 | if (documentUri !== null) { | ||
33 | const latestDecorations = this.decorationsSinceLastChange.get( | ||
34 | documentUri.toString() | ||
35 | ); | ||
36 | if (latestDecorations === undefined) { | ||
37 | await this.updateDecorationsFromServer( | ||
38 | documentUri, | ||
39 | editor! | ||
40 | ); | ||
41 | } else { | ||
42 | await editor!.setDecorations( | ||
43 | typeHintDecorationType, | ||
44 | latestDecorations | ||
45 | ); | ||
46 | } | ||
47 | } | ||
48 | } | ||
49 | } | ||
50 | 24 | ||
51 | public async toggleHintsDisplay(displayHints: boolean): Promise<void> { | 25 | public async toggleHintsDisplay(displayHints: boolean): Promise<void> { |
52 | if (this.displayHints !== displayHints) { | 26 | if (this.displayHints !== displayHints) { |
53 | this.displayHints = displayHints; | 27 | this.displayHints = displayHints; |
54 | this.decorationsSinceLastChange.clear(); | 28 | return this.refreshVisibleEditorsHints( |
55 | 29 | displayHints ? undefined : [] | |
56 | if (displayHints) { | 30 | ); |
57 | return this.updateHints(); | ||
58 | } else { | ||
59 | const currentEditor = vscode.window.activeTextEditor; | ||
60 | if (this.getEditorDocumentUri(currentEditor) !== null) { | ||
61 | return currentEditor!.setDecorations( | ||
62 | typeHintDecorationType, | ||
63 | [] | ||
64 | ); | ||
65 | } | ||
66 | } | ||
67 | } | 31 | } |
68 | } | 32 | } |
69 | 33 | ||
70 | public async updateHints(cause?: TextDocumentChangeEvent): Promise<void> { | 34 | public async refreshHintsForVisibleEditors( |
35 | cause?: TextDocumentChangeEvent | ||
36 | ): Promise<void> { | ||
71 | if (!this.displayHints) { | 37 | if (!this.displayHints) { |
72 | return; | 38 | return; |
73 | } | 39 | } |
74 | const editor = vscode.window.activeTextEditor; | 40 | if ( |
75 | if (editor === undefined) { | 41 | cause !== undefined && |
42 | (cause.contentChanges.length === 0 || | ||
43 | !this.isRustDocument(cause.document)) | ||
44 | ) { | ||
76 | return; | 45 | return; |
77 | } | 46 | } |
78 | const document = cause === undefined ? editor.document : cause.document; | 47 | return this.refreshVisibleEditorsHints(); |
79 | if (!this.isRustDocument(document)) { | 48 | } |
80 | 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 | } | ||
81 | } | 70 | } |
82 | 71 | ||
83 | this.decorationsSinceLastChange.clear(); | 72 | for (const promise of promises) { |
84 | return await this.updateDecorationsFromServer(document.uri, editor); | 73 | await promise; |
74 | } | ||
85 | } | 75 | } |
86 | 76 | ||
87 | private isRustDocument(document: vscode.TextDocument): boolean { | 77 | private isRustDocument(document: vscode.TextDocument): boolean { |
@@ -89,23 +79,14 @@ export class HintsUpdater { | |||
89 | } | 79 | } |
90 | 80 | ||
91 | private async updateDecorationsFromServer( | 81 | private async updateDecorationsFromServer( |
92 | documentUri: vscode.Uri, | ||
93 | editor: TextEditor | 82 | editor: TextEditor |
94 | ): Promise<void> { | 83 | ): Promise<void> { |
95 | const newHints = await this.queryHints(documentUri.toString()); | 84 | const newHints = await this.queryHints(editor.document.uri.toString()); |
96 | if ( | 85 | if (newHints !== null) { |
97 | newHints !== null && | ||
98 | this.getEditorDocumentUri(vscode.window.activeTextEditor) === | ||
99 | documentUri | ||
100 | ) { | ||
101 | const newDecorations = newHints.map(hint => ({ | 86 | const newDecorations = newHints.map(hint => ({ |
102 | range: hint.range, | 87 | range: hint.range, |
103 | renderOptions: { after: { contentText: `: ${hint.label}` } } | 88 | renderOptions: { after: { contentText: `: ${hint.label}` } } |
104 | })); | 89 | })); |
105 | this.decorationsSinceLastChange.set( | ||
106 | documentUri.toString(), | ||
107 | newDecorations | ||
108 | ); | ||
109 | return editor.setDecorations( | 90 | return editor.setDecorations( |
110 | typeHintDecorationType, | 91 | typeHintDecorationType, |
111 | newDecorations | 92 | newDecorations |
@@ -127,13 +108,4 @@ export class HintsUpdater { | |||
127 | ) | 108 | ) |
128 | ); | 109 | ); |
129 | } | 110 | } |
130 | |||
131 | private getEditorDocumentUri( | ||
132 | editor?: vscode.TextEditor | ||
133 | ): vscode.Uri | null { | ||
134 | if (editor && this.isRustDocument(editor.document)) { | ||
135 | return editor.document.uri; | ||
136 | } | ||
137 | return null; | ||
138 | } | ||
139 | } | 111 | } |
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( |