diff --git a/src/integrations/editor/DiffViewProvider.ts b/src/integrations/editor/DiffViewProvider.ts index 64820beffb..765d81c282 100644 --- a/src/integrations/editor/DiffViewProvider.ts +++ b/src/integrations/editor/DiffViewProvider.ts @@ -187,7 +187,10 @@ export class DiffViewProvider { } } - async saveChanges(diagnosticsEnabled: boolean = true, writeDelayMs: number = DEFAULT_WRITE_DELAY_MS): Promise<{ + async saveChanges( + diagnosticsEnabled: boolean = true, + writeDelayMs: number = DEFAULT_WRITE_DELAY_MS, + ): Promise<{ newProblemsMessage: string | undefined userEdits: string | undefined finalContent: string | undefined @@ -222,22 +225,22 @@ export class DiffViewProvider { // and can address them accordingly. If problems don't change immediately after // applying a fix, won't be notified, which is generally fine since the // initial fix is usually correct and it may just take time for linters to catch up. - + let newProblemsMessage = "" - + if (diagnosticsEnabled) { // Add configurable delay to allow linters time to process and clean up issues // like unused imports (especially important for Go and other languages) // Ensure delay is non-negative const safeDelayMs = Math.max(0, writeDelayMs) - + try { await delay(safeDelayMs) } catch (error) { // Log error but continue - delay failure shouldn't break the save operation console.warn(`Failed to apply write delay: ${error}`) } - + const postDiagnostics = vscode.languages.getDiagnostics() // Get diagnostic settings from state @@ -551,8 +554,21 @@ export class DiffViewProvider { ) }) .then( - () => { - // Command executed successfully, now wait for the editor to appear + async () => { + // Command executed successfully, now check if the diff editor is already visible + // This handles cases where the document was pre-opened and events might not fire + await new Promise((r) => setTimeout(r, 100)) // Small delay to ensure UI updates + + // Check if the diff editor is already visible + const diffEditor = vscode.window.visibleTextEditors.find((e) => + arePathsEqual(e.document.uri.fsPath, uri.fsPath), + ) + + if (diffEditor) { + cleanup() + resolve(diffEditor) + } + // If not found immediately, the event listeners will handle it }, (err: any) => { cleanup() diff --git a/src/integrations/editor/__tests__/DiffViewProvider.spec.ts b/src/integrations/editor/__tests__/DiffViewProvider.spec.ts index 7159aca57a..a4d47caeef 100644 --- a/src/integrations/editor/__tests__/DiffViewProvider.spec.ts +++ b/src/integrations/editor/__tests__/DiffViewProvider.spec.ts @@ -267,6 +267,62 @@ describe("DiffViewProvider", () => { "Failed to execute diff command for /mock/cwd/test.md: Cannot open file", ) }) + + it("should resolve immediately if diff editor is already visible after command", async () => { + // Setup + const mockEditor = { + document: { + uri: { fsPath: `${mockCwd}/test.md` }, + getText: vi.fn().mockReturnValue(""), + lineCount: 0, + }, + selection: { + active: { line: 0, character: 0 }, + anchor: { line: 0, character: 0 }, + }, + edit: vi.fn().mockResolvedValue(true), + revealRange: vi.fn(), + } + + // Mock showTextDocument + vi.mocked(vscode.window.showTextDocument).mockResolvedValue(mockEditor as any) + + // Mock executeCommand to succeed + vi.mocked(vscode.commands.executeCommand).mockResolvedValue(undefined) + + // Mock workspace.onDidOpenTextDocument - don't trigger callback + vi.mocked(vscode.workspace.onDidOpenTextDocument).mockReturnValue({ dispose: vi.fn() }) + + // Mock window.onDidChangeVisibleTextEditors - don't trigger callback + vi.mocked(vscode.window.onDidChangeVisibleTextEditors).mockReturnValue({ dispose: vi.fn() }) + + // Mock window.visibleTextEditors to return our editor immediately after command + vi.mocked(vscode.window).visibleTextEditors = [mockEditor as any] + + // Set up for file + ;(diffViewProvider as any).editType = "modify" + + // Execute open - should complete successfully + await diffViewProvider.open("test.md") + + // Verify that showTextDocument was called + expect(vscode.window.showTextDocument).toHaveBeenCalledWith( + expect.objectContaining({ fsPath: `${mockCwd}/test.md` }), + { preview: false, viewColumn: vscode.ViewColumn.Active, preserveFocus: true }, + ) + + // Verify that the diff command was executed + expect(vscode.commands.executeCommand).toHaveBeenCalledWith( + "vscode.diff", + expect.any(Object), + expect.any(Object), + `test.md: ${DIFF_VIEW_LABEL_CHANGES} (Editable)`, + { preserveFocus: true }, + ) + + // Verify that the activeDiffEditor was set + expect((diffViewProvider as any).activeDiffEditor).toBe(mockEditor) + }) }) describe("closeAllDiffViews method", () => {