From a7be358d5989ceb5b932461d48bdaecd6792c5ad Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Tue, 25 Aug 2026 08:03:18 +0200 Subject: [PATCH 1/2] Fix stuck changes-since-review progress Always end the changes-since-review progress when refreshing PR data fails, while preserving the original error for existing logging and handling. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/test/view/progress.test.ts | 27 +++++++++++++++++++++++++++ src/view/progress.ts | 9 +++++++++ src/view/reviewManager.ts | 6 ++---- 3 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 src/test/view/progress.test.ts diff --git a/src/test/view/progress.test.ts b/src/test/view/progress.test.ts new file mode 100644 index 0000000000..db5d52756c --- /dev/null +++ b/src/test/view/progress.test.ts @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { default as assert } from 'assert'; +import { ProgressHelper } from '../../view/progress'; + +describe('ProgressHelper', function () { + it('ends progress when the task fails', async function () { + const helper = new ProgressHelper(); + const error = new Error('Failed to update'); + let progressEnded = false; + + const task = helper.run(async () => { + throw error; + }); + helper.progress.then(() => { + progressEnded = true; + }); + + await assert.rejects(task, candidate => candidate === error); + await Promise.resolve(); + + assert.strictEqual(progressEnded, true); + }); +}); diff --git a/src/view/progress.ts b/src/view/progress.ts index 04ef0370bf..001a837b42 100644 --- a/src/view/progress.ts +++ b/src/view/progress.ts @@ -25,4 +25,13 @@ export class ProgressHelper { endProgress() { this._endProgress.fire(); } + + async run(task: () => Promise): Promise { + this.startProgress(); + try { + await task(); + } finally { + this.endProgress(); + } + } } \ No newline at end of file diff --git a/src/view/reviewManager.ts b/src/view/reviewManager.ts index 396e5d0ba7..19baa1c9ba 100644 --- a/src/view/reviewManager.ts +++ b/src/view/reviewManager.ts @@ -806,16 +806,14 @@ export class ReviewManager extends Disposable { this._activePrViewCoordinator.setPullRequest(pr, this._folderRepoManager, this, previousActive); this._localToDispose.push( - pr.onDidChangeChangesSinceReview(async _ => { - this._changesSinceLastReviewProgress.startProgress(); + pr.onDidChangeChangesSinceReview(_ => this._changesSinceLastReviewProgress.run(async () => { this.changesInPrDataProvider.refresh(); await this.updateComments(); await this.reopenNewReviewDiffs(); if (pr) { PullRequestModel.openChanges(this._folderRepoManager, pr); } - this._changesSinceLastReviewProgress.endProgress(); - }) + })) ); Logger.appendLine(`Register in memory content provider`, this.id); if (previousPrNumber !== pr.number) { From 9e95716c5534e561cb0260dccea347b8de6b42a1 Mon Sep 17 00:00:00 2001 From: Alex Ross <38270282+alexr00@users.noreply.github.com> Date: Thu, 27 Aug 2026 13:08:38 +0200 Subject: [PATCH 2/2] Clean up --- src/view/progress.ts | 7 ++++--- src/view/reviewManager.ts | 6 ++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/view/progress.ts b/src/view/progress.ts index 001a837b42..26eef008ea 100644 --- a/src/view/progress.ts +++ b/src/view/progress.ts @@ -7,12 +7,13 @@ import * as vscode from 'vscode'; export class ProgressHelper { private _progress: Promise = Promise.resolve(); - private _endProgress: vscode.EventEmitter = new vscode.EventEmitter(); + private readonly _endProgress = new vscode.EventEmitter(); get progress(): Promise { return this._progress; } - startProgress() { + + private startProgress(): void { this.endProgress(); this._progress = new Promise(resolve => { const disposable = this._endProgress.event(() => { @@ -22,7 +23,7 @@ export class ProgressHelper { }); } - endProgress() { + private endProgress(): void { this._endProgress.fire(); } diff --git a/src/view/reviewManager.ts b/src/view/reviewManager.ts index 19baa1c9ba..3abaa96d7b 100644 --- a/src/view/reviewManager.ts +++ b/src/view/reviewManager.ts @@ -806,13 +806,11 @@ export class ReviewManager extends Disposable { this._activePrViewCoordinator.setPullRequest(pr, this._folderRepoManager, this, previousActive); this._localToDispose.push( - pr.onDidChangeChangesSinceReview(_ => this._changesSinceLastReviewProgress.run(async () => { + pr.onDidChangeChangesSinceReview(() => this._changesSinceLastReviewProgress.run(async () => { this.changesInPrDataProvider.refresh(); await this.updateComments(); await this.reopenNewReviewDiffs(); - if (pr) { - PullRequestModel.openChanges(this._folderRepoManager, pr); - } + PullRequestModel.openChanges(this._folderRepoManager, pr); })) ); Logger.appendLine(`Register in memory content provider`, this.id);