Avoid shared mutable state
This commit is contained in:
@@ -21,67 +21,57 @@ const typeHintDecorationType = vscode.window.createTextEditorDecorationType({
|
|||||||
|
|
||||||
export class HintsUpdater {
|
export class HintsUpdater {
|
||||||
private displayHints = true;
|
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> {
|
public async toggleHintsDisplay(displayHints: boolean): Promise<void> {
|
||||||
if (this.displayHints !== displayHints) {
|
if (this.displayHints !== displayHints) {
|
||||||
this.displayHints = displayHints;
|
this.displayHints = displayHints;
|
||||||
this.decorationsSinceLastChange.clear();
|
return this.refreshVisibleEditorsHints(
|
||||||
|
displayHints ? undefined : []
|
||||||
if (displayHints) {
|
|
||||||
return this.updateHints();
|
|
||||||
} else {
|
|
||||||
const currentEditor = vscode.window.activeTextEditor;
|
|
||||||
if (this.getEditorDocumentUri(currentEditor) !== null) {
|
|
||||||
return currentEditor!.setDecorations(
|
|
||||||
typeHintDecorationType,
|
|
||||||
[]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateHints(cause?: TextDocumentChangeEvent): Promise<void> {
|
public async refreshHintsForVisibleEditors(
|
||||||
|
cause?: TextDocumentChangeEvent
|
||||||
|
): Promise<void> {
|
||||||
if (!this.displayHints) {
|
if (!this.displayHints) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const editor = vscode.window.activeTextEditor;
|
if (
|
||||||
if (editor === undefined) {
|
cause !== undefined &&
|
||||||
|
(cause.contentChanges.length === 0 ||
|
||||||
|
!this.isRustDocument(cause.document))
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const document = cause === undefined ? editor.document : cause.document;
|
return this.refreshVisibleEditorsHints();
|
||||||
if (!this.isRustDocument(document)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.decorationsSinceLastChange.clear();
|
private async refreshVisibleEditorsHints(
|
||||||
return await this.updateDecorationsFromServer(document.uri, editor);
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const promise of promises) {
|
||||||
|
await promise;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private isRustDocument(document: vscode.TextDocument): boolean {
|
private isRustDocument(document: vscode.TextDocument): boolean {
|
||||||
@@ -89,23 +79,14 @@ export class HintsUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async updateDecorationsFromServer(
|
private async updateDecorationsFromServer(
|
||||||
documentUri: vscode.Uri,
|
|
||||||
editor: TextEditor
|
editor: TextEditor
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const newHints = await this.queryHints(documentUri.toString());
|
const newHints = await this.queryHints(editor.document.uri.toString());
|
||||||
if (
|
if (newHints !== null) {
|
||||||
newHints !== null &&
|
|
||||||
this.getEditorDocumentUri(vscode.window.activeTextEditor) ===
|
|
||||||
documentUri
|
|
||||||
) {
|
|
||||||
const newDecorations = newHints.map(hint => ({
|
const newDecorations = newHints.map(hint => ({
|
||||||
range: hint.range,
|
range: hint.range,
|
||||||
renderOptions: { after: { contentText: `: ${hint.label}` } }
|
renderOptions: { after: { contentText: `: ${hint.label}` } }
|
||||||
}));
|
}));
|
||||||
this.decorationsSinceLastChange.set(
|
|
||||||
documentUri.toString(),
|
|
||||||
newDecorations
|
|
||||||
);
|
|
||||||
return editor.setDecorations(
|
return editor.setDecorations(
|
||||||
typeHintDecorationType,
|
typeHintDecorationType,
|
||||||
newDecorations
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,15 +151,27 @@ export function activate(context: vscode.ExtensionContext) {
|
|||||||
|
|
||||||
if (Server.config.displayInlayHints) {
|
if (Server.config.displayInlayHints) {
|
||||||
const hintsUpdater = new HintsUpdater();
|
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(
|
disposeOnDeactivation(
|
||||||
vscode.window.onDidChangeActiveTextEditor(editor =>
|
vscode.window.onDidChangeVisibleTextEditors(_ =>
|
||||||
hintsUpdater.loadHints(editor)
|
hintsUpdater.refreshHintsForVisibleEditors()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
disposeOnDeactivation(
|
disposeOnDeactivation(
|
||||||
vscode.workspace.onDidChangeTextDocument(e =>
|
vscode.workspace.onDidChangeTextDocument(e =>
|
||||||
hintsUpdater.updateHints(e)
|
hintsUpdater.refreshHintsForVisibleEditors(e)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
disposeOnDeactivation(
|
disposeOnDeactivation(
|
||||||
|
|||||||
Reference in New Issue
Block a user