From c5598d9ade92e9ec4474a14229bb34a44a4edad5 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 5 Aug 2019 22:31:12 +0300 Subject: Avoid shared mutable state --- editors/code/src/commands/inlay_hints.ts | 106 ++++++++++++------------------- 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({ export class HintsUpdater { private displayHints = true; - private decorationsSinceLastChange = new Map< - string, - vscode.DecorationOptions[] - >(); - - public async loadHints(editor?: vscode.TextEditor): Promise { - 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 { 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 { + public async refreshHintsForVisibleEditors( + cause?: TextDocumentChangeEvent + ): Promise { 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> = []; + + 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 { - 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; - } } 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) { 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( -- cgit v1.2.3