]> git.lizzy.rs Git - rust.git/commitdiff
Avoid shared mutable state
authorKirill Bulatov <mail4score@gmail.com>
Mon, 5 Aug 2019 19:31:12 +0000 (22:31 +0300)
committerKirill Bulatov <mail4score@gmail.com>
Mon, 5 Aug 2019 20:11:16 +0000 (23:11 +0300)
editors/code/src/commands/inlay_hints.ts
editors/code/src/extension.ts

index d6d1f61f9e4581cf199aba1c01275b451b3ddf0b..5393a2bc928ff8c69392b146c1b64406a26acf2f 100644 (file)
@@ -21,67 +21,57 @@ const typeHintDecorationType = vscode.window.createTextEditorDecorationType({
 
 export class HintsUpdater {
     private displayHints = true;
-    private decorationsSinceLastChange = new Map<
-        string,
-        vscode.DecorationOptions[]
-    >();
-
-    public async loadHints(editor?: vscode.TextEditor): Promise<void> {
-        if (this.displayHints) {
-            const documentUri = this.getEditorDocumentUri(editor);
-            if (documentUri !== null) {
-                const latestDecorations = this.decorationsSinceLastChange.get(
-                    documentUri.toString()
-                );
-                if (latestDecorations === undefined) {
-                    await this.updateDecorationsFromServer(
-                        documentUri,
-                        editor!
-                    );
-                } else {
-                    await editor!.setDecorations(
-                        typeHintDecorationType,
-                        latestDecorations
-                    );
-                }
-            }
-        }
-    }
 
     public async toggleHintsDisplay(displayHints: boolean): Promise<void> {
         if (this.displayHints !== displayHints) {
             this.displayHints = displayHints;
-            this.decorationsSinceLastChange.clear();
-
-            if (displayHints) {
-                return this.updateHints();
-            } else {
-                const currentEditor = vscode.window.activeTextEditor;
-                if (this.getEditorDocumentUri(currentEditor) !== null) {
-                    return currentEditor!.setDecorations(
-                        typeHintDecorationType,
-                        []
-                    );
-                }
-            }
+            return this.refreshVisibleEditorsHints(
+                displayHints ? undefined : []
+            );
         }
     }
 
-    public async updateHints(cause?: TextDocumentChangeEvent): Promise<void> {
+    public async refreshHintsForVisibleEditors(
+        cause?: TextDocumentChangeEvent
+    ): Promise<void> {
         if (!this.displayHints) {
             return;
         }
-        const editor = vscode.window.activeTextEditor;
-        if (editor === undefined) {
+        if (
+            cause !== undefined &&
+            (cause.contentChanges.length === 0 ||
+                !this.isRustDocument(cause.document))
+        ) {
             return;
         }
-        const document = cause === undefined ? editor.document : cause.document;
-        if (!this.isRustDocument(document)) {
-            return;
+        return this.refreshVisibleEditorsHints();
+    }
+
+    private async refreshVisibleEditorsHints(
+        newDecorations?: vscode.DecorationOptions[]
+    ) {
+        const promises: Array<Promise<void>> = [];
+
+        for (const rustEditor of vscode.window.visibleTextEditors.filter(
+            editor => this.isRustDocument(editor.document)
+        )) {
+            if (newDecorations !== undefined) {
+                promises.push(
+                    Promise.resolve(
+                        rustEditor.setDecorations(
+                            typeHintDecorationType,
+                            newDecorations
+                        )
+                    )
+                );
+            } else {
+                promises.push(this.updateDecorationsFromServer(rustEditor));
+            }
         }
 
-        this.decorationsSinceLastChange.clear();
-        return await this.updateDecorationsFromServer(document.uri, editor);
+        for (const promise of promises) {
+            await promise;
+        }
     }
 
     private isRustDocument(document: vscode.TextDocument): boolean {
@@ -89,23 +79,14 @@ export class HintsUpdater {
     }
 
     private async updateDecorationsFromServer(
-        documentUri: vscode.Uri,
         editor: TextEditor
     ): Promise<void> {
-        const newHints = await this.queryHints(documentUri.toString());
-        if (
-            newHints !== null &&
-            this.getEditorDocumentUri(vscode.window.activeTextEditor) ===
-                documentUri
-        ) {
+        const newHints = await this.queryHints(editor.document.uri.toString());
+        if (newHints !== null) {
             const newDecorations = newHints.map(hint => ({
                 range: hint.range,
                 renderOptions: { after: { contentText: `: ${hint.label}` } }
             }));
-            this.decorationsSinceLastChange.set(
-                documentUri.toString(),
-                newDecorations
-            );
             return editor.setDecorations(
                 typeHintDecorationType,
                 newDecorations
@@ -127,13 +108,4 @@ export class HintsUpdater {
                 )
             );
     }
-
-    private getEditorDocumentUri(
-        editor?: vscode.TextEditor
-    ): vscode.Uri | null {
-        if (editor && this.isRustDocument(editor.document)) {
-            return editor.document.uri;
-        }
-        return null;
-    }
 }
index c6efc2e7e041c8fa802376a9fcb78e7f5ad6a97f..39fe6efd8890e2a8345f1334f28094e316b7547f 100644 (file)
@@ -151,15 +151,27 @@ export function activate(context: vscode.ExtensionContext) {
 
     if (Server.config.displayInlayHints) {
         const hintsUpdater = new HintsUpdater();
-        hintsUpdater.loadHints(vscode.window.activeTextEditor).then(() => {
+        hintsUpdater.refreshHintsForVisibleEditors().then(() => {
+            // vscode may ignore top level hintsUpdater.refreshHintsForVisibleEditors()
+            // so update the hints once when the focus changes to guarantee their presence
+            let editorChangeDisposable: vscode.Disposable | null = null;
+            editorChangeDisposable = vscode.window.onDidChangeActiveTextEditor(
+                _ => {
+                    if (editorChangeDisposable !== null) {
+                        editorChangeDisposable.dispose();
+                    }
+                    return hintsUpdater.refreshHintsForVisibleEditors();
+                }
+            );
+
             disposeOnDeactivation(
-                vscode.window.onDidChangeActiveTextEditor(editor =>
-                    hintsUpdater.loadHints(editor)
+                vscode.window.onDidChangeVisibleTextEditors(_ =>
+                    hintsUpdater.refreshHintsForVisibleEditors()
                 )
             );
             disposeOnDeactivation(
                 vscode.workspace.onDidChangeTextDocument(e =>
-                    hintsUpdater.updateHints(e)
+                    hintsUpdater.refreshHintsForVisibleEditors(e)
                 )
             );
             disposeOnDeactivation(